Annotation of gcc/integrate.c, revision 1.1.1.12

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

unix.superglobalmegacorp.com

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