|
|
1.1 root 1: /* Procedure integration for GNU CC.
2: Copyright (C) 1988, 1991 Free Software Foundation, Inc.
3: Contributed by Michael Tiemann ([email protected])
4:
5: This file is part of GNU CC.
6:
7: GNU CC is free software; you can redistribute it and/or modify
8: it under the terms of the GNU General Public License as published by
9: the Free Software Foundation; either version 2, or (at your option)
10: any later version.
11:
12: GNU CC is distributed in the hope that it will be useful,
13: but WITHOUT ANY WARRANTY; without even the implied warranty of
14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15: GNU General Public License for more details.
16:
17: You should have received a copy of the GNU General Public License
18: along with GNU CC; see the file COPYING. If not, write to
19: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20:
21:
22: #include <stdio.h>
23:
24: #include "config.h"
25: #include "rtl.h"
26: #include "tree.h"
27: #include "flags.h"
28: #include "insn-config.h"
29: #include "insn-flags.h"
30: #include "expr.h"
31: #include "output.h"
32: #include "integrate.h"
33: #include "real.h"
34: #include "function.h"
35:
36: #include "obstack.h"
37: #define obstack_chunk_alloc xmalloc
38: #define obstack_chunk_free free
39: extern int xmalloc ();
40: extern void free ();
41:
42: extern struct obstack *function_maybepermanent_obstack;
43:
44: extern tree pushdecl ();
45: extern tree poplevel ();
46:
47: /* Similar, but round to the next highest integer that meets the
48: alignment. */
49: #define CEIL_ROUND(VALUE,ALIGN) (((VALUE) + (ALIGN) - 1) & ~((ALIGN)- 1))
50:
51: /* Default max number of insns a function can have and still be inline.
52: This is overridden on RISC machines. */
53: #ifndef INTEGRATE_THRESHOLD
54: #define INTEGRATE_THRESHOLD(DECL) \
55: (8 * (8 + list_length (DECL_ARGUMENTS (DECL))))
56: #endif
57:
58: /* Save any constant pool constants in an insn. */
59: static void save_constants ();
60:
61: /* Note when parameter registers are the destination of a SET. */
62: static void note_modified_parmregs ();
63:
64: /* Copy an rtx for save_for_inline_copying. */
65: static rtx copy_for_inline ();
66:
67: /* Make copies of MEMs in DECL_RTLs. */
68: static void copy_decl_rtls ();
69:
70: static tree copy_decl_tree ();
71:
72: /* Return the constant equivalent of a given rtx, or 0 if none. */
73: static rtx const_equiv ();
74:
75: static void integrate_parm_decls ();
76: static void integrate_decl_tree ();
77:
78: static void subst_constants ();
79: static rtx fold_out_const_cc0 ();
80:
81: /* Zero if the current function (whose FUNCTION_DECL is FNDECL)
82: is safe and reasonable to integrate into other functions.
83: Nonzero means value is a warning message with a single %s
84: for the function's name. */
85:
86: char *
87: function_cannot_inline_p (fndecl)
88: register tree fndecl;
89: {
90: register rtx insn;
91: tree last = tree_last (TYPE_ARG_TYPES (TREE_TYPE (fndecl)));
92: int max_insns = INTEGRATE_THRESHOLD (fndecl);
93: register int ninsns = 0;
94: register tree parms;
95:
96: /* No inlines with varargs. `grokdeclarator' gives a warning
97: message about that if `inline' is specified. This code
98: it put in to catch the volunteers. */
99: if ((last && TREE_VALUE (last) != void_type_node)
100: || (DECL_ARGUMENTS (fndecl) && DECL_NAME (DECL_ARGUMENTS (fndecl))
101: && ! strcmp (IDENTIFIER_POINTER (DECL_NAME (DECL_ARGUMENTS (fndecl))),
102: "__builtin_va_alist")))
103: return "varargs function cannot be inline";
104:
105: if (current_function_calls_alloca)
106: return "function using alloca cannot be inline";
107:
108: if (current_function_contains_functions)
109: return "function with nested functions cannot be inline";
110:
111: /* This restriction may be eliminated sometime soon. But for now, don't
112: worry about remapping the static chain. */
113: if (current_function_needs_context)
114: return "nested function cannot be inline";
115:
116: /* If its not even close, don't even look. */
117: if (!TREE_INLINE (fndecl) && get_max_uid () > 3 * max_insns)
118: return "function too large to be inline";
119:
120: #if 0
121: /* Large stacks are OK now that inlined functions can share them. */
122: /* Don't inline functions with large stack usage,
123: since they can make other recursive functions burn up stack. */
124: if (!TREE_INLINE (fndecl) && get_frame_size () > 100)
125: return "function stack frame for inlining";
126: #endif
127:
128: #if 0
129: /* Don't inline functions which do not specify a function prototype and
130: have BLKmode argument or take the address of a parameter. */
131: for (parms = DECL_ARGUMENTS (fndecl); parms; parms = TREE_CHAIN (parms))
132: {
133: if (TYPE_MODE (TREE_TYPE (parms)) == BLKmode)
134: TREE_ADDRESSABLE (parms) = 1;
135: if (last == NULL_TREE && TREE_ADDRESSABLE (parms))
136: return "no prototype, and parameter address used; cannot be inline";
137: }
138: #endif
139:
140: /* We can't inline functions that return structures
141: the old-fashioned PCC way, copying into a static block. */
142: if (current_function_returns_pcc_struct)
143: return "inline functions not supported for this return value type";
144:
145: /* We can't inline functions that return structures of varying size. */
146: if (int_size_in_bytes (TREE_TYPE (TREE_TYPE (fndecl))) < 0)
147: return "function with varying-size return value cannot be inline";
148:
149: /* Cannot inline a function with a varying size argument. */
150: for (parms = DECL_ARGUMENTS (fndecl); parms; parms = TREE_CHAIN (parms))
151: if (int_size_in_bytes (TREE_TYPE (parms)) < 0)
152: return "function with varying-size parameter cannot be inline";
153:
154: if (!TREE_INLINE (fndecl) && get_max_uid () > max_insns)
155: {
156: for (ninsns = 0, insn = get_first_nonparm_insn (); insn && ninsns < max_insns;
157: insn = NEXT_INSN (insn))
158: {
159: if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
160: ninsns++;
161: }
162:
163: if (ninsns >= max_insns)
164: return "function too large to be inline";
165: }
166:
1.1.1.2 ! root 167: /* We cannot inline this function if forced_labels is non-zero. This
! 168: implies that a label in this function was used as an initializer.
! 169: Because labels can not be duplicated, all labels in the function
! 170: will be renamed when it is inlined. However, there is no way to find
! 171: and fix all variables initialized with addresses of labels in this
! 172: function, hence inlining is impossible. */
! 173:
! 174: if (forced_labels)
! 175: return "function with label addresses used in initializers cannot inline";
! 176:
1.1 root 177: return 0;
178: }
179:
180: /* Variables used within save_for_inline. */
181:
182: /* Mapping from old pseudo-register to new pseudo-registers.
183: The first element of this map is reg_map[FIRST_PSEUDO_REGISTER].
184: It is allocated in `save_for_inline' and `expand_inline_function',
185: and deallocated on exit from each of those routines. */
186: static rtx *reg_map;
187:
188: /* Mapping from old code-labels to new code-labels.
189: The first element of this map is label_map[min_labelno].
190: It is allocated in `save_for_inline' and `expand_inline_function',
191: and deallocated on exit from each of those routines. */
192: static rtx *label_map;
193:
194: /* Mapping from old insn uid's to copied insns.
195: It is allocated in `save_for_inline' and `expand_inline_function',
196: and deallocated on exit from each of those routines. */
197: static rtx *insn_map;
198:
199: /* Map pseudo reg number into the PARM_DECL for the parm living in the reg.
200: Zero for a reg that isn't a parm's home.
201: Only reg numbers less than max_parm_reg are mapped here. */
202: static tree *parmdecl_map;
203:
204: /* Keep track of first pseudo-register beyond those that are parms. */
205: static int max_parm_reg;
206:
207: /* When an insn is being copied by copy_for_inline,
208: this is nonzero if we have copied an ASM_OPERANDS.
209: In that case, it is the original input-operand vector. */
210: static rtvec orig_asm_operands_vector;
211:
212: /* When an insn is being copied by copy_for_inline,
213: this is nonzero if we have copied an ASM_OPERANDS.
214: In that case, it is the copied input-operand vector. */
215: static rtvec copy_asm_operands_vector;
216:
217: /* Likewise, this is the copied constraints vector. */
218: static rtvec copy_asm_constraints_vector;
219:
220: /* In save_for_inline, nonzero if past the parm-initialization insns. */
221: static int in_nonparm_insns;
222:
223: /* Subroutine for `save_for_inline{copying,nocopy}'. Performs initialization
224: needed to save FNDECL's insns and info for future inline expansion. */
225:
226: static rtx
227: initialize_for_inline (fndecl, min_labelno, max_labelno, max_reg, copy)
228: tree fndecl;
229: int min_labelno;
230: int max_labelno;
231: int max_reg;
232: int copy;
233: {
234: int function_flags, i;
235: rtvec arg_vector;
236: tree parms;
237:
238: /* Compute the values of any flags we must restore when inlining this. */
239:
240: function_flags
241: = (current_function_calls_alloca * FUNCTION_FLAGS_CALLS_ALLOCA
242: + current_function_calls_setjmp * FUNCTION_FLAGS_CALLS_SETJMP
243: + current_function_calls_longjmp * FUNCTION_FLAGS_CALLS_LONGJMP
244: + current_function_returns_struct * FUNCTION_FLAGS_RETURNS_STRUCT
245: + current_function_returns_pcc_struct * FUNCTION_FLAGS_RETURNS_PCC_STRUCT
246: + current_function_needs_context * FUNCTION_FLAGS_NEEDS_CONTEXT
247: + current_function_has_nonlocal_label * FUNCTION_FLAGS_HAS_NONLOCAL_LABEL
248: + current_function_returns_pointer * FUNCTION_FLAGS_RETURNS_POINTER
249: + current_function_uses_const_pool * FUNCTION_FLAGS_USES_CONST_POOL
250: + current_function_uses_pic_offset_table * FUNCTION_FLAGS_USES_PIC_OFFSET_TABLE);
251:
252: /* Clear out PARMDECL_MAP. It was allocated in the caller's frame. */
253: bzero (parmdecl_map, max_parm_reg * sizeof (tree));
254: arg_vector = rtvec_alloc (list_length (DECL_ARGUMENTS (fndecl)));
255:
256: for (parms = DECL_ARGUMENTS (fndecl), i = 0;
257: parms;
258: parms = TREE_CHAIN (parms), i++)
259: {
260: rtx p = DECL_RTL (parms);
261:
262: if (GET_CODE (p) == MEM && copy)
1.1.1.2 ! root 263: {
! 264: /* Copy the rtl so that modifications of the addresses
! 265: later in compilation won't affect this arg_vector.
! 266: Virtual register instantiation can screw the address
! 267: of the rtl. */
! 268: rtx new = copy_rtx (p);
! 269:
! 270: /* Don't leave the old copy anywhere in this decl. */
! 271: if (DECL_RTL (parms) == DECL_INCOMING_RTL (parms))
! 272: DECL_INCOMING_RTL (parms) = new;
! 273: DECL_RTL (parms) = new;
! 274: }
1.1 root 275:
276: RTVEC_ELT (arg_vector, i) = p;
277:
278: if (GET_CODE (p) == REG)
279: parmdecl_map[REGNO (p)] = parms;
280: TREE_READONLY (parms) = 1;
281: }
282:
283: /* Assume we start out in the insns that set up the parameters. */
284: in_nonparm_insns = 0;
285:
286: /* The list of DECL_SAVED_INSNS, starts off with a header which
287: contains the following information:
288:
289: the first insn of the function (not including the insns that copy
290: parameters into registers).
291: the first parameter insn of the function,
292: the first label used by that function,
293: the last label used by that function,
294: the highest register number used for parameters,
295: the total number of registers used,
296: the size of the incoming stack area for parameters,
297: the number of bytes popped on return,
298: the stack slot list,
299: some flags that are used to restore compiler globals,
300: the value of current_function_outgoing_args_size,
301: the original argument vector,
302: and the original DECL_INITIAL. */
303:
304: return gen_inline_header_rtx (NULL, NULL, min_labelno, max_labelno,
305: max_parm_reg, max_reg,
306: current_function_args_size,
307: current_function_pops_args,
308: stack_slot_list, function_flags,
309: current_function_outgoing_args_size,
310: arg_vector, (rtx) DECL_INITIAL (fndecl));
311: }
312:
313: /* Subroutine for `save_for_inline{copying,nocopy}'. Finishes up the
314: things that must be done to make FNDECL expandable as an inline function.
315: HEAD contains the chain of insns to which FNDECL will expand. */
316:
317: static void
318: finish_inline (fndecl, head)
319: tree fndecl;
320: rtx head;
321: {
322: NEXT_INSN (head) = get_first_nonparm_insn ();
323: FIRST_PARM_INSN (head) = get_insns ();
324: DECL_SAVED_INSNS (fndecl) = head;
325: DECL_FRAME_SIZE (fndecl) = get_frame_size ();
326: TREE_INLINE (fndecl) = 1;
327: }
328:
329: /* Make the insns and PARM_DECLs of the current function permanent
330: and record other information in DECL_SAVED_INSNS to allow inlining
331: of this function in subsequent calls.
332:
333: This function is called when we are going to immediately compile
334: the insns for FNDECL. The insns in maybepermanent_obstack cannot be
335: modified by the compilation process, so we copy all of them to
336: new storage and consider the new insns to be the insn chain to be
337: compiled. */
338:
339: void
340: save_for_inline_copying (fndecl)
341: tree fndecl;
342: {
343: rtx first_insn, last_insn, insn;
344: rtx head, copy;
345: int max_labelno, min_labelno, i, len;
346: int max_reg;
347: int max_uid;
348: rtx first_nonparm_insn;
349:
350: /* Make and emit a return-label if we have not already done so.
351: Do this before recording the bounds on label numbers. */
352:
353: if (return_label == 0)
354: {
355: return_label = gen_label_rtx ();
356: emit_label (return_label);
357: }
358:
359: /* Get some bounds on the labels and registers used. */
360:
361: max_labelno = max_label_num ();
362: min_labelno = get_first_label_num ();
363: max_reg = max_reg_num ();
364:
365: /* Set up PARMDECL_MAP which maps pseudo-reg number to its PARM_DECL.
366: Later we set TREE_READONLY to 0 if the parm is modified inside the fn.
367: Also set up ARG_VECTOR, which holds the unmodified DECL_RTX values
368: for the parms, prior to elimination of virtual registers.
369: These values are needed for substituting parms properly. */
370:
371: max_parm_reg = max_parm_reg_num ();
372: parmdecl_map = (tree *) alloca (max_parm_reg * sizeof (tree));
373:
374: head = initialize_for_inline (fndecl, min_labelno, max_labelno, max_reg, 1);
375:
376: if (current_function_uses_const_pool)
377: {
378: /* Replace any constant pool references with the actual constant. We
379: will put the constants back in the copy made below. */
380: for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
381: if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
382: {
383: save_constants (&PATTERN (insn));
384: if (REG_NOTES (insn))
385: save_constants (®_NOTES (insn));
386: }
387:
388: /* Clear out the constant pool so that we can recreate it with the
389: copied constants below. */
390: init_const_rtx_hash_table ();
391: clear_const_double_mem ();
392: }
393:
394: max_uid = INSN_UID (head);
395:
396: /* We have now allocated all that needs to be allocated permanently
397: on the rtx obstack. Set our high-water mark, so that we
398: can free the rest of this when the time comes. */
399:
400: preserve_data ();
401:
402: /* Copy the chain insns of this function.
403: Install the copied chain as the insns of this function,
404: for continued compilation;
405: the original chain is recorded as the DECL_SAVED_INSNS
406: for inlining future calls. */
407:
408: /* If there are insns that copy parms from the stack into pseudo registers,
409: those insns are not copied. `expand_inline_function' must
410: emit the correct code to handle such things. */
411:
412: insn = get_insns ();
413: if (GET_CODE (insn) != NOTE)
414: abort ();
415: first_insn = rtx_alloc (NOTE);
416: NOTE_SOURCE_FILE (first_insn) = NOTE_SOURCE_FILE (insn);
417: NOTE_LINE_NUMBER (first_insn) = NOTE_LINE_NUMBER (insn);
418: INSN_UID (first_insn) = INSN_UID (insn);
419: PREV_INSN (first_insn) = NULL;
420: NEXT_INSN (first_insn) = NULL;
421: last_insn = first_insn;
422:
423: /* Each pseudo-reg in the old insn chain must have a unique rtx in the copy.
424: Make these new rtx's now, and install them in regno_reg_rtx, so they
425: will be the official pseudo-reg rtx's for the rest of compilation. */
426:
427: reg_map = (rtx *) alloca ((max_reg + 1) * sizeof (rtx));
428:
429: len = sizeof (struct rtx_def) + (GET_RTX_LENGTH (REG) - 1) * sizeof (rtunion);
430: for (i = max_reg - 1; i > LAST_VIRTUAL_REGISTER; i--)
431: reg_map[i] = (rtx)obstack_copy (function_maybepermanent_obstack,
432: regno_reg_rtx[i], len);
433:
434: bcopy (reg_map + LAST_VIRTUAL_REGISTER + 1,
435: regno_reg_rtx + LAST_VIRTUAL_REGISTER + 1,
436: (max_reg - (LAST_VIRTUAL_REGISTER + 1)) * sizeof (rtx));
437:
438: /* Likewise each label rtx must have a unique rtx as its copy. */
439:
440: label_map = (rtx *)alloca ((max_labelno - min_labelno) * sizeof (rtx));
441: label_map -= min_labelno;
442:
443: for (i = min_labelno; i < max_labelno; i++)
444: label_map[i] = gen_label_rtx ();
445:
446: /* Record the mapping of old insns to copied insns. */
447:
448: insn_map = (rtx *) alloca (max_uid * sizeof (rtx));
449: bzero (insn_map, max_uid * sizeof (rtx));
450:
451: /* Get the insn which signals the end of parameter setup code. */
452: first_nonparm_insn = get_first_nonparm_insn ();
453:
454: /* Copy any entries in regno_reg_rtx or DECL_RTLs that reference MEM
455: (the former occurs when a variable has its address taken)
456: since these may be shared and can be changed by virtual
457: register instantiation. DECL_RTL values for our arguments
458: have already been copied by initialize_for_inline. */
459: for (i = LAST_VIRTUAL_REGISTER + 1; i < max_reg; i++)
460: if (GET_CODE (regno_reg_rtx[i]) == MEM)
461: XEXP (regno_reg_rtx[i], 0)
462: = copy_for_inline (XEXP (regno_reg_rtx[i], 0));
463:
464: /* Copy the tree of subblocks of the function, and the decls in them.
465: We will use the copy for compiling this function, then restore the original
466: subblocks and decls for use when inlining this function.
467:
468: Several parts of the compiler modify BLOCK trees. In particular,
469: instantiate_virtual_regs will instantiate any virtual regs
470: mentioned in the DECL_RTLs of the decls, and loop
471: unrolling will replicate any BLOCK trees inside an unrolled loop.
472:
473: The modified subblocks or DECL_RTLs would be incorrect for the original rtl
474: which we will use for inlining. The rtl might even contain pseudoregs
475: whose space has been freed. */
476:
477: DECL_INITIAL (fndecl) = copy_decl_tree (DECL_INITIAL (fndecl));
478:
479: /* Now copy each DECL_RTL which is a MEM,
480: so it is safe to modify their addresses. */
481: copy_decl_rtls (DECL_INITIAL (fndecl));
482:
483: /* Now copy the chain of insns. Do this twice. The first copy the insn
484: itself and its body. The second time copy of REG_NOTES. This is because
485: a REG_NOTE may have a forward pointer to another insn. */
486:
487: for (insn = NEXT_INSN (insn); insn; insn = NEXT_INSN (insn))
488: {
489: orig_asm_operands_vector = 0;
490:
491: if (insn == first_nonparm_insn)
492: in_nonparm_insns = 1;
493:
494: switch (GET_CODE (insn))
495: {
496: case NOTE:
497: /* No need to keep these. */
498: if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED)
499: continue;
500:
501: copy = rtx_alloc (NOTE);
502: NOTE_SOURCE_FILE (copy) = NOTE_SOURCE_FILE (insn);
503: NOTE_LINE_NUMBER (copy) = NOTE_LINE_NUMBER (insn);
504: break;
505:
506: case INSN:
507: case CALL_INSN:
508: case JUMP_INSN:
509: copy = rtx_alloc (GET_CODE (insn));
510: PATTERN (copy) = copy_for_inline (PATTERN (insn));
511: INSN_CODE (copy) = -1;
512: LOG_LINKS (copy) = NULL;
513: RTX_INTEGRATED_P (copy) = RTX_INTEGRATED_P (insn);
514: break;
515:
516: case CODE_LABEL:
517: copy = label_map[CODE_LABEL_NUMBER (insn)];
1.1.1.2 ! root 518: LABEL_NAME (copy) = LABEL_NAME (insn);
1.1 root 519: break;
520:
521: case BARRIER:
522: copy = rtx_alloc (BARRIER);
523: break;
524:
525: default:
526: abort ();
527: }
528: INSN_UID (copy) = INSN_UID (insn);
529: insn_map[INSN_UID (insn)] = copy;
530: NEXT_INSN (last_insn) = copy;
531: PREV_INSN (copy) = last_insn;
532: last_insn = copy;
533: }
534:
535: /* Now copy the REG_NOTES. */
536: for (insn = NEXT_INSN (get_insns ()); insn; insn = NEXT_INSN (insn))
537: if (GET_RTX_CLASS (GET_CODE (insn)) == 'i'
538: && insn_map[INSN_UID(insn)])
539: REG_NOTES (insn_map[INSN_UID (insn)])
540: = copy_for_inline (REG_NOTES (insn));
541:
542: NEXT_INSN (last_insn) = NULL;
543:
544: finish_inline (fndecl, head);
545:
546: set_new_first_and_last_insn (first_insn, last_insn);
547: }
548:
549: /* Make a copy of the entire tree of blocks BLOCK, and return it. */
550:
551: static tree
552: copy_decl_tree (block)
553: tree block;
554: {
555: tree t, vars, subblocks;
556:
557: vars = copy_list (BLOCK_VARS (block));
558: subblocks = 0;
559:
560: /* Process all subblocks. */
561: for (t = BLOCK_SUBBLOCKS (block); t; t = TREE_CHAIN (t))
562: {
563: tree copy = copy_decl_tree (t);
564: TREE_CHAIN (copy) = subblocks;
565: subblocks = copy;
566: }
567:
568: t = copy_node (block);
569: BLOCK_VARS (t) = vars;
570: BLOCK_SUBBLOCKS (t) = nreverse (subblocks);
571: return t;
572: }
573:
574: /* Copy DECL_RTLs in all decls in the given BLOCK node. */
575:
576: static void
577: copy_decl_rtls (block)
578: tree block;
579: {
580: tree t;
581:
582: for (t = BLOCK_VARS (block); t; t = TREE_CHAIN (t))
583: if (DECL_RTL (t) && GET_CODE (DECL_RTL (t)) == MEM)
584: DECL_RTL (t) = copy_for_inline (DECL_RTL (t));
585:
586: /* Process all subblocks. */
587: for (t = BLOCK_SUBBLOCKS (block); t; t = TREE_CHAIN (t))
588: copy_decl_rtls (t);
589: }
590:
591: /* Make the insns and PARM_DECLs of the current function permanent
592: and record other information in DECL_SAVED_INSNS to allow inlining
593: of this function in subsequent calls.
594:
595: This routine need not copy any insns because we are not going
596: to immediately compile the insns in the insn chain. There
597: are two cases when we would compile the insns for FNDECL:
598: (1) when FNDECL is expanded inline, and (2) when FNDECL needs to
599: be output at the end of other compilation, because somebody took
600: its address. In the first case, the insns of FNDECL are copied
601: as it is expanded inline, so FNDECL's saved insns are not
602: modified. In the second case, FNDECL is used for the last time,
603: so modifying the rtl is not a problem.
604:
605: ??? Actually, we do not verify that FNDECL is not inline expanded
606: by other functions which must also be written down at the end
607: of compilation. We could set flag_no_inline to nonzero when
608: the time comes to write down such functions. */
609:
610: void
611: save_for_inline_nocopy (fndecl)
612: tree fndecl;
613: {
614: rtx insn;
615: rtx head, copy;
616: tree parms;
617: int max_labelno, min_labelno, i, len;
618: int max_reg;
619: int max_uid;
620: rtx first_nonparm_insn;
621: int function_flags;
622:
623: /* Set up PARMDECL_MAP which maps pseudo-reg number to its PARM_DECL.
624: Later we set TREE_READONLY to 0 if the parm is modified inside the fn.
625: Also set up ARG_VECTOR, which holds the unmodified DECL_RTX values
626: for the parms, prior to elimination of virtual registers.
627: These values are needed for substituting parms properly. */
628:
629: max_parm_reg = max_parm_reg_num ();
630: parmdecl_map = (tree *) alloca (max_parm_reg * sizeof (tree));
631:
632: /* Make and emit a return-label if we have not already done so. */
633:
634: if (return_label == 0)
635: {
636: return_label = gen_label_rtx ();
637: emit_label (return_label);
638: }
639:
640: head = initialize_for_inline (fndecl, get_first_label_num (),
641: max_label_num (), max_reg_num (), 0);
642:
643: /* If there are insns that copy parms from the stack into pseudo registers,
644: those insns are not copied. `expand_inline_function' must
645: emit the correct code to handle such things. */
646:
647: insn = get_insns ();
648: if (GET_CODE (insn) != NOTE)
649: abort ();
650:
651: /* Get the insn which signals the end of parameter setup code. */
652: first_nonparm_insn = get_first_nonparm_insn ();
653:
654: /* Now just scan the chain of insns to see what happens to our
655: PARM_DECLs. If a PARM_DECL is used but never modified, we
656: can substitute its rtl directly when expanding inline (and
657: perform constant folding when its incoming value is constant).
658: Otherwise, we have to copy its value into a new register and track
659: the new register's life. */
660:
661: for (insn = NEXT_INSN (insn); insn; insn = NEXT_INSN (insn))
662: {
663: if (insn == first_nonparm_insn)
664: in_nonparm_insns = 1;
665:
666: if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
667: {
668: if (current_function_uses_const_pool)
669: {
670: /* Replace any constant pool references with the actual constant.
671: We will put the constant back if we need to write the
672: function out after all. */
673: save_constants (&PATTERN (insn));
674: if (REG_NOTES (insn))
675: save_constants (®_NOTES (insn));
676: }
677:
678: /* Record what interesting things happen to our parameters. */
679: note_stores (PATTERN (insn), note_modified_parmregs);
680: }
681: }
682:
683: /* We have now allocated all that needs to be allocated permanently
684: on the rtx obstack. Set our high-water mark, so that we
685: can free the rest of this when the time comes. */
686:
687: preserve_data ();
688:
689: finish_inline (fndecl, head);
690: }
691:
692: /* Given PX, a pointer into an insn, search for references to the constant
693: pool. Replace each with a CONST that has the mode of the original
694: constant, contains the constant, and has RTX_INTEGRATED_P set.
695: Similarly, constant pool addresses not enclosed in a MEM are replaced
696: with an ADDRESS rtx which also gives the constant, mode, and has
697: RTX_INTEGRATED_P set. */
698:
699: static void
700: save_constants (px)
701: rtx *px;
702: {
703: rtx x;
704: int i, j;
705:
706: again:
707: x = *px;
708:
709: /* If this is a CONST_DOUBLE, don't try to fix things up in
710: CONST_DOUBLE_MEM, because this is an infinite recursion. */
711: if (GET_CODE (x) == CONST_DOUBLE)
712: return;
713: else if (GET_CODE (x) == MEM && GET_CODE (XEXP (x, 0)) == SYMBOL_REF
714: && CONSTANT_POOL_ADDRESS_P (XEXP (x,0)))
715: {
716: enum machine_mode const_mode = get_pool_mode (XEXP (x, 0));
717: rtx new = gen_rtx (CONST, const_mode, get_pool_constant (XEXP (x, 0)));
718: RTX_INTEGRATED_P (new) = 1;
719:
720: /* If the MEM was in a different mode than the constant (perhaps we
721: were only looking at the low-order part), surround it with a
722: SUBREG so we can save both modes. */
723:
724: if (GET_MODE (x) != const_mode)
725: {
726: new = gen_rtx (SUBREG, GET_MODE (x), new, 0);
727: RTX_INTEGRATED_P (new) = 1;
728: }
729:
730: *px = new;
731: save_constants (&XEXP (*px, 0));
732: }
733: else if (GET_CODE (x) == SYMBOL_REF
734: && CONSTANT_POOL_ADDRESS_P (x))
735: {
736: *px = gen_rtx (ADDRESS, get_pool_mode (x), get_pool_constant (x));
737: save_constants (&XEXP (*px, 0));
738: RTX_INTEGRATED_P (*px) = 1;
739: }
740:
741: else
742: {
743: char *fmt = GET_RTX_FORMAT (GET_CODE (x));
744: int len = GET_RTX_LENGTH (GET_CODE (x));
745:
746: for (i = len-1; i >= 0; i--)
747: {
748: switch (fmt[i])
749: {
750: case 'E':
751: for (j = 0; j < XVECLEN (x, i); j++)
752: save_constants (&XVECEXP (x, i, j));
753: break;
754:
755: case 'e':
756: if (XEXP (x, i) == 0)
757: continue;
758: if (i == 0)
759: {
760: /* Hack tail-recursion here. */
761: px = &XEXP (x, 0);
762: goto again;
763: }
764: save_constants (&XEXP (x, i));
765: break;
766: }
767: }
768: }
769: }
770:
771: /* Note whether a parameter is modified or not. */
772:
773: static void
774: note_modified_parmregs (reg, x)
775: rtx reg;
776: rtx x;
777: {
778: if (GET_CODE (reg) == REG && in_nonparm_insns
779: && REGNO (reg) < max_parm_reg
780: && REGNO (reg) >= FIRST_PSEUDO_REGISTER
781: && parmdecl_map[REGNO (reg)] != 0)
782: TREE_READONLY (parmdecl_map[REGNO (reg)]) = 0;
783: }
784:
785: /* Copy the rtx ORIG recursively, replacing pseudo-regs and labels
786: according to `reg_map' and `label_map'. The original rtl insns
787: will be saved for inlining; this is used to make a copy
788: which is used to finish compiling the inline function itself.
789:
790: If we find a "saved" constant pool entry, one which was replaced with
791: the value of the constant, convert it back to a constant pool entry.
792: Since the pool wasn't touched, this should simply restore the old
793: address.
794:
795: All other kinds of rtx are copied except those that can never be
796: changed during compilation. */
797:
798: static rtx
799: copy_for_inline (orig)
800: rtx orig;
801: {
802: register rtx x = orig;
803: register int i;
804: register enum rtx_code code;
805: register char *format_ptr;
806:
807: if (x == 0)
808: return x;
809:
810: code = GET_CODE (x);
811:
812: /* These types may be freely shared. */
813:
814: switch (code)
815: {
816: case QUEUED:
817: case CONST_INT:
818: case SYMBOL_REF:
819: case PC:
820: case CC0:
821: return x;
822:
823: case CONST_DOUBLE:
824: /* We have to make a new CONST_DOUBLE to ensure that we account for
825: it correctly. Using the old CONST_DOUBLE_MEM data is wrong. */
826: if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
827: {
828: REAL_VALUE_TYPE d;
829:
830: REAL_VALUE_FROM_CONST_DOUBLE (d, x);
831: return immed_real_const_1 (d, GET_MODE (x));
832: }
833: else
834: return immed_double_const (CONST_DOUBLE_LOW (x), CONST_DOUBLE_HIGH (x),
835: VOIDmode);
836:
837: case CONST:
838: /* Get constant pool entry for constant in the pool. */
839: if (RTX_INTEGRATED_P (x))
840: return validize_mem (force_const_mem (GET_MODE (x),
841: copy_for_inline (XEXP (x, 0))));
842: break;
843:
844: case SUBREG:
845: /* Get constant pool entry, but access in different mode. */
846: if (RTX_INTEGRATED_P (x))
847: {
848: rtx new
849: = force_const_mem (GET_MODE (SUBREG_REG (x)),
850: copy_for_inline (XEXP (SUBREG_REG (x), 0)));
851:
852: PUT_MODE (new, GET_MODE (x));
853: return validize_mem (new);
854: }
855: break;
856:
857: case ADDRESS:
858: /* If not special for constant pool error. Else get constant pool
859: address. */
860: if (! RTX_INTEGRATED_P (x))
861: abort ();
862:
863: return XEXP (force_const_mem (GET_MODE (x),
864: copy_for_inline (XEXP (x, 0))), 0);
865:
866: case ASM_OPERANDS:
867: /* If a single asm insn contains multiple output operands
868: then it contains multiple ASM_OPERANDS rtx's that share operand 3.
869: We must make sure that the copied insn continues to share it. */
870: if (orig_asm_operands_vector == XVEC (orig, 3))
871: {
872: x = rtx_alloc (ASM_OPERANDS);
873: XSTR (x, 0) = XSTR (orig, 0);
874: XSTR (x, 1) = XSTR (orig, 1);
875: XINT (x, 2) = XINT (orig, 2);
876: XVEC (x, 3) = copy_asm_operands_vector;
877: XVEC (x, 4) = copy_asm_constraints_vector;
878: XSTR (x, 5) = XSTR (orig, 5);
879: XINT (x, 6) = XINT (orig, 6);
880: return x;
881: }
882: break;
883:
884: case MEM:
885: /* A MEM is usually allowed to be shared if its address is constant
886: or is a constant plus one of the special registers.
887:
888: We do not allow sharing of addresses that are either a special
889: register or the sum of a constant and a special register because
890: it is possible for unshare_all_rtl to copy the address, into memory
891: that won't be saved. Although the MEM can safely be shared, and
892: won't be copied there, the address itself cannot be shared, and may
893: need to be copied.
894:
895: There are also two exceptions with constants: The first is if the
896: constant is a LABEL_REF or the sum of the LABEL_REF
897: and an integer. This case can happen if we have an inline
898: function that supplies a constant operand to the call of another
899: inline function that uses it in a switch statement. In this case,
900: we will be replacing the LABEL_REF, so we have to replace this MEM
901: as well.
902:
903: The second case is if we have a (const (plus (address ..) ...)).
904: In that case we need to put back the address of the constant pool
905: entry. */
906:
907: if (CONSTANT_ADDRESS_P (XEXP (x, 0))
908: && GET_CODE (XEXP (x, 0)) != LABEL_REF
909: && ! (GET_CODE (XEXP (x, 0)) == CONST
910: && (GET_CODE (XEXP (XEXP (x, 0), 0)) == PLUS
911: && ((GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0))
912: == LABEL_REF)
913: || (GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0))
914: == ADDRESS)))))
915: return x;
916: break;
917:
918: case LABEL_REF:
919: {
920: /* Must point to the new insn. */
921: return gen_rtx (LABEL_REF, GET_MODE (orig),
922: label_map[CODE_LABEL_NUMBER (XEXP (orig, 0))]);
923: }
924:
925: case REG:
926: if (REGNO (x) > LAST_VIRTUAL_REGISTER)
927: return reg_map [REGNO (x)];
928: else
929: return x;
930:
931: case SET:
932: /* If a parm that gets modified lives in a pseudo-reg,
933: clear its TREE_READONLY to prevent certain optimizations. */
934: {
935: rtx dest = SET_DEST (x);
936:
937: while (GET_CODE (dest) == STRICT_LOW_PART
938: || GET_CODE (dest) == ZERO_EXTRACT
939: || GET_CODE (dest) == SUBREG)
940: dest = XEXP (dest, 0);
941:
942: if (GET_CODE (dest) == REG
943: && REGNO (dest) < max_parm_reg
944: && REGNO (dest) >= FIRST_PSEUDO_REGISTER
945: && parmdecl_map[REGNO (dest)] != 0
946: /* The insn to load an arg pseudo from a stack slot
947: does not count as modifying it. */
948: && in_nonparm_insns)
949: TREE_READONLY (parmdecl_map[REGNO (dest)]) = 0;
950: }
951: break;
952:
953: #if 0 /* This is a good idea, but here is the wrong place for it. */
954: /* Arrange that CONST_INTs always appear as the second operand
955: if they appear, and that `frame_pointer_rtx' or `arg_pointer_rtx'
956: always appear as the first. */
957: case PLUS:
958: if (GET_CODE (XEXP (x, 0)) == CONST_INT
959: || (XEXP (x, 1) == frame_pointer_rtx
960: || (ARG_POINTER_REGNUM != FRAME_POINTER_REGNUM
961: && XEXP (x, 1) == arg_pointer_rtx)))
962: {
963: rtx t = XEXP (x, 0);
964: XEXP (x, 0) = XEXP (x, 1);
965: XEXP (x, 1) = t;
966: }
967: break;
968: #endif
969: }
970:
971: /* Replace this rtx with a copy of itself. */
972:
973: x = rtx_alloc (code);
974: bcopy (orig, x, (sizeof (*x) - sizeof (x->fld)
975: + sizeof (x->fld[0]) * GET_RTX_LENGTH (code)));
976:
977: /* Now scan the subexpressions recursively.
978: We can store any replaced subexpressions directly into X
979: since we know X is not shared! Any vectors in X
980: must be copied if X was copied. */
981:
982: format_ptr = GET_RTX_FORMAT (code);
983:
984: for (i = 0; i < GET_RTX_LENGTH (code); i++)
985: {
986: switch (*format_ptr++)
987: {
988: case 'e':
989: XEXP (x, i) = copy_for_inline (XEXP (x, i));
990: break;
991:
992: case 'u':
993: /* Change any references to old-insns to point to the
994: corresponding copied insns. */
995: XEXP (x, i) = insn_map[INSN_UID (XEXP (x, i))];
996: break;
997:
998: case 'E':
999: if (XVEC (x, i) != NULL && XVECLEN (x, i) != 0)
1000: {
1001: register int j;
1002:
1003: XVEC (x, i) = gen_rtvec_v (XVECLEN (x, i), &XVECEXP (x, i, 0));
1004: for (j = 0; j < XVECLEN (x, i); j++)
1005: XVECEXP (x, i, j)
1006: = copy_for_inline (XVECEXP (x, i, j));
1007: }
1008: break;
1009: }
1010: }
1011:
1012: if (code == ASM_OPERANDS && orig_asm_operands_vector == 0)
1013: {
1014: orig_asm_operands_vector = XVEC (orig, 3);
1015: copy_asm_operands_vector = XVEC (x, 3);
1016: copy_asm_constraints_vector = XVEC (x, 4);
1017: }
1018:
1019: return x;
1020: }
1021:
1022: /* Unfortunately, we need a global copy of const_equiv map for communication
1023: with a function called from note_stores. Be *very* careful that this
1024: is used properly in the presence of recursion. */
1025:
1026: rtx *global_const_equiv_map;
1027:
1028: #define FIXED_BASE_PLUS_P(X) \
1029: (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 1)) == CONST_INT \
1030: && GET_CODE (XEXP (X, 0)) == REG \
1031: && REGNO (XEXP (X, 0)) >= FIRST_VIRTUAL_REGISTER \
1032: && REGNO (XEXP (X, 0)) < LAST_VIRTUAL_REGISTER)
1033:
1034: /* Integrate the procedure defined by FNDECL. Note that this function
1035: may wind up calling itself. Since the static variables are not
1036: reentrant, we do not assign them until after the possibility
1037: or recursion is eliminated.
1038:
1039: If IGNORE is nonzero, do not produce a value.
1040: Otherwise store the value in TARGET if it is nonzero and that is convenient.
1041:
1042: Value is:
1043: (rtx)-1 if we could not substitute the function
1044: 0 if we substituted it and it does not produce a value
1045: else an rtx for where the value is stored. */
1046:
1047: rtx
1048: expand_inline_function (fndecl, parms, target, ignore, type, structure_value_addr)
1049: tree fndecl, parms;
1050: rtx target;
1051: int ignore;
1052: tree type;
1053: rtx structure_value_addr;
1054: {
1055: tree formal, actual;
1056: rtx header = DECL_SAVED_INSNS (fndecl);
1057: rtx insns = FIRST_FUNCTION_INSN (header);
1058: rtx parm_insns = FIRST_PARM_INSN (header);
1059: tree *arg_trees;
1060: rtx *arg_vals;
1061: rtx insn;
1062: int max_regno;
1063: register int i;
1064: int min_labelno = FIRST_LABELNO (header);
1065: int max_labelno = LAST_LABELNO (header);
1066: int nargs;
1067: rtx local_return_label = 0;
1068: rtx loc;
1069: rtx temp;
1070: struct inline_remap *map;
1071: rtx cc0_insn = 0;
1072: rtvec arg_vector = ORIGINAL_ARG_VECTOR (header);
1073:
1074: /* Allow for equivalences of the pseudos we make for virtual fp and ap. */
1075: max_regno = MAX_REGNUM (header) + 3;
1076: if (max_regno < FIRST_PSEUDO_REGISTER)
1077: abort ();
1078:
1079: nargs = list_length (DECL_ARGUMENTS (fndecl));
1080:
1081: /* We expect PARMS to have the right length; don't crash if not. */
1082: if (list_length (parms) != nargs)
1083: return (rtx)-1;
1084: /* Also check that the parms type match. Since the appropriate
1085: conversions or default promotions have already been applied,
1086: the machine modes should match exactly. */
1087: for (formal = DECL_ARGUMENTS (fndecl),
1088: actual = parms;
1089: formal;
1090: formal = TREE_CHAIN (formal),
1091: actual = TREE_CHAIN (actual))
1092: {
1093: tree arg = TREE_VALUE (actual);
1094: enum machine_mode mode = TYPE_MODE (DECL_ARG_TYPE (formal));
1095: if (mode != TYPE_MODE (TREE_TYPE (arg)))
1096: return (rtx)-1;
1097: /* If they are block mode, the types should match exactly.
1098: They don't match exactly if TREE_TYPE (FORMAL) == ERROR_MARK_NODE,
1099: which could happen if the parameter has incomplete type. */
1100: if (mode == BLKmode && TREE_TYPE (arg) != TREE_TYPE (formal))
1101: return (rtx)-1;
1102: }
1103:
1104: /* Make a binding contour to keep inline cleanups called at
1105: outer function-scope level from looking like they are shadowing
1106: parameter declarations. */
1107: pushlevel (0);
1108:
1109: /* Make a fresh binding contour that we can easily remove. */
1110: pushlevel (0);
1111: expand_start_bindings (0);
1112: if (GET_CODE (parm_insns) == NOTE
1113: && NOTE_LINE_NUMBER (parm_insns) > 0)
1114: emit_note (NOTE_SOURCE_FILE (parm_insns), NOTE_LINE_NUMBER (parm_insns));
1115:
1116: /* Expand the function arguments. Do this first so that any
1117: new registers get created before we allocate the maps. */
1118:
1119: arg_vals = (rtx *) alloca (nargs * sizeof (rtx));
1120: arg_trees = (tree *) alloca (nargs * sizeof (tree));
1121:
1122: for (formal = DECL_ARGUMENTS (fndecl), actual = parms, i = 0;
1123: formal;
1124: formal = TREE_CHAIN (formal), actual = TREE_CHAIN (actual), i++)
1125: {
1126: /* Actual parameter, converted to the type of the argument within the
1127: function. */
1128: tree arg = convert (TREE_TYPE (formal), TREE_VALUE (actual));
1129: /* Mode of the variable used within the function. */
1130: enum machine_mode mode = TYPE_MODE (TREE_TYPE (formal));
1131: /* Where parameter is located in the function. */
1132: rtx copy;
1133:
1134: emit_note (DECL_SOURCE_FILE (formal), DECL_SOURCE_LINE (formal));
1135:
1136: arg_trees[i] = arg;
1137: loc = RTVEC_ELT (arg_vector, i);
1138:
1139: /* If this is an object passed by invisible reference, we copy the
1140: object into a stack slot and save its address. If this will go
1141: into memory, we do nothing now. Otherwise, we just expand the
1142: argument. */
1143: if (GET_CODE (loc) == MEM && GET_CODE (XEXP (loc, 0)) == REG
1144: && REGNO (XEXP (loc, 0)) > LAST_VIRTUAL_REGISTER)
1145: {
1146: enum machine_mode mode = TYPE_MODE (TREE_TYPE (arg));
1147: rtx stack_slot = assign_stack_temp (mode, int_size_in_bytes (TREE_TYPE (arg)), 1);
1148:
1149: store_expr (arg, stack_slot, 0);
1150:
1151: arg_vals[i] = XEXP (stack_slot, 0);
1152: }
1153: else if (GET_CODE (loc) != MEM)
1154: arg_vals[i] = expand_expr (arg, 0, mode, EXPAND_SUM);
1155: else
1156: arg_vals[i] = 0;
1157:
1158: if (arg_vals[i] != 0
1159: && (! TREE_READONLY (formal)
1160: /* If the parameter is not read-only, copy our argument through
1161: a register. Also, we cannot use ARG_VALS[I] if it overlaps
1162: TARGET in any way. In the inline function, they will likely
1163: be two different pseudos, and `safe_from_p' will make all
1164: sorts of smart assumptions about their not conflicting.
1165: But if ARG_VALS[I] overlaps TARGET, these assumptions are
1166: wrong, so put ARG_VALS[I] into a fresh register. */
1167: || (target != 0
1168: && (GET_CODE (arg_vals[i]) == REG
1169: || GET_CODE (arg_vals[i]) == SUBREG
1170: || GET_CODE (arg_vals[i]) == MEM)
1171: && reg_overlap_mentioned_p (arg_vals[i], target))))
1172: arg_vals[i] = copy_to_mode_reg (mode, arg_vals[i]);
1173: }
1174:
1175: /* Allocate the structures we use to remap things. */
1176:
1177: map = (struct inline_remap *) alloca (sizeof (struct inline_remap));
1178: map->fndecl = fndecl;
1179:
1180: map->reg_map = (rtx *) alloca (max_regno * sizeof (rtx));
1181: bzero (map->reg_map, max_regno * sizeof (rtx));
1182:
1183: map->label_map = (rtx *)alloca ((max_labelno - min_labelno) * sizeof (rtx));
1184: map->label_map -= min_labelno;
1185:
1186: map->insn_map = (rtx *) alloca (INSN_UID (header) * sizeof (rtx));
1187: bzero (map->insn_map, INSN_UID (header) * sizeof (rtx));
1188: map->min_insnno = 0;
1189: map->max_insnno = INSN_UID (header);
1190:
1191: /* const_equiv_map maps pseudos in our routine to constants, so it needs to
1192: be large enough for all our pseudos. This is the number we are currently
1193: using plus the number in the called routine, plus 15 for each arg,
1194: five to compute the virtual frame pointer, and five for the return value.
1195: This should be enough for most cases. We do not reference entries
1196: outside the range of the map.
1197:
1198: ??? These numbers are quite arbitrary and were obtained by
1199: experimentation. At some point, we should try to allocate the
1200: table after all the parameters are set up so we an more accurately
1201: estimate the number of pseudos we will need. */
1202:
1203: map->const_equiv_map_size
1204: = max_reg_num () + (max_regno - FIRST_PSEUDO_REGISTER) + 15 * nargs + 10;
1205:
1206: map->const_equiv_map
1207: = (rtx *)alloca (map->const_equiv_map_size * sizeof (rtx));
1208: bzero (map->const_equiv_map, map->const_equiv_map_size * sizeof (rtx));
1209:
1210: map->const_age_map
1211: = (unsigned *)alloca (map->const_equiv_map_size * sizeof (unsigned));
1212: bzero (map->const_age_map, map->const_equiv_map_size * sizeof (unsigned));
1213: map->const_age = 0;
1214:
1215: /* Record the current insn in case we have to set up pointers to frame
1216: and argument memory blocks. */
1217: map->insns_at_start = get_last_insn ();
1218:
1219: /* Update the outgoing argument size to allow for those in the inlined
1220: function. */
1221: if (OUTGOING_ARGS_SIZE (header) > current_function_outgoing_args_size)
1222: current_function_outgoing_args_size = OUTGOING_ARGS_SIZE (header);
1223:
1224: /* If the inline function needs to make PIC references, that means
1225: that this function's PIC offset table must be used. */
1226: if (FUNCTION_FLAGS (header) & FUNCTION_FLAGS_USES_PIC_OFFSET_TABLE)
1227: current_function_uses_pic_offset_table = 1;
1228:
1229: /* Process each argument. For each, set up things so that the function's
1230: reference to the argument will refer to the argument being passed.
1231: We only replace REG with REG here. Any simplifications are done
1232: via const_equiv_map.
1233:
1234: We make two passes: In the first, we deal with parameters that will
1235: be placed into registers, since we need to ensure that the allocated
1236: register number fits in const_equiv_map. Then we store all non-register
1237: parameters into their memory location. */
1238:
1239: for (i = 0; i < nargs; i++)
1240: {
1241: rtx copy = arg_vals[i];
1242:
1243: loc = RTVEC_ELT (arg_vector, i);
1244:
1245: /* There are three cases, each handled separately. */
1246: if (GET_CODE (loc) == MEM && GET_CODE (XEXP (loc, 0)) == REG
1247: && REGNO (XEXP (loc, 0)) > LAST_VIRTUAL_REGISTER)
1248: {
1249: /* This must be an object passed by invisible reference (it could
1250: also be a variable-sized object, but we forbid inlining functions
1251: with variable-sized arguments). COPY is the address of the
1252: actual value (this computation will cause it to be copied). We
1253: map that address for the register, noting the actual address as
1254: an equivalent in case it can be substituted into the insns. */
1255:
1256: if (GET_CODE (copy) != REG)
1257: {
1258: temp = copy_addr_to_reg (copy);
1259: if (CONSTANT_P (copy) || FIXED_BASE_PLUS_P (copy))
1260: {
1261: map->const_equiv_map[REGNO (temp)] = copy;
1262: map->const_age_map[REGNO (temp)] = CONST_AGE_PARM;
1263: }
1264: copy = temp;
1265: }
1266: map->reg_map[REGNO (XEXP (loc, 0))] = copy;
1267: }
1268: else if (GET_CODE (loc) == MEM)
1269: {
1270: /* This is the case of a parameter that lives in memory.
1271: It will live in the block we allocate in the called routine's
1272: frame that simulates the incoming argument area. Do nothing
1273: now; we will call store_expr later. */
1274: ;
1275: }
1276: else if (GET_CODE (loc) == REG)
1277: {
1278: /* This is the good case where the parameter is in a register.
1279: If it is read-only and our argument is a constant, set up the
1280: constant equivalence. */
1281: if (GET_CODE (copy) != REG && GET_CODE (copy) != SUBREG)
1282: {
1283: temp = copy_to_mode_reg (GET_MODE (loc), copy);
1284: if (CONSTANT_P (copy) || FIXED_BASE_PLUS_P (copy))
1285: {
1286: map->const_equiv_map[REGNO (temp)] = copy;
1287: map->const_age_map[REGNO (temp)] = CONST_AGE_PARM;
1288: }
1289: copy = temp;
1290: }
1291: map->reg_map[REGNO (loc)] = copy;
1292: }
1293: else
1294: abort ();
1295:
1296: /* Free any temporaries we made setting up this parameter. */
1297: free_temp_slots ();
1298: }
1299:
1300: /* Now do the parameters that will be placed in memory. */
1301:
1302: for (formal = DECL_ARGUMENTS (fndecl), i = 0;
1303: formal; formal = TREE_CHAIN (formal), i++)
1304: {
1305: rtx copy = arg_vals[i];
1306:
1307: loc = RTVEC_ELT (arg_vector, i);
1308:
1309: if (GET_CODE (loc) == MEM
1310: /* Exclude case handled above. */
1311: && ! (GET_CODE (XEXP (loc, 0)) == REG
1312: && REGNO (XEXP (loc, 0)) > LAST_VIRTUAL_REGISTER))
1313: {
1314: emit_note (DECL_SOURCE_FILE (formal), DECL_SOURCE_LINE (formal));
1315:
1316: /* Compute the address in the area we reserved and store the
1317: value there. */
1318: temp = copy_rtx_and_substitute (loc, map);
1319: subst_constants (&temp, 0, map);
1320: apply_change_group ();
1321: if (! memory_address_p (GET_MODE (temp), XEXP (temp, 0)))
1322: temp = change_address (temp, VOIDmode, XEXP (temp, 0));
1323: store_expr (arg_trees[i], temp, 0);
1324:
1325: /* Free any temporaries we made setting up this parameter. */
1326: free_temp_slots ();
1327: }
1328: }
1329:
1330: /* Deal with the places that the function puts its result.
1331: We are driven by what is placed into DECL_RESULT.
1332:
1333: Initially, we assume that we don't have anything special handling for
1334: REG_FUNCTION_RETURN_VALUE_P. */
1335:
1336: map->inline_target = 0;
1337: loc = DECL_RTL (DECL_RESULT (fndecl));
1338: if (TYPE_MODE (type) == VOIDmode)
1339: /* There is no return value to worry about. */
1340: ;
1341: else if (GET_CODE (loc) == MEM)
1342: {
1343: if (! structure_value_addr || ! aggregate_value_p (DECL_RESULT (fndecl)))
1344: abort ();
1345:
1346: /* Pass the function the address in which to return a structure value.
1347: Note that a constructor can cause someone to call us with
1348: STRUCTURE_VALUE_ADDR, but the initialization takes place
1349: via the first parameter, rather than the struct return address.
1350:
1351: We have two cases: If the address is a simple register indirect,
1352: use the mapping mechanism to point that register to our structure
1353: return address. Otherwise, store the structure return value into
1354: the place that it will be referenced from. */
1355:
1356: if (GET_CODE (XEXP (loc, 0)) == REG)
1357: {
1358: temp = force_reg (Pmode, structure_value_addr);
1359: map->reg_map[REGNO (XEXP (loc, 0))] = temp;
1360: if (CONSTANT_P (structure_value_addr)
1361: || (GET_CODE (structure_value_addr) == PLUS
1362: && XEXP (structure_value_addr, 0) == virtual_stack_vars_rtx
1363: && GET_CODE (XEXP (structure_value_addr, 1)) == CONST_INT))
1364: {
1365: map->const_equiv_map[REGNO (temp)] = structure_value_addr;
1366: map->const_age_map[REGNO (temp)] = CONST_AGE_PARM;
1367: }
1368: }
1369: else
1370: {
1371: temp = copy_rtx_and_substitute (loc, map);
1372: subst_constants (&temp, 0, map);
1373: apply_change_group ();
1374: emit_move_insn (temp, structure_value_addr);
1375: }
1376: }
1377: else if (ignore)
1378: /* We will ignore the result value, so don't look at its structure.
1379: Note that preparations for an aggregate return value
1380: do need to be made (above) even if it will be ignored. */
1381: ;
1382: else if (GET_CODE (loc) == REG)
1383: {
1384: /* The function returns an object in a register and we use the return
1385: value. Set up our target for remapping. */
1386:
1387: /* Machine mode function was declared to return. */
1388: enum machine_mode departing_mode = TYPE_MODE (type);
1389: /* (Possibly wider) machine mode it actually computes
1390: (for the sake of callers that fail to declare it right). */
1391: enum machine_mode arriving_mode
1392: = TYPE_MODE (TREE_TYPE (DECL_RESULT (fndecl)));
1393: rtx reg_to_map;
1394:
1395: /* Don't use MEMs as direct targets because on some machines
1396: substituting a MEM for a REG makes invalid insns.
1397: Let the combiner substitute the MEM if that is valid. */
1398: if (target == 0 || GET_CODE (target) != REG
1399: || GET_MODE (target) != departing_mode)
1400: target = gen_reg_rtx (departing_mode);
1401:
1402: /* If function's value was promoted before return,
1403: avoid machine mode mismatch when we substitute INLINE_TARGET.
1404: But TARGET is what we will return to the caller. */
1405: if (arriving_mode != departing_mode)
1406: reg_to_map = gen_rtx (SUBREG, arriving_mode, target, 0);
1407: else
1408: reg_to_map = target;
1409:
1410: /* Usually, the result value is the machine's return register.
1411: Sometimes it may be a pseudo. Handle both cases. */
1412: if (REG_FUNCTION_VALUE_P (loc))
1413: map->inline_target = reg_to_map;
1414: else
1415: map->reg_map[REGNO (loc)] = reg_to_map;
1416: }
1417:
1418: /* Make new label equivalences for the labels in the called function. */
1419: for (i = min_labelno; i < max_labelno; i++)
1420: map->label_map[i] = gen_label_rtx ();
1421:
1422: /* Perform postincrements before actually calling the function. */
1423: emit_queue ();
1424:
1425: /* Clean up stack so that variables might have smaller offsets. */
1426: do_pending_stack_adjust ();
1427:
1428: /* Save a copy of the location of const_equiv_map for mark_stores, called
1429: via note_stores. */
1430: global_const_equiv_map = map->const_equiv_map;
1431:
1432: /* Now copy the insns one by one. Do this in two passes, first the insns and
1433: then their REG_NOTES, just like save_for_inline. */
1434:
1435: /* This loop is very similar to the loop in copy_loop_body in unroll.c. */
1436:
1437: for (insn = insns; insn; insn = NEXT_INSN (insn))
1438: {
1439: rtx copy, pattern;
1440:
1441: map->orig_asm_operands_vector = 0;
1442:
1443: switch (GET_CODE (insn))
1444: {
1445: case INSN:
1446: pattern = PATTERN (insn);
1447: copy = 0;
1448: if (GET_CODE (pattern) == USE
1449: && GET_CODE (XEXP (pattern, 0)) == REG
1450: && REG_FUNCTION_VALUE_P (XEXP (pattern, 0)))
1451: /* The (USE (REG n)) at return from the function should
1452: be ignored since we are changing (REG n) into
1453: inline_target. */
1454: break;
1455:
1456: /* Ignore setting a function value that we don't want to use. */
1457: if (map->inline_target == 0
1458: && GET_CODE (pattern) == SET
1459: && GET_CODE (SET_DEST (pattern)) == REG
1460: && REG_FUNCTION_VALUE_P (SET_DEST (pattern)))
1461: break;
1462:
1463: copy = emit_insn (copy_rtx_and_substitute (pattern, map));
1464: /* REG_NOTES will be copied later. */
1465:
1466: #ifdef HAVE_cc0
1467: /* If this insn is setting CC0, it may need to look at
1468: the insn that uses CC0 to see what type of insn it is.
1469: In that case, the call to recog via validate_change will
1470: fail. So don't substitute constants here. Instead,
1471: do it when we emit the following insn.
1472:
1473: For example, see the pyr.md file. That machine has signed and
1474: unsigned compares. The compare patterns must check the
1475: following branch insn to see which what kind of compare to
1476: emit.
1477:
1478: If the previous insn set CC0, substitute constants on it as
1479: well. */
1480: if (sets_cc0_p (PATTERN (copy)) != 0)
1481: cc0_insn = copy;
1482: else
1483: {
1484: if (cc0_insn)
1485: try_constants (cc0_insn, map);
1486: cc0_insn = 0;
1487: try_constants (copy, map);
1488: }
1489: #else
1490: try_constants (copy, map);
1491: #endif
1492: break;
1493:
1494: case JUMP_INSN:
1495: if (GET_CODE (PATTERN (insn)) == RETURN)
1496: {
1497: if (local_return_label == 0)
1498: local_return_label = gen_label_rtx ();
1499: pattern = gen_jump (local_return_label);
1500: }
1501: else
1502: pattern = copy_rtx_and_substitute (PATTERN (insn), map);
1503:
1504: copy = emit_jump_insn (pattern);
1505:
1506: #ifdef HAVE_cc0
1507: if (cc0_insn)
1508: try_constants (cc0_insn, map);
1509: cc0_insn = 0;
1510: #endif
1511: try_constants (copy, map);
1512:
1513: /* If this used to be a conditional jump insn but whose branch
1514: direction is now know, we must do something special. */
1515: if (condjump_p (insn) && ! simplejump_p (insn) && map->last_pc_value)
1516: {
1517: #ifdef HAVE_cc0
1518: /* The previous insn set cc0 for us. So delete it. */
1519: delete_insn (PREV_INSN (copy));
1520: #endif
1521:
1522: /* If this is now a no-op, delete it. */
1523: if (map->last_pc_value == pc_rtx)
1524: {
1525: delete_insn (copy);
1526: copy = 0;
1527: }
1528: else
1529: /* Otherwise, this is unconditional jump so we must put a
1530: BARRIER after it. We could do some dead code elimination
1531: here, but jump.c will do it just as well. */
1532: emit_barrier ();
1533: }
1534: break;
1535:
1536: case CALL_INSN:
1537: pattern = copy_rtx_and_substitute (PATTERN (insn), map);
1538: copy = emit_call_insn (pattern);
1539:
1540: #ifdef HAVE_cc0
1541: if (cc0_insn)
1542: try_constants (cc0_insn, map);
1543: cc0_insn = 0;
1544: #endif
1545: try_constants (copy, map);
1546:
1547: /* Be lazy and assume CALL_INSNs clobber all hard registers. */
1548: for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
1549: map->const_equiv_map[i] = 0;
1550: break;
1551:
1552: case CODE_LABEL:
1553: copy = emit_label (map->label_map[CODE_LABEL_NUMBER (insn)]);
1554: map->const_age++;
1555: break;
1556:
1557: case BARRIER:
1558: copy = emit_barrier ();
1559: break;
1560:
1561: case NOTE:
1562: /* It is important to discard function-end and function-beg notes,
1563: so we have only one of each in the current function.
1564: Also, NOTE_INSN_DELETED notes aren't useful (save_for_inline
1565: deleted these in the copy used for continuing compilation,
1566: not the copy used for inlining). */
1567: if (NOTE_LINE_NUMBER (insn) != NOTE_INSN_FUNCTION_END
1568: && NOTE_LINE_NUMBER (insn) != NOTE_INSN_FUNCTION_BEG
1569: && NOTE_LINE_NUMBER (insn) != NOTE_INSN_DELETED)
1570: copy = emit_note (NOTE_SOURCE_FILE (insn), NOTE_LINE_NUMBER (insn));
1571: else
1572: copy = 0;
1573: break;
1574:
1575: default:
1576: abort ();
1577: break;
1578: }
1579:
1580: if (copy)
1581: RTX_INTEGRATED_P (copy) = 1;
1582:
1583: map->insn_map[INSN_UID (insn)] = copy;
1584: }
1585:
1586: /* Now copy the REG_NOTES. */
1587: for (insn = insns; insn; insn = NEXT_INSN (insn))
1588: if (GET_RTX_CLASS (GET_CODE (insn)) == 'i'
1589: && map->insn_map[INSN_UID (insn)])
1590: REG_NOTES (map->insn_map[INSN_UID (insn)])
1591: = copy_rtx_and_substitute (REG_NOTES (insn), map);
1592:
1593: if (local_return_label)
1594: emit_label (local_return_label);
1595:
1596: /* Make copies of the decls of the symbols in the inline function, so that
1597: the copies of the variables get declared in the current function. Set
1598: up things so that lookup_static_chain knows that to interpret registers
1599: in SAVE_EXPRs for TYPE_SIZEs as local. */
1600:
1601: inline_function_decl = fndecl;
1602: integrate_decl_tree ((tree) ORIGINAL_DECL_INITIAL (header), 0, map, 0);
1603: integrate_parm_decls (DECL_ARGUMENTS (fndecl), map, arg_vector);
1604: inline_function_decl = 0;
1605:
1606: /* End the scope containing the copied formal parameter variables. */
1607:
1608: expand_end_bindings (getdecls (), 1, 1);
1609: poplevel (1, 1, 0);
1610: poplevel (0, 0, 0);
1611: emit_line_note (input_filename, lineno);
1612:
1613: if (structure_value_addr)
1614: return gen_rtx (MEM, TYPE_MODE (type),
1615: memory_address (TYPE_MODE (type), structure_value_addr));
1616: return target;
1617: }
1618:
1619: /* Given a chain of PARM_DECLs, ARGS, copy each decl into a VAR_DECL,
1620: push all of those decls and give each one the corresponding home. */
1621:
1622: static void
1623: integrate_parm_decls (args, map, arg_vector)
1624: tree args;
1625: struct inline_remap *map;
1626: rtvec arg_vector;
1627: {
1628: register tree tail;
1629: register int i;
1630:
1631: for (tail = args, i = 0; tail; tail = TREE_CHAIN (tail), i++)
1632: {
1633: register tree decl = build_decl (VAR_DECL, DECL_NAME (tail),
1634: TREE_TYPE (tail));
1635: rtx new_decl_rtl
1636: = copy_rtx_and_substitute (RTVEC_ELT (arg_vector, i), map);
1637:
1638: /* These args would always appear unused, if not for this. */
1639: TREE_USED (decl) = 1;
1640: /* Prevent warning for shadowing with these. */
1641: DECL_FROM_INLINE (decl) = 1;
1642: pushdecl (decl);
1643: /* Fully instantiate the address with the equivalent form so that the
1644: debugging information contains the actual register, instead of the
1645: virtual register. Do this by not passing an insn to
1646: subst_constants. */
1647: subst_constants (&new_decl_rtl, 0, map);
1648: apply_change_group ();
1649: DECL_RTL (decl) = new_decl_rtl;
1650: }
1651: }
1652:
1653: /* Given a BLOCK node LET, push decls and levels so as to construct in the
1654: current function a tree of contexts isomorphic to the one that is given.
1655:
1656: LEVEL indicates how far down into the BLOCK tree is the node we are
1657: currently traversing. It is always zero for the initial call.
1658:
1659: MAP, if nonzero, is a pointer to a inline_remap map which indicates how
1660: registers used in the DECL_RTL field should be remapped. If it is zero,
1661: no mapping is necessary.
1662:
1663: FUNCTIONBODY indicates whether the top level block tree corresponds to
1664: a function body. This is identical in meaning to the functionbody
1665: argument of poplevel. */
1666:
1667: static void
1668: integrate_decl_tree (let, level, map, functionbody)
1669: tree let;
1670: int level;
1671: struct inline_remap *map;
1672: int functionbody;
1673: {
1674: tree t, node;
1675:
1676: pushlevel (0);
1677:
1678: for (t = BLOCK_VARS (let); t; t = TREE_CHAIN (t))
1679: {
1680: tree d = build_decl (TREE_CODE (t), DECL_NAME (t), TREE_TYPE (t));
1681: DECL_SOURCE_LINE (d) = DECL_SOURCE_LINE (t);
1682: DECL_SOURCE_FILE (d) = DECL_SOURCE_FILE (t);
1683: if (! functionbody && DECL_RTL (t) != 0)
1684: {
1685: DECL_RTL (d) = copy_rtx_and_substitute (DECL_RTL (t), map);
1686: /* Fully instantiate the address with the equivalent form so that the
1687: debugging information contains the actual register, instead of the
1688: virtual register. Do this by not passing an insn to
1689: subst_constants. */
1690: subst_constants (&DECL_RTL (d), 0, map);
1691: apply_change_group ();
1692: }
1693: else if (DECL_RTL (t))
1694: DECL_RTL (d) = copy_rtx (DECL_RTL (t));
1695: TREE_EXTERNAL (d) = TREE_EXTERNAL (t);
1696: TREE_STATIC (d) = TREE_STATIC (t);
1697: TREE_PUBLIC (d) = TREE_PUBLIC (t);
1698: TREE_CONSTANT (d) = TREE_CONSTANT (t);
1699: TREE_ADDRESSABLE (d) = TREE_ADDRESSABLE (t);
1700: TREE_READONLY (d) = TREE_READONLY (t);
1701: TREE_SIDE_EFFECTS (d) = TREE_SIDE_EFFECTS (t);
1702: /* These args would always appear unused, if not for this. */
1703: TREE_USED (d) = 1;
1704: /* Prevent warning for shadowing with these. */
1705: DECL_FROM_INLINE (d) = 1;
1706: pushdecl (d);
1707: }
1708:
1709: for (t = BLOCK_SUBBLOCKS (let); t; t = TREE_CHAIN (t))
1710: integrate_decl_tree (t, level + 1, map, functionbody);
1711:
1712: node = poplevel (level > 0, 0, level == 0 && functionbody);
1713: if (node)
1714: TREE_USED (node) = TREE_USED (let);
1715: }
1716:
1717: /* Create a new copy of an rtx.
1718: Recursively copies the operands of the rtx,
1719: except for those few rtx codes that are sharable.
1720:
1721: We always return an rtx that is similar to that incoming rtx, with the
1722: exception of possibly changing a REG to a SUBREG or vice versa. No
1723: rtl is ever emitted.
1724:
1725: Handle constants that need to be placed in the constant pool by
1726: calling `force_const_mem'. */
1727:
1728: rtx
1729: copy_rtx_and_substitute (orig, map)
1730: register rtx orig;
1731: struct inline_remap *map;
1732: {
1733: register rtx copy, temp;
1734: register int i, j;
1735: register RTX_CODE code;
1736: register enum machine_mode mode;
1737: register char *format_ptr;
1738: int regno;
1739:
1740: if (orig == 0)
1741: return 0;
1742:
1743: code = GET_CODE (orig);
1744: mode = GET_MODE (orig);
1745:
1746: switch (code)
1747: {
1748: case REG:
1749: /* If the stack pointer register shows up, it must be part of
1750: stack-adjustments (*not* because we eliminated the frame pointer!).
1751: Small hard registers are returned as-is. Pseudo-registers
1752: go through their `reg_map'. */
1753: regno = REGNO (orig);
1754: if (regno <= LAST_VIRTUAL_REGISTER)
1755: {
1756: /* Some hard registers are also mapped,
1757: but others are not translated. */
1758: if (map->reg_map[regno] != 0)
1759: return map->reg_map[regno];
1760:
1761: /* If this is the virtual frame pointer, make space in current
1762: function's stack frame for the stack frame of the inline function.
1763:
1764: Copy the address of this area into a pseudo. Map
1765: virtual_stack_vars_rtx to this pseudo and set up a constant
1766: equivalence for it to be the address. This will substitute the
1767: address into insns where it can be substituted and use the new
1768: pseudo where it can't. */
1769: if (regno == VIRTUAL_STACK_VARS_REGNUM)
1770: {
1771: rtx loc, seq;
1772: int size = DECL_FRAME_SIZE (map->fndecl);
1773: int rounded;
1774:
1775: start_sequence ();
1776: loc = assign_stack_temp (BLKmode, size, 1);
1777: loc = XEXP (loc, 0);
1778: #ifdef FRAME_GROWS_DOWNWARD
1779: /* In this case, virtual_stack_vars_rtx points to one byte
1780: higher than the top of the frame area. So compute the offset
1781: to one byte higher than our substitute frame.
1782: Keep the fake frame pointer aligned like a real one. */
1783: rounded = CEIL_ROUND (size, BIGGEST_ALIGNMENT / BITS_PER_UNIT);
1784: loc = plus_constant (loc, rounded);
1785: #endif
1.1.1.2 ! root 1786: map->reg_map[regno] = temp = force_operand (loc, 0);
! 1787: map->const_equiv_map[REGNO (temp)] = loc;
! 1788: map->const_age_map[REGNO (temp)] = CONST_AGE_PARM;
1.1 root 1789:
1790: seq = gen_sequence ();
1791: end_sequence ();
1792: emit_insn_after (seq, map->insns_at_start);
1.1.1.2 ! root 1793: return temp;
1.1 root 1794: }
1795: else if (regno == VIRTUAL_INCOMING_ARGS_REGNUM)
1796: {
1797: /* Do the same for a block to contain any arguments referenced
1798: in memory. */
1799: rtx loc, seq;
1800: int size = FUNCTION_ARGS_SIZE (DECL_SAVED_INSNS (map->fndecl));
1801:
1802: start_sequence ();
1803: loc = assign_stack_temp (BLKmode, size, 1);
1804: loc = XEXP (loc, 0);
1.1.1.2 ! root 1805: map->reg_map[regno] = temp = force_operand (loc, 0);
! 1806: map->const_equiv_map[REGNO (temp)] = loc;
! 1807: map->const_age_map[REGNO (temp)] = CONST_AGE_PARM;
1.1 root 1808:
1809: seq = gen_sequence ();
1810: end_sequence ();
1811: emit_insn_after (seq, map->insns_at_start);
1.1.1.2 ! root 1812: return temp;
1.1 root 1813: }
1814: else if (REG_FUNCTION_VALUE_P (orig))
1815: {
1816: /* This is a reference to the function return value. If
1817: the function doesn't have a return value, error. If the
1818: mode doesn't agree, make a SUBREG. */
1819: if (map->inline_target == 0)
1820: /* Must be unrolling loops or replicating code if we
1821: reach here, so return the register unchanged. */
1822: return orig;
1823: else if (mode != GET_MODE (map->inline_target))
1824: return gen_rtx (SUBREG, mode, map->inline_target, 0);
1825: else
1826: return map->inline_target;
1827: }
1828: return orig;
1829: }
1830: if (map->reg_map[regno] == NULL)
1831: {
1832: map->reg_map[regno] = gen_reg_rtx (mode);
1833: REG_USERVAR_P (map->reg_map[regno]) = REG_USERVAR_P (orig);
1834: REG_LOOP_TEST_P (map->reg_map[regno]) = REG_LOOP_TEST_P (orig);
1835: RTX_UNCHANGING_P (map->reg_map[regno]) = RTX_UNCHANGING_P (orig);
1836: /* A reg with REG_FUNCTION_VALUE_P true will never reach here. */
1837: }
1838: return map->reg_map[regno];
1839:
1840: case SUBREG:
1841: copy = copy_rtx_and_substitute (SUBREG_REG (orig), map);
1842: /* SUBREG is ordinary, but don't make nested SUBREGs. */
1843: if (GET_CODE (copy) == SUBREG)
1844: return gen_rtx (SUBREG, GET_MODE (orig), SUBREG_REG (copy),
1845: SUBREG_WORD (orig) + SUBREG_WORD (copy));
1846: else
1847: return gen_rtx (SUBREG, GET_MODE (orig), copy,
1848: SUBREG_WORD (orig));
1849:
1850: case USE:
1851: case CLOBBER:
1852: /* USE and CLOBBER are ordinary, but we convert (use (subreg foo))
1853: to (use foo). */
1854: copy = copy_rtx_and_substitute (XEXP (orig, 0), map);
1855: if (GET_CODE (copy) == SUBREG)
1856: copy = SUBREG_REG (copy);
1857: return gen_rtx (code, VOIDmode, copy);
1858:
1859: case CODE_LABEL:
1860: LABEL_PRESERVE_P (map->label_map[CODE_LABEL_NUMBER (orig)])
1861: = LABEL_PRESERVE_P (orig);
1862: return map->label_map[CODE_LABEL_NUMBER (orig)];
1863:
1864: case LABEL_REF:
1865: copy = rtx_alloc (LABEL_REF);
1866: PUT_MODE (copy, mode);
1867: XEXP (copy, 0) = map->label_map[CODE_LABEL_NUMBER (XEXP (orig, 0))];
1868: LABEL_OUTSIDE_LOOP_P (copy) = LABEL_OUTSIDE_LOOP_P (orig);
1869: return copy;
1870:
1871: case PC:
1872: case CC0:
1873: case CONST_INT:
1874: case SYMBOL_REF:
1875: return orig;
1876:
1877: case CONST_DOUBLE:
1878: /* We have to make a new copy of this CONST_DOUBLE because don't want
1879: to use the old value of CONST_DOUBLE_MEM. Also, this may be a
1880: duplicate of a CONST_DOUBLE we have already seen. */
1881: if (GET_MODE_CLASS (GET_MODE (orig)) == MODE_FLOAT)
1882: {
1883: REAL_VALUE_TYPE d;
1884:
1885: REAL_VALUE_FROM_CONST_DOUBLE (d, orig);
1886: return immed_real_const_1 (d, GET_MODE (orig));
1887: }
1888: else
1889: return immed_double_const (CONST_DOUBLE_LOW (orig),
1890: CONST_DOUBLE_HIGH (orig), VOIDmode);
1891:
1892: case CONST:
1893: /* Make new constant pool entry for a constant
1894: that was in the pool of the inline function. */
1895: if (RTX_INTEGRATED_P (orig))
1896: {
1897: /* If this was an address of a constant pool entry that itself
1898: had to be placed in the constant pool, it might not be a
1899: valid address. So the recursive call below might turn it
1900: into a register. In that case, it isn't a constant any
1901: more, so return it. This has the potential of changing a
1902: MEM into a REG, but we'll assume that it safe. */
1903: temp = copy_rtx_and_substitute (XEXP (orig, 0), map);
1904: if (! CONSTANT_P (temp))
1905: return temp;
1906: return validize_mem (force_const_mem (GET_MODE (orig), temp));
1907: }
1908: break;
1909:
1910: case ADDRESS:
1911: /* If from constant pool address, make new constant pool entry and
1912: return its address. */
1913: if (! RTX_INTEGRATED_P (orig))
1914: abort ();
1915:
1916: temp = force_const_mem (GET_MODE (orig),
1917: copy_rtx_and_substitute (XEXP (orig, 0), map));
1918:
1919: #if 0
1920: /* Legitimizing the address here is incorrect.
1921:
1922: The only ADDRESS rtx's that can reach here are ones created by
1923: save_constants. Hence the operand of the ADDRESS is always legal
1924: in this position of the instruction, since the original rtx without
1925: the ADDRESS was legal.
1926:
1927: The reason we don't legitimize the address here is that on the
1928: Sparc, the caller may have a (high ...) surrounding this ADDRESS.
1929: This code forces the operand of the address to a register, which
1930: fails because we can not take the HIGH part of a register.
1931:
1932: Also, change_address may create new registers. These registers
1933: will not have valid reg_map entries. This can cause try_constants()
1934: to fail because assumes that all registers in the rtx have valid
1935: reg_map entries, and it may end up replacing one of these new
1936: registers with junk. */
1937:
1938: if (! memory_address_p (GET_MODE (temp), XEXP (temp, 0)))
1939: temp = change_address (temp, GET_MODE (temp), XEXP (temp, 0));
1940: #endif
1941:
1942: return XEXP (temp, 0);
1943:
1944: case ASM_OPERANDS:
1945: /* If a single asm insn contains multiple output operands
1946: then it contains multiple ASM_OPERANDS rtx's that share operand 3.
1947: We must make sure that the copied insn continues to share it. */
1948: if (map->orig_asm_operands_vector == XVEC (orig, 3))
1949: {
1950: copy = rtx_alloc (ASM_OPERANDS);
1951: XSTR (copy, 0) = XSTR (orig, 0);
1952: XSTR (copy, 1) = XSTR (orig, 1);
1953: XINT (copy, 2) = XINT (orig, 2);
1954: XVEC (copy, 3) = map->copy_asm_operands_vector;
1955: XVEC (copy, 4) = map->copy_asm_constraints_vector;
1956: XSTR (copy, 5) = XSTR (orig, 5);
1957: XINT (copy, 6) = XINT (orig, 6);
1958: return copy;
1959: }
1960: break;
1961:
1962: case CALL:
1963: /* This is given special treatment because the first
1964: operand of a CALL is a (MEM ...) which may get
1965: forced into a register for cse. This is undesirable
1966: if function-address cse isn't wanted or if we won't do cse. */
1967: #ifndef NO_FUNCTION_CSE
1968: if (! (optimize && ! flag_no_function_cse))
1969: #endif
1970: return gen_rtx (CALL, GET_MODE (orig),
1971: gen_rtx (MEM, GET_MODE (XEXP (orig, 0)),
1972: copy_rtx_and_substitute (XEXP (XEXP (orig, 0), 0), map)),
1973: copy_rtx_and_substitute (XEXP (orig, 1), map));
1974: break;
1975:
1976: #if 0
1977: /* Must be ifdefed out for loop unrolling to work. */
1978: case RETURN:
1979: abort ();
1980: #endif
1981:
1982: case SET:
1983: /* If this is setting fp or ap, it means that we have a nonlocal goto.
1984: Don't alter that.
1985: If the nonlocal goto is into the current function,
1986: this will result in unnecessarily bad code, but should work. */
1987: if (SET_DEST (orig) == virtual_stack_vars_rtx
1988: || SET_DEST (orig) == virtual_incoming_args_rtx)
1989: return gen_rtx (SET, VOIDmode, SET_DEST (orig),
1990: copy_rtx_and_substitute (SET_SRC (orig), map));
1991: break;
1992:
1993: case MEM:
1994: copy = rtx_alloc (MEM);
1995: PUT_MODE (copy, mode);
1996: XEXP (copy, 0) = copy_rtx_and_substitute (XEXP (orig, 0), map);
1997: MEM_IN_STRUCT_P (copy) = MEM_IN_STRUCT_P (orig);
1998: MEM_VOLATILE_P (copy) = MEM_VOLATILE_P (orig);
1999: RTX_UNCHANGING_P (copy) = RTX_UNCHANGING_P (orig);
2000: return copy;
2001: }
2002:
2003: copy = rtx_alloc (code);
2004: PUT_MODE (copy, mode);
2005: copy->in_struct = orig->in_struct;
2006: copy->volatil = orig->volatil;
2007: copy->unchanging = orig->unchanging;
2008:
2009: format_ptr = GET_RTX_FORMAT (GET_CODE (copy));
2010:
2011: for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++)
2012: {
2013: switch (*format_ptr++)
2014: {
2015: case '0':
2016: break;
2017:
2018: case 'e':
2019: XEXP (copy, i) = copy_rtx_and_substitute (XEXP (orig, i), map);
2020: break;
2021:
2022: case 'u':
2023: /* Change any references to old-insns to point to the
2024: corresponding copied insns. */
2025: XEXP (copy, i) = map->insn_map[INSN_UID (XEXP (orig, i))];
2026: break;
2027:
2028: case 'E':
2029: XVEC (copy, i) = XVEC (orig, i);
2030: if (XVEC (orig, i) != NULL && XVECLEN (orig, i) != 0)
2031: {
2032: XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i));
2033: for (j = 0; j < XVECLEN (copy, i); j++)
2034: XVECEXP (copy, i, j)
2035: = copy_rtx_and_substitute (XVECEXP (orig, i, j), map);
2036: }
2037: break;
2038:
2039: case 'i':
2040: XINT (copy, i) = XINT (orig, i);
2041: break;
2042:
2043: case 's':
2044: XSTR (copy, i) = XSTR (orig, i);
2045: break;
2046:
2047: default:
2048: abort ();
2049: }
2050: }
2051:
2052: if (code == ASM_OPERANDS && map->orig_asm_operands_vector == 0)
2053: {
2054: map->orig_asm_operands_vector = XVEC (orig, 3);
2055: map->copy_asm_operands_vector = XVEC (copy, 3);
2056: map->copy_asm_constraints_vector = XVEC (copy, 4);
2057: }
2058:
2059: return copy;
2060: }
2061:
2062: /* Substitute known constant values into INSN, if that is valid. */
2063:
2064: void
2065: try_constants (insn, map)
2066: rtx insn;
2067: struct inline_remap *map;
2068: {
2069: int i;
2070:
2071: map->num_sets = 0;
2072: subst_constants (&PATTERN (insn), insn, map);
2073:
2074: /* Apply the changes if they are valid; otherwise discard them. */
2075: apply_change_group ();
2076:
2077: /* Show we don't know the value of anything stored or clobbered. */
2078: note_stores (PATTERN (insn), mark_stores);
2079: map->last_pc_value = 0;
2080: #ifdef HAVE_cc0
2081: map->last_cc0_value = 0;
2082: #endif
2083:
2084: /* Set up any constant equivalences made in this insn. */
2085: for (i = 0; i < map->num_sets; i++)
2086: {
2087: if (GET_CODE (map->equiv_sets[i].dest) == REG)
2088: {
2089: int regno = REGNO (map->equiv_sets[i].dest);
2090:
2091: if (map->const_equiv_map[regno] == 0
2092: /* Following clause is a hack to make case work where GNU C++
2093: reassigns a variable to make cse work right. */
2094: || ! rtx_equal_p (map->const_equiv_map[regno],
2095: map->equiv_sets[i].equiv))
2096: {
2097: map->const_equiv_map[regno] = map->equiv_sets[i].equiv;
2098: map->const_age_map[regno] = map->const_age;
2099: }
2100: }
2101: else if (map->equiv_sets[i].dest == pc_rtx)
2102: map->last_pc_value = map->equiv_sets[i].equiv;
2103: #ifdef HAVE_cc0
2104: else if (map->equiv_sets[i].dest == cc0_rtx)
2105: map->last_cc0_value = map->equiv_sets[i].equiv;
2106: #endif
2107: }
2108: }
2109:
2110: /* Substitute known constants for pseudo regs in the contents of LOC,
2111: which are part of INSN.
1.1.1.2 ! root 2112: If INSN is zero, the substitution should always be done (this is used to
1.1 root 2113: update DECL_RTL).
2114: These changes are taken out by try_constants if the result is not valid.
2115:
2116: Note that we are more concerned with determining when the result of a SET
2117: is a constant, for further propagation, than actually inserting constants
2118: into insns; cse will do the latter task better.
2119:
2120: This function is also used to adjust address of items previously addressed
2121: via the virtual stack variable or virtual incoming arguments registers. */
2122:
2123: static void
2124: subst_constants (loc, insn, map)
2125: rtx *loc;
2126: rtx insn;
2127: struct inline_remap *map;
2128: {
2129: rtx x = *loc;
2130: register int i;
2131: register enum rtx_code code;
2132: register char *format_ptr;
2133: int num_changes = num_validated_changes ();
2134: rtx new = 0;
2135: enum machine_mode op0_mode;
2136:
2137: code = GET_CODE (x);
2138:
2139: switch (code)
2140: {
2141: case PC:
2142: case CONST_INT:
2143: case CONST_DOUBLE:
2144: case SYMBOL_REF:
2145: case CONST:
2146: case LABEL_REF:
2147: case ADDRESS:
2148: return;
2149:
2150: #ifdef HAVE_cc0
2151: case CC0:
2152: validate_change (insn, loc, map->last_cc0_value, 1);
2153: return;
2154: #endif
2155:
2156: case USE:
2157: case CLOBBER:
2158: /* The only thing we can do with a USE or CLOBBER is possibly do
2159: some substitutions in a MEM within it. */
2160: if (GET_CODE (XEXP (x, 0)) == MEM)
2161: subst_constants (&XEXP (XEXP (x, 0), 0), insn, map);
2162: return;
2163:
2164: case REG:
2165: /* Substitute for parms and known constants. Don't replace
2166: hard regs used as user variables with constants. */
2167: {
2168: int regno = REGNO (x);
2169:
2170: if (! (regno < FIRST_PSEUDO_REGISTER && REG_USERVAR_P (x))
2171: && regno < map->const_equiv_map_size
2172: && map->const_equiv_map[regno] != 0
2173: && map->const_age_map[regno] >= map->const_age)
2174: validate_change (insn, loc, map->const_equiv_map[regno], 1);
2175: return;
2176: }
2177:
2178: case SUBREG:
2179: /* SUBREG is ordinary, but don't make nested SUBREGs and try to simplify
2180: constants. */
2181: {
2182: rtx inner = SUBREG_REG (x);
2183: rtx new = 0;
2184:
2185: /* We can't call subst_constants on &SUBREG_REG (x) because any
2186: constant or SUBREG wouldn't be valid inside our SUBEG. Instead,
2187: see what is inside, try to form the new SUBREG and see if that is
2188: valid. We handle two cases: extracting a full word in an
2189: integral mode and extracting the low part. */
2190: subst_constants (&inner, 0, map);
2191:
2192: if (GET_MODE_CLASS (GET_MODE (x)) == MODE_INT
2193: && GET_MODE_SIZE (GET_MODE (x)) == UNITS_PER_WORD
2194: && GET_MODE (SUBREG_REG (x)) != VOIDmode)
2195: new = operand_subword (inner, SUBREG_WORD (x), 0,
2196: GET_MODE (SUBREG_REG (x)));
2197:
2198: if (new == 0 && subreg_lowpart_p (x))
2199: new = gen_lowpart_common (GET_MODE (x), inner);
2200:
2201: if (new)
2202: validate_change (insn, loc, new, 1);
2203:
2204: return;
2205: }
2206:
2207: case MEM:
2208: subst_constants (&XEXP (x, 0), insn, map);
2209:
2210: /* If a memory address got spoiled, change it back. */
2211: if (insn != 0 && num_validated_changes () != num_changes
2212: && !memory_address_p (GET_MODE (x), XEXP (x, 0)))
2213: cancel_changes (num_changes);
2214: return;
2215:
2216: case SET:
2217: {
2218: /* Substitute constants in our source, and in any arguments to a
2219: complex (e..g, ZERO_EXTRACT) destination, but not in the destination
2220: itself. */
2221: rtx *dest_loc = &SET_DEST (x);
2222: rtx dest = *dest_loc;
2223: rtx src, tem;
2224:
2225: subst_constants (&SET_SRC (x), insn, map);
2226: src = SET_SRC (x);
2227:
2228: while (GET_CODE (*dest_loc) == ZERO_EXTRACT
2229: || GET_CODE (*dest_loc) == SIGN_EXTRACT
2230: || GET_CODE (*dest_loc) == SUBREG
2231: || GET_CODE (*dest_loc) == STRICT_LOW_PART)
2232: {
2233: if (GET_CODE (*dest_loc) == ZERO_EXTRACT)
2234: {
2235: subst_constants (&XEXP (*dest_loc, 1), insn, map);
2236: subst_constants (&XEXP (*dest_loc, 2), insn, map);
2237: }
2238: dest_loc = &XEXP (*dest_loc, 0);
2239: }
2240:
2241: /* Check for the case of DEST a SUBREG, both it and the underlying
2242: register are less than one word, and the SUBREG has the wider mode.
2243: In the case, we are really setting the underlying register to the
2244: source converted to the mode of DEST. So indicate that. */
2245: if (GET_CODE (dest) == SUBREG
2246: && GET_MODE_SIZE (GET_MODE (dest)) <= UNITS_PER_WORD
2247: && GET_MODE_SIZE (GET_MODE (SUBREG_REG (dest))) <= UNITS_PER_WORD
2248: && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (dest)))
2249: <= GET_MODE_SIZE (GET_MODE (dest)))
2250: && (tem = gen_lowpart_if_possible (GET_MODE (dest), src)))
2251: src = tem, dest = SUBREG_REG (dest);
2252:
2253: /* If storing a recognizable value save it for later recording. */
2254: if ((map->num_sets < MAX_RECOG_OPERANDS)
2255: && (CONSTANT_P (src)
2256: || (GET_CODE (src) == PLUS
2257: && GET_CODE (XEXP (src, 0)) == REG
2258: && REGNO (XEXP (src, 0)) >= FIRST_VIRTUAL_REGISTER
2259: && REGNO (XEXP (src, 0)) <= LAST_VIRTUAL_REGISTER
2260: && CONSTANT_P (XEXP (src, 1)))
2261: || GET_CODE (src) == COMPARE
2262: #ifdef HAVE_cc0
2263: || dest == cc0_rtx
2264: #endif
2265: || (dest == pc_rtx
2266: && (src == pc_rtx || GET_CODE (src) == RETURN
2267: || GET_CODE (src) == LABEL_REF))))
2268: {
2269: /* Normally, this copy won't do anything. But, if SRC is a COMPARE
2270: it will cause us to save the COMPARE with any constants
2271: substituted, which is what we want for later. */
2272: map->equiv_sets[map->num_sets].equiv = copy_rtx (src);
2273: map->equiv_sets[map->num_sets++].dest = dest;
2274: }
2275:
2276: return;
2277: }
2278: }
2279:
2280: format_ptr = GET_RTX_FORMAT (code);
2281:
2282: /* If the first operand is an expression, save its mode for later. */
2283: if (*format_ptr == 'e')
2284: op0_mode = GET_MODE (XEXP (x, 0));
2285:
2286: for (i = 0; i < GET_RTX_LENGTH (code); i++)
2287: {
2288: switch (*format_ptr++)
2289: {
2290: case '0':
2291: break;
2292:
2293: case 'e':
2294: if (XEXP (x, i))
2295: subst_constants (&XEXP (x, i), insn, map);
2296: break;
2297:
2298: case 'u':
2299: case 'i':
2300: case 's':
2301: break;
2302:
2303: case 'E':
2304: if (XVEC (x, i) != NULL && XVECLEN (x, i) != 0)
2305: {
2306: int j;
2307: for (j = 0; j < XVECLEN (x, i); j++)
2308: subst_constants (&XVECEXP (x, i, j), insn, map);
2309: }
2310: break;
2311:
2312: default:
2313: abort ();
2314: }
2315: }
2316:
2317: /* If this is a commutative operation, move a constant to the second
2318: operand unless the second operand is already a CONST_INT. */
2319: if ((GET_RTX_CLASS (code) == 'c' || code == NE || code == EQ)
2320: && CONSTANT_P (XEXP (x, 0)) && GET_CODE (XEXP (x, 1)) != CONST_INT)
2321: {
2322: rtx tem = XEXP (x, 0);
2323: validate_change (insn, &XEXP (x, 0), XEXP (x, 1), 1);
2324: validate_change (insn, &XEXP (x, 1), tem, 1);
2325: }
2326:
2327: /* Simplify the expression in case we put in some constants. */
2328: switch (GET_RTX_CLASS (code))
2329: {
2330: case '1':
2331: new = simplify_unary_operation (code, GET_MODE (x),
2332: XEXP (x, 0), op0_mode);
2333: break;
2334:
2335: case '<':
2336: {
2337: enum machine_mode op_mode = GET_MODE (XEXP (x, 0));
2338: if (op_mode == VOIDmode)
2339: op_mode = GET_MODE (XEXP (x, 1));
2340: new = simplify_relational_operation (code, op_mode,
2341: XEXP (x, 0), XEXP (x, 1));
2342: break;
2343: }
2344:
2345: case '2':
2346: case 'c':
2347: new = simplify_binary_operation (code, GET_MODE (x),
2348: XEXP (x, 0), XEXP (x, 1));
2349: break;
2350:
2351: case 'b':
2352: case '3':
2353: new = simplify_ternary_operation (code, GET_MODE (x), op0_mode,
2354: XEXP (x, 0), XEXP (x, 1), XEXP (x, 2));
2355: break;
2356: }
2357:
2358: if (new)
2359: validate_change (insn, loc, new, 1);
2360: }
2361:
2362: /* Show that register modified no longer contain known constants. We are
2363: called from note_stores with parts of the new insn. */
2364:
2365: void
2366: mark_stores (dest, x)
2367: rtx dest;
2368: rtx x;
2369: {
2370: if (GET_CODE (dest) == SUBREG)
2371: dest = SUBREG_REG (dest);
2372:
2373: if (GET_CODE (dest) == REG)
2374: global_const_equiv_map[REGNO (dest)] = 0;
2375: }
2376:
2377: /* If any CONST expressions with RTX_INTEGRATED_P are present in the rtx
2378: pointed to by PX, they represent constants in the constant pool.
2379: Replace these with a new memory reference obtained from force_const_mem.
2380: Similarly, ADDRESS expressions with RTX_INTEGRATED_P represent the
2381: address of a constant pool entry. Replace them with the address of
2382: a new constant pool entry obtained from force_const_mem. */
2383:
2384: static void
2385: restore_constants (px)
2386: rtx *px;
2387: {
2388: rtx x = *px;
2389: int i, j;
2390: char *fmt;
2391:
2392: if (x == 0)
2393: return;
2394:
2395: if (GET_CODE (x) == CONST_DOUBLE)
2396: {
2397: /* We have to make a new CONST_DOUBLE to ensure that we account for
2398: it correctly. Using the old CONST_DOUBLE_MEM data is wrong. */
2399: if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
2400: {
2401: REAL_VALUE_TYPE d;
2402:
2403: REAL_VALUE_FROM_CONST_DOUBLE (d, x);
2404: *px = immed_real_const_1 (d, GET_MODE (x));
2405: }
2406: else
2407: *px = immed_double_const (CONST_DOUBLE_LOW (x), CONST_DOUBLE_HIGH (x),
2408: VOIDmode);
2409: }
2410:
2411: else if (RTX_INTEGRATED_P (x) && GET_CODE (x) == CONST)
2412: {
2413: restore_constants (&XEXP (x, 0));
2414: *px = validize_mem (force_const_mem (GET_MODE (x), XEXP (x, 0)));
2415: }
2416: else if (RTX_INTEGRATED_P (x) && GET_CODE (x) == SUBREG)
2417: {
2418: /* This must be (subreg/i:M1 (const/i:M2 ...) 0). */
2419: rtx new = XEXP (SUBREG_REG (x), 0);
2420:
2421: restore_constants (&new);
2422: new = force_const_mem (GET_MODE (SUBREG_REG (x)), new);
2423: PUT_MODE (new, GET_MODE (x));
2424: *px = validize_mem (new);
2425: }
2426: else if (RTX_INTEGRATED_P (x) && GET_CODE (x) == ADDRESS)
2427: {
2428: restore_constants (&XEXP (x, 0));
2429: *px = XEXP (force_const_mem (GET_MODE (x), XEXP (x, 0)), 0);
2430: }
2431: else
2432: {
2433: fmt = GET_RTX_FORMAT (GET_CODE (x));
2434: for (i = 0; i < GET_RTX_LENGTH (GET_CODE (x)); i++)
2435: {
2436: switch (*fmt++)
2437: {
2438: case 'E':
2439: for (j = 0; j < XVECLEN (x, i); j++)
2440: restore_constants (&XVECEXP (x, i, j));
2441: break;
2442:
2443: case 'e':
2444: restore_constants (&XEXP (x, i));
2445: break;
2446: }
2447: }
2448: }
2449: }
2450:
2451: /* Output the assembly language code for the function FNDECL
2452: from its DECL_SAVED_INSNS. Used for inline functions that are output
2453: at end of compilation instead of where they came in the source. */
2454:
2455: void
2456: output_inline_function (fndecl)
2457: tree fndecl;
2458: {
2459: rtx head = DECL_SAVED_INSNS (fndecl);
2460: rtx last;
2461:
2462: temporary_allocation ();
2463:
2464: current_function_decl = fndecl;
2465:
2466: /* This call is only used to initialize global variables. */
2467: init_function_start (fndecl, "lossage", 1);
2468:
2469: /* Redo parameter determinations in case the FUNCTION_...
2470: macros took machine-specific actions that need to be redone. */
2471: assign_parms (fndecl, 1);
2472:
2473: /* Set stack frame size. */
2474: assign_stack_local (BLKmode, DECL_FRAME_SIZE (fndecl), 0);
2475:
2476: restore_reg_data (FIRST_PARM_INSN (head));
2477:
2478: stack_slot_list = STACK_SLOT_LIST (head);
2479:
2480: if (FUNCTION_FLAGS (head) & FUNCTION_FLAGS_CALLS_ALLOCA)
2481: current_function_calls_alloca = 1;
2482:
2483: if (FUNCTION_FLAGS (head) & FUNCTION_FLAGS_CALLS_SETJMP)
2484: current_function_calls_setjmp = 1;
2485:
2486: if (FUNCTION_FLAGS (head) & FUNCTION_FLAGS_CALLS_LONGJMP)
2487: current_function_calls_longjmp = 1;
2488:
2489: if (FUNCTION_FLAGS (head) & FUNCTION_FLAGS_RETURNS_STRUCT)
2490: current_function_returns_struct = 1;
2491:
2492: if (FUNCTION_FLAGS (head) & FUNCTION_FLAGS_RETURNS_PCC_STRUCT)
2493: current_function_returns_pcc_struct = 1;
2494:
2495: if (FUNCTION_FLAGS (head) & FUNCTION_FLAGS_NEEDS_CONTEXT)
2496: current_function_needs_context = 1;
2497:
2498: if (FUNCTION_FLAGS (head) & FUNCTION_FLAGS_HAS_NONLOCAL_LABEL)
2499: current_function_has_nonlocal_label = 1;
2500:
2501: if (FUNCTION_FLAGS (head) & FUNCTION_FLAGS_RETURNS_POINTER)
2502: current_function_returns_pointer = 1;
2503:
2504: if (FUNCTION_FLAGS (head) & FUNCTION_FLAGS_USES_CONST_POOL)
2505: current_function_uses_const_pool = 1;
2506:
2507: if (FUNCTION_FLAGS (head) & FUNCTION_FLAGS_USES_PIC_OFFSET_TABLE)
2508: current_function_uses_pic_offset_table = 1;
2509:
2510: current_function_outgoing_args_size = OUTGOING_ARGS_SIZE (head);
2511: current_function_pops_args = POPS_ARGS (head);
2512:
2513: /* There is no need to output a return label again. */
2514: return_label = 0;
2515:
2516: expand_function_end (DECL_SOURCE_FILE (fndecl), DECL_SOURCE_LINE (fndecl));
2517:
2518: /* Find last insn and rebuild the constant pool. */
2519: for (last = FIRST_PARM_INSN (head);
2520: NEXT_INSN (last); last = NEXT_INSN (last))
2521: {
2522: if (GET_RTX_CLASS (GET_CODE (last)) == 'i')
2523: {
2524: restore_constants (&PATTERN (last));
2525: restore_constants (®_NOTES (last));
2526: }
2527: }
2528:
2529: set_new_first_and_last_insn (FIRST_PARM_INSN (head), last);
2530: set_new_first_and_last_label_num (FIRST_LABELNO (head), LAST_LABELNO (head));
2531:
2532: /* Compile this function all the way down to assembly code. */
2533: rest_of_compilation (fndecl);
2534:
2535: current_function_decl = 0;
2536:
2537: permanent_allocation ();
2538: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.