Annotation of GNUtools/cc/integrate.c, revision 1.1

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 (&REG_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 (&REG_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 (&REG_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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.