Annotation of gcc/integrate.c, revision 1.1.1.14

1.1       root        1: /* Procedure integration for GNU CC.
                      2:    Copyright (C) 1988 Free Software Foundation, Inc.
                      3:    Contributed by Michael Tiemann ([email protected])
                      4: 
                      5: This file is part of GNU CC.
                      6: 
1.1.1.12  root        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 1, or (at your option)
                     10: any later version.
                     11: 
1.1       root       12: GNU CC is distributed in the hope that it will be useful,
1.1.1.12  root       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.  */
1.1       root       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-flags.h"
                     29: #include "expr.h"
                     30: 
                     31: #include "obstack.h"
                     32: #define        obstack_chunk_alloc     xmalloc
                     33: #define        obstack_chunk_free      free
                     34: extern int xmalloc ();
                     35: extern void free ();
                     36: 
                     37: extern struct obstack permanent_obstack, maybepermanent_obstack;
                     38: extern struct obstack *rtl_obstack, *saveable_obstack, *current_obstack;
                     39: 
1.1.1.14! root       40: extern rtx stack_slot_list;
        !            41: 
1.1       root       42: #define MIN(x,y) ((x < y) ? x : y)
                     43: 
                     44: extern tree pushdecl ();
1.1.1.14! root       45: extern tree poplevel ();
1.1.1.5   root       46: 
                     47: /* Default max number of insns a function can have and still be inline.
                     48:    This is overridden on RISC machines.  */
                     49: #ifndef INTEGRATE_THRESHOLD
                     50: #define INTEGRATE_THRESHOLD(DECL) \
1.1.1.14! root       51:   (8 * (8 + list_length (DECL_ARGUMENTS (DECL))))
1.1.1.5   root       52: #endif
1.1       root       53: 
                     54: /* This is the target of the inline function being expanded,
                     55:    or NULL if there is none.  */
                     56: static rtx inline_target;
                     57: 
                     58: /* We must take special care not to disrupt life too severely
                     59:    when performing procedure integration.  One thing that that
                     60:    involves is not creating illegitimate address which reload
                     61:    cannot fix.  Since we don't know what the frame pointer is
                     62:    not capable of (in a machine independent way), we create
                     63:    a pseudo-frame pointer which will have to do for now.  */
                     64: static rtx inline_fp_rtx;
                     65: 
                     66: /* Convert old frame-pointer offsets to new.  Parameters which only
                     67:    produce values (no addresses, and are never assigned), map directly
                     68:    to the pseudo-reg of the incoming value.  Parameters that are
                     69:    assigned to but do not have their address taken are given a fresh
                     70:    pseudo-register.  Parameters that have their address take are
                     71:    given a fresh stack-slot.  */
                     72: static rtx *parm_map;
                     73: 
                     74: /* ?? Should this be done here??  It is not right now.
                     75:    Keep track of whether a given pseudo-register is the sum
                     76:    of the frame pointer and a const_int (or zero).  */
                     77: static char *fp_addr_p;
                     78: 
                     79: /* For the local variables of the procdure being integrated that live
                     80:    on the frame, FRAME_POINTER_DELTA says how much to change their
                     81:    offsets by, so that they now live in the correct place on the
                     82:    frame of the function being compiled.  */
                     83: static int fp_delta;
                     84: 
1.1.1.11  root       85: /* When an insn is being copied by copy_rtx_and_substitute,
                     86:    this is nonzero if we have copied an ASM_OPERANDS.
                     87:    In that case, it is the original input-operand vector.
                     88:    Likewise in copy_for_inline.  */
                     89: static rtvec orig_asm_operands_vector;
                     90: 
                     91: /* When an insn is being copied by copy_rtx_and_substitute,
                     92:    this is nonzero if we have copied an ASM_OPERANDS.
                     93:    In that case, it is the copied input-operand vector.
                     94:    Likewise in copy_for_inline.  */
                     95: static rtvec copy_asm_operands_vector;
                     96: 
1.1.1.14! root       97: /* Likewise, this is the copied constraints vector.  */
        !            98: static rtvec copy_asm_constraints_vector;
        !            99: 
1.1       root      100: /* Return a copy of an rtx (as needed), substituting pseudo-register,
                    101:    labels, and frame-pointer offsets as necessary.  */
                    102: static rtx copy_rtx_and_substitute ();
1.1.1.7   root      103: /* Variant, used for memory addresses that are not memory_address_p.  */
                    104: static rtx copy_address ();
1.1       root      105: 
1.1.1.14! root      106: /* Return the rtx corresponding to a given index in the stack arguments.  */
        !           107: static rtx access_parm_map ();
        !           108: 
1.1       root      109: static void copy_parm_decls ();
                    110: static void copy_decl_tree ();
                    111: 
                    112: static rtx try_fold_cc0 ();
                    113: 
                    114: /* We do some simple constant folding optimization.  This optimization
                    115:    really exists primarily to save time inlining a function.  It
1.1.1.5   root      116:    also helps users who ask for inline functions without -O.  */
1.1       root      117: static rtx fold_out_const_cc0 ();
                    118: 
                    119: /* Zero if the current function (whose FUNCTION_DECL is FNDECL)
                    120:    is safe and reasonable to integrate into other functions.
                    121:    Nonzero means value is a warning message with a single %s
                    122:    for the function's name.  */
                    123: 
                    124: char *
                    125: function_cannot_inline_p (fndecl)
                    126:      register tree fndecl;
                    127: {
                    128:   register rtx insn;
                    129:   tree last = tree_last (TYPE_ARG_TYPES (TREE_TYPE (fndecl)));
1.1.1.5   root      130:   int max_insns = INTEGRATE_THRESHOLD (fndecl);
1.1       root      131:   register int ninsns = 0;
                    132:   register tree parms;
                    133: 
                    134:   /* No inlines with varargs.  `grokdeclarator' gives a warning
                    135:      message about that if `inline' is specified.  This code
                    136:      it put in to catch the volunteers.  */
                    137:   if (last && TREE_VALUE (last) != void_type_node)
1.1.1.7   root      138:     return "varargs function cannot be inline";
1.1       root      139: 
                    140:   /* If its not even close, don't even look.  */
1.1.1.14! root      141:   if (!TREE_INLINE (fndecl) && get_max_uid () > 3 * max_insns)
1.1.1.7   root      142:     return "function too large to be inline";
1.1       root      143: 
1.1.1.14! root      144:   /* We can't inline functions that return structures
        !           145:      the old-fashioned PCC way, copying into a static block.  */
        !           146: #ifdef PCC_STATIC_STRUCT_RETURN
        !           147:   if (flag_pcc_struct_return
        !           148:       && (TYPE_MODE (TREE_TYPE (TREE_TYPE (fndecl))) == BLKmode
        !           149:          || RETURN_IN_MEMORY (TREE_TYPE (TREE_TYPE (fndecl)))))
1.1.1.13  root      150:     return "inline functions not supported for this return value type";
1.1.1.11  root      151: #endif
                    152: 
1.1       root      153:   /* Don't inline functions which have BLKmode arguments.
                    154:      Don't inline functions that take the address of
                    155:        a parameter and do not specify a function prototype.  */
                    156:   for (parms = DECL_ARGUMENTS (fndecl); parms; parms = TREE_CHAIN (parms))
                    157:     {
                    158:       if (TYPE_MODE (TREE_TYPE (parms)) == BLKmode)
1.1.1.7   root      159:        return "function with large aggregate parameter cannot be inline";
1.1       root      160:       if (last == NULL_TREE && TREE_ADDRESSABLE (parms))
1.1.1.7   root      161:        return "no prototype, and parameter address used; cannot be inline";
1.1.1.11  root      162:       /* If an aggregate is thought of as "in memory"
                    163:         then its components are referred to by narrower memory refs.
                    164:         If the actual parameter is a reg, these refs can't be translated,
                    165:         esp. since copy_rtx_and_substitute doesn't know whether it is
                    166:         reading or writing.  */
                    167:       if ((TREE_CODE (TREE_TYPE (parms)) == RECORD_TYPE
                    168:           || TREE_CODE (TREE_TYPE (parms)) == UNION_TYPE)
                    169:          && GET_CODE (DECL_RTL (parms)) == MEM)
                    170:        return "address of an aggregate parameter is used; cannot be inline";
1.1       root      171:     }
                    172: 
1.1.1.14! root      173:   if (!TREE_INLINE (fndecl) && get_max_uid () > max_insns)
1.1       root      174:     {
                    175:       for (ninsns = 0, insn = get_first_nonparm_insn (); insn && ninsns < max_insns;
                    176:           insn = NEXT_INSN (insn))
                    177:        {
                    178:          if (GET_CODE (insn) == INSN
                    179:              || GET_CODE (insn) == JUMP_INSN
                    180:              || GET_CODE (insn) == CALL_INSN)
                    181:            ninsns++;
                    182:        }
                    183: 
                    184:       if (ninsns >= max_insns)
1.1.1.7   root      185:        return "function too large to be inline";
1.1       root      186:     }
                    187: 
                    188:   return 0;
                    189: }
                    190: 
                    191: /* Variables used within save_for_inline.  */
                    192: 
                    193: /* Mapping from old pesudo-register to new pseudo-registers.
                    194:    The first element of this map is reg_map[FIRST_PSEUDO_REGISTER].
1.1.1.6   root      195:    It is allocated in `save_for_inline' and `expand_inline_function',
1.1       root      196:    and deallocated on exit from each of those routines.  */
                    197: static rtx *reg_map;
                    198: 
                    199: /* Mapping from old code-labels to new code-labels.
                    200:    The first element of this map is label_map[min_labelno].
1.1.1.6   root      201:    It is allocated in `save_for_inline' and `expand_inline_function',
1.1       root      202:    and deallocated on exit from each of those routines.  */
                    203: static rtx *label_map;
                    204: 
1.1.1.6   root      205: /* Mapping from old insn uid's to copied insns.
                    206:    It is allocated in `save_for_inline' and `expand_inline_function',
                    207:    and deallocated on exit from each of those routines.  */
                    208: static rtx *insn_map;
                    209: 
1.1       root      210: /* Map pseudo reg number into the PARM_DECL for the parm living in the reg.
                    211:    Zero for a reg that isn't a parm's home.
                    212:    Only reg numbers less than max_parm_reg are mapped here.  */
                    213: static tree *parmdecl_map;
                    214: 
                    215: /* Keep track of first pseudo-register beyond those that are parms.  */
                    216: static int max_parm_reg;
                    217: 
1.1.1.7   root      218: /* Offset from arg ptr to the first parm of this inline function.  */
                    219: static int first_parm_offset;
                    220: 
