Annotation of gcc/integrate.c, revision 1.1.1.19

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

unix.superglobalmegacorp.com

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