386BSD 0.0 development
[unix-history] / usr / src / usr.bin / gcc / cc1 / explow.c
CommitLineData
60b058ed
WJ
1/* Subroutines for manipulating rtx's in semantically interesting ways.
2 Copyright (C) 1987 Free Software Foundation, Inc.
3
4This file is part of GNU CC.
5
6GNU CC is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 1, or (at your option)
9any later version.
10
11GNU CC is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU CC; see the file COPYING. If not, write to
18the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20
21#include "config.h"
22#include "rtl.h"
23#include "tree.h"
24#include "flags.h"
25#include "expr.h"
26
27/* Return an rtx for the sum of X and the integer C. */
28
29rtx
30plus_constant (x, c)
31 register rtx x;
32 register int c;
33{
34 register RTX_CODE code = GET_CODE (x);
35 register enum machine_mode mode = GET_MODE (x);
36 int all_constant = 0;
37
38 if (c == 0)
39 return x;
40
41 if (code == CONST_INT)
42 return gen_rtx (CONST_INT, VOIDmode, (INTVAL (x) + c));
43
44 /* If adding to something entirely constant, set a flag
45 so that we can add a CONST around the result. */
46 if (code == CONST)
47 {
48 x = XEXP (x, 0);
49 all_constant = 1;
50 }
51 else if (code == SYMBOL_REF || code == LABEL_REF)
52 all_constant = 1;
53
54 /* The interesting case is adding the integer to a sum.
55 Look for constant term in the sum and combine
56 with C. For an integer constant term, we make a combined
57 integer. For a constant term that is not an explicit integer,
58 we cannot really combine, but group them together anyway. */
59
60 if (GET_CODE (x) == PLUS)
61 {
62 if (GET_CODE (XEXP (x, 0)) == CONST_INT)
63 {
64 c += INTVAL (XEXP (x, 0));
65 x = XEXP (x, 1);
66 }
67 else if (GET_CODE (XEXP (x, 1)) == CONST_INT)
68 {
69 c += INTVAL (XEXP (x, 1));
70 x = XEXP (x, 0);
71 }
72 else if (CONSTANT_P (XEXP (x, 0)))
73 {
74 return gen_rtx (PLUS, mode,
75 plus_constant (XEXP (x, 0), c),
76 XEXP (x, 1));
77 }
78 else if (CONSTANT_P (XEXP (x, 1)))
79 {
80 return gen_rtx (PLUS, mode,
81 XEXP (x, 0),
82 plus_constant (XEXP (x, 1), c));
83 }
84#ifdef OLD_INDEXING
85 /* Detect adding a constant to an indexed address
86 of the form (PLUS (MULT (REG) (CONST)) regs-and-constants).
87 Keep the (MULT ...) at the top level of addition so that
88 the result is still suitable for indexing and constants
89 are combined. */
90 else if (GET_CODE (XEXP (x, 0)) == MULT)
91 {
92 return gen_rtx (PLUS, mode, XEXP (x, 0),
93 plus_constant (XEXP (x, 1), c));
94 }
95 else if (GET_CODE (XEXP (x, 1)) == MULT)
96 {
97 return gen_rtx (PLUS, mode, plus_constant (XEXP (x, 0), c),
98 XEXP (x, 1));
99 }
100#endif
101 }
102 if (c != 0)
103 x = gen_rtx (PLUS, mode, x, gen_rtx (CONST_INT, VOIDmode, c));
104
105 if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF)
106 return x;
107 else if (all_constant)
108 return gen_rtx (CONST, mode, x);
109 else
110 return x;
111}
112\f
113/* If X is a sum, return a new sum like X but lacking any constant terms.
114 Add all the removed constant terms into *CONSTPTR.
115 X itself is not altered. The result != X if and only if
116 it is not isomorphic to X. */
117
118rtx
119eliminate_constant_term (x, constptr)
120 rtx x;
121 int *constptr;
122{
123 int c;
124 register rtx x0, x1;
125
126 if (GET_CODE (x) != PLUS)
127 return x;
128
129 /* First handle constants appearing at this level explicitly. */
130 if (GET_CODE (XEXP (x, 0)) == CONST_INT)
131 {
132 *constptr += INTVAL (XEXP (x, 0));
133 return eliminate_constant_term (XEXP (x, 1), constptr);
134 }
135
136 if (GET_CODE (XEXP (x, 1)) == CONST_INT)
137 {
138 *constptr += INTVAL (XEXP (x, 1));
139 return eliminate_constant_term (XEXP (x, 0), constptr);
140 }
141
142 c = 0;
143 x0 = eliminate_constant_term (XEXP (x, 0), &c);
144 x1 = eliminate_constant_term (XEXP (x, 1), &c);
145 if (x1 != XEXP (x, 1) || x0 != XEXP (x, 0))
146 {
147 *constptr += c;
148 return gen_rtx (PLUS, GET_MODE (x), x0, x1);
149 }
150 return x;
151}
152
153/* Return an rtx for the size in bytes of the value of EXP. */
154
155rtx
156expr_size (exp)
157 tree exp;
158{
159 return expand_expr (size_in_bytes (TREE_TYPE (exp)), 0, SImode, 0);
160}
161
162/* Not yet really written since C does not need it. */
163
164rtx
165lookup_static_chain (context)
166 rtx context;
167{
168 abort ();
169}
170\f
171/* Return a copy of X in which all memory references
172 and all constants that involve symbol refs
173 have been replaced with new temporary registers.
174 Also emit code to load the memory locations and constants
175 into those registers.
176
177 If X contains no such constants or memory references,
178 X itself (not a copy) is returned.
179
180 X may contain no arithmetic except addition, subtraction and multiplication.
181 Values returned by expand_expr with 1 for sum_ok fit this constraint. */
182
183static rtx
184break_out_memory_refs (x)
185 register rtx x;
186{
187 if (GET_CODE (x) == MEM || GET_CODE (x) == CONST
188 || GET_CODE (x) == SYMBOL_REF)
189 {
190 register rtx temp = force_reg (Pmode, x);
191 mark_reg_pointer (temp);
192 x = temp;
193 }
194 else if (GET_CODE (x) == PLUS || GET_CODE (x) == MINUS
195 || GET_CODE (x) == MULT)
196 {
197 register rtx op0 = break_out_memory_refs (XEXP (x, 0));
198 register rtx op1 = break_out_memory_refs (XEXP (x, 1));
199 if (op0 != XEXP (x, 0) || op1 != XEXP (x, 1))
200 x = gen_rtx (GET_CODE (x), Pmode, op0, op1);
201 }
202 return x;
203}
204
205/* Given a memory address or facsimile X, construct a new address,
206 currently equivalent, that is stable: future stores won't change it.
207
208 X must be composed of constants, register and memory references
209 combined with addition, subtraction and multiplication:
210 in other words, just what you can get from expand_expr if sum_ok is 1.
211
212 Works by making copies of all regs and memory locations used
213 by X and combining them the same way X does.
214 You could also stabilize the reference to this address
215 by copying the address to a register with copy_to_reg;
216 but then you wouldn't get indexed addressing in the reference. */
217
218rtx
219copy_all_regs (x)
220 register rtx x;
221{
222 if (GET_CODE (x) == REG)
223 {
224 if (REGNO (x) != FRAME_POINTER_REGNUM)
225 x = copy_to_reg (x);
226 }
227 else if (GET_CODE (x) == MEM)
228 x = copy_to_reg (x);
229 else if (GET_CODE (x) == PLUS || GET_CODE (x) == MINUS
230 || GET_CODE (x) == MULT)
231 {
232 register rtx op0 = copy_all_regs (XEXP (x, 0));
233 register rtx op1 = copy_all_regs (XEXP (x, 1));
234 if (op0 != XEXP (x, 0) || op1 != XEXP (x, 1))
235 x = gen_rtx (GET_CODE (x), Pmode, op0, op1);
236 }
237 return x;
238}
239\f
240/* Return something equivalent to X but valid as a memory address
241 for something of mode MODE. When X is not itself valid, this
242 works by copying X or subexpressions of it into registers. */
243
244rtx
245memory_address (mode, x)
246 enum machine_mode mode;
247 register rtx x;
248{
249 register rtx oldx;
250
251 /* By passing constant addresses thru registers
252 we get a chance to cse them. */
253 if (! cse_not_expected && CONSTANT_P (x))
254 return force_reg (Pmode, x);
255
256 /* Accept a QUEUED that refers to a REG
257 even though that isn't a valid address.
258 On attempting to put this in an insn we will call protect_from_queue
259 which will turn it into a REG, which is valid. */
260 if (GET_CODE (x) == QUEUED
261 && GET_CODE (QUEUED_VAR (x)) == REG)
262 return x;
263
264 /* We get better cse by rejecting indirect addressing at this stage.
265 Let the combiner create indirect addresses where appropriate.
266 For now, generate the code so that the subexpressions useful to share
267 are visible. But not if cse won't be done! */
268 oldx = x;
269 if (! cse_not_expected && GET_CODE (x) != REG)
270 x = break_out_memory_refs (x);
271
272 /* At this point, any valid address is accepted. */
273 GO_IF_LEGITIMATE_ADDRESS (mode, x, win);
274
275 /* If it was valid before but breaking out memory refs invalidated it,
276 use it the old way. */
277 if (memory_address_p (mode, oldx))
278 goto win2;
279
280 /* Perform machine-dependent transformations on X
281 in certain cases. This is not necessary since the code
282 below can handle all possible cases, but machine-dependent
283 transformations can make better code. */
284 LEGITIMIZE_ADDRESS (x, oldx, mode, win);
285
286 /* PLUS and MULT can appear in special ways
287 as the result of attempts to make an address usable for indexing.
288 Usually they are dealt with by calling force_operand, below.
289 But a sum containing constant terms is special
290 if removing them makes the sum a valid address:
291 then we generate that address in a register
292 and index off of it. We do this because it often makes
293 shorter code, and because the addresses thus generated
294 in registers often become common subexpressions. */
295 if (GET_CODE (x) == PLUS)
296 {
297 int constant_term = 0;
298 rtx y = eliminate_constant_term (x, &constant_term);
299 if (constant_term == 0
300 || ! memory_address_p (mode, y))
301 return force_operand (x, 0);
302
303 y = plus_constant (copy_to_reg (y), constant_term);
304 if (! memory_address_p (mode, y))
305 return force_operand (x, 0);
306 return y;
307 }
308 if (GET_CODE (x) == MULT || GET_CODE (x) == MINUS)
309 return force_operand (x, 0);
310
311 /* If we have a register that's an invalid address,
312 it must be a hard reg of the wrong class. Copy it to a pseudo. */
313 if (GET_CODE (x) == REG)
314 return copy_to_reg (x);
315
316 /* Last resort: copy the value to a register, since
317 the register is a valid address. */
318 return force_reg (Pmode, x);
319
320 win2:
321 x = oldx;
322 win:
323 if (flag_force_addr && optimize && GET_CODE (x) != REG
324 /* Don't copy an addr via a reg if it is one of our stack slots.
325 If we did, it would cause invalid REG_EQUIV notes for parms. */
326 && ! (GET_CODE (x) == PLUS
327 && (XEXP (x, 0) == frame_pointer_rtx
328 || XEXP (x, 0) == arg_pointer_rtx)))
329 {
330 if (general_operand (x, Pmode))
331 return force_reg (Pmode, x);
332 else
333 return force_operand (x, 0);
334 }
335 return x;
336}
337
338/* Like `memory_address' but pretend `flag_force_addr' is 0. */
339
340rtx
341memory_address_noforce (mode, x)
342 enum machine_mode mode;
343 rtx x;
344{
345 int ambient_force_addr = flag_force_addr;
346 rtx val;
347
348 flag_force_addr = 0;
349 val = memory_address (mode, x);
350 flag_force_addr = ambient_force_addr;
351 return val;
352}
353\f
354/* Return a modified copy of X with its memory address copied
355 into a temporary register to protect it from side effects.
356 If X is not a MEM, it is returned unchanged (and not copied).
357 Perhaps even if it is a MEM, if there is no need to change it. */
358
359rtx
360stabilize (x)
361 rtx x;
362{
363 register rtx addr;
364 if (GET_CODE (x) != MEM)
365 return x;
366 addr = XEXP (x, 0);
367 if (rtx_unstable_p (addr))
368 {
369 rtx temp = copy_all_regs (addr);
370 rtx mem;
371 if (GET_CODE (temp) != REG)
372 temp = copy_to_reg (temp);
373 mem = gen_rtx (MEM, GET_MODE (x), temp);
374 /* Mark returned memref with in_struct
375 if it's in an array or structure. */
376 if (GET_CODE (addr) == PLUS || MEM_IN_STRUCT_P (x))
377 MEM_IN_STRUCT_P (mem) = 1;
378 return mem;
379 }
380 return x;
381}
382\f
383/* Copy the value or contents of X to a new temp reg and return that reg. */
384
385rtx
386copy_to_reg (x)
387 rtx x;
388{
389 register rtx temp = gen_reg_rtx (GET_MODE (x));
390
391 /* If not an operand, must be an address with PLUS and MULT so
392 do the computation. */
393 if (! general_operand (x, VOIDmode))
394 x = force_operand (x, temp);
395
396 if (x != temp)
397 emit_move_insn (temp, x);
398
399 return temp;
400}
401
402/* Like copy_to_reg but always give the new register mode Pmode
403 in case X is a constant. */
404
405rtx
406copy_addr_to_reg (x)
407 rtx x;
408{
409 return copy_to_mode_reg (Pmode, x);
410}
411
412/* Like copy_to_reg but always give the new register mode MODE
413 in case X is a constant. */
414
415rtx
416copy_to_mode_reg (mode, x)
417 enum machine_mode mode;
418 rtx x;
419{
420 register rtx temp = gen_reg_rtx (mode);
421
422 /* If not an operand, must be an address with PLUS and MULT so
423 do the computation. */
424 if (! general_operand (x, VOIDmode))
425 x = force_operand (x, temp);
426
427 if (GET_MODE (x) != mode && GET_MODE (x) != VOIDmode)
428 abort ();
429 if (x != temp)
430 emit_move_insn (temp, x);
431 return temp;
432}
433
434/* Load X into a register if it is not already one.
435 Use mode MODE for the register.
436 X should be valid for mode MODE, but it may be a constant which
437 is valid for all integer modes; that's why caller must specify MODE.
438
439 The caller must not alter the value in the register we return,
440 since we mark it as a "constant" register. */
441
442rtx
443force_reg (mode, x)
444 enum machine_mode mode;
445 rtx x;
446{
447 register rtx temp, insn;
448
449 if (GET_CODE (x) == REG)
450 return x;
451 temp = gen_reg_rtx (mode);
452 insn = emit_move_insn (temp, x);
453 /* Let optimizers know that TEMP's value never changes
454 and that X can be substituted for it. */
455 if (CONSTANT_P (x))
456 REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUIV, x, REG_NOTES (insn));
457 return temp;
458}
459
460/* If X is a memory ref, copy its contents to a new temp reg and return
461 that reg. Otherwise, return X. */
462
463rtx
464force_not_mem (x)
465 rtx x;
466{
467 register rtx temp;
468 if (GET_CODE (x) != MEM)
469 return x;
470 temp = gen_reg_rtx (GET_MODE (x));
471 emit_move_insn (temp, x);
472 return temp;
473}
474
475/* Copy X to TARGET (if it's nonzero and a reg)
476 or to a new temp reg and return that reg. */
477
478rtx
479copy_to_suggested_reg (x, target)
480 rtx x, target;
481{
482 register rtx temp;
483 if (target && GET_CODE (target) == REG)
484 temp = target;
485 else
486 temp = gen_reg_rtx (GET_MODE (x));
487 emit_move_insn (temp, x);
488 return temp;
489}
490\f
491/* Adjust the stack pointer by ADJUST (an rtx for a number of bytes).
492 This pops when ADJUST is positive. ADJUST need not be constant. */
493
494void
495adjust_stack (adjust)
496 rtx adjust;
497{
498 adjust = protect_from_queue (adjust, 0);
499
500#ifdef STACK_GROWS_DOWNWARD
501 emit_insn (gen_add2_insn (stack_pointer_rtx, adjust));
502#else
503 emit_insn (gen_sub2_insn (stack_pointer_rtx, adjust));
504#endif
505}
506
507/* Adjust the stack pointer by minus ADJUST (an rtx for a number of bytes).
508 This pushes when ADJUST is positive. ADJUST need not be constant. */
509
510void
511anti_adjust_stack (adjust)
512 rtx adjust;
513{
514 adjust = protect_from_queue (adjust, 0);
515
516#ifdef STACK_GROWS_DOWNWARD
517 emit_insn (gen_sub2_insn (stack_pointer_rtx, adjust));
518#else
519 emit_insn (gen_add2_insn (stack_pointer_rtx, adjust));
520#endif
521}
522
523/* Round the size of a block to be pushed up to the boundary required
524 by this machine. SIZE is the desired size, which need not be constant. */
525
526rtx
527round_push (size)
528 rtx size;
529{
530#ifdef STACK_BOUNDARY
531 int align = STACK_BOUNDARY / BITS_PER_UNIT;
532 if (align == 1)
533 return size;
534 if (GET_CODE (size) == CONST_INT)
535 {
536 int new = (INTVAL (size) + align - 1) / align * align;
537 if (INTVAL (size) != new)
538 size = gen_rtx (CONST_INT, VOIDmode, new);
539 }
540 else
541 {
542 size = expand_divmod (0, CEIL_DIV_EXPR, Pmode, size,
543 gen_rtx (CONST_INT, VOIDmode, align),
544 0, 1);
545 size = expand_mult (Pmode, size,
546 gen_rtx (CONST_INT, VOIDmode, align),
547 0, 1);
548 }
549#endif /* STACK_BOUNDARY */
550 return size;
551}
552
553/* Return an rtx representing the register or memory location
554 in which a scalar value of data type VALTYPE
555 was returned by a function call to function FUNC.
556 FUNC is a FUNCTION_DECL node if the precise function is known,
557 otherwise 0. */
558
559rtx
560hard_function_value (valtype, func)
561 tree valtype;
562 tree func;
563{
564 return FUNCTION_VALUE (valtype, func);
565}
566
567/* Return an rtx representing the register or memory location
568 in which a scalar value of mode MODE was returned by a library call. */
569
570rtx
571hard_libcall_value (mode)
572 enum machine_mode mode;
573{
574 return LIBCALL_VALUE (mode);
575}