1.1       root      221: /* On machines that perform a function return with a single
                    222:    instruction, such as the VAX, these return insns must be
                    223:    mapped into branch statements.  */
                    224: extern rtx return_label;
                    225: 
                    226: /* Copy an rtx for save_for_inline.  */
                    227: static rtx copy_for_inline ();
                    228: 
                    229: /* Make the insns and PARM_DECLs of the current function permanent
                    230:    and record other information in DECL_SAVED_INSNS to allow inlining
                    231:    of this function in subsequent calls.  */
                    232: 
                    233: void
                    234: save_for_inline (fndecl)
                    235:      tree fndecl;
                    236: {
                    237:   extern rtx *regno_reg_rtx;   /* in emit-rtl.c.  */
                    238:   extern current_function_args_size;
                    239: 
                    240:   rtx first_insn, last_insn, insn;
                    241:   rtx head, copy;
                    242:   tree parms;
                    243:   int max_labelno, min_labelno, i, len;
                    244:   int max_reg;
1.1.1.6   root      245:   int max_uid;
1.1       root      246: 
                    247:   /* Make and emit a return-label if we have not already done so.  */
                    248: 
                    249:   if (return_label == 0)
                    250:     {
                    251:       return_label = gen_label_rtx ();
                    252:       emit_label (return_label);
                    253:     }
                    254: 
                    255:   /* Get some bounds on the labels and registers used.  */
                    256: 
                    257:   max_labelno = max_label_num ();
                    258:   min_labelno = get_first_label_num ();
                    259:   max_parm_reg = max_parm_reg_num ();
                    260:   max_reg = max_reg_num ();
                    261: 
                    262:   /* Set up PARMDECL_MAP which maps pseudo-reg number to its PARM_DECL.
                    263: 
                    264:      Set TREE_VOLATILE to 0 if the parm is in a register, otherwise 1.
                    265:      Later we set TREE_READONLY to 0 if the parm is modified inside the fn.  */
                    266: 
                    267:   parmdecl_map = (tree *) alloca (max_parm_reg * sizeof (tree));
1.1.1.3   root      268:   bzero (parmdecl_map, max_parm_reg * sizeof (tree));
1.1       root      269: 
                    270:   for (parms = DECL_ARGUMENTS (fndecl); parms; parms = TREE_CHAIN (parms))
                    271:     {
                    272:       rtx p = DECL_RTL (parms);
                    273: 
                    274:       if (GET_CODE (p) == REG)
                    275:        {
                    276:          parmdecl_map[REGNO (p)] = parms;
                    277:          TREE_VOLATILE (parms) = 0;
                    278:        }
                    279:       else
                    280:        TREE_VOLATILE (parms) = 1;
                    281:       TREE_READONLY (parms) = 1;
                    282:     }
                    283: 
                    284:   /* The list of DECL_SAVES_INSNS, starts off with a header which
                    285:      contains the following information:
                    286: 
                    287:      the first insn of the function (not including the insns that copy
                    288:      parameters into registers).
                    289:      the first label used by that function,
                    290:      the last label used by that function,
                    291:      and the total number of registers used.  */
                    292: 
                    293:   head = gen_inline_header_rtx (NULL, NULL, min_labelno, max_labelno,
                    294:                                max_parm_reg, max_reg,
1.1.1.14! root      295:                                current_function_args_size, stack_slot_list);
1.1.1.6   root      296:   max_uid = INSN_UID (head);
1.1       root      297: 
                    298:   /* We have now allocated all that needs to be allocated permanently
                    299:      on the rtx obstack.  Set our high-water mark, so that we
                    300:      can free the rest of this when the time comes.  */
                    301: 
                    302:   preserve_data ();
                    303: 
                    304:   /* Copy the chain insns of this function.
                    305:      Install the copied chain as the insns of this function,
                    306:      for continued compilation;
                    307:      the original chain is recorded as the DECL_SAVED_INSNS
                    308:      for inlining future calls.  */
                    309: 
                    310:   /* If there are insns that copy parms from the stack into pseudo registers,
                    311:      those insns are not copied.  `expand_inline_function' must
                    312:      emit the correct code to handle such things.  */
                    313: 
                    314:   insn = get_insns ();
                    315:   if (GET_CODE (insn) != NOTE)
                    316:     abort ();
                    317:   first_insn = rtx_alloc (NOTE);
                    318:   NOTE_SOURCE_FILE (first_insn) = NOTE_SOURCE_FILE (insn);
                    319:   NOTE_LINE_NUMBER (first_insn) = NOTE_LINE_NUMBER (insn);
                    320:   INSN_UID (first_insn) = INSN_UID (insn);
                    321:   PREV_INSN (first_insn) = NULL;
                    322:   NEXT_INSN (first_insn) = NULL;
                    323:   last_insn = first_insn;
                    324: 
                    325:   /* Each pseudo-reg in the old insn chain must have a unique rtx in the copy.
                    326:      Make these new rtx's now, and install them in regno_reg_rtx, so they
                    327:      will be the official pseudo-reg rtx's for the rest of compilation.  */
                    328: 
                    329:   reg_map = (rtx *) alloca ((max_reg + 1) * sizeof (rtx));
                    330: 
                    331:   len = sizeof (struct rtx_def) + (GET_RTX_LENGTH (REG) - 1) * sizeof (rtunion);
                    332:   for (i = max_reg - 1; i >= FIRST_PSEUDO_REGISTER; i--)
                    333:     reg_map[i] = (rtx)obstack_copy (&maybepermanent_obstack, regno_reg_rtx[i], len);
                    334:   bcopy (reg_map + FIRST_PSEUDO_REGISTER,
                    335:         regno_reg_rtx + FIRST_PSEUDO_REGISTER,
1.1.1.7   root      336:         (max_reg - FIRST_PSEUDO_REGISTER) * sizeof (rtx));
1.1       root      337: 
                    338:   /* Likewise each label rtx must have a unique rtx as its copy.  */
                    339: 
                    340:   label_map = (rtx *)alloca ((max_labelno - min_labelno) * sizeof (rtx));
                    341:   label_map -= min_labelno;
                    342: 
                    343:   for (i = min_labelno; i < max_labelno; i++)
                    344:     label_map[i] = gen_label_rtx ();
                    345: 
1.1.1.6   root      346:   /* Record the mapping of old insns to copied insns.  */
                    347: 
                    348:   insn_map = (rtx *) alloca (max_uid * sizeof (rtx));
                    349:   bzero (insn_map, max_uid * sizeof (rtx));
                    350: 
1.1       root      351:   /* Now copy the chain of insns.  */
                    352: 
                    353:   for (insn = NEXT_INSN (insn); insn; insn = NEXT_INSN (insn))
                    354:     {
1.1.1.11  root      355:       orig_asm_operands_vector = 0;
                    356:       copy_asm_operands_vector = 0;
                    357: 
1.1       root      358:       switch (GET_CODE (insn))
                    359:        {
                    360:        case NOTE:
1.1.1.14! root      361:          /* It is probably essential to discard these.  */
        !           362:          if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_END
        !           363:              /* No need to keep these.  */
        !           364:              || NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED)
1.1.1.7   root      365:            continue;
                    366: 
1.1       root      367:          copy = rtx_alloc (NOTE);
                    368:          NOTE_SOURCE_FILE (copy) = NOTE_SOURCE_FILE (insn);
                    369:          NOTE_LINE_NUMBER (copy) = NOTE_LINE_NUMBER (insn);
                    370:          break;
                    371: 
                    372:        case INSN:
                    373:        case CALL_INSN:
                    374:        case JUMP_INSN:
                    375:          copy = rtx_alloc (GET_CODE (insn));
                    376:          PATTERN (copy) = copy_for_inline (PATTERN (insn));
                    377:          INSN_CODE (copy) = -1;
                    378:          LOG_LINKS (copy) = NULL;
                    379:          REG_NOTES (copy) = copy_for_inline (REG_NOTES (insn));
1.1.1.14! root      380:          RTX_INTEGRATED_P (copy) = RTX_INTEGRATED_P (insn);
1.1       root      381:          break;
                    382: 
                    383:        case CODE_LABEL:
                    384:          copy = label_map[CODE_LABEL_NUMBER (insn)];
                    385:          break;
                    386: 
                    387:        case BARRIER:
                    388:          copy = rtx_alloc (BARRIER);
                    389:          break;
                    390: 
                    391:        default:
                    392:          abort ();
                    393:        }
                    394:       INSN_UID (copy) = INSN_UID (insn);
1.1.1.6   root      395:       insn_map[INSN_UID (insn)] = copy;
1.1       root      396:       NEXT_INSN (last_insn) = copy;
                    397:       PREV_INSN (copy) = last_insn;
                    398:       last_insn = copy;
                    399:     }
                    400: 
                    401:   NEXT_INSN (last_insn) = NULL;
                    402: 
                    403:   NEXT_INSN (head) = get_first_nonparm_insn ();
                    404:   FIRST_PARM_INSN (head) = get_insns ();
                    405:   DECL_SAVED_INSNS (fndecl) = head;
                    406:   DECL_FRAME_SIZE (fndecl) = get_frame_size ();
                    407:   TREE_INLINE (fndecl) = 1;
                    408: 
                    409:   parmdecl_map = 0;
                    410:   label_map = 0;
                    411:   reg_map = 0;
                    412:   return_label = 0;
                    413: 
                    414:   set_new_first_and_last_insn (first_insn, last_insn);
                    415: }
                    416: 
                    417: /* Copy the rtx ORIG recursively, replacing pseudo-regs and labels
                    418:    according to `reg_map' and `label_map'.
                    419:    All other kinds of rtx are copied except those that can never be
                    420:    changed during compilation.  */
                    421: 
                    422: static rtx
                    423: copy_for_inline (orig)
                    424:      rtx orig;
                    425: {
                    426:   register rtx x = orig;
                    427:   register int i;
                    428:   register enum rtx_code code;
                    429:   register char *format_ptr;
                    430: 
                    431:   if (x == 0)
                    432:     return x;
                    433: 
                    434:   code = GET_CODE (x);
                    435: 
                    436:   /* These types may be freely shared.  */
                    437: 
                    438:   switch (code)
                    439:     {
                    440:     case QUEUED:
                    441:     case CONST_INT:
                    442:     case CONST_DOUBLE:
                    443:     case SYMBOL_REF:
                    444:     case PC:
                    445:     case CC0:
                    446:       return x;
                    447: 
1.1.1.11  root      448:     case ASM_OPERANDS:
                    449:       /* If a single asm insn contains multiple output operands
                    450:         then it contains multiple ASM_OPERANDS rtx's that share operand 3.
                    451:         We must make sure that the copied insn continues to share it.  */
                    452:       if (orig_asm_operands_vector == XVEC (orig, 3))
                    453:        {
                    454:          x = rtx_alloc (ASM_OPERANDS);
                    455:          XSTR (x, 0) = XSTR (orig, 0);
                    456:          XSTR (x, 1) = XSTR (orig, 1);
                    457:          XINT (x, 2) = XINT (orig, 2);
                    458:          XVEC (x, 3) = copy_asm_operands_vector;
1.1.1.14! root      459:          XVEC (x, 4) = copy_asm_constraints_vector;
        !           460:          XSTR (x, 5) = XSTR (orig, 5);
        !           461:          XINT (x, 6) = XINT (orig, 6);
1.1.1.11  root      462:          return x;
                    463:        }
                    464:       break;
                    465: 
1.1       root      466:     case MEM:
                    467:       /* A MEM is allowed to be shared if its address is constant
                    468:         or is a constant plus one of the special registers.  */
                    469:       if (CONSTANT_ADDRESS_P (XEXP (x, 0)))
                    470:        return x;
1.1.1.14! root      471: #if 0 /* This is turned off because it is possible for
        !           472:         unshare_all_rtl to copy the address, into memory that won't be saved.
        !           473:         Although the MEM can safely be shared, and won't be copied there,
        !           474:         the address itself cannot be shared, and may need to be copied.  */
1.1       root      475:       if (GET_CODE (XEXP (x, 0)) == PLUS
                    476:          && GET_CODE (XEXP (XEXP (x, 0), 0)) == REG
                    477:          && (REGNO (XEXP (XEXP (x, 0), 0)) == FRAME_POINTER_REGNUM
                    478:              || REGNO (XEXP (XEXP (x, 0), 0)) == ARG_POINTER_REGNUM)
                    479:          && CONSTANT_ADDRESS_P (XEXP (XEXP (x, 0), 1)))
1.1.1.14! root      480: #if 0
        !           481:        /* This statement was accidentally deleted in the remote past.
        !           482:           Reinsert it for 1.37.  Don't take the risk now.  */
        !           483:        return x;
        !           484: #endif
1.1       root      485:        if (GET_CODE (XEXP (x, 0)) == REG
                    486:            && (REGNO (XEXP (x, 0)) == FRAME_POINTER_REGNUM
                    487:                || REGNO (XEXP (x, 0)) == ARG_POINTER_REGNUM)
                    488:            && CONSTANT_ADDRESS_P (XEXP (x, 1)))
                    489:        return x;
1.1.1.14! root      490: #endif /* 0 */
1.1       root      491:       break;
                    492: 
                    493:     case LABEL_REF:
                    494:       {
                    495:        /* Must point to the new insn.  */
                    496:        return gen_rtx (LABEL_REF, GET_MODE (orig),
                    497:                        label_map[CODE_LABEL_NUMBER (XEXP (orig, 0))]);
                    498:       }
                    499: 
                    500:     case REG:
                    501:       if (REGNO (x) >= FIRST_PSEUDO_REGISTER)
                    502:        return reg_map [REGNO (x)];
                    503:       else
                    504:        return x;
                    505: 
                    506:       /* If a parm that gets modified lives in a pseudo-reg,
                    507:         set its TREE_VOLATILE to prevent certain optimizations.  */
                    508:     case SET:
                    509:       {
                    510:        rtx dest = SET_DEST (x);
                    511: 
                    512:        if (GET_CODE (dest) == REG
                    513:            && REGNO (dest) < max_parm_reg
1.1.1.3   root      514:            && REGNO (dest) >= FIRST_PSEUDO_REGISTER
                    515:            && parmdecl_map[REGNO (dest)] != 0)
1.1       root      516:          TREE_READONLY (parmdecl_map[REGNO (dest)]) = 0;
                    517:       }
                    518:       break;
                    519:     }
                    520: 
                    521:   /* Replace this rtx with a copy of itself.  */
                    522: 
                    523:   x = rtx_alloc (code);
                    524:   bcopy (orig, x, sizeof (int) * (GET_RTX_LENGTH (code) + 1));
                    525: 
                    526:   /* Now scan the subexpressions recursively.
                    527:      We can store any replaced subexpressions directly into X
                    528:      since we know X is not shared!  Any vectors in X
                    529:      must be copied if X was copied.  */
                    530: 
                    531:   format_ptr = GET_RTX_FORMAT (code);
                    532: 
                    533:   for (i = 0; i < GET_RTX_LENGTH (code); i++)
                    534:     {
                    535:       switch (*format_ptr++)
                    536:        {
                    537:        case 'e':
                    538:          XEXP (x, i) = copy_for_inline (XEXP (x, i));
                    539:          break;
                    540: 
1.1.1.6   root      541:        case 'u':
                    542:          /* Change any references to old-insns to point to the
                    543:             corresponding copied insns.  */
                    544:          return insn_map[INSN_UID (XEXP (x, i))];
                    545: 
1.1       root      546:        case 'E':
1.1.1.6   root      547:          if (XVEC (x, i) != NULL && XVECLEN (x, i) != 0)
1.1       root      548:            {
                    549:              register int j;
                    550: 
                    551:              XVEC (x, i) = gen_rtvec_v (XVECLEN (x, i), &XVECEXP (x, i, 0));
                    552:              for (j = 0; j < XVECLEN (x, i); j++)
                    553:                XVECEXP (x, i, j)
                    554:                  = copy_for_inline (XVECEXP (x, i, j));
                    555:            }
                    556:          break;
                    557:        }
                    558:     }
1.1.1.11  root      559: 
                    560:   if (code == ASM_OPERANDS && orig_asm_operands_vector == 0)
                    561:     {
                    562:       orig_asm_operands_vector = XVEC (orig, 3);
                    563:       copy_asm_operands_vector = XVEC (x, 3);
1.1.1.14! root      564:       copy_asm_constraints_vector = XVEC (x, 4);
1.1.1.11  root      565:     }
                    566: 
1.1       root      567:   return x;
                    568: }
                    569: 
                    570: /* Integrate the procedure defined by FNDECL.  Note that this function
                    571:    may wind up calling itself.  Since the static variables are not
                    572:    reentrant, we do not assign them until after the possibility
                    573:    or recursion is eliminated.
                    574: 
                    575:    If IGNORE is nonzero, do not produce a value.
                    576:    Otherwise store the value in TARGET if it is nonzero and that is convenient.
                    577: 
                    578:    Value is:
                    579:    (rtx)-1 if we could not substitute the function
                    580:    0 if we substituted it and it does not produce a value
                    581:    else an rtx for where the value is stored.  */
                    582: 
                    583: rtx
                    584: expand_inline_function (fndecl, parms, target, ignore, type, structure_value_addr)
                    585:      tree fndecl, parms;
                    586:      rtx target;
                    587:      int ignore;
                    588:      tree type;
                    589:      rtx structure_value_addr;
                    590: {
                    591:   tree formal, actual;
                    592:   rtx header = DECL_SAVED_INSNS (fndecl);
                    593:   rtx insns = FIRST_FUNCTION_INSN (header);
1.1.1.9   root      594:   rtx insn;
1.1       root      595:   int max_regno = MAX_REGNUM (header) + 1;
                    596:   register int i;
                    597:   int min_labelno = FIRST_LABELNO (header);
                    598:   int max_labelno = LAST_LABELNO (header);
                    599:   int nargs;
                    600:   rtx *arg_vec;
1.1.1.9   root      601:   rtx local_return_label = 0;
1.1       root      602:   rtx follows_call = 0;
1.1.1.7   root      603:   rtx this_struct_value_rtx = 0;
1.1       root      604: 
                    605:   if (max_regno < FIRST_PSEUDO_REGISTER)
1.1.1.3   root      606:     abort ();
1.1       root      607: 
                    608:   nargs = list_length (DECL_ARGUMENTS (fndecl));
                    609: 
                    610:   /* We expect PARMS to have the right length; don't crash if not.  */
                    611:   if (list_length (parms) != nargs)
                    612:     return (rtx)-1;
1.1.1.13  root      613:   /* Also check that the parms type match.  Since the appropriate
                    614:      conversions or default promotions have already been applied,
                    615:      the machine modes should match exactly.  */
                    616:   for (formal = DECL_ARGUMENTS (fndecl),
                    617:        actual = parms;
                    618:        formal;
                    619:        formal = TREE_CHAIN (formal),
                    620:        actual = TREE_CHAIN (actual))
                    621:     {
                    622:       tree arg = TREE_VALUE (actual);
                    623:       enum machine_mode mode = TYPE_MODE (DECL_ARG_TYPE (formal));
                    624:       if (mode != TYPE_MODE (TREE_TYPE (arg)))
                    625:        return (rtx)-1;
                    626:       /* If they are block mode, the types should match exactly.  */
                    627:       if (mode == BLKmode && TREE_TYPE (arg) != TREE_TYPE (formal))
                    628:        return (rtx)-1;
                    629:     }
1.1       root      630: 
1.1.1.14! root      631:   /* Make a binding contour to keep inline cleanups called at
        !           632:      outer function-scope level from looking like they are shadowing
        !           633:      parameter declarations.  */
        !           634:   pushlevel (0);
        !           635: 
1.1       root      636:   /* Make a fresh binding contour that we can easily remove.  */
                    637:   pushlevel (0);
                    638:   expand_start_bindings (0);
                    639: 
                    640:   /* Get all the actual args as RTL, and store them in ARG_VEC.  */
                    641: 
                    642:   arg_vec = (rtx *)alloca (nargs * sizeof (rtx));
                    643: 
                    644:   for (formal = DECL_ARGUMENTS (fndecl),
                    645:        actual = parms,
                    646:        i = 0;
                    647:        formal;
                    648:        formal = TREE_CHAIN (formal),
                    649:        actual = TREE_CHAIN (actual),
                    650:        i++)
                    651:     {
1.1.1.14! root      652:       /* Actual parameter, already converted to DECL_ARG_TYPE (formal).  */
        !           653:       tree arg = TREE_VALUE (actual);
        !           654:       /* Mode of the value supplied.  */
1.1.1.13  root      655:       enum machine_mode tmode = TYPE_MODE (DECL_ARG_TYPE (formal));
1.1.1.14! root      656:       /* Mode of the variable used within the function.  */
1.1.1.13  root      657:       enum machine_mode imode = TYPE_MODE (TREE_TYPE (formal));
1.1       root      658:       rtx copy;
                    659: 
1.1.1.7   root      660:       emit_note (DECL_SOURCE_FILE (formal), DECL_SOURCE_LINE (formal));
1.1       root      661: 
1.1.1.14! root      662:       /* Make a place to hold the argument value, still in mode TMODE,
        !           663:         and put it in COPY.  */
1.1       root      664:       if (TREE_ADDRESSABLE (formal))
                    665:        {
1.1.1.14! root      666:          int size = int_size_in_bytes (DECL_ARG_TYPE (formal));
1.1       root      667:          copy = assign_stack_local (tmode, size);
1.1.1.12  root      668:          if (!memory_address_p (DECL_MODE (formal), XEXP (copy, 0)))
                    669:            copy = change_address (copy, VOIDmode, copy_rtx (XEXP (copy, 0)));
1.1       root      670:          store_expr (arg, copy, 0);
                    671:        }
                    672:       else if (! TREE_READONLY (formal)
                    673:               || TREE_VOLATILE (formal))
                    674:        {
                    675:          /* If parm is modified or if it hasn't a pseudo reg,
                    676:             we may not simply substitute the actual value;
                    677:             copy it through a register.  */
                    678:          copy = gen_reg_rtx (tmode);
                    679:          store_expr (arg, copy, 0);
                    680:        }
                    681:       else
                    682:        {
                    683:          copy = expand_expr (arg, 0, tmode, 0);
                    684: 
                    685:          /* We do not use CONSTANT_ADDRESS_P here because
                    686:             the set of cases where that might make a difference
                    687:             are a subset of the cases that arise even when
                    688:             it is a CONSTANT_ADDRESS_P (i.e., fp_delta
                    689:             gets into the act.  */
                    690:          if (GET_CODE (copy) != REG && ! CONSTANT_P (copy))
                    691:            copy = copy_to_reg (copy);
                    692:        }
1.1.1.13  root      693:       /* If passed mode != nominal mode, COPY is now the passed mode.
                    694:         Convert it to the nominal mode (i.e. truncate it).  */
                    695:       if (tmode != imode)
1.1.1.14! root      696:        copy = convert_to_mode (imode, copy, 0);
1.1       root      697:       arg_vec[i] = copy;
                    698:     }
                    699: 
                    700:   copy_parm_decls (DECL_ARGUMENTS (fndecl), arg_vec);
                    701: 
                    702:   /* Perform postincrements before actually calling the function.  */
                    703:   emit_queue ();
                    704: 
                    705:   /* clean up stack so that variables might have smaller offsets.  */
                    706:   do_pending_stack_adjust ();
                    707: 
                    708:   /* Pass the function the address in which to return a structure value.  */
                    709:   if (structure_value_addr)
1.1.1.7   root      710:     {
1.1.1.14! root      711:       if (GET_CODE (structure_value_addr) == REG
        !           712:          && (struct_value_rtx == 0 || GET_CODE (struct_value_rtx) == MEM))
        !           713:        this_struct_value_rtx = structure_value_addr;
1.1.1.7   root      714:       else
1.1.1.14! root      715:        this_struct_value_rtx = copy_to_mode_reg (Pmode, structure_value_addr);
1.1.1.7   root      716:     }
1.1       root      717: 
                    718:   /* Now prepare for copying the insns.
                    719:      Set up reg_map, parm_map and label_map saying how to translate
                    720:      the pseudo-registers, stack-parm references and labels when copying.  */
                    721: 
                    722:   reg_map = (rtx *) alloca (max_regno * sizeof (rtx));
                    723:   bzero (reg_map, max_regno * sizeof (rtx));
                    724: 
1.1.1.14! root      725:   parm_map = (rtx *)alloca ((FUNCTION_ARGS_SIZE (header)
        !           726:                             / UNITS_PER_WORD) * sizeof (rtx));
        !           727:   bzero (parm_map, ((FUNCTION_ARGS_SIZE (header)
        !           728:                     / UNITS_PER_WORD)
        !           729:                    * sizeof (rtx)));
        !           730: 
        !           731:   /* Note that expand_expr (called above) can clobber first_parm_offset.  */
        !           732:   first_parm_offset = FIRST_PARM_OFFSET (fndecl);
        !           733:   parm_map -= first_parm_offset / UNITS_PER_WORD;
        !           734: 
1.1       root      735:   if (DECL_ARGUMENTS (fndecl))
                    736:     {
                    737:       tree decl = DECL_ARGUMENTS (fndecl);
                    738: 
                    739:       for (formal = decl, i = 0; formal; formal = TREE_CHAIN (formal), i++)
                    740:        {
                    741:          /* Create an entry in PARM_MAP that says what pseudo register
                    742:             is associated with an address we might compute.  */
1.1.1.7   root      743:          if (DECL_OFFSET (formal) >= 0)
                    744:            {
                    745:              /* This parameter has a home in the stack.  */
                    746:              parm_map[DECL_OFFSET (formal) / BITS_PER_WORD] = arg_vec[i];
                    747:            }
                    748:          else
                    749:            {
                    750:              /* Parameter that was passed in a register;
                    751:                 does it have a home on the stack (as a local)?  */
                    752:              rtx frtx = DECL_RTL (formal);
                    753:              rtx offset = 0;
                    754:              if (GET_CODE (frtx) == MEM)
                    755:                {
                    756:                  frtx = XEXP (frtx, 0);
                    757:                  if (GET_CODE (frtx) == PLUS)
                    758:                    {
                    759:                      if (XEXP (frtx, 0) == frame_pointer_rtx
                    760:                          && GET_CODE (XEXP (frtx, 1)) == CONST_INT)
                    761:                        offset = XEXP (frtx, 1);
                    762:                      else if (XEXP (frtx, 1) == frame_pointer_rtx
                    763:                               && GET_CODE (XEXP (frtx, 0)) == CONST_INT)
                    764:                        offset = XEXP (frtx, 0);
1.1.1.14! root      765: #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
        !           766:                      /* If there is a separate arg pointer
        !           767:                         and REG_PARM_STACK_SPACE is defined,
        !           768:                         parms passed in regs can be copied
        !           769:                         to slots reached via the arg pointer.  */
        !           770:                      if (XEXP (frtx, 0) == arg_pointer_rtx
        !           771:                          && GET_CODE (XEXP (frtx, 1)) == CONST_INT)
        !           772:                        offset = XEXP (frtx, 1);
        !           773:                      else if (XEXP (frtx, 1) == arg_pointer_rtx
        !           774:                               && GET_CODE (XEXP (frtx, 0)) == CONST_INT)
        !           775:                        offset = XEXP (frtx, 0);
        !           776: #endif
1.1.1.7   root      777:                    }
                    778:                  if (offset)
                    779:                    parm_map[INTVAL (offset) / UNITS_PER_WORD] = arg_vec[i];
1.1.1.14! root      780:                  else if (TREE_TYPE (formal) != error_mark_node)
        !           781:                    abort ();
1.1.1.7   root      782:                }
                    783:              else if (GET_CODE (frtx) != REG)
                    784:                abort ();
                    785:            }
1.1       root      786:          /* Create an entry in REG_MAP that says what rtx is associated
                    787:             with a pseudo register from the function being inlined.  */
                    788:          if (GET_CODE (DECL_RTL (formal)) == REG)
                    789:            reg_map[REGNO (DECL_RTL (formal))] = arg_vec[i];
                    790:        }
1.1.1.14! root      791:     }
1.1.1.7   root      792: 
1.1.1.14! root      793: #if 0  /* This was turned off when it was written,
        !           794:          because expand_call was changed not to need it.  */
        !           795:   /* Handle the case where our caller offers a register target
        !           796:      but the called function wants to return the value in memory.  */
        !           797:   if (this_struct_value_rtx == 0
        !           798:       && aggregate_value_p (DECL_RESULT (fndecl)))
        !           799:     {
        !           800:       enum machine_mode mode1 = GET_MODE (DECL_RTL (DECL_RESULT (fndecl)));
        !           801:       this_struct_value_rtx
        !           802:        = assign_stack_local (mode1, GET_MODE_SIZE (mode1));
        !           803:       target = 0;
1.1       root      804:     }
1.1.1.14! root      805: #endif
        !           806: 
        !           807:   /* Make certain that we can accept struct_value_{incoming_rtx,rtx},
        !           808:      and map it.  */
        !           809:   if (this_struct_value_rtx == 0)
        !           810:     ;
        !           811:   else if (GET_CODE (struct_value_incoming_rtx) == REG)
        !           812:     reg_map[REGNO (XEXP (DECL_RTL (DECL_RESULT (fndecl)), 0))]
        !           813:       = this_struct_value_rtx;
        !           814:   else if (GET_CODE (struct_value_incoming_rtx) == MEM
        !           815:           && XEXP (XEXP (struct_value_incoming_rtx, 0), 0) == frame_pointer_rtx
        !           816:           && GET_CODE (XEXP (XEXP (struct_value_incoming_rtx, 0), 1)) == CONST_INT)
        !           817:     reg_map[REGNO (XEXP (DECL_RTL (DECL_RESULT (fndecl)), 0))]
        !           818:       = this_struct_value_rtx;
        !           819: #if 0
        !           820:     parm_map[INTVAL (XEXP (XEXP (struct_value_incoming_rtx, 0), 1)) / UNITS_PER_WORD]
        !           821:       = this_struct_value_rtx;
        !           822: #endif
1.1       root      823:   else
1.1.1.14! root      824:     abort ();
1.1       root      825: 
                    826:   label_map = (rtx *)alloca ((max_labelno - min_labelno) * sizeof (rtx));
                    827:   label_map -= min_labelno;
                    828: 
                    829:   for (i = min_labelno; i < max_labelno; i++)
                    830:     label_map[i] = gen_label_rtx ();
                    831: 
1.1.1.6   root      832:   /* As we copy insns, record the correspondence, so that inter-insn
                    833:      references can be copied into isomorphic structure.  */
                    834: 
                    835:   insn_map = (rtx *) alloca (INSN_UID (header) * sizeof (rtx));
                    836:   bzero (insn_map, INSN_UID (header) * sizeof (rtx));
                    837: 
1.1       root      838:   /* Set up a target to translate the inline function's value-register.  */
                    839: 
1.1.1.14! root      840:   if (this_struct_value_rtx != 0 || TYPE_MODE (type) == VOIDmode)
1.1       root      841:     inline_target = 0;
                    842:   else
1.1.1.3   root      843:     {
                    844:       /* Machine mode function was declared to return.   */
                    845:       enum machine_mode departing_mode = TYPE_MODE (type);
                    846:       /* (Possibly wider) machine mode it actually computes
                    847:         (for the sake of callers that fail to declare it right).  */
                    848:       enum machine_mode arriving_mode
1.1.1.10  root      849:        = TYPE_MODE (DECL_RESULT_TYPE (fndecl));
1.1.1.3   root      850: 
1.1.1.5   root      851:       /* Don't use MEMs as direct targets because on some machines
                    852:         substituting a MEM for a REG makes invalid insns.
                    853:         Let the combiner substitute the MEM if that is valid.  */
                    854:       if (target && GET_CODE (target) == REG
                    855:          && GET_MODE (target) == departing_mode)
1.1.1.3   root      856:        inline_target = target;
                    857:       else
                    858:        inline_target = target = gen_reg_rtx (departing_mode);
                    859: 
                    860:       /* If function's value was promoted before return,
                    861:         avoid machine mode mismatch when we substitute INLINE_TARGET.
                    862:         But TARGET is what we will return to the caller.  */
                    863:       if (arriving_mode != departing_mode)
                    864:        inline_target = gen_rtx (SUBREG, arriving_mode, target, 0);
                    865:     }
1.1       root      866: 
1.1.1.14! root      867:   /* Make space in current function's stack frame
        !           868:      for the stack frame of the inline function.
        !           869:      Adjust all frame-pointer references by the difference
        !           870:      between the offset to this space
        !           871:      and the offset to the equivalent space in the inline
        !           872:      function's frame.
        !           873:      This difference equals the size of preexisting locals.  */
1.1       root      874: 
                    875:   fp_delta = get_frame_size ();
                    876: #ifdef FRAME_GROWS_DOWNWARD
                    877:   fp_delta = - fp_delta;
                    878: #endif
                    879: 
                    880:   inline_fp_rtx
                    881:     = copy_to_mode_reg (Pmode,
                    882:                        plus_constant (frame_pointer_rtx, fp_delta));
                    883: 
                    884:   /* Now allocate the space for that to point at.  */
                    885: 
                    886:   assign_stack_local (VOIDmode, DECL_FRAME_SIZE (fndecl));
                    887: 
                    888:   /* Now copy the insns one by one.  */
                    889: 
                    890:   for (insn = insns; insn; insn = NEXT_INSN (insn))
                    891:     {
                    892:       rtx copy, pattern, next = 0;
                    893: 
1.1.1.11  root      894:       orig_asm_operands_vector = 0;
                    895:       copy_asm_operands_vector = 0;
                    896: 
1.1       root      897:       switch (GET_CODE (insn))
                    898:        {
                    899:        case INSN:
                    900:          pattern = PATTERN (insn);
                    901: 
                    902:          /* Special handling for the insn immediately after a CALL_INSN
                    903:             that returned a value:
                    904:             If it does copy the value, we must avoid the usual translation
                    905:             of the return-register into INLINE_TARGET.
                    906:             If it just USEs the value, the inline function expects it to
                    907:             stay in the return-register and be returned,
                    908:             so copy it into INLINE_TARGET.  */
                    909: 
                    910:          if (follows_call
                    911:              /* Allow a stack-adjust, handled normally, to come in between
                    912:                 the call and the value-copying insn.  */
                    913:              && ! (GET_CODE (pattern) == SET
                    914:                    && SET_DEST (pattern) == stack_pointer_rtx))
                    915:            {
                    916:              if (GET_CODE (pattern) == SET
                    917:                  && rtx_equal_p (SET_SRC (pattern), follows_call))
                    918:                /* This insn copies the value: take special care to copy
                    919:                   that value to this insn's destination.  */
                    920:                {
                    921:                  copy = emit_insn (gen_rtx (SET, VOIDmode,
                    922:                                             copy_rtx_and_substitute (SET_DEST (pattern)),
                    923:                                             follows_call));
1.1.1.9   root      924:                  RTX_INTEGRATED_P (copy) = 1;
1.1       root      925:                  follows_call = 0;
                    926:                  break;
                    927:                }
                    928:              else if (GET_CODE (pattern) == USE
                    929:                       && rtx_equal_p (XEXP (pattern, 0), follows_call))
                    930:                /* This insn does nothing but says the value is expected
                    931:                   to flow through to the inline function's return-value.
                    932:                   Make that happen, then ignore this insn.  */
                    933:                {
                    934:                  copy = emit_insn (gen_rtx (SET, VOIDmode, inline_target,
                    935:                                             follows_call));
1.1.1.9   root      936:                  RTX_INTEGRATED_P (copy) = 1;
1.1       root      937:                  follows_call = 0;
                    938:                  break;
                    939:                }
                    940:              /* If it does neither, this value must be ignored.  */
                    941:              follows_call = 0;
                    942:            }
                    943: 
                    944:          /* The (USE (REG n)) at return from the function should be ignored
                    945:             since we are changing (REG n) into inline_target.  */
1.1.1.6   root      946:          copy = 0;
1.1       root      947:          if (GET_CODE (pattern) == USE
                    948:              && GET_CODE (XEXP (pattern, 0)) == REG
1.1.1.5   root      949:              && REG_FUNCTION_VALUE_P (XEXP (pattern, 0)))
1.1       root      950:            break;
1.1.1.14! root      951:          /* Ignore setting a function value that we don't want to use.  */
        !           952:          if (inline_target == 0
        !           953:              && GET_CODE (pattern) == SET
        !           954:              && GET_CODE (SET_DEST (pattern)) == REG
        !           955:              && REG_FUNCTION_VALUE_P (SET_DEST (pattern)))
        !           956:            break;
1.1       root      957: 
                    958:          /* Try to do some quick constant folding here.
                    959:             This will save save execution time of the compiler,
                    960:             as well time and space of the program if done here.  */
                    961:          if (GET_CODE (pattern) == SET
                    962:              && SET_DEST (pattern) == cc0_rtx)
                    963:            next = try_fold_cc0 (insn);
                    964: 
                    965:          if (next != 0)
                    966:            {
                    967:              insn = next;
                    968:            }
                    969:          else
                    970:            {
1.1.1.14! root      971:              rtx note = find_reg_note (insn, REG_EQUIV, 0);
        !           972: 
1.1       root      973:              copy = emit_insn (copy_rtx_and_substitute (pattern));
1.1.1.9   root      974:              RTX_INTEGRATED_P (copy) = 1;
1.1.1.14! root      975: 
        !           976:              /* If we are copying an insn that loads a constant,
        !           977:                 record the constantness.  */
        !           978:              if (note)
        !           979:                REG_NOTES (copy)
        !           980:                  = gen_rtx (EXPR_LIST, REG_EQUIV, XEXP (note, 0),
        !           981:                             REG_NOTES (copy));
1.1       root      982:            }
                    983:          break;
                    984: 
                    985:        case JUMP_INSN:
                    986:          follows_call = 0;
                    987:          if (GET_CODE (PATTERN (insn)) == RETURN)
                    988:            {
1.1.1.9   root      989:              if (local_return_label == 0)
                    990:                local_return_label = gen_label_rtx ();
                    991:              emit_jump (local_return_label);
1.1       root      992:              break;
                    993:            }
                    994:          copy = emit_jump_insn (copy_rtx_and_substitute (PATTERN (insn)));
1.1.1.9   root      995:          RTX_INTEGRATED_P (copy) = 1;
1.1       root      996:          break;
                    997: 
                    998:        case CALL_INSN:
1.1.1.6   root      999: #if 0
                   1000:          /* This should no longer be necessary now that references
                   1001:             to this function's return value are flagged to distinguish
                   1002:             them from other references to the same hard register.  */
1.1       root     1003:          {
                   1004:            rtx newbod;
                   1005:            /* If the call's body is (set (reg...) (call...)),
                   1006:               the register is a function return register, but DON'T
                   1007:               translate it into INLINE_TARGET because it describes the
                   1008:               called function, not the caller's return value.  */
                   1009:            if (GET_CODE (PATTERN (insn)) == SET)
                   1010:              newbod = gen_rtx (SET, VOIDmode, SET_DEST (PATTERN (insn)),
                   1011:                                copy_rtx_and_substitute (SET_SRC (PATTERN (insn))));
1.1.1.6   root     1012:            else if (GET_CODE (PATTERN (insn)) == PARALLEL
                   1013:                     && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == SET)
                   1014:              {
                   1015:                register int j;
                   1016:                rtx newelem;
                   1017:                newbod = gen_rtx (PARALLEL, VOIDmode,
                   1018:                                  rtvec_alloc (XVECLEN (PATTERN (insn), 0)));
                   1019:                newelem = gen_rtx (SET, VOIDmode,
                   1020:                                   SET_DEST (XVECEXP (PATTERN (insn), 0, 0)),
                   1021:                                   copy_rtx_and_substitute (SET_SRC (XVECEXP (PATTERN (insn), 0, 0))));
                   1022:                XVECEXP (newbod, 0, 0) = newelem;
                   1023:                for (j = 1; j < XVECLEN (newbod, 0); j++)
                   1024:                  XVECEXP (newbod, 0, j)
                   1025:                    = copy_rtx_and_substitute (XVECEXP (PATTERN (insn), 0, j));
                   1026:              }
1.1       root     1027:            else
                   1028:              newbod = copy_rtx_and_substitute (PATTERN (insn));
                   1029:            copy = emit_call_insn (newbod);
                   1030:          }
1.1.1.6   root     1031: #else /* 1 */
                   1032:          copy = emit_call_insn (copy_rtx_and_substitute (PATTERN (insn)));
                   1033: #endif /* 1 */
1.1.1.9   root     1034:          RTX_INTEGRATED_P (copy) = 1;
1.1       root     1035:          /* Special handling needed for the following INSN depending on
                   1036:             whether it copies the value from the fcn return reg.  */
                   1037:          if (GET_CODE (PATTERN (insn)) == SET)
                   1038:            follows_call = SET_DEST (PATTERN (insn));
                   1039:          break;
                   1040: 
                   1041:        case CODE_LABEL:
1.1.1.6   root     1042:          copy = emit_label (label_map[CODE_LABEL_NUMBER (insn)]);
1.1       root     1043:          follows_call = 0;
                   1044:          break;
                   1045: 
                   1046:        case BARRIER:
1.1.1.6   root     1047:          copy = emit_barrier ();
1.1       root     1048:          break;
                   1049: 
                   1050:        case NOTE:
1.1.1.14! root     1051:          if (NOTE_LINE_NUMBER (insn) != NOTE_INSN_FUNCTION_END
        !          1052:              && NOTE_LINE_NUMBER (insn) != NOTE_INSN_FUNCTION_BEG)
1.1.1.7   root     1053:            copy = emit_note (NOTE_SOURCE_FILE (insn), NOTE_LINE_NUMBER (insn));
                   1054:          else
                   1055:            copy = 0;
1.1       root     1056:          break;
                   1057: 
                   1058:        default:
                   1059:          abort ();
                   1060:          break;
                   1061:        }
1.1.1.6   root     1062: 
                   1063:       insn_map[INSN_UID (insn)] = copy;
1.1       root     1064:     }
                   1065: 
1.1.1.9   root     1066:   if (local_return_label)
                   1067:     emit_label (local_return_label);
1.1       root     1068: 
                   1069:   /* Make copies of the decls of the symbols in the inline function, so that
                   1070:      the copies of the variables get declared in the current function.  */
                   1071:   copy_decl_tree (DECL_INITIAL (fndecl), 0);
                   1072: 
                   1073:   /* End the scope containing the copied formal parameter variables.  */
                   1074: 
1.1.1.10  root     1075:   expand_end_bindings (getdecls (), 1, 1);
1.1       root     1076:   poplevel (1, 1, 0);
1.1.1.14! root     1077:   poplevel (0, 0, 0);
1.1       root     1078: 
                   1079:   reg_map = NULL;
                   1080:   label_map = NULL;
                   1081: 
                   1082:   if (ignore || TYPE_MODE (type) == VOIDmode)
                   1083:     return 0;
                   1084: 
                   1085:   if (structure_value_addr)
                   1086:     {
                   1087:       if (target)
                   1088:        return target;
1.1.1.14! root     1089:       return gen_rtx (MEM, TYPE_MODE (type),
1.1       root     1090:                      memory_address (BLKmode, structure_value_addr));
                   1091:     }
                   1092: 
1.1.1.3   root     1093:   return target;
1.1       root     1094: }
                   1095: 
                   1096: /* Given a chain of PARM_DECLs, ARGS, and a vector of RTL homes VEC,
                   1097:    copy each decl into a VAR_DECL, push all of those decls
                   1098:    and give each one the corresponding home.  */
                   1099: 
                   1100: static void
                   1101: copy_parm_decls (args, vec)
                   1102:      tree args;
                   1103:      rtx *vec;
                   1104: {
                   1105:   register tree tail;
                   1106:   register int i;
                   1107: 
                   1108:   for (tail = args, i = 0; tail; tail = TREE_CHAIN (tail), i++)
                   1109:     {
                   1110:       register tree decl = pushdecl (build_decl (VAR_DECL, DECL_NAME (tail),
                   1111:                                                 TREE_TYPE (tail)));
1.1.1.9   root     1112:       /* These args would always appear unused, if not for this.  */
                   1113:       TREE_USED (decl) = 1;
1.1       root     1114:       DECL_RTL (decl) = vec[i];
                   1115:     }
                   1116: }
                   1117: 
                   1118: /* Given a LET_STMT node, push decls and levels
                   1119:    so as to construct in the current function a tree of contexts
                   1120:    isomorphic to the one that is given.  */
                   1121: 
                   1122: static void
                   1123: copy_decl_tree (let, level)
                   1124:      tree let;
                   1125:      int level;
                   1126: {
1.1.1.14! root     1127:   tree t, node;
1.1       root     1128: 
                   1129:   pushlevel (0);
                   1130:   
                   1131:   for (t = STMT_VARS (let); t; t = TREE_CHAIN (t))
                   1132:     {
                   1133:       tree d = build_decl (TREE_CODE (t), DECL_NAME (t), TREE_TYPE (t));
                   1134:       DECL_SOURCE_LINE (d) = DECL_SOURCE_LINE (t);
                   1135:       DECL_SOURCE_FILE (d) = DECL_SOURCE_FILE (t);
                   1136:       if (DECL_RTL (t) != 0)
1.1.1.8   root     1137:        {
                   1138:          if (GET_CODE (DECL_RTL (t)) == MEM
                   1139:              && CONSTANT_ADDRESS_P (XEXP (DECL_RTL (t), 0)))
                   1140:            /* copy_rtx_and_substitute would call memory_address
                   1141:               which would copy the address into a register.
                   1142:               Then debugging-output wouldn't know how to handle it.  */
                   1143:            DECL_RTL (d) = DECL_RTL (t);
                   1144:          else
                   1145:            DECL_RTL (d) = copy_rtx_and_substitute (DECL_RTL (t));
                   1146:        }
1.1       root     1147:       TREE_EXTERNAL (d) = TREE_EXTERNAL (t);
                   1148:       TREE_STATIC (d) = TREE_STATIC (t);
                   1149:       TREE_PUBLIC (d) = TREE_PUBLIC (t);
                   1150:       TREE_LITERAL (d) = TREE_LITERAL (t);
                   1151:       TREE_ADDRESSABLE (d) = TREE_ADDRESSABLE (t);
                   1152:       TREE_READONLY (d) = TREE_READONLY (t);
                   1153:       TREE_VOLATILE (d) = TREE_VOLATILE (t);
1.1.1.9   root     1154:       /* These args would always appear unused, if not for this.  */
                   1155:       TREE_USED (d) = 1;
1.1       root     1156:       pushdecl (d);
                   1157:     }
                   1158: 
1.1.1.14! root     1159:   for (t = STMT_SUBBLOCKS (let); t; t = TREE_CHAIN (t))
1.1       root     1160:     copy_decl_tree (t, level + 1);
                   1161: 
1.1.1.14! root     1162:   node = poplevel (level > 0, 0, 0);
        !          1163:   if (node)
        !          1164:     TREE_USED (node) = TREE_USED (let);
1.1       root     1165: }
                   1166: 
                   1167: /* Create a new copy of an rtx.
                   1168:    Recursively copies the operands of the rtx,
                   1169:    except for those few rtx codes that are sharable.  */
                   1170: 
                   1171: static rtx
                   1172: copy_rtx_and_substitute (orig)
                   1173:      register rtx orig;
                   1174: {
                   1175:   register rtx copy, temp;
                   1176:   register int i, j;
                   1177:   register RTX_CODE code;
                   1178:   register enum machine_mode mode;
                   1179:   register char *format_ptr;
                   1180:   int regno;
                   1181: 
                   1182:   if (orig == 0)
                   1183:     return 0;
                   1184: 
                   1185:   code = GET_CODE (orig);
                   1186:   mode = GET_MODE (orig);
                   1187: 
                   1188:   switch (code)
                   1189:     {
                   1190:     case REG:
                   1191:       /* If a frame-pointer register shows up, then we
                   1192:         must `fix' the reference.  If the stack pointer
                   1193:         register shows up, it must be part of stack-adjustments
                   1194:         (*not* because we eliminated the frame pointer!).
                   1195:         Small hard registers are returned as-is.  Pseudo-registers
                   1196:         go through their `reg_map'.  */
                   1197:       regno = REGNO (orig);
                   1198:       if (regno < FIRST_PSEUDO_REGISTER)
                   1199:        {
1.1.1.14! root     1200:          /* Some hard registers are also mapped,
        !          1201:             but others are not translated.  */
        !          1202:          if (reg_map[regno] != 0)
        !          1203:            return reg_map[regno];
1.1.1.5   root     1204:          if (REG_FUNCTION_VALUE_P (orig))
1.1.1.9   root     1205:            {
                   1206:              /* This is a reference to the function return value.  If
                   1207:                 the function doesn't have a return value, error.
                   1208:                 If it does, it may not be the same mode as `inline_target'
                   1209:                 because SUBREG is not required for hard regs.
                   1210:                 If not, adjust mode of inline_target to fit the context.  */
                   1211:              if (inline_target == 0)
                   1212:                abort ();
                   1213:              if (mode == GET_MODE (inline_target))
                   1214:                return inline_target;
                   1215:              return gen_rtx (SUBREG, mode, inline_target, 0);
                   1216:            }
1.1       root     1217:          if (regno == FRAME_POINTER_REGNUM)
                   1218:            return plus_constant (orig, fp_delta);
                   1219:          return orig;
                   1220:        }
                   1221:       if (reg_map[regno] == NULL)
                   1222:        reg_map[regno] = gen_reg_rtx (mode);
                   1223:       return reg_map[regno];
                   1224: 
1.1.1.14! root     1225:     case SUBREG:
        !          1226:       copy = copy_rtx_and_substitute (SUBREG_REG (orig));
        !          1227:       /* SUBREG is ordinary, but don't make nested SUBREGs.  */
        !          1228:       if (GET_CODE (copy) == SUBREG)
        !          1229:        return gen_rtx (SUBREG, GET_MODE (orig), SUBREG_REG (copy),
        !          1230:                        SUBREG_WORD (orig) + SUBREG_WORD (copy));
        !          1231:       return gen_rtx (SUBREG, GET_MODE (orig), copy,
        !          1232:                      SUBREG_WORD (orig));
        !          1233: 
1.1       root     1234:     case CODE_LABEL:
                   1235:       return label_map[CODE_LABEL_NUMBER (orig)];
                   1236: 
                   1237:     case LABEL_REF:
                   1238:       copy = rtx_alloc (LABEL_REF);
                   1239:       PUT_MODE (copy, mode);
                   1240:       XEXP (copy, 0) = label_map[CODE_LABEL_NUMBER (XEXP (orig, 0))];
                   1241:       return copy;
                   1242: 
                   1243:     case PC:
                   1244:     case CC0:
                   1245:     case CONST_INT:
                   1246:     case CONST_DOUBLE:
                   1247:     case SYMBOL_REF:
                   1248:       return orig;
                   1249: 
1.1.1.11  root     1250:     case ASM_OPERANDS:
                   1251:       /* If a single asm insn contains multiple output operands
                   1252:         then it contains multiple ASM_OPERANDS rtx's that share operand 3.
                   1253:         We must make sure that the copied insn continues to share it.  */
                   1254:       if (orig_asm_operands_vector == XVEC (orig, 3))
                   1255:        {
                   1256:          copy = rtx_alloc (ASM_OPERANDS);
                   1257:          XSTR (copy, 0) = XSTR (orig, 0);
                   1258:          XSTR (copy, 1) = XSTR (orig, 1);
                   1259:          XINT (copy, 2) = XINT (orig, 2);
                   1260:          XVEC (copy, 3) = copy_asm_operands_vector;
1.1.1.14! root     1261:          XVEC (copy, 4) = copy_asm_constraints_vector;
        !          1262:          XSTR (copy, 5) = XSTR (orig, 5);
        !          1263:          XINT (copy, 6) = XINT (orig, 6);
1.1.1.11  root     1264:          return copy;
                   1265:        }
                   1266:       break;
                   1267: 
1.1.1.5   root     1268:     case CALL:
                   1269:       /* This is given special treatment because the first
                   1270:         operand of a CALL is a (MEM ...) which may get
                   1271:         forced into a register for cse.  This is undesirable
                   1272:         if function-address cse isn't wanted or if we won't do cse.  */
                   1273: #ifndef NO_FUNCTION_CSE
                   1274:       if (! (optimize && ! flag_no_function_cse))
                   1275: #endif
                   1276:        return gen_rtx (CALL, GET_MODE (orig),
                   1277:                        gen_rtx (MEM, GET_MODE (XEXP (orig, 0)),
                   1278:                                 copy_rtx_and_substitute (XEXP (XEXP (orig, 0), 0))),
                   1279:                        copy_rtx_and_substitute (XEXP (orig, 1)));
                   1280:       break;
                   1281: 
1.1       root     1282:     case PLUS:
                   1283:       /* Note:  the PLUS case is not nearly as careful as the MEM
                   1284:         case in terms of preserving addresses.  The reason for this
                   1285:         is that it is expected that if a PLUS_EXPR turns out not
                   1286:         to be a legitimate address, reload can fix that up, without
                   1287:         doing major damage.  However, a MEM rtx must preside
                   1288:         over a legitimate address.  The MEM case has lots of hair
                   1289:         to deal with what happens when it sits on a PLUS...  */
                   1290:       /* Take care of the easy case quickly.  */
                   1291:       if (XEXP (orig, 0) == frame_pointer_rtx
                   1292:          || XEXP (orig, 1) == frame_pointer_rtx
                   1293:          || (ARG_POINTER_REGNUM != FRAME_POINTER_REGNUM
                   1294:              && (XEXP (orig, 0) == arg_pointer_rtx
                   1295:                  || XEXP (orig, 1) == arg_pointer_rtx)))
                   1296:        {
1.1.1.14! root     1297:          rtx reg;
1.1       root     1298:          if (XEXP (orig, 0) == frame_pointer_rtx
                   1299:              || XEXP (orig, 0) == arg_pointer_rtx)
1.1.1.14! root     1300:            reg = XEXP (orig, 0), copy = XEXP (orig, 1);
1.1       root     1301:          else
1.1.1.14! root     1302:            reg = XEXP (orig, 1), copy = XEXP (orig, 0);
1.1       root     1303: 
                   1304:          if (GET_CODE (copy) == CONST_INT)
                   1305:            {
                   1306:              int c = INTVAL (copy);
                   1307: 
1.1.1.14! root     1308:              if (reg == arg_pointer_rtx && c >= first_parm_offset)
1.1       root     1309:                {
1.1.1.14! root     1310:                  copy = access_parm_map (c, VOIDmode);
        !          1311:                  if (GET_CODE (copy) != MEM)
        !          1312:                    /* Should not happen, because a parm we need to address
        !          1313:                       should not be living in a register.
        !          1314:                       (expand_inline_function copied it to a stack slot.)  */
        !          1315:                    abort ();
1.1       root     1316:                  return XEXP (copy, 0);
                   1317:                }
                   1318:              return gen_rtx (PLUS, mode,
                   1319:                              frame_pointer_rtx,
                   1320:                              gen_rtx (CONST_INT, SImode,
                   1321:                                       c + fp_delta));
                   1322:            }
                   1323:          copy = copy_rtx_and_substitute (copy);
1.1.1.6   root     1324:          temp = force_reg (mode, gen_rtx (PLUS, mode, frame_pointer_rtx, copy));
1.1       root     1325:          return plus_constant (temp, fp_delta);
                   1326:        }
                   1327:       else if (reg_mentioned_p (frame_pointer_rtx, orig)
                   1328:               || (ARG_POINTER_REGNUM != FRAME_POINTER_REGNUM
                   1329:                   && reg_mentioned_p (arg_pointer_rtx, orig)))
                   1330:        {
                   1331:          /* If we have a complex sum which has a frame pointer
                   1332:             in it, and it was a legitimate address, then
                   1333:             keep it that way.  */
                   1334:          if (memory_address_p (mode, orig))
                   1335:            {
                   1336:              if (GET_CODE (XEXP (orig, 0)) == CONST_INT)
                   1337:                {
                   1338:                  copy = copy_rtx_and_substitute (XEXP (orig, 1));
                   1339:                  temp = plus_constant (copy, INTVAL (XEXP (orig, 0)));
                   1340:                }
                   1341:              else if (GET_CODE (XEXP (orig, 1)) == CONST_INT)
                   1342:                {
                   1343:                  copy = copy_rtx_and_substitute (XEXP (orig, 0));
                   1344:                  temp = plus_constant (copy, INTVAL (XEXP (orig, 1)));
                   1345:                }
                   1346:              else
                   1347:                {
                   1348:                  temp = gen_rtx (PLUS, GET_MODE (orig),
                   1349:                                  copy_rtx_and_substitute (XEXP (orig, 0)),
                   1350:                                  copy_rtx_and_substitute (XEXP (orig, 1)));
                   1351:                }
                   1352:              temp = memory_address (mode, temp);
                   1353:            }
                   1354:          else
                   1355:            temp = gen_rtx (PLUS, GET_MODE (orig),
                   1356:                            copy_rtx_and_substitute (XEXP (orig, 0)),
                   1357:                            copy_rtx_and_substitute (XEXP (orig, 1)));
                   1358:        }
                   1359:       else
                   1360:        temp = gen_rtx (PLUS, GET_MODE (orig),
                   1361:                        copy_rtx_and_substitute (XEXP (orig, 0)),
                   1362:                        copy_rtx_and_substitute (XEXP (orig, 1)));
                   1363: 
                   1364:       return temp;
1.1.1.7   root     1365: 
1.1       root     1366:     case MEM:
                   1367:       /* Take care of easiest case here.  */
                   1368:       copy = XEXP (orig, 0);
                   1369:       if (copy == frame_pointer_rtx || copy == arg_pointer_rtx)
                   1370:        return gen_rtx (MEM, mode,
                   1371:                        plus_constant (frame_pointer_rtx, fp_delta));
1.1.1.6   root     1372: 
                   1373:       /* Allow a pushing-address even if that is not valid as an
                   1374:         ordinary memory address.  It indicates we are inlining a special
1.1.1.9   root     1375:         push-insn.  These must be copied; otherwise unshare_all_rtl
                   1376:         might clobber them to point at temporary rtl of this function.  */
1.1.1.6   root     1377: #ifdef STACK_GROWS_DOWNWARD
                   1378:       if (GET_CODE (copy) == PRE_DEC && XEXP (copy, 0) == stack_pointer_rtx)
1.1.1.9   root     1379:        return gen_rtx (MEM, mode, copy_rtx_and_substitute (copy));
1.1.1.6   root     1380: #else
                   1381:       if (GET_CODE (copy) == PRE_INC && XEXP (copy, 0) == stack_pointer_rtx)
1.1.1.9   root     1382:        return gen_rtx (MEM, mode, copy_rtx_and_substitute (copy));
1.1.1.6   root     1383: #endif
                   1384: 
1.1.1.7   root     1385:       /* If this is some other sort of address that isn't generally valid,
                   1386:         break out all the registers referred to.  */
                   1387:       if (! memory_address_p (mode, copy))
                   1388:        return gen_rtx (MEM, mode, copy_address (copy));
                   1389: 
1.1       root     1390:       if (GET_CODE (copy) == PLUS)
                   1391:        {
                   1392:          if (XEXP (copy, 0) == frame_pointer_rtx
                   1393:              || XEXP (copy, 1) == frame_pointer_rtx
                   1394:              || (ARG_POINTER_REGNUM != FRAME_POINTER_REGNUM
                   1395:                  && (XEXP (copy, 0) == arg_pointer_rtx
                   1396:                      || XEXP (copy, 1) == arg_pointer_rtx)))
                   1397:            {
                   1398:              rtx reg;
                   1399:              if (XEXP (copy, 0) == frame_pointer_rtx
                   1400:                  || XEXP (copy, 0) == arg_pointer_rtx)
                   1401:                reg = XEXP (copy, 0), copy = XEXP (copy, 1);
                   1402:              else
                   1403:                reg = XEXP (copy, 1), copy = XEXP (copy, 0);
                   1404: 
                   1405:              if (GET_CODE (copy) == CONST_INT)
                   1406:                {
                   1407:                  int c = INTVAL (copy);
                   1408: 
1.1.1.7   root     1409:                  if (reg == arg_pointer_rtx && c >= first_parm_offset)
1.1.1.14! root     1410:                    return access_parm_map (c, mode);
1.1.1.11  root     1411: 
1.1       root     1412:                  temp = gen_rtx (PLUS, Pmode,
                   1413:                                  frame_pointer_rtx,
                   1414:                                  gen_rtx (CONST_INT, SImode,
                   1415:                                           c + fp_delta));
                   1416:                  if (! memory_address_p (Pmode, temp))
                   1417:                    return gen_rtx (MEM, mode, plus_constant (inline_fp_rtx, c));
                   1418:                }
                   1419:              copy =  copy_rtx_and_substitute (copy);
                   1420:              temp = gen_rtx (PLUS, Pmode, frame_pointer_rtx, copy);
                   1421:              temp = plus_constant (temp, fp_delta);
                   1422:              temp = memory_address (Pmode, temp);
                   1423:            }
                   1424:          else if (reg_mentioned_p (frame_pointer_rtx, copy)
                   1425:                   || (ARG_POINTER_REGNUM != FRAME_POINTER_REGNUM
                   1426:                       && reg_mentioned_p (arg_pointer_rtx, copy)))
                   1427:            {
                   1428:              if (GET_CODE (XEXP (copy, 0)) == CONST_INT)
                   1429:                {
                   1430:                  temp = copy_rtx_and_substitute (XEXP (copy, 1));
                   1431:                  temp = plus_constant (temp, INTVAL (XEXP (copy, 0)));
                   1432:                }
                   1433:              else if (GET_CODE (XEXP (copy, 1)) == CONST_INT)
                   1434:                {
                   1435:                  temp = copy_rtx_and_substitute (XEXP (copy, 0));
                   1436:                  temp = plus_constant (temp, INTVAL (XEXP (copy, 1)));
                   1437:                }
                   1438:              else
                   1439:                {
                   1440:                  temp = gen_rtx (PLUS, GET_MODE (copy),
                   1441:                                  copy_rtx_and_substitute (XEXP (copy, 0)),
                   1442:                                  copy_rtx_and_substitute (XEXP (copy, 1)));
                   1443:                }
                   1444:            }
                   1445:          else
                   1446:            {
                   1447:              if (GET_CODE (XEXP (copy, 1)) == CONST_INT)
                   1448:                temp = plus_constant (copy_rtx_and_substitute (XEXP (copy, 0)),
                   1449:                                      INTVAL (XEXP (copy, 1)));
                   1450:              else if (GET_CODE (XEXP (copy, 0)) == CONST_INT)
                   1451:                temp = plus_constant (copy_rtx_and_substitute (XEXP (copy, 1)),
                   1452:                                      INTVAL (XEXP (copy, 0)));
                   1453:              else
                   1454:                {
                   1455:                  rtx left = copy_rtx_and_substitute (XEXP (copy, 0));
                   1456:                  rtx right = copy_rtx_and_substitute (XEXP (copy, 1));
                   1457: 
                   1458:                  temp = gen_rtx (PLUS, GET_MODE (copy), left, right);
                   1459:                }
                   1460:            }
                   1461:        }
                   1462:       else
                   1463:        temp = copy_rtx_and_substitute (copy);
                   1464: 
                   1465:       return change_address (orig, mode, temp);
                   1466: 
                   1467:     case RETURN:
                   1468:       abort ();
                   1469:     }
                   1470: 
                   1471:   copy = rtx_alloc (code);
                   1472:   PUT_MODE (copy, mode);
                   1473:   copy->in_struct = orig->in_struct;
                   1474:   copy->volatil = orig->volatil;
                   1475:   copy->unchanging = orig->unchanging;
                   1476: 
                   1477:   format_ptr = GET_RTX_FORMAT (GET_CODE (copy));
                   1478: 
                   1479:   for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++)
                   1480:     {
                   1481:       switch (*format_ptr++)
                   1482:        {
                   1483:        case '0':
                   1484:          break;
                   1485: 
                   1486:        case 'e':
                   1487:          XEXP (copy, i) = copy_rtx_and_substitute (XEXP (orig, i));
                   1488:          break;
                   1489: 
1.1.1.6   root     1490:        case 'u':
                   1491:          /* Change any references to old-insns to point to the
                   1492:             corresponding copied insns.  */
1.1.1.9   root     1493:          XEXP (copy, i) = insn_map[INSN_UID (XEXP (orig, i))];
                   1494:          break;
1.1.1.6   root     1495: 
1.1       root     1496:        case 'E':
                   1497:          XVEC (copy, i) = XVEC (orig, i);
1.1.1.6   root     1498:          if (XVEC (orig, i) != NULL && XVECLEN (orig, i) != 0)
1.1       root     1499:            {
                   1500:              XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i));
                   1501:              for (j = 0; j < XVECLEN (copy, i); j++)
                   1502:                XVECEXP (copy, i, j) = copy_rtx_and_substitute (XVECEXP (orig, i, j));
                   1503:            }
                   1504:          break;
                   1505: 
                   1506:        case 'i':
                   1507:          XINT (copy, i) = XINT (orig, i);
                   1508:          break;
                   1509: 
                   1510:        case 's':
                   1511:          XSTR (copy, i) = XSTR (orig, i);
                   1512:          break;
                   1513: 
                   1514:        default:
                   1515:          abort ();
                   1516:        }
                   1517:     }
