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