1.1.1.11  root     1518: 
                   1519:   if (code == ASM_OPERANDS && orig_asm_operands_vector == 0)
                   1520:     {
                   1521:       orig_asm_operands_vector = XVEC (orig, 3);
                   1522:       copy_asm_operands_vector = XVEC (copy, 3);
1.1.1.14! root     1523:       copy_asm_constraints_vector = XVEC (copy, 4);
        !          1524:     }
        !          1525: 
        !          1526:   return copy;
        !          1527: }
        !          1528: 
        !          1529: /* Get the value corresponding to an address relative to the arg pointer
        !          1530:    at index RELADDRESS.  MODE is the machine mode of the reference.
        !          1531:    MODE is used only when the value is a REG.
        !          1532:    Pass VOIDmode for MODE when the mode is not known;
        !          1533:    in such cases, you should make sure the value is a MEM.  */
        !          1534: 
        !          1535: static rtx
        !          1536: access_parm_map (reladdress, mode)
        !          1537:      int reladdress;
        !          1538:      enum machine_mode mode;
        !          1539: {
        !          1540:   /* Index in parm_map.  */
        !          1541:   int index = reladdress / UNITS_PER_WORD;
        !          1542:   /* Offset of the data being referenced
        !          1543:      from the beginning of the value for that parm.  */
        !          1544:   int offset = reladdress % UNITS_PER_WORD;
        !          1545:   rtx copy;
        !          1546: 
        !          1547:   /* If we are referring to the middle of a multiword parm,
        !          1548:      find the beginning of that parm.
        !          1549:      OFFSET gets the offset of the reference from
        !          1550:      the beginning of the parm.  */
        !          1551: 
        !          1552:   while (parm_map[index] == 0)
        !          1553:     {
        !          1554:       index--;
        !          1555:       if (index < first_parm_offset / UNITS_PER_WORD)
        !          1556:        /* If this abort happens, it means we need
        !          1557:           to handle "decrementing" INDEX back far
        !          1558:           enough to start looking among the reg parms
        !          1559:           instead of the stack parms.  What a mess!  */
        !          1560:        abort ();
        !          1561:       offset += UNITS_PER_WORD;
        !          1562:     }
        !          1563: 
        !          1564:   copy = parm_map[index];
        !          1565: 
        !          1566: #ifdef BYTES_BIG_ENDIAN
        !          1567:   /* Subtract from OFFSET the offset of where
        !          1568:      the actual parm value would start.  */
        !          1569:   if (GET_MODE_SIZE (GET_MODE (copy)) < UNITS_PER_WORD)
        !          1570:     offset
        !          1571:       -= (UNITS_PER_WORD
        !          1572:          - GET_MODE_SIZE (GET_MODE (copy)));
        !          1573: #endif
        !          1574: 
        !          1575:   /* For memory ref, adjust it by the desired offset.  */
        !          1576:   if (GET_CODE (copy) == MEM)
        !          1577:     {
        !          1578:       if (offset != 0)
        !          1579:        return change_address (copy, mode,
        !          1580:                               plus_constant (XEXP (copy, 0),
        !          1581:                                              offset));
        !          1582:       return copy;
        !          1583:     }
        !          1584: 
        !          1585:   if (GET_CODE (copy) != REG && GET_CODE (copy) != SUBREG
        !          1586:       && ! CONSTANT_P (copy))
        !          1587:     abort ();
        !          1588:   if (mode == VOIDmode)
        !          1589:     abort ();
        !          1590: 
        !          1591:   /* A REG cannot be offset by bytes, so use a subreg
        !          1592:      (which is possible only in certain cases).  */
        !          1593:   if (GET_MODE (copy) != mode
        !          1594:       && GET_MODE (copy) != VOIDmode)
        !          1595:     {
        !          1596:       int word;
        !          1597:       /* Crash if the portion of the arg wanted
        !          1598:         is not the least significant.
        !          1599:         Functions with refs to other parts of a
        !          1600:         parameter should not be inline--
        !          1601:         see function_cannot_inline_p. */
        !          1602: #ifdef BYTES_BIG_ENDIAN
        !          1603:       if (offset + GET_MODE_SIZE (mode)
        !          1604:          != GET_MODE_SIZE (GET_MODE (copy)))
        !          1605:        abort ();
        !          1606: #else
        !          1607:       if (offset != 0)
        !          1608:        abort ();
        !          1609: #endif
        !          1610:       word = 0;
        !          1611:       if (GET_CODE (copy) == SUBREG)
        !          1612:        word = SUBREG_WORD (copy), copy = SUBREG_REG (copy);
        !          1613:       if (CONSTANT_P (copy))
        !          1614:        copy = force_reg (GET_MODE (copy), copy);
        !          1615:       return gen_rtx (SUBREG, mode, copy, word);
1.1.1.11  root     1616:     }
                   1617: 
1.1       root     1618:   return copy;
                   1619: }
                   1620: 
1.1.1.7   root     1621: /* Like copy_rtx_and_substitute but produces different output, suitable
                   1622:    for an ideosyncractic address that isn't memory_address_p.
                   1623:    The output resembles the input except that REGs and MEMs are replaced
                   1624:    with new psuedo registers.  All the "real work" is done in separate
                   1625:    insns which set up the values of these new registers.  */
                   1626: 
                   1627: static rtx
                   1628: copy_address (orig)
                   1629:      register rtx orig;
                   1630: {
1.1.1.9   root     1631:   register rtx copy;
1.1.1.7   root     1632:   register int i, j;
                   1633:   register RTX_CODE code;
                   1634:   register enum machine_mode mode;
                   1635:   register char *format_ptr;
                   1636: 
                   1637:   if (orig == 0)
                   1638:     return 0;
                   1639: 
                   1640:   code = GET_CODE (orig);
                   1641:   mode = GET_MODE (orig);
                   1642: 
                   1643:   switch (code)
                   1644:     {
                   1645:     case REG:
1.1.1.9   root     1646:       if (REGNO (orig) != FRAME_POINTER_REGNUM)
                   1647:        return copy_rtx_and_substitute (orig);
                   1648:       return plus_constant (frame_pointer_rtx, fp_delta);
                   1649: 
                   1650:     case PLUS:
                   1651:       if (GET_CODE (XEXP (orig, 0)) == REG
                   1652:          && REGNO (XEXP (orig, 0)) == FRAME_POINTER_REGNUM)
                   1653:        return plus_constant (orig, fp_delta);
                   1654:       break;
                   1655: 
1.1.1.7   root     1656:     case MEM:
1.1.1.9   root     1657:       return copy_to_reg (copy_rtx_and_substitute (orig));
1.1.1.7   root     1658: 
                   1659:     case CODE_LABEL:
                   1660:     case LABEL_REF:
1.1.1.9   root     1661:       return copy_rtx_and_substitute (orig);
1.1.1.7   root     1662: 
                   1663:     case PC:
                   1664:     case CC0:
                   1665:     case CONST_INT:
                   1666:     case CONST_DOUBLE:
                   1667:     case SYMBOL_REF:
                   1668:       return orig;
                   1669:     }
                   1670: 
                   1671:   copy = rtx_alloc (code);
                   1672:   PUT_MODE (copy, mode);
                   1673:   copy->in_struct = orig->in_struct;
                   1674:   copy->volatil = orig->volatil;
                   1675:   copy->unchanging = orig->unchanging;
                   1676: 
                   1677:   format_ptr = GET_RTX_FORMAT (GET_CODE (copy));
                   1678: 
                   1679:   for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++)
                   1680:     {
                   1681:       switch (*format_ptr++)
                   1682:        {
                   1683:        case '0':
                   1684:          break;
                   1685: 
                   1686:        case 'e':
                   1687:          XEXP (copy, i) = copy_rtx_and_substitute (XEXP (orig, i));
                   1688:          break;
                   1689: 
                   1690:        case 'u':
                   1691:          /* Change any references to old-insns to point to the
                   1692:             corresponding copied insns.  */
1.1.1.9   root     1693:          XEXP (copy, i) = insn_map[INSN_UID (XEXP (orig, i))];
                   1694:          break;
1.1.1.7   root     1695: 
                   1696:        case 'E':
                   1697:          XVEC (copy, i) = XVEC (orig, i);
                   1698:          if (XVEC (orig, i) != NULL && XVECLEN (orig, i) != 0)
                   1699:            {
                   1700:              XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i));
                   1701:              for (j = 0; j < XVECLEN (copy, i); j++)
                   1702:                XVECEXP (copy, i, j) = copy_rtx_and_substitute (XVECEXP (orig, i, j));
                   1703:            }
                   1704:          break;
                   1705: 
                   1706:        case 'i':
                   1707:          XINT (copy, i) = XINT (orig, i);
                   1708:          break;
                   1709: 
                   1710:        case 's':
                   1711:          XSTR (copy, i) = XSTR (orig, i);
                   1712:          break;
                   1713: 
                   1714:        default:
                   1715:          abort ();
                   1716:        }
                   1717:     }
                   1718:   return copy;
                   1719: }
                   1720: 
1.1       root     1721: /* Attempt to simplify INSN while copying it from an inline fn,
                   1722:    assuming it is a SET that sets CC0.
                   1723: 
                   1724:    If we simplify it, we emit the appropriate insns and return
                   1725:    the last insn that we have handled (since we may handle the insn
                   1726:    that follows INSN as well as INSN itself).
                   1727: 
                   1728:    Otherwise we do nothing and return zero.  */
                   1729: 
                   1730: static rtx
                   1731: try_fold_cc0 (insn)
                   1732:      rtx insn;
                   1733: {
                   1734:   rtx cnst = copy_rtx_and_substitute (SET_SRC (PATTERN (insn)));
                   1735:   rtx pat, copy;
                   1736: 
                   1737:   if (CONSTANT_P (cnst)
                   1738:       /* @@ Cautious: Don't know how many of these tests we need.  */
                   1739:       && NEXT_INSN (insn)
                   1740:       && GET_CODE (pat = PATTERN (NEXT_INSN (insn))) == SET
                   1741:       && SET_DEST (pat) == pc_rtx
                   1742:       && GET_CODE (pat = SET_SRC (pat)) == IF_THEN_ELSE
                   1743:       && GET_RTX_LENGTH (GET_CODE (XEXP (pat, 0))) == 2)
                   1744:     {
                   1745:       rtx cnst2;
                   1746:       rtx cond = XEXP (pat, 0);
                   1747: 
                   1748:       if ((XEXP (cond, 0) == cc0_rtx
                   1749:           && CONSTANT_P (XEXP (cond, 1))
                   1750:           && (cnst2 = XEXP (cond, 1)))
                   1751:          || (XEXP (cond, 1) == cc0_rtx
                   1752:              && CONSTANT_P (XEXP (cond, 0))
                   1753:              && (cnst2 = XEXP (cond, 0))))
                   1754:        {
                   1755:          copy = fold_out_const_cc0 (cond, XEXP (pat, 1), XEXP (pat, 2),
                   1756:                                     cnst, cnst2);
                   1757:          if (copy)
                   1758:            {
                   1759:              if (GET_CODE (copy) == LABEL_REF)
                   1760:                {
                   1761:                  /* We will branch unconditionally to
                   1762:                     the label specified by COPY.
                   1763:                     Eliminate dead code by running down the
                   1764:                     list of insn until we see a CODE_LABEL.
                   1765:                     If the CODE_LABEL is the one specified
                   1766:                     by COPY, we win, and can delete all code
                   1767:                     up to (but not necessarily including)
                   1768:                     that label.  Otherwise only win a little:
                   1769:                     emit the branch insn, and continue expanding.  */
                   1770:                  rtx tmp = NEXT_INSN (insn);
                   1771:                  while (tmp && GET_CODE (tmp) != CODE_LABEL)
                   1772:                    tmp = NEXT_INSN (tmp);
                   1773:                  if (! tmp)
                   1774:                    abort ();
                   1775:                  if (label_map[CODE_LABEL_NUMBER (tmp)] == XEXP (copy, 0))
                   1776:                    {
                   1777:                      /* Big win.  */
                   1778:                      return PREV_INSN (tmp);
                   1779:                    }
                   1780:                  else
                   1781:                    {
                   1782:                      /* Small win.  Emit the unconditional branch,
                   1783:                         followed by a BARRIER, so that jump optimization
                   1784:                         will know what to do.  */
                   1785:                      emit_jump (copy);
                   1786:                      return NEXT_INSN (insn);
                   1787:                    }
                   1788:                }
                   1789:              else if (copy == pc_rtx)
                   1790:                {
                   1791:                  /* Do not take the branch, just fall through.
                   1792:                     Jump optimize should handle the elimination of
                   1793:                     dead code if appropriate.  */
                   1794:                  return NEXT_INSN (insn);
                   1795:                }
                   1796:              else
                   1797:                abort ();
                   1798:            }
                   1799:        }
                   1800:     }
                   1801:   return 0;
                   1802: }
                   1803: 
                   1804: /* If (COND_RTX CNST1 CNST2) yield a result we can treat
                   1805:    as being constant, return THEN_RTX if the result is always
                   1806:    non-zero, and return ELSE_RTX otherwise.  */
                   1807: static rtx
                   1808: fold_out_const_cc0 (cond_rtx, then_rtx, else_rtx, cnst1, cnst2)
                   1809:      rtx cond_rtx, then_rtx, else_rtx;
                   1810:      rtx cnst1, cnst2;
                   1811: {
                   1812:   int value1, value2;
                   1813:   int int1 = GET_CODE (cnst1) == CONST_INT;
                   1814:   int int2 = GET_CODE (cnst2) == CONST_INT;
                   1815:   if (int1)
                   1816:     value1 = INTVAL (cnst1);
                   1817:   else
                   1818:     value1 = 1;
                   1819:   if (int2)
                   1820:     value2 = INTVAL (cnst2);
                   1821:   else
                   1822:     value2 = 1;
                   1823: 
                   1824:   switch (GET_CODE (cond_rtx))
                   1825:     {
                   1826:     case NE:
                   1827:       if (int1 && int2)
                   1828:        if (value1 != value2)
                   1829:          return copy_rtx_and_substitute (then_rtx);
                   1830:        else
                   1831:          return copy_rtx_and_substitute (else_rtx);
                   1832:       if (value1 == 0 || value2 == 0)
                   1833:        return copy_rtx_and_substitute (then_rtx);
                   1834:       if (int1 == 0 && int2 == 0)
                   1835:        if (rtx_equal_p (cnst1, cnst2))
                   1836:          return copy_rtx_and_substitute (else_rtx);
                   1837:       break;
                   1838:     case EQ:
                   1839:       if (int1 && int2)
                   1840:        if (value1 == value2)
                   1841:          return copy_rtx_and_substitute (then_rtx);
                   1842:        else
                   1843:          return copy_rtx_and_substitute (else_rtx);
                   1844:       if (value1 == 0 || value2 == 0)
                   1845:        return copy_rtx_and_substitute (else_rtx);
                   1846:       if (int1 == 0 && int2 == 0)
                   1847:        if (rtx_equal_p (cnst1, cnst2))
                   1848:          return copy_rtx_and_substitute (then_rtx);
                   1849:       break;
                   1850:     case GE:
                   1851:       if (int1 && int2)
                   1852:        if (value1 >= value2)
                   1853:          return copy_rtx_and_substitute (then_rtx);
                   1854:        else
                   1855:          return copy_rtx_and_substitute (else_rtx);
                   1856:       if (value1 == 0)
                   1857:        return copy_rtx_and_substitute (else_rtx);
                   1858:       if (value2 == 0)
                   1859:        return copy_rtx_and_substitute (then_rtx);
                   1860:       break;
                   1861:     case GT:
                   1862:       if (int1 && int2)
                   1863:        if (value1 > value2)
                   1864:          return copy_rtx_and_substitute (then_rtx);
                   1865:        else
                   1866:          return copy_rtx_and_substitute (else_rtx);
                   1867:       if (value1 == 0)
                   1868:        return copy_rtx_and_substitute (else_rtx);
                   1869:       if (value2 == 0)
                   1870:        return copy_rtx_and_substitute (then_rtx);
                   1871:       break;
                   1872:     case LE:
                   1873:       if (int1 && int2)
                   1874:        if (value1 <= value2)
                   1875:          return copy_rtx_and_substitute (then_rtx);
                   1876:        else
                   1877:          return copy_rtx_and_substitute (else_rtx);
                   1878:       if (value1 == 0)
                   1879:        return copy_rtx_and_substitute (then_rtx);
                   1880:       if (value2 == 0)
                   1881:        return copy_rtx_and_substitute (else_rtx);
                   1882:       break;
                   1883:     case LT:
                   1884:       if (int1 && int2)
                   1885:        if (value1 < value2)
                   1886:          return copy_rtx_and_substitute (then_rtx);
                   1887:        else
                   1888:          return copy_rtx_and_substitute (else_rtx);
                   1889:       if (value1 == 0)
                   1890:        return copy_rtx_and_substitute (then_rtx);
                   1891:       if (value2 == 0)
                   1892:        return copy_rtx_and_substitute (else_rtx);
                   1893:       break;
                   1894:     case GEU:
                   1895:       if (int1 && int2)
                   1896:        if ((unsigned)value1 >= (unsigned)value2)
                   1897:          return copy_rtx_and_substitute (then_rtx);
                   1898:        else
                   1899:          return copy_rtx_and_substitute (else_rtx);
                   1900:       if (value1 == 0)
                   1901:        return copy_rtx_and_substitute (else_rtx);
                   1902:       if (value2 == 0)
                   1903:        return copy_rtx_and_substitute (then_rtx);
                   1904:       break;
                   1905:     case GTU:
                   1906:       if (int1 && int2)
                   1907:        if ((unsigned)value1 > (unsigned)value2)
                   1908:          return copy_rtx_and_substitute (then_rtx);
                   1909:        else
                   1910:          return copy_rtx_and_substitute (else_rtx);
                   1911:       if (value1 == 0)
                   1912:        return copy_rtx_and_substitute (else_rtx);
                   1913:       if (value2 == 0)
                   1914:        return copy_rtx_and_substitute (then_rtx);
                   1915:       break;
                   1916:     case LEU:
                   1917:       if (int1 && int2)
                   1918:        if ((unsigned)value1 <= (unsigned)value2)
                   1919:          return copy_rtx_and_substitute (then_rtx);
                   1920:        else
                   1921:          return copy_rtx_and_substitute (else_rtx);
                   1922:       if (value1 == 0)
                   1923:        return copy_rtx_and_substitute (then_rtx);
                   1924:       if (value2 == 0)
                   1925:        return copy_rtx_and_substitute (else_rtx);
                   1926:       break;
                   1927:     case LTU:
                   1928:       if (int1 && int2)
                   1929:        if ((unsigned)value1 < (unsigned)value2)
                   1930:          return copy_rtx_and_substitute (then_rtx);
                   1931:        else
                   1932:          return copy_rtx_and_substitute (else_rtx);
                   1933:       if (value1 == 0)
                   1934:        return copy_rtx_and_substitute (then_rtx);
                   1935:       if (value2 == 0)
                   1936:        return copy_rtx_and_substitute (else_rtx);
                   1937:       break;
                   1938:     }
                   1939:   /* Could not hack it.  */
                   1940:   return 0;
                   1941: }
                   1942: 
                   1943: /* Output the assembly language code for the function FNDECL
                   1944:    from its DECL_SAVED_INSNS.  Used for inline functions that are output
                   1945:    at end of compilation instead of where they came in the source.  */
                   1946: 
                   1947: void
                   1948: output_inline_function (fndecl)
                   1949:      tree fndecl;
                   1950: {
                   1951:   rtx head = DECL_SAVED_INSNS (fndecl);
                   1952:   rtx last;
1.1.1.14! root     1953:   extern rtx stack_slot_list;
1.1       root     1954: 
                   1955:   temporary_allocation ();
                   1956: 
1.1.1.4   root     1957:   current_function_decl = fndecl;
                   1958: 
1.1.1.14! root     1959:   /* This call is only used to initialize global variables.  */
        !          1960:   init_function_start (fndecl);
1.1       root     1961: 
                   1962:   /* Set stack frame size.  */
                   1963:   assign_stack_local (BLKmode, DECL_FRAME_SIZE (fndecl));
                   1964: 
                   1965:   restore_reg_data (FIRST_PARM_INSN (head));
                   1966: 
1.1.1.14! root     1967:   stack_slot_list = XEXP (head, 9);
        !          1968: 
1.1.1.10  root     1969:   expand_function_end (DECL_SOURCE_FILE (fndecl), DECL_SOURCE_LINE (fndecl));
1.1       root     1970: 
                   1971:   for (last = head; NEXT_INSN (last); last = NEXT_INSN (last))
                   1972:     ;
                   1973: 
                   1974:   set_new_first_and_last_insn (FIRST_PARM_INSN (head), last);
                   1975: 
                   1976:   /* Compile this function all the way down to assembly code.  */
                   1977:   rest_of_compilation (fndecl);
                   1978: 
1.1.1.4   root     1979:   current_function_decl = 0;
                   1980: 
1.1       root     1981:   permanent_allocation ();
                   1982: }

unix.superglobalmegacorp.com

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