Annotation of GNUtools/cc/emit-rtl.c, revision 1.1

1.1     ! root        1: /* Emit RTL for the GNU C-Compiler expander.
        !             2:    Copyright (C) 1987, 1988, 1992, 1993 Free Software Foundation, Inc.
        !             3: 
        !             4: This file is part of GNU CC.
        !             5: 
        !             6: GNU CC is free software; you can redistribute it and/or modify
        !             7: it under the terms of the GNU General Public License as published by
        !             8: the Free Software Foundation; either version 2, or (at your option)
        !             9: any later version.
        !            10: 
        !            11: GNU CC is distributed in the hope that it will be useful,
        !            12: but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            14: GNU General Public License for more details.
        !            15: 
        !            16: You should have received a copy of the GNU General Public License
        !            17: along with GNU CC; see the file COPYING.  If not, write to
        !            18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
        !            19: 
        !            20: 
        !            21: /* Middle-to-low level generation of rtx code and insns.
        !            22: 
        !            23:    This file contains the functions `gen_rtx', `gen_reg_rtx'
        !            24:    and `gen_label_rtx' that are the usual ways of creating rtl
        !            25:    expressions for most purposes.
        !            26: 
        !            27:    It also has the functions for creating insns and linking
        !            28:    them in the doubly-linked chain.
        !            29: 
        !            30:    The patterns of the insns are created by machine-dependent
        !            31:    routines in insn-emit.c, which is generated automatically from
        !            32:    the machine description.  These routines use `gen_rtx' to make
        !            33:    the individual rtx's of the pattern; what is machine dependent
        !            34:    is the kind of rtx's they make and what arguments they use.  */
        !            35: 
        !            36: #include "config.h"
        !            37: #include "gvarargs.h"
        !            38: #include "rtl.h"
        !            39: #include "tree.h"
        !            40: #include "flags.h"
        !            41: #include "function.h"
        !            42: #include "expr.h"
        !            43: #include "regs.h"
        !            44: #include "insn-config.h"
        !            45: #include "real.h"
        !            46: #include "obstack.h"
        !            47: 
        !            48: #include "bytecode.h"
        !            49: #include "machmode.h"
        !            50: #include "bc-opcode.h"
        !            51: #include "bc-typecd.h"
        !            52: #include "bc-optab.h"
        !            53: #include "bc-emit.h"
        !            54: 
        !            55: #include <stdio.h>
        !            56: 
        !            57: 
        !            58: /* Opcode names */
        !            59: #ifdef BCDEBUG_PRINT_CODE
        !            60: char *opcode_name[] =
        !            61: {
        !            62: #include "bc-opname.h"
        !            63: 
        !            64: "***END***"
        !            65: };
        !            66: #endif
        !            67: 
        !            68: 
        !            69: /* Commonly used modes.  */
        !            70: 
        !            71: enum machine_mode byte_mode;   /* Mode whose width is BITS_PER_UNIT */
        !            72: enum machine_mode word_mode;   /* Mode whose width is BITS_PER_WORD */
        !            73: 
        !            74: /* This is reset to LAST_VIRTUAL_REGISTER + 1 at the start of each function.
        !            75:    After rtl generation, it is 1 plus the largest register number used.  */
        !            76: 
        !            77: int reg_rtx_no = LAST_VIRTUAL_REGISTER + 1;
        !            78: 
        !            79: /* This is *not* reset after each function.  It gives each CODE_LABEL
        !            80:    in the entire compilation a unique label number.  */
        !            81: 
        !            82: static int label_num = 1;
        !            83: 
        !            84: /* Lowest label number in current function.  */
        !            85: 
        !            86: static int first_label_num;
        !            87: 
        !            88: /* Highest label number in current function.
        !            89:    Zero means use the value of label_num instead.
        !            90:    This is nonzero only when belatedly compiling an inline function.  */
        !            91: 
        !            92: static int last_label_num;
        !            93: 
        !            94: /* Value label_num had when set_new_first_and_last_label_number was called.
        !            95:    If label_num has not changed since then, last_label_num is valid.  */
        !            96: 
        !            97: static int base_label_num;
        !            98: 
        !            99: /* Nonzero means do not generate NOTEs for source line numbers.  */
        !           100: 
        !           101: static int no_line_numbers;
        !           102: 
        !           103: /* Commonly used rtx's, so that we only need space for one copy.
        !           104:    These are initialized once for the entire compilation.
        !           105:    All of these except perhaps the floating-point CONST_DOUBLEs
        !           106:    are unique; no other rtx-object will be equal to any of these.  */
        !           107: 
        !           108: rtx pc_rtx;                    /* (PC) */
        !           109: rtx cc0_rtx;                   /* (CC0) */
        !           110: rtx cc1_rtx;                   /* (CC1) (not actually used nowadays) */
        !           111: rtx const0_rtx;                        /* (CONST_INT 0) */
        !           112: rtx const1_rtx;                        /* (CONST_INT 1) */
        !           113: rtx const2_rtx;                        /* (CONST_INT 2) */
        !           114: rtx constm1_rtx;               /* (CONST_INT -1) */
        !           115: rtx const_true_rtx;            /* (CONST_INT STORE_FLAG_VALUE) */
        !           116: 
        !           117: /* We record floating-point CONST_DOUBLEs in each floating-point mode for
        !           118:    the values of 0, 1, and 2.  For the integer entries and VOIDmode, we
        !           119:    record a copy of const[012]_rtx.  */
        !           120: 
        !           121: rtx const_tiny_rtx[3][(int) MAX_MACHINE_MODE];
        !           122: 
        !           123: REAL_VALUE_TYPE dconst0;
        !           124: REAL_VALUE_TYPE dconst1;
        !           125: REAL_VALUE_TYPE dconst2;
        !           126: REAL_VALUE_TYPE dconstm1;
        !           127: 
        !           128: /* All references to the following fixed hard registers go through
        !           129:    these unique rtl objects.  On machines where the frame-pointer and
        !           130:    arg-pointer are the same register, they use the same unique object.
        !           131: 
        !           132:    After register allocation, other rtl objects which used to be pseudo-regs
        !           133:    may be clobbered to refer to the frame-pointer register.
        !           134:    But references that were originally to the frame-pointer can be
        !           135:    distinguished from the others because they contain frame_pointer_rtx.
        !           136: 
        !           137:    When to use frame_pointer_rtx and hard_frame_pointer_rtx is a little
        !           138:    tricky: until register elimination has taken place hard_frame_pointer_rtx
        !           139:    should be used if it is being set, and frame_pointer_rtx otherwise.  After 
        !           140:    register elimination hard_frame_pointer_rtx should always be used.
        !           141:    On machines where the two registers are same (most) then these are the
        !           142:    same.
        !           143: 
        !           144:    In an inline procedure, the stack and frame pointer rtxs may not be
        !           145:    used for anything else.  */
        !           146: rtx stack_pointer_rtx;         /* (REG:Pmode STACK_POINTER_REGNUM) */
        !           147: rtx frame_pointer_rtx;         /* (REG:Pmode FRAME_POINTER_REGNUM) */
        !           148: rtx hard_frame_pointer_rtx;    /* (REG:Pmode HARD_FRAME_POINTER_REGNUM) */
        !           149: rtx arg_pointer_rtx;           /* (REG:Pmode ARG_POINTER_REGNUM) */
        !           150: rtx struct_value_rtx;          /* (REG:Pmode STRUCT_VALUE_REGNUM) */
        !           151: rtx struct_value_incoming_rtx; /* (REG:Pmode STRUCT_VALUE_INCOMING_REGNUM) */
        !           152: rtx static_chain_rtx;          /* (REG:Pmode STATIC_CHAIN_REGNUM) */
        !           153: rtx static_chain_incoming_rtx; /* (REG:Pmode STATIC_CHAIN_INCOMING_REGNUM) */
        !           154: rtx pic_offset_table_rtx;      /* (REG:Pmode PIC_OFFSET_TABLE_REGNUM) */
        !           155: 
        !           156: rtx virtual_incoming_args_rtx; /* (REG:Pmode VIRTUAL_INCOMING_ARGS_REGNUM) */
        !           157: rtx virtual_stack_vars_rtx;    /* (REG:Pmode VIRTUAL_STACK_VARS_REGNUM) */
        !           158: rtx virtual_stack_dynamic_rtx; /* (REG:Pmode VIRTUAL_STACK_DYNAMIC_REGNUM) */
        !           159: rtx virtual_outgoing_args_rtx; /* (REG:Pmode VIRTUAL_OUTGOING_ARGS_REGNUM) */
        !           160: 
        !           161: /* We make one copy of (const_int C) where C is in
        !           162:    [- MAX_SAVED_CONST_INT, MAX_SAVED_CONST_INT]
        !           163:    to save space during the compilation and simplify comparisons of
        !           164:    integers.  */
        !           165: 
        !           166: #define MAX_SAVED_CONST_INT 64
        !           167: 
        !           168: static rtx const_int_rtx[MAX_SAVED_CONST_INT * 2 + 1];
        !           169: 
        !           170: /* The ends of the doubly-linked chain of rtl for the current function.
        !           171:    Both are reset to null at the start of rtl generation for the function.
        !           172:    
        !           173:    start_sequence saves both of these on `sequence_stack' along with
        !           174:    `sequence_rtl_expr' and then starts a new, nested sequence of insns.  */
        !           175: 
        !           176: static rtx first_insn = NULL;
        !           177: static rtx last_insn = NULL;
        !           178: 
        !           179: /* RTL_EXPR within which the current sequence will be placed.  Use to
        !           180:    prevent reuse of any temporaries within the sequence until after the
        !           181:    RTL_EXPR is emitted.  */
        !           182: 
        !           183: tree sequence_rtl_expr = NULL;
        !           184: 
        !           185: /* INSN_UID for next insn emitted.
        !           186:    Reset to 1 for each function compiled.  */
        !           187: 
        !           188: static int cur_insn_uid = 1;
        !           189: 
        !           190: /* Line number and source file of the last line-number NOTE emitted.
        !           191:    This is used to avoid generating duplicates.  */
        !           192: 
        !           193: static int last_linenum = 0;
        !           194: static char *last_filename = 0;
        !           195: 
        !           196: /* A vector indexed by pseudo reg number.  The allocated length
        !           197:    of this vector is regno_pointer_flag_length.  Since this
        !           198:    vector is needed during the expansion phase when the total
        !           199:    number of registers in the function is not yet known,
        !           200:    it is copied and made bigger when necessary.  */
        !           201: 
        !           202: char *regno_pointer_flag;
        !           203: int regno_pointer_flag_length;
        !           204: 
        !           205: /* Indexed by pseudo register number, gives the rtx for that pseudo.
        !           206:    Allocated in parallel with regno_pointer_flag.  */
        !           207: 
        !           208: rtx *regno_reg_rtx;
        !           209: 
        !           210: /* Stack of pending (incomplete) sequences saved by `start_sequence'.
        !           211:    Each element describes one pending sequence.
        !           212:    The main insn-chain is saved in the last element of the chain,
        !           213:    unless the chain is empty.  */
        !           214: 
        !           215: struct sequence_stack *sequence_stack;
        !           216: 
        !           217: /* start_sequence and gen_sequence can make a lot of rtx expressions which are
        !           218:    shortly thrown away.  We use two mechanisms to prevent this waste:
        !           219: 
        !           220:    First, we keep a list of the expressions used to represent the sequence
        !           221:    stack in sequence_element_free_list.
        !           222: 
        !           223:    Second, for sizes up to 5 elements, we keep a SEQUENCE and its associated
        !           224:    rtvec for use by gen_sequence.  One entry for each size is sufficient
        !           225:    because most cases are calls to gen_sequence followed by immediately
        !           226:    emitting the SEQUENCE.  Reuse is safe since emitting a sequence is
        !           227:    destructive on the insn in it anyway and hence can't be redone.
        !           228: 
        !           229:    We do not bother to save this cached data over nested function calls.
        !           230:    Instead, we just reinitialize them.  */
        !           231: 
        !           232: #define SEQUENCE_RESULT_SIZE 5
        !           233: 
        !           234: static struct sequence_stack *sequence_element_free_list;
        !           235: static rtx sequence_result[SEQUENCE_RESULT_SIZE];
        !           236: 
        !           237: extern int rtx_equal_function_value_matters;
        !           238: 
        !           239: /* Filename and line number of last line-number note,
        !           240:    whether we actually emitted it or not.  */
        !           241: extern char *emit_filename;
        !           242: extern int emit_lineno;
        !           243: 
        !           244: rtx change_address ();
        !           245: void init_emit ();
        !           246: 
        !           247: extern struct obstack *rtl_obstack;
        !           248: 
        !           249: extern int stack_depth;
        !           250: extern int max_stack_depth;
        !           251: 
        !           252: /* rtx gen_rtx (code, mode, [element1, ..., elementn])
        !           253: **
        !           254: **         This routine generates an RTX of the size specified by
        !           255: **     <code>, which is an RTX code.   The RTX structure is initialized
        !           256: **     from the arguments <element1> through <elementn>, which are
        !           257: **     interpreted according to the specific RTX type's format.   The
        !           258: **     special machine mode associated with the rtx (if any) is specified
        !           259: **     in <mode>.
        !           260: **
        !           261: **         gen_rtx can be invoked in a way which resembles the lisp-like
        !           262: **     rtx it will generate.   For example, the following rtx structure:
        !           263: **
        !           264: **           (plus:QI (mem:QI (reg:SI 1))
        !           265: **                    (mem:QI (plusw:SI (reg:SI 2) (reg:SI 3))))
        !           266: **
        !           267: **             ...would be generated by the following C code:
        !           268: **
        !           269: **             gen_rtx (PLUS, QImode,
        !           270: **                 gen_rtx (MEM, QImode,
        !           271: **                     gen_rtx (REG, SImode, 1)),
        !           272: **                 gen_rtx (MEM, QImode,
        !           273: **                     gen_rtx (PLUS, SImode,
        !           274: **                         gen_rtx (REG, SImode, 2),
        !           275: **                         gen_rtx (REG, SImode, 3)))),
        !           276: */
        !           277: 
        !           278: /*VARARGS2*/
        !           279: rtx
        !           280: gen_rtx (va_alist)
        !           281:      va_dcl
        !           282: {
        !           283:   va_list p;
        !           284:   enum rtx_code code;
        !           285:   enum machine_mode mode;
        !           286:   register int i;              /* Array indices...                     */
        !           287:   register char *fmt;          /* Current rtx's format...              */
        !           288:   register rtx rt_val;         /* RTX to return to caller...           */
        !           289: 
        !           290:   va_start (p);
        !           291:   code = va_arg (p, enum rtx_code);
        !           292:   mode = va_arg (p, enum machine_mode);
        !           293: 
        !           294:   if (code == CONST_INT)
        !           295:     {
        !           296:       HOST_WIDE_INT arg = va_arg (p, HOST_WIDE_INT);
        !           297: 
        !           298:       if (arg >= - MAX_SAVED_CONST_INT && arg <= MAX_SAVED_CONST_INT)
        !           299:        return const_int_rtx[arg + MAX_SAVED_CONST_INT];
        !           300: 
        !           301:       if (const_true_rtx && arg == STORE_FLAG_VALUE)
        !           302:        return const_true_rtx;
        !           303: 
        !           304:       rt_val = rtx_alloc (code);
        !           305:       INTVAL (rt_val) = arg;
        !           306:     }
        !           307:   else if (code == REG)
        !           308:     {
        !           309:       int regno = va_arg (p, int);
        !           310: 
        !           311:       /* In case the MD file explicitly references the frame pointer, have
        !           312:         all such references point to the same frame pointer.  This is used
        !           313:         during frame pointer elimination to distinguish the explicit
        !           314:         references to these registers from pseudos that happened to be
        !           315:         assigned to them.
        !           316: 
        !           317:         If we have eliminated the frame pointer or arg pointer, we will
        !           318:         be using it as a normal register, for example as a spill register.
        !           319:         In such cases, we might be accessing it in a mode that is not
        !           320:         Pmode and therefore cannot use the pre-allocated rtx.
        !           321: 
        !           322:         Also don't do this when we are making new REGs in reload,
        !           323:         since we don't want to get confused with the real pointers.  */
        !           324: 
        !           325:       if (frame_pointer_rtx && regno == FRAME_POINTER_REGNUM && mode == Pmode
        !           326:          && ! reload_in_progress)
        !           327:        return frame_pointer_rtx;
        !           328: #if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
        !           329:       if (hard_frame_pointer_rtx && regno == HARD_FRAME_POINTER_REGNUM
        !           330:          && mode == Pmode && ! reload_in_progress)
        !           331:        return hard_frame_pointer_rtx;
        !           332: #endif
        !           333: #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM && HARD_FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
        !           334:       if (arg_pointer_rtx && regno == ARG_POINTER_REGNUM && mode == Pmode
        !           335:          && ! reload_in_progress)
        !           336:        return arg_pointer_rtx;
        !           337: #endif
        !           338:       if (stack_pointer_rtx && regno == STACK_POINTER_REGNUM && mode == Pmode
        !           339:          && ! reload_in_progress)
        !           340:        return stack_pointer_rtx;
        !           341:       else
        !           342:        {
        !           343:          rt_val = rtx_alloc (code);
        !           344:          rt_val->mode = mode;
        !           345:          REGNO (rt_val) = regno;
        !           346:          return rt_val;
        !           347:        }
        !           348:     }
        !           349:   else
        !           350:     {
        !           351:       rt_val = rtx_alloc (code);       /* Allocate the storage space.  */
        !           352:       rt_val->mode = mode;             /* Store the machine mode...  */
        !           353: 
        !           354:       fmt = GET_RTX_FORMAT (code);     /* Find the right format...  */
        !           355:       for (i = 0; i < GET_RTX_LENGTH (code); i++)
        !           356:        {
        !           357:          switch (*fmt++)
        !           358:            {
        !           359:            case '0':           /* Unused field.  */
        !           360:              break;
        !           361: 
        !           362:            case 'i':           /* An integer?  */
        !           363:              XINT (rt_val, i) = va_arg (p, int);
        !           364:              break;
        !           365: 
        !           366:            case 'w':           /* A wide integer? */
        !           367:              XWINT (rt_val, i) = va_arg (p, HOST_WIDE_INT);
        !           368:              break;
        !           369: 
        !           370:            case 's':           /* A string?  */
        !           371:              XSTR (rt_val, i) = va_arg (p, char *);
        !           372:              break;
        !           373: 
        !           374:            case 'e':           /* An expression?  */
        !           375:            case 'u':           /* An insn?  Same except when printing.  */
        !           376:              XEXP (rt_val, i) = va_arg (p, rtx);
        !           377:              break;
        !           378: 
        !           379:            case 'E':           /* An RTX vector?  */
        !           380:              XVEC (rt_val, i) = va_arg (p, rtvec);
        !           381:              break;
        !           382: 
        !           383:            default:
        !           384:              abort ();
        !           385:            }
        !           386:        }
        !           387:     }
        !           388:   va_end (p);
        !           389:   return rt_val;               /* Return the new RTX...                */
        !           390: }
        !           391: 
        !           392: /* gen_rtvec (n, [rt1, ..., rtn])
        !           393: **
        !           394: **         This routine creates an rtvec and stores within it the
        !           395: **     pointers to rtx's which are its arguments.
        !           396: */
        !           397: 
        !           398: /*VARARGS1*/
        !           399: rtvec
        !           400: gen_rtvec (va_alist)
        !           401:      va_dcl
        !           402: {
        !           403:   int n, i;
        !           404:   va_list p;
        !           405:   rtx *vector;
        !           406: 
        !           407:   va_start (p);
        !           408:   n = va_arg (p, int);
        !           409: 
        !           410:   if (n == 0)
        !           411:     return NULL_RTVEC;         /* Don't allocate an empty rtvec...     */
        !           412: 
        !           413:   vector = (rtx *) alloca (n * sizeof (rtx));
        !           414:   for (i = 0; i < n; i++)
        !           415:     vector[i] = va_arg (p, rtx);
        !           416:   va_end (p);
        !           417: 
        !           418:   return gen_rtvec_v (n, vector);
        !           419: }
        !           420: 
        !           421: rtvec
        !           422: gen_rtvec_v (n, argp)
        !           423:      int n;
        !           424:      rtx *argp;
        !           425: {
        !           426:   register int i;
        !           427:   register rtvec rt_val;
        !           428: 
        !           429:   if (n == 0)
        !           430:     return NULL_RTVEC;         /* Don't allocate an empty rtvec...     */
        !           431: 
        !           432:   rt_val = rtvec_alloc (n);    /* Allocate an rtvec...                 */
        !           433: 
        !           434:   for (i = 0; i < n; i++)
        !           435:     rt_val->elem[i].rtx = *argp++;
        !           436: 
        !           437:   return rt_val;
        !           438: }
        !           439: 
        !           440: /* Generate a REG rtx for a new pseudo register of mode MODE.
        !           441:    This pseudo is assigned the next sequential register number.  */
        !           442: 
        !           443: rtx
        !           444: gen_reg_rtx (mode)
        !           445:      enum machine_mode mode;
        !           446: {
        !           447:   register rtx val;
        !           448: 
        !           449:   /* Don't let anything called by or after reload create new registers
        !           450:      (actually, registers can't be created after flow, but this is a good
        !           451:      approximation).  */
        !           452: 
        !           453:   if (reload_in_progress || reload_completed)
        !           454:     abort ();
        !           455: 
        !           456:   if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
        !           457:       || GET_MODE_CLASS (mode) == MODE_COMPLEX_INT)
        !           458:     {
        !           459:       /* For complex modes, don't make a single pseudo.
        !           460:         Instead, make a CONCAT of two pseudos.
        !           461:         This allows noncontiguous allocation of the real and imaginary parts,
        !           462:         which makes much better code.  Besides, allocating DCmode
        !           463:         pseudos overstrains reload on some machines like the 386.  */
        !           464:       rtx realpart, imagpart;
        !           465:       int size = GET_MODE_UNIT_SIZE (mode);
        !           466:       enum machine_mode partmode
        !           467:        = mode_for_size (size * BITS_PER_UNIT,
        !           468:                         (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
        !           469:                          ? MODE_FLOAT : MODE_INT),
        !           470:                         0);
        !           471: 
        !           472:       realpart = gen_reg_rtx (partmode);
        !           473:       imagpart = gen_reg_rtx (partmode);
        !           474:       return gen_rtx (CONCAT, mode, realpart, imagpart);
        !           475:     }
        !           476: 
        !           477:   /* Make sure regno_pointer_flag and regno_reg_rtx are large
        !           478:      enough to have an element for this pseudo reg number.  */
        !           479: 
        !           480:   if (reg_rtx_no == regno_pointer_flag_length)
        !           481:     {
        !           482:       rtx *new1;
        !           483:       char *new =
        !           484:        (char *) oballoc (regno_pointer_flag_length * 2);
        !           485:       bzero (new, regno_pointer_flag_length * 2);
        !           486:       bcopy (regno_pointer_flag, new, regno_pointer_flag_length);
        !           487:       regno_pointer_flag = new;
        !           488: 
        !           489:       new1 = (rtx *) oballoc (regno_pointer_flag_length * 2 * sizeof (rtx));
        !           490:       bzero (new1, regno_pointer_flag_length * 2 * sizeof (rtx));
        !           491:       bcopy (regno_reg_rtx, new1, regno_pointer_flag_length * sizeof (rtx));
        !           492:       regno_reg_rtx = new1;
        !           493: 
        !           494:       regno_pointer_flag_length *= 2;
        !           495:     }
        !           496: 
        !           497:   val = gen_rtx (REG, mode, reg_rtx_no);
        !           498:   regno_reg_rtx[reg_rtx_no++] = val;
        !           499:   return val;
        !           500: }
        !           501: 
        !           502: /* Identify REG as a probable pointer register.  */
        !           503: 
        !           504: void
        !           505: mark_reg_pointer (reg)
        !           506:      rtx reg;
        !           507: {
        !           508:   REGNO_POINTER_FLAG (REGNO (reg)) = 1;
        !           509: }
        !           510: 
        !           511: /* Return 1 plus largest pseudo reg number used in the current function.  */
        !           512: 
        !           513: int
        !           514: max_reg_num ()
        !           515: {
        !           516:   return reg_rtx_no;
        !           517: }
        !           518: 
        !           519: /* Return 1 + the largest label number used so far in the current function.  */
        !           520: 
        !           521: int
        !           522: max_label_num ()
        !           523: {
        !           524:   if (last_label_num && label_num == base_label_num)
        !           525:     return last_label_num;
        !           526:   return label_num;
        !           527: }
        !           528: 
        !           529: /* Return first label number used in this function (if any were used).  */
        !           530: 
        !           531: int
        !           532: get_first_label_num ()
        !           533: {
        !           534:   return first_label_num;
        !           535: }
        !           536: 
        !           537: /* Return a value representing some low-order bits of X, where the number
        !           538:    of low-order bits is given by MODE.  Note that no conversion is done
        !           539:    between floating-point and fixed-point values, rather, the bit 
        !           540:    representation is returned.
        !           541: 
        !           542:    This function handles the cases in common between gen_lowpart, below,
        !           543:    and two variants in cse.c and combine.c.  These are the cases that can
        !           544:    be safely handled at all points in the compilation.
        !           545: 
        !           546:    If this is not a case we can handle, return 0.  */
        !           547: 
        !           548: rtx
        !           549: gen_lowpart_common (mode, x)
        !           550:      enum machine_mode mode;
        !           551:      register rtx x;
        !           552: {
        !           553:   int word = 0;
        !           554: 
        !           555:   if (GET_MODE (x) == mode)
        !           556:     return x;
        !           557: 
        !           558:   /* MODE must occupy no more words than the mode of X.  */
        !           559:   if (GET_MODE (x) != VOIDmode
        !           560:       && ((GET_MODE_SIZE (mode) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD
        !           561:          > ((GET_MODE_SIZE (GET_MODE (x)) + (UNITS_PER_WORD - 1))
        !           562:             / UNITS_PER_WORD)))
        !           563:     return 0;
        !           564: 
        !           565:   if (WORDS_BIG_ENDIAN && GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD)
        !           566:     word = ((GET_MODE_SIZE (GET_MODE (x))
        !           567:             - MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD))
        !           568:            / UNITS_PER_WORD);
        !           569: 
        !           570:   if ((GET_CODE (x) == ZERO_EXTEND || GET_CODE (x) == SIGN_EXTEND)
        !           571:       && (GET_MODE_CLASS (mode) == MODE_INT
        !           572:          || GET_MODE_CLASS (mode) == MODE_PARTIAL_INT))
        !           573:     {
        !           574:       /* If we are getting the low-order part of something that has been
        !           575:         sign- or zero-extended, we can either just use the object being
        !           576:         extended or make a narrower extension.  If we want an even smaller
        !           577:         piece than the size of the object being extended, call ourselves
        !           578:         recursively.
        !           579: 
        !           580:         This case is used mostly by combine and cse.  */
        !           581: 
        !           582:       if (GET_MODE (XEXP (x, 0)) == mode)
        !           583:        return XEXP (x, 0);
        !           584:       else if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (XEXP (x, 0))))
        !           585:        return gen_lowpart_common (mode, XEXP (x, 0));
        !           586:       else if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (x)))
        !           587:        return gen_rtx (GET_CODE (x), mode, XEXP (x, 0));
        !           588:     }
        !           589:   else if (GET_CODE (x) == SUBREG
        !           590:           && (GET_MODE_SIZE (mode) <= UNITS_PER_WORD
        !           591:               || GET_MODE_SIZE (mode) == GET_MODE_UNIT_SIZE (GET_MODE (x))))
        !           592:     return (GET_MODE (SUBREG_REG (x)) == mode && SUBREG_WORD (x) == 0
        !           593:            ? SUBREG_REG (x)
        !           594:            : gen_rtx (SUBREG, mode, SUBREG_REG (x), SUBREG_WORD (x)));
        !           595:   else if (GET_CODE (x) == REG)
        !           596:     {
        !           597:       /* If the register is not valid for MODE, return 0.  If we don't
        !           598:         do this, there is no way to fix up the resulting REG later.  
        !           599:         But we do do this if the current REG is not valid for its
        !           600:         mode.  This latter is a kludge, but is required due to the
        !           601:         way that parameters are passed on some machines, most
        !           602:         notably Sparc.  */
        !           603:       if (REGNO (x) < FIRST_PSEUDO_REGISTER
        !           604:          && ! HARD_REGNO_MODE_OK (REGNO (x) + word, mode)
        !           605:          && HARD_REGNO_MODE_OK (REGNO (x), GET_MODE (x)))
        !           606:        return 0;
        !           607:       else if (REGNO (x) < FIRST_PSEUDO_REGISTER
        !           608:               /* integrate.c can't handle parts of a return value register. */
        !           609:               && (! REG_FUNCTION_VALUE_P (x)
        !           610:                   || ! rtx_equal_function_value_matters)
        !           611:               /* We want to keep the stack, frame, and arg pointers
        !           612:                  special.  */
        !           613:               && REGNO (x) != FRAME_POINTER_REGNUM
        !           614: #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
        !           615:               && REGNO (x) != ARG_POINTER_REGNUM
        !           616: #endif
        !           617:               && REGNO (x) != STACK_POINTER_REGNUM)
        !           618:        return gen_rtx (REG, mode, REGNO (x) + word);
        !           619:       else
        !           620:        return gen_rtx (SUBREG, mode, x, word);
        !           621:     }
        !           622:   else if (GET_CODE (x) == CONCAT)
        !           623:     {
        !           624:       if (GET_MODE (XEXP (x, 0)) != mode)
        !           625:        abort ();
        !           626:       return XEXP (x, 0);
        !           627:     }
        !           628:   /* If X is a CONST_INT or a CONST_DOUBLE, extract the appropriate bits
        !           629:      from the low-order part of the constant.  */
        !           630:   else if ((GET_MODE_CLASS (mode) == MODE_INT
        !           631:            || GET_MODE_CLASS (mode) == MODE_PARTIAL_INT)
        !           632:           && GET_MODE (x) == VOIDmode
        !           633:           && (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE))
        !           634:     {
        !           635:       /* If MODE is twice the host word size, X is already the desired
        !           636:         representation.  Otherwise, if MODE is wider than a word, we can't
        !           637:         do this.  If MODE is exactly a word, return just one CONST_INT.
        !           638:         If MODE is smaller than a word, clear the bits that don't belong
        !           639:         in our mode, unless they and our sign bit are all one.  So we get
        !           640:         either a reasonable negative value or a reasonable unsigned value
        !           641:         for this mode.  */
        !           642: 
        !           643:       if (GET_MODE_BITSIZE (mode) == 2 * HOST_BITS_PER_WIDE_INT)
        !           644:        return x;
        !           645:       else if (GET_MODE_BITSIZE (mode) > HOST_BITS_PER_WIDE_INT)
        !           646:        return 0;
        !           647:       else if (GET_MODE_BITSIZE (mode) == HOST_BITS_PER_WIDE_INT)
        !           648:        return (GET_CODE (x) == CONST_INT ? x
        !           649:                : GEN_INT (CONST_DOUBLE_LOW (x)));
        !           650:       else
        !           651:        {
        !           652:          /* MODE must be narrower than HOST_BITS_PER_INT.  */
        !           653:          int width = GET_MODE_BITSIZE (mode);
        !           654:          HOST_WIDE_INT val = (GET_CODE (x) == CONST_INT ? INTVAL (x)
        !           655:                               : CONST_DOUBLE_LOW (x));
        !           656: 
        !           657:          if (((val & ((HOST_WIDE_INT) (-1) << (width - 1)))
        !           658:               != ((HOST_WIDE_INT) (-1) << (width - 1))))
        !           659:            val &= ((HOST_WIDE_INT) 1 << width) - 1;
        !           660: 
        !           661:          return (GET_CODE (x) == CONST_INT && INTVAL (x) == val ? x
        !           662:                  : GEN_INT (val));
        !           663:        }
        !           664:     }
        !           665: 
        !           666:   /* If X is an integral constant but we want it in floating-point, it
        !           667:      must be the case that we have a union of an integer and a floating-point
        !           668:      value.  If the machine-parameters allow it, simulate that union here
        !           669:      and return the result.  The two-word and single-word cases are 
        !           670:      different.  */
        !           671: 
        !           672:   else if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT
        !           673:             && HOST_BITS_PER_WIDE_INT == BITS_PER_WORD)
        !           674:            || flag_pretend_float)
        !           675:           && GET_MODE_CLASS (mode) == MODE_FLOAT
        !           676:           && GET_MODE_SIZE (mode) == UNITS_PER_WORD
        !           677:           && GET_CODE (x) == CONST_INT
        !           678:           && sizeof (float) * HOST_BITS_PER_CHAR == HOST_BITS_PER_WIDE_INT)
        !           679: #ifdef REAL_ARITHMETIC
        !           680:     {
        !           681:       REAL_VALUE_TYPE r;
        !           682:       HOST_WIDE_INT i;
        !           683: 
        !           684:       i = INTVAL (x);
        !           685:       r = REAL_VALUE_FROM_TARGET_SINGLE (i);
        !           686:       return immed_real_const_1 (r, mode);
        !           687:     }
        !           688: #else
        !           689:     {
        !           690:       union {HOST_WIDE_INT i; float d; } u;
        !           691: 
        !           692:       u.i = INTVAL (x);
        !           693:       return immed_real_const_1 (u.d, mode);
        !           694:     }
        !           695: #endif
        !           696:   else if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT
        !           697:             && HOST_BITS_PER_WIDE_INT == BITS_PER_WORD)
        !           698:            || flag_pretend_float)
        !           699:           && GET_MODE_CLASS (mode) == MODE_FLOAT
        !           700:           && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
        !           701:           && (GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST_DOUBLE)
        !           702:           && GET_MODE (x) == VOIDmode
        !           703:           && (sizeof (double) * HOST_BITS_PER_CHAR
        !           704:               == 2 * HOST_BITS_PER_WIDE_INT))
        !           705: #ifdef REAL_ARITHMETIC
        !           706:     {
        !           707:       REAL_VALUE_TYPE r;
        !           708:       HOST_WIDE_INT i[2];
        !           709:       HOST_WIDE_INT low, high;
        !           710: 
        !           711:       if (GET_CODE (x) == CONST_INT)
        !           712:        low = INTVAL (x), high = low >> (HOST_BITS_PER_WIDE_INT -1);
        !           713:       else
        !           714:        low = CONST_DOUBLE_LOW (x), high = CONST_DOUBLE_HIGH (x);
        !           715: 
        !           716: /* TARGET_DOUBLE takes the addressing order of the target machine. */
        !           717: #ifdef WORDS_BIG_ENDIAN
        !           718:       i[0] = high, i[1] = low;
        !           719: #else
        !           720:       i[0] = low, i[1] = high;
        !           721: #endif
        !           722: 
        !           723:       r = REAL_VALUE_FROM_TARGET_DOUBLE (i);
        !           724:       return immed_real_const_1 (r, mode);
        !           725:     }
        !           726: #else
        !           727:     {
        !           728:       union {HOST_WIDE_INT i[2]; double d; } u;
        !           729:       HOST_WIDE_INT low, high;
        !           730: 
        !           731:       if (GET_CODE (x) == CONST_INT)
        !           732:        low = INTVAL (x), high = low >> (HOST_BITS_PER_WIDE_INT -1);
        !           733:       else
        !           734:        low = CONST_DOUBLE_LOW (x), high = CONST_DOUBLE_HIGH (x);
        !           735: 
        !           736: #ifdef HOST_WORDS_BIG_ENDIAN
        !           737:       u.i[0] = high, u.i[1] = low;
        !           738: #else
        !           739:       u.i[0] = low, u.i[1] = high;
        !           740: #endif
        !           741: 
        !           742:       return immed_real_const_1 (u.d, mode);
        !           743:     }
        !           744: #endif
        !           745:   /* Similarly, if this is converting a floating-point value into a
        !           746:      single-word integer.  Only do this is the host and target parameters are
        !           747:      compatible.  */
        !           748: 
        !           749:   else if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT
        !           750:             && HOST_BITS_PER_WIDE_INT == BITS_PER_WORD)
        !           751:            || flag_pretend_float)
        !           752:           && (GET_MODE_CLASS (mode) == MODE_INT
        !           753:               || GET_MODE_CLASS (mode) == MODE_PARTIAL_INT)
        !           754:           && GET_CODE (x) == CONST_DOUBLE
        !           755:           && GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT
        !           756:           && GET_MODE_BITSIZE (mode) == BITS_PER_WORD)
        !           757:     return operand_subword (x, 0, 0, GET_MODE (x));
        !           758: 
        !           759:   /* Similarly, if this is converting a floating-point value into a
        !           760:      two-word integer, we can do this one word at a time and make an
        !           761:      integer.  Only do this is the host and target parameters are
        !           762:      compatible.  */
        !           763: 
        !           764:   else if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT
        !           765:             && HOST_BITS_PER_WIDE_INT == BITS_PER_WORD)
        !           766:            || flag_pretend_float)
        !           767:           && (GET_MODE_CLASS (mode) == MODE_INT
        !           768:               || GET_MODE_CLASS (mode) == MODE_PARTIAL_INT)
        !           769:           && GET_CODE (x) == CONST_DOUBLE
        !           770:           && GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT
        !           771:           && GET_MODE_BITSIZE (mode) == 2 * BITS_PER_WORD)
        !           772:     {
        !           773:       rtx lowpart = operand_subword (x, WORDS_BIG_ENDIAN, 0, GET_MODE (x));
        !           774:       rtx highpart = operand_subword (x, ! WORDS_BIG_ENDIAN, 0, GET_MODE (x));
        !           775: 
        !           776:       if (lowpart && GET_CODE (lowpart) == CONST_INT
        !           777:          && highpart && GET_CODE (highpart) == CONST_INT)
        !           778:        return immed_double_const (INTVAL (lowpart), INTVAL (highpart), mode);
        !           779:     }
        !           780: 
        !           781:   /* Otherwise, we can't do this.  */
        !           782:   return 0;
        !           783: }
        !           784: 
        !           785: /* Return the real part (which has mode MODE) of a complex value X.
        !           786:    This always comes at the low address in memory.  */
        !           787: 
        !           788: rtx
        !           789: gen_realpart (mode, x)
        !           790:      enum machine_mode mode;
        !           791:      register rtx x;
        !           792: {
        !           793:   if (WORDS_BIG_ENDIAN)
        !           794:     return gen_highpart (mode, x);
        !           795:   else
        !           796:     return gen_lowpart (mode, x);
        !           797: }
        !           798: 
        !           799: /* Return the imaginary part (which has mode MODE) of a complex value X.
        !           800:    This always comes at the high address in memory.  */
        !           801: 
        !           802: rtx
        !           803: gen_imagpart (mode, x)
        !           804:      enum machine_mode mode;
        !           805:      register rtx x;
        !           806: {
        !           807:   if (WORDS_BIG_ENDIAN)
        !           808:     return gen_lowpart (mode, x);
        !           809:   else
        !           810:     return gen_highpart (mode, x);
        !           811: }
        !           812: 
        !           813: /* Assuming that X is an rtx (e.g., MEM, REG or SUBREG) for a value,
        !           814:    return an rtx (MEM, SUBREG, or CONST_INT) that refers to the
        !           815:    least-significant part of X.
        !           816:    MODE specifies how big a part of X to return;
        !           817:    it usually should not be larger than a word.
        !           818:    If X is a MEM whose address is a QUEUED, the value may be so also.  */
        !           819: 
        !           820: rtx
        !           821: gen_lowpart (mode, x)
        !           822:      enum machine_mode mode;
        !           823:      register rtx x;
        !           824: {
        !           825:   rtx result = gen_lowpart_common (mode, x);
        !           826: 
        !           827:   if (result)
        !           828:     return result;
        !           829:   else if (GET_CODE (x) == MEM)
        !           830:     {
        !           831:       /* The only additional case we can do is MEM.  */
        !           832:       register int offset = 0;
        !           833:       if (WORDS_BIG_ENDIAN)
        !           834:        offset = (MAX (GET_MODE_SIZE (GET_MODE (x)), UNITS_PER_WORD)
        !           835:                  - MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD));
        !           836: 
        !           837:       if (BYTES_BIG_ENDIAN)
        !           838:        /* Adjust the address so that the address-after-the-data
        !           839:           is unchanged.  */
        !           840:        offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (mode))
        !           841:                   - MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (x))));
        !           842: 
        !           843:       return change_address (x, mode, plus_constant (XEXP (x, 0), offset));
        !           844:     }
        !           845:   else
        !           846:     abort ();
        !           847: }
        !           848: 
        !           849: /* Like `gen_lowpart', but refer to the most significant part. 
        !           850:    This is used to access the imaginary part of a complex number.  */
        !           851: 
        !           852: rtx
        !           853: gen_highpart (mode, x)
        !           854:      enum machine_mode mode;
        !           855:      register rtx x;
        !           856: {
        !           857:   /* This case loses if X is a subreg.  To catch bugs early,
        !           858:      complain if an invalid MODE is used even in other cases.  */
        !           859:   if (GET_MODE_SIZE (mode) > UNITS_PER_WORD
        !           860:       && GET_MODE_SIZE (mode) != GET_MODE_UNIT_SIZE (GET_MODE (x)))
        !           861:     abort ();
        !           862:   if (GET_CODE (x) == CONST_DOUBLE
        !           863: #if !(TARGET_FLOAT_FORMAT != HOST_FLOAT_FORMAT || defined (REAL_IS_NOT_DOUBLE))
        !           864:       && GET_MODE_CLASS (GET_MODE (x)) != MODE_FLOAT
        !           865: #endif
        !           866:       )
        !           867:     return gen_rtx (CONST_INT, VOIDmode,
        !           868:                    CONST_DOUBLE_HIGH (x) & GET_MODE_MASK (mode));
        !           869:   else if (GET_CODE (x) == CONST_INT)
        !           870:     return const0_rtx;
        !           871:   else if (GET_CODE (x) == MEM)
        !           872:     {
        !           873:       register int offset = 0;
        !           874: #if !WORDS_BIG_ENDIAN
        !           875:       offset = (MAX (GET_MODE_SIZE (GET_MODE (x)), UNITS_PER_WORD)
        !           876:                - MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD));
        !           877: #endif
        !           878: #if !BYTES_BIG_ENDIAN
        !           879:       if (GET_MODE_SIZE (mode) < UNITS_PER_WORD)
        !           880:        offset -= (GET_MODE_SIZE (mode)
        !           881:                   - MIN (UNITS_PER_WORD,
        !           882:                          GET_MODE_SIZE (GET_MODE (x))));
        !           883: #endif
        !           884:       return change_address (x, mode, plus_constant (XEXP (x, 0), offset));
        !           885:     }
        !           886:   else if (GET_CODE (x) == SUBREG)
        !           887:     {
        !           888:       /* The only time this should occur is when we are looking at a
        !           889:         multi-word item with a SUBREG whose mode is the same as that of the
        !           890:         item.  It isn't clear what we would do if it wasn't.  */
        !           891:       if (SUBREG_WORD (x) != 0)
        !           892:        abort ();
        !           893:       return gen_highpart (mode, SUBREG_REG (x));
        !           894:     }
        !           895:   else if (GET_CODE (x) == REG)
        !           896:     {
        !           897:       int word = 0;
        !           898: 
        !           899: #if !WORDS_BIG_ENDIAN
        !           900:       if (GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD)
        !           901:        word = ((GET_MODE_SIZE (GET_MODE (x))
        !           902:                 - MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD))
        !           903:                / UNITS_PER_WORD);
        !           904: #endif
        !           905:       if (REGNO (x) < FIRST_PSEUDO_REGISTER
        !           906:          /* integrate.c can't handle parts of a return value register. */
        !           907:          && (! REG_FUNCTION_VALUE_P (x)
        !           908:              || ! rtx_equal_function_value_matters)
        !           909:          /* We want to keep the stack, frame, and arg pointers special.  */
        !           910:          && REGNO (x) != FRAME_POINTER_REGNUM
        !           911: #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
        !           912:          && REGNO (x) != ARG_POINTER_REGNUM
        !           913: #endif
        !           914:          && REGNO (x) != STACK_POINTER_REGNUM)
        !           915:        return gen_rtx (REG, mode, REGNO (x) + word);
        !           916:       else
        !           917:        return gen_rtx (SUBREG, mode, x, word);
        !           918:     }
        !           919:   else if (GET_CODE (x) == CONCAT)
        !           920:     {
        !           921:       if (GET_MODE (XEXP (x, 1)) != mode)
        !           922:        abort ();
        !           923:       return XEXP (x, 1);
        !           924:     }
        !           925:   else
        !           926:     abort ();
        !           927: }
        !           928: 
        !           929: /* Return 1 iff X, assumed to be a SUBREG,
        !           930:    refers to the least significant part of its containing reg.
        !           931:    If X is not a SUBREG, always return 1 (it is its own low part!).  */
        !           932: 
        !           933: int
        !           934: subreg_lowpart_p (x)
        !           935:      rtx x;
        !           936: {
        !           937:   if (GET_CODE (x) != SUBREG)
        !           938:     return 1;
        !           939: 
        !           940:   if (WORDS_BIG_ENDIAN
        !           941:       && GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))) > UNITS_PER_WORD)
        !           942:     return (SUBREG_WORD (x)
        !           943:            == ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))
        !           944:                 - MAX (GET_MODE_SIZE (GET_MODE (x)), UNITS_PER_WORD))
        !           945:                / UNITS_PER_WORD));
        !           946: 
        !           947:   return SUBREG_WORD (x) == 0;
        !           948: }
        !           949: 
        !           950: /* Return subword I of operand OP.
        !           951:    The word number, I, is interpreted as the word number starting at the
        !           952:    low-order address.  Word 0 is the low-order word if not WORDS_BIG_ENDIAN,
        !           953:    otherwise it is the high-order word.
        !           954: 
        !           955:    If we cannot extract the required word, we return zero.  Otherwise, an
        !           956:    rtx corresponding to the requested word will be returned.
        !           957: 
        !           958:    VALIDATE_ADDRESS is nonzero if the address should be validated.  Before
        !           959:    reload has completed, a valid address will always be returned.  After
        !           960:    reload, if a valid address cannot be returned, we return zero.
        !           961: 
        !           962:    If VALIDATE_ADDRESS is zero, we simply form the required address; validating
        !           963:    it is the responsibility of the caller.
        !           964: 
        !           965:    MODE is the mode of OP in case it is a CONST_INT.  */
        !           966: 
        !           967: rtx
        !           968: operand_subword (op, i, validate_address, mode)
        !           969:      rtx op;
        !           970:      int i;
        !           971:      int validate_address;
        !           972:      enum machine_mode mode;
        !           973: {
        !           974:   HOST_WIDE_INT val;
        !           975:   int size_ratio = HOST_BITS_PER_WIDE_INT / BITS_PER_WORD;
        !           976: 
        !           977:   if (mode == VOIDmode)
        !           978:     mode = GET_MODE (op);
        !           979: 
        !           980:   if (mode == VOIDmode)
        !           981:     abort ();
        !           982: 
        !           983:   /* If OP is narrower than a word or if we want a word outside OP, fail.  */
        !           984:   if (mode != BLKmode
        !           985:       && (GET_MODE_SIZE (mode) < UNITS_PER_WORD
        !           986:          || (i + 1) * UNITS_PER_WORD > GET_MODE_SIZE (mode)))
        !           987:     return 0;
        !           988: 
        !           989:   /* If OP is already an integer word, return it.  */
        !           990:   if (GET_MODE_CLASS (mode) == MODE_INT
        !           991:       && GET_MODE_SIZE (mode) == UNITS_PER_WORD)
        !           992:     return op;
        !           993: 
        !           994:   /* If OP is a REG or SUBREG, we can handle it very simply.  */
        !           995:   if (GET_CODE (op) == REG)
        !           996:     {
        !           997:       /* If the register is not valid for MODE, return 0.  If we don't
        !           998:         do this, there is no way to fix up the resulting REG later.  */
        !           999:       if (REGNO (op) < FIRST_PSEUDO_REGISTER
        !          1000:          && ! HARD_REGNO_MODE_OK (REGNO (op) + i, word_mode))
        !          1001:        return 0;
        !          1002:       else if (REGNO (op) >= FIRST_PSEUDO_REGISTER
        !          1003:               || (REG_FUNCTION_VALUE_P (op)
        !          1004:                   && rtx_equal_function_value_matters)
        !          1005:               /* We want to keep the stack, frame, and arg pointers
        !          1006:                  special.  */
        !          1007:               || REGNO (op) == FRAME_POINTER_REGNUM
        !          1008: #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
        !          1009:               || REGNO (op) == ARG_POINTER_REGNUM
        !          1010: #endif
        !          1011:               || REGNO (op) == STACK_POINTER_REGNUM)
        !          1012:        return gen_rtx (SUBREG, word_mode, op, i);
        !          1013:       else
        !          1014:        return gen_rtx (REG, word_mode, REGNO (op) + i);
        !          1015:     }
        !          1016:   else if (GET_CODE (op) == SUBREG)
        !          1017:     return gen_rtx (SUBREG, word_mode, SUBREG_REG (op), i + SUBREG_WORD (op));
        !          1018:   else if (GET_CODE (op) == CONCAT)
        !          1019:     {
        !          1020:       int partwords = GET_MODE_UNIT_SIZE (GET_MODE (op)) / UNITS_PER_WORD;
        !          1021:       if (i < partwords)
        !          1022:        return operand_subword (XEXP (op, 0), i, validate_address, mode);
        !          1023:       return operand_subword (XEXP (op, 1), i - partwords,
        !          1024:                              validate_address, mode);
        !          1025:     }
        !          1026: 
        !          1027:   /* Form a new MEM at the requested address.  */
        !          1028:   if (GET_CODE (op) == MEM)
        !          1029:     {
        !          1030:       rtx addr = plus_constant (XEXP (op, 0), i * UNITS_PER_WORD);
        !          1031:       rtx new;
        !          1032: 
        !          1033:       if (validate_address)
        !          1034:        {
        !          1035:          if (reload_completed)
        !          1036:            {
        !          1037:              if (! strict_memory_address_p (word_mode, addr))
        !          1038:                return 0;
        !          1039:            }
        !          1040:          else
        !          1041:            addr = memory_address (word_mode, addr);
        !          1042:        }
        !          1043: 
        !          1044:       new = gen_rtx (MEM, word_mode, addr);
        !          1045: 
        !          1046:       MEM_VOLATILE_P (new) = MEM_VOLATILE_P (op);
        !          1047:       MEM_IN_STRUCT_P (new) = MEM_IN_STRUCT_P (op);
        !          1048:       RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (op);
        !          1049: 
        !          1050:       return new;
        !          1051:     }
        !          1052: 
        !          1053:   /* The only remaining cases are when OP is a constant.  If the host and
        !          1054:      target floating formats are the same, handling two-word floating
        !          1055:      constants are easy.  Note that REAL_VALUE_TO_TARGET_{SINGLE,DOUBLE}
        !          1056:      are defined as returning 32 bit and 64-bit values, respectively,
        !          1057:      and not values of BITS_PER_WORD and 2 * BITS_PER_WORD bits.  */
        !          1058: #ifdef REAL_ARITHMETIC
        !          1059:   if ((HOST_BITS_PER_WIDE_INT == BITS_PER_WORD)
        !          1060:       && GET_MODE_CLASS (mode) == MODE_FLOAT
        !          1061:       && GET_MODE_BITSIZE (mode) == 64
        !          1062:       && GET_CODE (op) == CONST_DOUBLE)
        !          1063:     {
        !          1064:       HOST_WIDE_INT k[2];
        !          1065:       REAL_VALUE_TYPE rv;
        !          1066: 
        !          1067:       REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
        !          1068:       REAL_VALUE_TO_TARGET_DOUBLE (rv, k);
        !          1069: 
        !          1070:       /* We handle 32-bit and 64-bit host words here.  Note that the order in
        !          1071:         which the words are written depends on the word endianness.
        !          1072: 
        !          1073:         ??? This is a potential portability problem and should
        !          1074:         be fixed at some point.  */
        !          1075:       if (HOST_BITS_PER_WIDE_INT == 32)
        !          1076:        return GEN_INT (k[i]);
        !          1077:       else if (HOST_BITS_PER_WIDE_INT == 64 && i == 0)
        !          1078:        return GEN_INT ((k[! WORDS_BIG_ENDIAN] << (HOST_BITS_PER_WIDE_INT / 2))
        !          1079:                        | k[WORDS_BIG_ENDIAN]);
        !          1080:       else
        !          1081:        abort ();
        !          1082:     }
        !          1083: #else /* no REAL_ARITHMETIC */
        !          1084:   if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT
        !          1085:        && HOST_BITS_PER_WIDE_INT == BITS_PER_WORD)
        !          1086:        || flag_pretend_float)
        !          1087:       && GET_MODE_CLASS (mode) == MODE_FLOAT
        !          1088:       && GET_MODE_SIZE (mode) == 2 * UNITS_PER_WORD
        !          1089:       && GET_CODE (op) == CONST_DOUBLE)
        !          1090:     {
        !          1091:       /* The constant is stored in the host's word-ordering,
        !          1092:         but we want to access it in the target's word-ordering.  Some
        !          1093:         compilers don't like a conditional inside macro args, so we have two
        !          1094:         copies of the return.  */
        !          1095: #ifdef HOST_WORDS_BIG_ENDIAN
        !          1096:       return GEN_INT (i == WORDS_BIG_ENDIAN
        !          1097:                      ? CONST_DOUBLE_HIGH (op) : CONST_DOUBLE_LOW (op));
        !          1098: #else
        !          1099:       return GEN_INT (i != WORDS_BIG_ENDIAN
        !          1100:                      ? CONST_DOUBLE_HIGH (op) : CONST_DOUBLE_LOW (op));
        !          1101: #endif
        !          1102:     }
        !          1103: #endif /* no REAL_ARITHMETIC */
        !          1104: 
        !          1105:   /* Single word float is a little harder, since single- and double-word
        !          1106:      values often do not have the same high-order bits.  We have already
        !          1107:      verified that we want the only defined word of the single-word value.  */
        !          1108: #ifdef REAL_ARITHMETIC
        !          1109:   if ((HOST_BITS_PER_WIDE_INT == BITS_PER_WORD)
        !          1110:       && GET_MODE_CLASS (mode) == MODE_FLOAT
        !          1111:       && GET_MODE_BITSIZE (mode) == 32
        !          1112:       && GET_CODE (op) == CONST_DOUBLE)
        !          1113:     {
        !          1114:       HOST_WIDE_INT l;
        !          1115:       REAL_VALUE_TYPE rv;
        !          1116: 
        !          1117:       REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
        !          1118:       REAL_VALUE_TO_TARGET_SINGLE (rv, l);
        !          1119:       return GEN_INT (l);
        !          1120:     }
        !          1121: #else
        !          1122:   if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT
        !          1123:        && HOST_BITS_PER_WIDE_INT == BITS_PER_WORD)
        !          1124:        || flag_pretend_float)
        !          1125:       && GET_MODE_CLASS (mode) == MODE_FLOAT
        !          1126:       && GET_MODE_SIZE (mode) == UNITS_PER_WORD
        !          1127:       && GET_CODE (op) == CONST_DOUBLE)
        !          1128:     {
        !          1129:       double d;
        !          1130:       union {float f; HOST_WIDE_INT i; } u;
        !          1131: 
        !          1132:       REAL_VALUE_FROM_CONST_DOUBLE (d, op);
        !          1133: 
        !          1134:       u.f = d;
        !          1135:       return GEN_INT (u.i);
        !          1136:     }
        !          1137: #endif /* no REAL_ARITHMETIC */
        !          1138:       
        !          1139:   /* The only remaining cases that we can handle are integers.
        !          1140:      Convert to proper endianness now since these cases need it.
        !          1141:      At this point, i == 0 means the low-order word.  
        !          1142: 
        !          1143:      We do not want to handle the case when BITS_PER_WORD <= HOST_BITS_PER_INT
        !          1144:      in general.  However, if OP is (const_int 0), we can just return
        !          1145:      it for any word.  */
        !          1146: 
        !          1147:   if (op == const0_rtx)
        !          1148:     return op;
        !          1149: 
        !          1150:   if (GET_MODE_CLASS (mode) != MODE_INT
        !          1151:       || (GET_CODE (op) != CONST_INT && GET_CODE (op) != CONST_DOUBLE)
        !          1152:       || BITS_PER_WORD > HOST_BITS_PER_INT)
        !          1153:     return 0;
        !          1154: 
        !          1155:   if (WORDS_BIG_ENDIAN)
        !          1156:     i = GET_MODE_SIZE (mode) / UNITS_PER_WORD - 1 - i;
        !          1157: 
        !          1158:   /* Find out which word on the host machine this value is in and get
        !          1159:      it from the constant.  */
        !          1160:   val = (i / size_ratio == 0
        !          1161:         ? (GET_CODE (op) == CONST_INT ? INTVAL (op) : CONST_DOUBLE_LOW (op))
        !          1162:         : (GET_CODE (op) == CONST_INT
        !          1163:            ? (INTVAL (op) < 0 ? ~0 : 0) : CONST_DOUBLE_HIGH (op)));
        !          1164: 
        !          1165:   /* If BITS_PER_WORD is smaller than an int, get the appropriate bits.  */
        !          1166:   if (BITS_PER_WORD < HOST_BITS_PER_WIDE_INT)
        !          1167:     val = ((val >> ((i % size_ratio) * BITS_PER_WORD))
        !          1168:           & (((HOST_WIDE_INT) 1
        !          1169:               << (BITS_PER_WORD % HOST_BITS_PER_WIDE_INT)) - 1));
        !          1170: 
        !          1171:   return GEN_INT (val);
        !          1172: }
        !          1173: 
        !          1174: /* Similar to `operand_subword', but never return 0.  If we can't extract
        !          1175:    the required subword, put OP into a register and try again.  If that fails,
        !          1176:    abort.  We always validate the address in this case.  It is not valid
        !          1177:    to call this function after reload; it is mostly meant for RTL
        !          1178:    generation. 
        !          1179: 
        !          1180:    MODE is the mode of OP, in case it is CONST_INT.  */
        !          1181: 
        !          1182: rtx
        !          1183: operand_subword_force (op, i, mode)
        !          1184:      rtx op;
        !          1185:      int i;
        !          1186:      enum machine_mode mode;
        !          1187: {
        !          1188:   rtx result = operand_subword (op, i, 1, mode);
        !          1189: 
        !          1190:   if (result)
        !          1191:     return result;
        !          1192: 
        !          1193:   if (mode != BLKmode && mode != VOIDmode)
        !          1194:     op = force_reg (mode, op);
        !          1195: 
        !          1196:   result = operand_subword (op, i, 1, mode);
        !          1197:   if (result == 0)
        !          1198:     abort ();
        !          1199: 
        !          1200:   return result;
        !          1201: }
        !          1202: 
        !          1203: /* Given a compare instruction, swap the operands.
        !          1204:    A test instruction is changed into a compare of 0 against the operand.  */
        !          1205: 
        !          1206: void
        !          1207: reverse_comparison (insn)
        !          1208:      rtx insn;
        !          1209: {
        !          1210:   rtx body = PATTERN (insn);
        !          1211:   rtx comp;
        !          1212: 
        !          1213:   if (GET_CODE (body) == SET)
        !          1214:     comp = SET_SRC (body);
        !          1215:   else
        !          1216:     comp = SET_SRC (XVECEXP (body, 0, 0));
        !          1217: 
        !          1218:   if (GET_CODE (comp) == COMPARE)
        !          1219:     {
        !          1220:       rtx op0 = XEXP (comp, 0);
        !          1221:       rtx op1 = XEXP (comp, 1);
        !          1222:       XEXP (comp, 0) = op1;
        !          1223:       XEXP (comp, 1) = op0;
        !          1224:     }
        !          1225:   else
        !          1226:     {
        !          1227:       rtx new = gen_rtx (COMPARE, VOIDmode,
        !          1228:                         CONST0_RTX (GET_MODE (comp)), comp);
        !          1229:       if (GET_CODE (body) == SET)
        !          1230:        SET_SRC (body) = new;
        !          1231:       else
        !          1232:        SET_SRC (XVECEXP (body, 0, 0)) = new;
        !          1233:     }
        !          1234: }
        !          1235: 
        !          1236: /* Return a memory reference like MEMREF, but with its mode changed
        !          1237:    to MODE and its address changed to ADDR.
        !          1238:    (VOIDmode means don't change the mode.
        !          1239:    NULL for ADDR means don't change the address.)  */
        !          1240: 
        !          1241: rtx
        !          1242: change_address (memref, mode, addr)
        !          1243:      rtx memref;
        !          1244:      enum machine_mode mode;
        !          1245:      rtx addr;
        !          1246: {
        !          1247:   rtx new;
        !          1248: 
        !          1249:   if (GET_CODE (memref) != MEM)
        !          1250:     abort ();
        !          1251:   if (mode == VOIDmode)
        !          1252:     mode = GET_MODE (memref);
        !          1253:   if (addr == 0)
        !          1254:     addr = XEXP (memref, 0);
        !          1255: 
        !          1256:   /* If reload is in progress or has completed, ADDR must be valid.
        !          1257:      Otherwise, we can call memory_address to make it valid.  */
        !          1258:   if (reload_completed || reload_in_progress)
        !          1259:     {
        !          1260:       if (! memory_address_p (mode, addr))
        !          1261:        abort ();
        !          1262:     }
        !          1263:   else
        !          1264:     addr = memory_address (mode, addr);
        !          1265:        
        !          1266:   new = gen_rtx (MEM, mode, addr);
        !          1267:   MEM_VOLATILE_P (new) = MEM_VOLATILE_P (memref);
        !          1268:   RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (memref);
        !          1269:   MEM_IN_STRUCT_P (new) = MEM_IN_STRUCT_P (memref);
        !          1270:   return new;
        !          1271: }
        !          1272: 
        !          1273: /* Return a newly created CODE_LABEL rtx with a unique label number.  */
        !          1274: 
        !          1275: rtx
        !          1276: gen_label_rtx ()
        !          1277: {
        !          1278:   register rtx label;
        !          1279: 
        !          1280:   label = (output_bytecode
        !          1281:           ? gen_rtx (CODE_LABEL, VOIDmode, NULL, bc_get_bytecode_label ())
        !          1282:           : gen_rtx (CODE_LABEL, VOIDmode, 0, 0, 0, label_num++, NULL_PTR));
        !          1283: 
        !          1284:   LABEL_NUSES (label) = 0;
        !          1285:   return label;
        !          1286: }
        !          1287: 
        !          1288: /* For procedure integration.  */
        !          1289: 
        !          1290: /* Return a newly created INLINE_HEADER rtx.  Should allocate this
        !          1291:    from a permanent obstack when the opportunity arises.  */
        !          1292: 
        !          1293: rtx
        !          1294: gen_inline_header_rtx (first_insn, first_parm_insn, first_labelno,
        !          1295:                       last_labelno, max_parm_regnum, max_regnum, args_size,
        !          1296:                       pops_args, stack_slots, function_flags,
        !          1297:                       outgoing_args_size, original_arg_vector,
        !          1298:                       original_decl_initial)
        !          1299:      rtx first_insn, first_parm_insn;
        !          1300:      int first_labelno, last_labelno, max_parm_regnum, max_regnum, args_size;
        !          1301:      int pops_args;
        !          1302:      rtx stack_slots;
        !          1303:      int function_flags;
        !          1304:      int outgoing_args_size;
        !          1305:      rtvec original_arg_vector;
        !          1306:      rtx original_decl_initial;
        !          1307: {
        !          1308:   rtx header = gen_rtx (INLINE_HEADER, VOIDmode,
        !          1309:                        cur_insn_uid++, NULL_RTX,
        !          1310:                        first_insn, first_parm_insn,
        !          1311:                        first_labelno, last_labelno,
        !          1312:                        max_parm_regnum, max_regnum, args_size, pops_args,
        !          1313:                        stack_slots, function_flags, outgoing_args_size,
        !          1314:                        original_arg_vector, original_decl_initial);
        !          1315:   return header;
        !          1316: }
        !          1317: 
        !          1318: /* Install new pointers to the first and last insns in the chain.
        !          1319:    Used for an inline-procedure after copying the insn chain.  */
        !          1320: 
        !          1321: void
        !          1322: set_new_first_and_last_insn (first, last)
        !          1323:      rtx first, last;
        !          1324: {
        !          1325:   first_insn = first;
        !          1326:   last_insn = last;
        !          1327: }
        !          1328: 
        !          1329: /* Set the range of label numbers found in the current function.
        !          1330:    This is used when belatedly compiling an inline function.  */
        !          1331: 
        !          1332: void
        !          1333: set_new_first_and_last_label_num (first, last)
        !          1334:      int first, last;
        !          1335: {
        !          1336:   base_label_num = label_num;
        !          1337:   first_label_num = first;
        !          1338:   last_label_num = last;
        !          1339: }
        !          1340: 
        !          1341: /* Save all variables describing the current status into the structure *P.
        !          1342:    This is used before starting a nested function.  */
        !          1343: 
        !          1344: void
        !          1345: save_emit_status (p)
        !          1346:      struct function *p;
        !          1347: {
        !          1348:   p->reg_rtx_no = reg_rtx_no;
        !          1349:   p->first_label_num = first_label_num;
        !          1350:   p->first_insn = first_insn;
        !          1351:   p->last_insn = last_insn;
        !          1352:   p->sequence_rtl_expr = sequence_rtl_expr;
        !          1353:   p->sequence_stack = sequence_stack;
        !          1354:   p->cur_insn_uid = cur_insn_uid;
        !          1355:   p->last_linenum = last_linenum;
        !          1356:   p->last_filename = last_filename;
        !          1357:   p->regno_pointer_flag = regno_pointer_flag;
        !          1358:   p->regno_pointer_flag_length = regno_pointer_flag_length;
        !          1359:   p->regno_reg_rtx = regno_reg_rtx;
        !          1360: }
        !          1361: 
        !          1362: /* Restore all variables describing the current status from the structure *P.
        !          1363:    This is used after a nested function.  */
        !          1364: 
        !          1365: void
        !          1366: restore_emit_status (p)
        !          1367:      struct function *p;
        !          1368: {
        !          1369:   int i;
        !          1370: 
        !          1371:   reg_rtx_no = p->reg_rtx_no;
        !          1372:   first_label_num = p->first_label_num;
        !          1373:   last_label_num = 0;
        !          1374:   first_insn = p->first_insn;
        !          1375:   last_insn = p->last_insn;
        !          1376:   sequence_rtl_expr = p->sequence_rtl_expr;
        !          1377:   sequence_stack = p->sequence_stack;
        !          1378:   cur_insn_uid = p->cur_insn_uid;
        !          1379:   last_linenum = p->last_linenum;
        !          1380:   last_filename = p->last_filename;
        !          1381:   regno_pointer_flag = p->regno_pointer_flag;
        !          1382:   regno_pointer_flag_length = p->regno_pointer_flag_length;
        !          1383:   regno_reg_rtx = p->regno_reg_rtx;
        !          1384: 
        !          1385:   /* Clear our cache of rtx expressions for start_sequence and gen_sequence. */
        !          1386:   sequence_element_free_list = 0;
        !          1387:   for (i = 0; i < SEQUENCE_RESULT_SIZE; i++)
        !          1388:     sequence_result[i] = 0;
        !          1389: }
        !          1390: 
        !          1391: /* Go through all the RTL insn bodies and copy any invalid shared structure.
        !          1392:    It does not work to do this twice, because the mark bits set here
        !          1393:    are not cleared afterwards.  */
        !          1394: 
        !          1395: void
        !          1396: unshare_all_rtl (insn)
        !          1397:      register rtx insn;
        !          1398: {
        !          1399:   for (; insn; insn = NEXT_INSN (insn))
        !          1400:     if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN
        !          1401:        || GET_CODE (insn) == CALL_INSN)
        !          1402:       {
        !          1403:        PATTERN (insn) = copy_rtx_if_shared (PATTERN (insn));
        !          1404:        REG_NOTES (insn) = copy_rtx_if_shared (REG_NOTES (insn));
        !          1405:        LOG_LINKS (insn) = copy_rtx_if_shared (LOG_LINKS (insn));
        !          1406:       }
        !          1407: 
        !          1408:   /* Make sure the addresses of stack slots found outside the insn chain
        !          1409:      (such as, in DECL_RTL of a variable) are not shared
        !          1410:      with the insn chain.
        !          1411: 
        !          1412:      This special care is necessary when the stack slot MEM does not
        !          1413:      actually appear in the insn chain.  If it does appear, its address
        !          1414:      is unshared from all else at that point.  */
        !          1415: 
        !          1416:   copy_rtx_if_shared (stack_slot_list);
        !          1417: }
        !          1418: 
        !          1419: /* Mark ORIG as in use, and return a copy of it if it was already in use.
        !          1420:    Recursively does the same for subexpressions.  */
        !          1421: 
        !          1422: rtx
        !          1423: copy_rtx_if_shared (orig)
        !          1424:      rtx orig;
        !          1425: {
        !          1426:   register rtx x = orig;
        !          1427:   register int i;
        !          1428:   register enum rtx_code code;
        !          1429:   register char *format_ptr;
        !          1430:   int copied = 0;
        !          1431: 
        !          1432:   if (x == 0)
        !          1433:     return 0;
        !          1434: 
        !          1435:   code = GET_CODE (x);
        !          1436: 
        !          1437:   /* These types may be freely shared.  */
        !          1438: 
        !          1439:   switch (code)
        !          1440:     {
        !          1441:     case REG:
        !          1442:     case QUEUED:
        !          1443:     case CONST_INT:
        !          1444:     case CONST_DOUBLE:
        !          1445:     case SYMBOL_REF:
        !          1446:     case CODE_LABEL:
        !          1447:     case PC:
        !          1448:     case CC0:
        !          1449:     case SCRATCH:
        !          1450:       /* SCRATCH must be shared because they represent distinct values. */
        !          1451:       return x;
        !          1452: 
        !          1453:     case CONST:
        !          1454:       /* CONST can be shared if it contains a SYMBOL_REF.  If it contains
        !          1455:         a LABEL_REF, it isn't sharable.  */
        !          1456:       if (GET_CODE (XEXP (x, 0)) == PLUS
        !          1457:          && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
        !          1458:          && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
        !          1459:        return x;
        !          1460:       break;
        !          1461: 
        !          1462:     case INSN:
        !          1463:     case JUMP_INSN:
        !          1464:     case CALL_INSN:
        !          1465:     case NOTE:
        !          1466:     case LABEL_REF:
        !          1467:     case BARRIER:
        !          1468:       /* The chain of insns is not being copied.  */
        !          1469:       return x;
        !          1470: 
        !          1471:     case MEM:
        !          1472:       /* A MEM is allowed to be shared if its address is constant
        !          1473:         or is a constant plus one of the special registers.  */
        !          1474:       if (CONSTANT_ADDRESS_P (XEXP (x, 0))
        !          1475:          || XEXP (x, 0) == virtual_stack_vars_rtx
        !          1476:          || XEXP (x, 0) == virtual_incoming_args_rtx)
        !          1477:        return x;
        !          1478: 
        !          1479:       if (GET_CODE (XEXP (x, 0)) == PLUS
        !          1480:          && (XEXP (XEXP (x, 0), 0) == virtual_stack_vars_rtx
        !          1481:              || XEXP (XEXP (x, 0), 0) == virtual_incoming_args_rtx)
        !          1482:          && CONSTANT_ADDRESS_P (XEXP (XEXP (x, 0), 1)))
        !          1483:        {
        !          1484:          /* This MEM can appear in more than one place,
        !          1485:             but its address better not be shared with anything else.  */
        !          1486:          if (! x->used)
        !          1487:            XEXP (x, 0) = copy_rtx_if_shared (XEXP (x, 0));
        !          1488:          x->used = 1;
        !          1489:          return x;
        !          1490:        }
        !          1491:     }
        !          1492: 
        !          1493:   /* This rtx may not be shared.  If it has already been seen,
        !          1494:      replace it with a copy of itself.  */
        !          1495: 
        !          1496:   if (x->used)
        !          1497:     {
        !          1498:       register rtx copy;
        !          1499: 
        !          1500:       copy = rtx_alloc (code);
        !          1501:       bcopy (x, copy, (sizeof (*copy) - sizeof (copy->fld)
        !          1502:                       + sizeof (copy->fld[0]) * GET_RTX_LENGTH (code)));
        !          1503:       x = copy;
        !          1504:       copied = 1;
        !          1505:     }
        !          1506:   x->used = 1;
        !          1507: 
        !          1508:   /* Now scan the subexpressions recursively.
        !          1509:      We can store any replaced subexpressions directly into X
        !          1510:      since we know X is not shared!  Any vectors in X
        !          1511:      must be copied if X was copied.  */
        !          1512: 
        !          1513:   format_ptr = GET_RTX_FORMAT (code);
        !          1514: 
        !          1515:   for (i = 0; i < GET_RTX_LENGTH (code); i++)
        !          1516:     {
        !          1517:       switch (*format_ptr++)
        !          1518:        {
        !          1519:        case 'e':
        !          1520:          XEXP (x, i) = copy_rtx_if_shared (XEXP (x, i));
        !          1521:          break;
        !          1522: 
        !          1523:        case 'E':
        !          1524:          if (XVEC (x, i) != NULL)
        !          1525:            {
        !          1526:              register int j;
        !          1527:              int len = XVECLEN (x, i);
        !          1528: 
        !          1529:              if (copied && len > 0)
        !          1530:                XVEC (x, i) = gen_rtvec_v (len, &XVECEXP (x, i, 0));
        !          1531:              for (j = 0; j < len; j++)
        !          1532:                XVECEXP (x, i, j) = copy_rtx_if_shared (XVECEXP (x, i, j));
        !          1533:            }
        !          1534:          break;
        !          1535:        }
        !          1536:     }
        !          1537:   return x;
        !          1538: }
        !          1539: 
        !          1540: /* Clear all the USED bits in X to allow copy_rtx_if_shared to be used
        !          1541:    to look for shared sub-parts.  */
        !          1542: 
        !          1543: void
        !          1544: reset_used_flags (x)
        !          1545:      rtx x;
        !          1546: {
        !          1547:   register int i, j;
        !          1548:   register enum rtx_code code;
        !          1549:   register char *format_ptr;
        !          1550:   int copied = 0;
        !          1551: 
        !          1552:   if (x == 0)
        !          1553:     return;
        !          1554: 
        !          1555:   code = GET_CODE (x);
        !          1556: 
        !          1557:   /* These types may be freely shared so we needn't do any reseting
        !          1558:      for them.  */
        !          1559: 
        !          1560:   switch (code)
        !          1561:     {
        !          1562:     case REG:
        !          1563:     case QUEUED:
        !          1564:     case CONST_INT:
        !          1565:     case CONST_DOUBLE:
        !          1566:     case SYMBOL_REF:
        !          1567:     case CODE_LABEL:
        !          1568:     case PC:
        !          1569:     case CC0:
        !          1570:       return;
        !          1571: 
        !          1572:     case INSN:
        !          1573:     case JUMP_INSN:
        !          1574:     case CALL_INSN:
        !          1575:     case NOTE:
        !          1576:     case LABEL_REF:
        !          1577:     case BARRIER:
        !          1578:       /* The chain of insns is not being copied.  */
        !          1579:       return;
        !          1580:     }
        !          1581: 
        !          1582:   x->used = 0;
        !          1583: 
        !          1584:   format_ptr = GET_RTX_FORMAT (code);
        !          1585:   for (i = 0; i < GET_RTX_LENGTH (code); i++)
        !          1586:     {
        !          1587:       switch (*format_ptr++)
        !          1588:        {
        !          1589:        case 'e':
        !          1590:          reset_used_flags (XEXP (x, i));
        !          1591:          break;
        !          1592: 
        !          1593:        case 'E':
        !          1594:          for (j = 0; j < XVECLEN (x, i); j++)
        !          1595:            reset_used_flags (XVECEXP (x, i, j));
        !          1596:          break;
        !          1597:        }
        !          1598:     }
        !          1599: }
        !          1600: 
        !          1601: /* Copy X if necessary so that it won't be altered by changes in OTHER.
        !          1602:    Return X or the rtx for the pseudo reg the value of X was copied into.
        !          1603:    OTHER must be valid as a SET_DEST.  */
        !          1604: 
        !          1605: rtx
        !          1606: make_safe_from (x, other)
        !          1607:      rtx x, other;
        !          1608: {
        !          1609:   while (1)
        !          1610:     switch (GET_CODE (other))
        !          1611:       {
        !          1612:       case SUBREG:
        !          1613:        other = SUBREG_REG (other);
        !          1614:        break;
        !          1615:       case STRICT_LOW_PART:
        !          1616:       case SIGN_EXTEND:
        !          1617:       case ZERO_EXTEND:
        !          1618:        other = XEXP (other, 0);
        !          1619:        break;
        !          1620:       default:
        !          1621:        goto done;
        !          1622:       }
        !          1623:  done:
        !          1624:   if ((GET_CODE (other) == MEM
        !          1625:        && ! CONSTANT_P (x)
        !          1626:        && GET_CODE (x) != REG
        !          1627:        && GET_CODE (x) != SUBREG)
        !          1628:       || (GET_CODE (other) == REG
        !          1629:          && (REGNO (other) < FIRST_PSEUDO_REGISTER
        !          1630:              || reg_mentioned_p (other, x))))
        !          1631:     {
        !          1632:       rtx temp = gen_reg_rtx (GET_MODE (x));
        !          1633:       emit_move_insn (temp, x);
        !          1634:       return temp;
        !          1635:     }
        !          1636:   return x;
        !          1637: }
        !          1638: 
        !          1639: /* Emission of insns (adding them to the doubly-linked list).  */
        !          1640: 
        !          1641: /* Return the first insn of the current sequence or current function.  */
        !          1642: 
        !          1643: rtx
        !          1644: get_insns ()
        !          1645: {
        !          1646:   return first_insn;
        !          1647: }
        !          1648: 
        !          1649: /* Return the last insn emitted in current sequence or current function.  */
        !          1650: 
        !          1651: rtx
        !          1652: get_last_insn ()
        !          1653: {
        !          1654:   return last_insn;
        !          1655: }
        !          1656: 
        !          1657: /* Specify a new insn as the last in the chain.  */
        !          1658: 
        !          1659: void
        !          1660: set_last_insn (insn)
        !          1661:      rtx insn;
        !          1662: {
        !          1663:   if (NEXT_INSN (insn) != 0)
        !          1664:     abort ();
        !          1665:   last_insn = insn;
        !          1666: }
        !          1667: 
        !          1668: /* Return the last insn emitted, even if it is in a sequence now pushed.  */
        !          1669: 
        !          1670: rtx
        !          1671: get_last_insn_anywhere ()
        !          1672: {
        !          1673:   struct sequence_stack *stack;
        !          1674:   if (last_insn)
        !          1675:     return last_insn;
        !          1676:   for (stack = sequence_stack; stack; stack = stack->next)
        !          1677:     if (stack->last != 0)
        !          1678:       return stack->last;
        !          1679:   return 0;
        !          1680: }
        !          1681: 
        !          1682: /* Return a number larger than any instruction's uid in this function.  */
        !          1683: 
        !          1684: int
        !          1685: get_max_uid ()
        !          1686: {
        !          1687:   return cur_insn_uid;
        !          1688: }
        !          1689: 
        !          1690: /* Return the next insn.  If it is a SEQUENCE, return the first insn
        !          1691:    of the sequence.  */
        !          1692: 
        !          1693: rtx
        !          1694: next_insn (insn)
        !          1695:      rtx insn;
        !          1696: {
        !          1697:   if (insn)
        !          1698:     {
        !          1699:       insn = NEXT_INSN (insn);
        !          1700:       if (insn && GET_CODE (insn) == INSN
        !          1701:          && GET_CODE (PATTERN (insn)) == SEQUENCE)
        !          1702:        insn = XVECEXP (PATTERN (insn), 0, 0);
        !          1703:     }
        !          1704: 
        !          1705:   return insn;
        !          1706: }
        !          1707: 
        !          1708: /* Return the previous insn.  If it is a SEQUENCE, return the last insn
        !          1709:    of the sequence.  */
        !          1710: 
        !          1711: rtx
        !          1712: previous_insn (insn)
        !          1713:      rtx insn;
        !          1714: {
        !          1715:   if (insn)
        !          1716:     {
        !          1717:       insn = PREV_INSN (insn);
        !          1718:       if (insn && GET_CODE (insn) == INSN
        !          1719:          && GET_CODE (PATTERN (insn)) == SEQUENCE)
        !          1720:        insn = XVECEXP (PATTERN (insn), 0, XVECLEN (PATTERN (insn), 0) - 1);
        !          1721:     }
        !          1722: 
        !          1723:   return insn;
        !          1724: }
        !          1725: 
        !          1726: /* Return the next insn after INSN that is not a NOTE.  This routine does not
        !          1727:    look inside SEQUENCEs.  */
        !          1728: 
        !          1729: rtx
        !          1730: next_nonnote_insn (insn)
        !          1731:      rtx insn;
        !          1732: {
        !          1733:   while (insn)
        !          1734:     {
        !          1735:       insn = NEXT_INSN (insn);
        !          1736:       if (insn == 0 || GET_CODE (insn) != NOTE)
        !          1737:        break;
        !          1738:     }
        !          1739: 
        !          1740:   return insn;
        !          1741: }
        !          1742: 
        !          1743: /* Return the previous insn before INSN that is not a NOTE.  This routine does
        !          1744:    not look inside SEQUENCEs.  */
        !          1745: 
        !          1746: rtx
        !          1747: prev_nonnote_insn (insn)
        !          1748:      rtx insn;
        !          1749: {
        !          1750:   while (insn)
        !          1751:     {
        !          1752:       insn = PREV_INSN (insn);
        !          1753:       if (insn == 0 || GET_CODE (insn) != NOTE)
        !          1754:        break;
        !          1755:     }
        !          1756: 
        !          1757:   return insn;
        !          1758: }
        !          1759: 
        !          1760: /* Return the next INSN, CALL_INSN or JUMP_INSN after INSN;
        !          1761:    or 0, if there is none.  This routine does not look inside
        !          1762:    SEQUENCEs. */
        !          1763: 
        !          1764: rtx
        !          1765: next_real_insn (insn)
        !          1766:      rtx insn;
        !          1767: {
        !          1768:   while (insn)
        !          1769:     {
        !          1770:       insn = NEXT_INSN (insn);
        !          1771:       if (insn == 0 || GET_CODE (insn) == INSN
        !          1772:          || GET_CODE (insn) == CALL_INSN || GET_CODE (insn) == JUMP_INSN)
        !          1773:        break;
        !          1774:     }
        !          1775: 
        !          1776:   return insn;
        !          1777: }
        !          1778: 
        !          1779: /* Return the last INSN, CALL_INSN or JUMP_INSN before INSN;
        !          1780:    or 0, if there is none.  This routine does not look inside
        !          1781:    SEQUENCEs.  */
        !          1782: 
        !          1783: rtx
        !          1784: prev_real_insn (insn)
        !          1785:      rtx insn;
        !          1786: {
        !          1787:   while (insn)
        !          1788:     {
        !          1789:       insn = PREV_INSN (insn);
        !          1790:       if (insn == 0 || GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN
        !          1791:          || GET_CODE (insn) == JUMP_INSN)
        !          1792:        break;
        !          1793:     }
        !          1794: 
        !          1795:   return insn;
        !          1796: }
        !          1797: 
        !          1798: /* Find the next insn after INSN that really does something.  This routine
        !          1799:    does not look inside SEQUENCEs.  Until reload has completed, this is the
        !          1800:    same as next_real_insn.  */
        !          1801: 
        !          1802: rtx
        !          1803: next_active_insn (insn)
        !          1804:      rtx insn;
        !          1805: {
        !          1806:   while (insn)
        !          1807:     {
        !          1808:       insn = NEXT_INSN (insn);
        !          1809:       if (insn == 0
        !          1810:          || GET_CODE (insn) == CALL_INSN || GET_CODE (insn) == JUMP_INSN
        !          1811:          || (GET_CODE (insn) == INSN
        !          1812:              && (! reload_completed
        !          1813:                  || (GET_CODE (PATTERN (insn)) != USE
        !          1814:                      && GET_CODE (PATTERN (insn)) != CLOBBER))))
        !          1815:        break;
        !          1816:     }
        !          1817: 
        !          1818:   return insn;
        !          1819: }
        !          1820: 
        !          1821: /* Find the last insn before INSN that really does something.  This routine
        !          1822:    does not look inside SEQUENCEs.  Until reload has completed, this is the
        !          1823:    same as prev_real_insn.  */
        !          1824: 
        !          1825: rtx
        !          1826: prev_active_insn (insn)
        !          1827:      rtx insn;
        !          1828: {
        !          1829:   while (insn)
        !          1830:     {
        !          1831:       insn = PREV_INSN (insn);
        !          1832:       if (insn == 0
        !          1833:          || GET_CODE (insn) == CALL_INSN || GET_CODE (insn) == JUMP_INSN
        !          1834:          || (GET_CODE (insn) == INSN
        !          1835:              && (! reload_completed
        !          1836:                  || (GET_CODE (PATTERN (insn)) != USE
        !          1837:                      && GET_CODE (PATTERN (insn)) != CLOBBER))))
        !          1838:        break;
        !          1839:     }
        !          1840: 
        !          1841:   return insn;
        !          1842: }
        !          1843: 
        !          1844: /* Return the next CODE_LABEL after the insn INSN, or 0 if there is none.  */
        !          1845: 
        !          1846: rtx
        !          1847: next_label (insn)
        !          1848:      rtx insn;
        !          1849: {
        !          1850:   while (insn)
        !          1851:     {
        !          1852:       insn = NEXT_INSN (insn);
        !          1853:       if (insn == 0 || GET_CODE (insn) == CODE_LABEL)
        !          1854:        break;
        !          1855:     }
        !          1856: 
        !          1857:   return insn;
        !          1858: }
        !          1859: 
        !          1860: /* Return the last CODE_LABEL before the insn INSN, or 0 if there is none.  */
        !          1861: 
        !          1862: rtx
        !          1863: prev_label (insn)
        !          1864:      rtx insn;
        !          1865: {
        !          1866:   while (insn)
        !          1867:     {
        !          1868:       insn = PREV_INSN (insn);
        !          1869:       if (insn == 0 || GET_CODE (insn) == CODE_LABEL)
        !          1870:        break;
        !          1871:     }
        !          1872: 
        !          1873:   return insn;
        !          1874: }
        !          1875: 
        !          1876: #ifdef HAVE_cc0
        !          1877: /* INSN uses CC0 and is being moved into a delay slot.  Set up REG_CC_SETTER
        !          1878:    and REG_CC_USER notes so we can find it.  */
        !          1879: 
        !          1880: void
        !          1881: link_cc0_insns (insn)
        !          1882:      rtx insn;
        !          1883: {
        !          1884:   rtx user = next_nonnote_insn (insn);
        !          1885: 
        !          1886:   if (GET_CODE (user) == INSN && GET_CODE (PATTERN (user)) == SEQUENCE)
        !          1887:     user = XVECEXP (PATTERN (user), 0, 0);
        !          1888: 
        !          1889:   REG_NOTES (user) = gen_rtx (INSN_LIST, REG_CC_SETTER, insn,
        !          1890:                              REG_NOTES (user));
        !          1891:   REG_NOTES (insn) = gen_rtx (INSN_LIST, REG_CC_USER, user, REG_NOTES (insn));
        !          1892: }
        !          1893: 
        !          1894: /* Return the next insn that uses CC0 after INSN, which is assumed to
        !          1895:    set it.  This is the inverse of prev_cc0_setter (i.e., prev_cc0_setter
        !          1896:    applied to the result of this function should yield INSN).
        !          1897: 
        !          1898:    Normally, this is simply the next insn.  However, if a REG_CC_USER note
        !          1899:    is present, it contains the insn that uses CC0.
        !          1900: 
        !          1901:    Return 0 if we can't find the insn.  */
        !          1902: 
        !          1903: rtx
        !          1904: next_cc0_user (insn)
        !          1905:      rtx insn;
        !          1906: {
        !          1907:   rtx note = find_reg_note (insn, REG_CC_USER, NULL_RTX);
        !          1908: 
        !          1909:   if (note)
        !          1910:     return XEXP (note, 0);
        !          1911: 
        !          1912:   insn = next_nonnote_insn (insn);
        !          1913: 
        !          1914:   if (insn && GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE)
        !          1915:     insn = XVECEXP (PATTERN (insn), 0, 0);
        !          1916: 
        !          1917:   if (insn && GET_RTX_CLASS (GET_CODE (insn)) == 'i'
        !          1918:       && reg_mentioned_p (cc0_rtx, PATTERN (insn)))
        !          1919:     return insn;
        !          1920: 
        !          1921:   return 0;
        !          1922: }
        !          1923: 
        !          1924: /* Find the insn that set CC0 for INSN.  Unless INSN has a REG_CC_SETTER
        !          1925:    note, it is the previous insn.  */
        !          1926: 
        !          1927: rtx
        !          1928: prev_cc0_setter (insn)
        !          1929:      rtx insn;
        !          1930: {
        !          1931:   rtx note = find_reg_note (insn, REG_CC_SETTER, NULL_RTX);
        !          1932:   rtx link;
        !          1933: 
        !          1934:   if (note)
        !          1935:     return XEXP (note, 0);
        !          1936: 
        !          1937:   insn = prev_nonnote_insn (insn);
        !          1938:   if (! sets_cc0_p (PATTERN (insn)))
        !          1939:     abort ();
        !          1940: 
        !          1941:   return insn;
        !          1942: }
        !          1943: #endif
        !          1944: 
        !          1945: /* Try splitting insns that can be split for better scheduling.
        !          1946:    PAT is the pattern which might split.
        !          1947:    TRIAL is the insn providing PAT.
        !          1948:    BACKWARDS is non-zero if we are scanning insns from last to first.
        !          1949: 
        !          1950:    If this routine succeeds in splitting, it returns the first or last
        !          1951:    replacement insn depending on the value of BACKWARDS.  Otherwise, it
        !          1952:    returns TRIAL.  If the insn to be returned can be split, it will be.  */
        !          1953: 
        !          1954: rtx
        !          1955: try_split (pat, trial, backwards)
        !          1956:      rtx pat, trial;
        !          1957:      int backwards;
        !          1958: {
        !          1959:   rtx before = PREV_INSN (trial);
        !          1960:   rtx after = NEXT_INSN (trial);
        !          1961:   rtx seq = split_insns (pat, trial);
        !          1962:   int has_barrier = 0;
        !          1963:   rtx tem;
        !          1964: 
        !          1965:   /* If we are splitting a JUMP_INSN, it might be followed by a BARRIER.
        !          1966:      We may need to handle this specially.  */
        !          1967:   if (after && GET_CODE (after) == BARRIER)
        !          1968:     {
        !          1969:       has_barrier = 1;
        !          1970:       after = NEXT_INSN (after);
        !          1971:     }
        !          1972: 
        !          1973:   if (seq)
        !          1974:     {
        !          1975:       /* SEQ can either be a SEQUENCE or the pattern of a single insn.
        !          1976:         The latter case will normally arise only when being done so that
        !          1977:         it, in turn, will be split (SFmode on the 29k is an example).  */
        !          1978:       if (GET_CODE (seq) == SEQUENCE)
        !          1979:        {
        !          1980:          /* If we are splitting a JUMP_INSN, look for the JUMP_INSN in
        !          1981:             SEQ and copy our JUMP_LABEL to it.  If JUMP_LABEL is non-zero,
        !          1982:             increment the usage count so we don't delete the label.  */
        !          1983:          int i;
        !          1984: 
        !          1985:          if (GET_CODE (trial) == JUMP_INSN)
        !          1986:            for (i = XVECLEN (seq, 0) - 1; i >= 0; i--)
        !          1987:              if (GET_CODE (XVECEXP (seq, 0, i)) == JUMP_INSN)
        !          1988:                {
        !          1989:                  JUMP_LABEL (XVECEXP (seq, 0, i)) = JUMP_LABEL (trial);
        !          1990: 
        !          1991:                  if (JUMP_LABEL (trial))
        !          1992:                    LABEL_NUSES (JUMP_LABEL (trial))++;
        !          1993:                }
        !          1994: 
        !          1995:          tem = emit_insn_after (seq, before);
        !          1996: 
        !          1997:          delete_insn (trial);
        !          1998:          if (has_barrier)
        !          1999:            emit_barrier_after (tem);
        !          2000:        }
        !          2001:       /* Avoid infinite loop if the result matches the original pattern.  */
        !          2002:       else if (rtx_equal_p (seq, pat))
        !          2003:        return trial;
        !          2004:       else
        !          2005:        {
        !          2006:          PATTERN (trial) = seq;
        !          2007:          INSN_CODE (trial) = -1;
        !          2008:        }
        !          2009: 
        !          2010:       /* Set TEM to the insn we should return.  */
        !          2011:       tem = backwards ? prev_active_insn (after) : next_active_insn (before);
        !          2012:       return try_split (PATTERN (tem), tem, backwards);
        !          2013:     }
        !          2014: 
        !          2015:   return trial;
        !          2016: }
        !          2017: 
        !          2018: /* Make and return an INSN rtx, initializing all its slots.
        !          2019:    Store PATTERN in the pattern slots.  */
        !          2020: 
        !          2021: rtx
        !          2022: make_insn_raw (pattern)
        !          2023:      rtx pattern;
        !          2024: {
        !          2025:   register rtx insn;
        !          2026: 
        !          2027:   insn = rtx_alloc (INSN);
        !          2028:   INSN_UID (insn) = cur_insn_uid++;
        !          2029: 
        !          2030:   PATTERN (insn) = pattern;
        !          2031:   INSN_CODE (insn) = -1;
        !          2032:   LOG_LINKS (insn) = NULL;
        !          2033:   REG_NOTES (insn) = NULL;
        !          2034: 
        !          2035:   return insn;
        !          2036: }
        !          2037: 
        !          2038: /* Like `make_insn' but make a JUMP_INSN instead of an insn.  */
        !          2039: 
        !          2040: static rtx
        !          2041: make_jump_insn_raw (pattern)
        !          2042:      rtx pattern;
        !          2043: {
        !          2044:   register rtx insn;
        !          2045: 
        !          2046:   insn = rtx_alloc (JUMP_INSN);
        !          2047:   INSN_UID (insn) = cur_insn_uid++;
        !          2048: 
        !          2049:   PATTERN (insn) = pattern;
        !          2050:   INSN_CODE (insn) = -1;
        !          2051:   LOG_LINKS (insn) = NULL;
        !          2052:   REG_NOTES (insn) = NULL;
        !          2053:   JUMP_LABEL (insn) = NULL;
        !          2054: 
        !          2055:   return insn;
        !          2056: }
        !          2057: 
        !          2058: /* Add INSN to the end of the doubly-linked list.
        !          2059:    INSN may be an INSN, JUMP_INSN, CALL_INSN, CODE_LABEL, BARRIER or NOTE.  */
        !          2060: 
        !          2061: void
        !          2062: add_insn (insn)
        !          2063:      register rtx insn;
        !          2064: {
        !          2065:   PREV_INSN (insn) = last_insn;
        !          2066:   NEXT_INSN (insn) = 0;
        !          2067: 
        !          2068:   if (NULL != last_insn)
        !          2069:     NEXT_INSN (last_insn) = insn;
        !          2070: 
        !          2071:   if (NULL == first_insn)
        !          2072:     first_insn = insn;
        !          2073: 
        !          2074:   last_insn = insn;
        !          2075: }
        !          2076: 
        !          2077: /* Add INSN into the doubly-linked list after insn AFTER.  This should be the
        !          2078:    only function called to insert an insn once delay slots have been filled
        !          2079:    since only it knows how to update a SEQUENCE.  */
        !          2080: 
        !          2081: void
        !          2082: add_insn_after (insn, after)
        !          2083:      rtx insn, after;
        !          2084: {
        !          2085:   rtx next = NEXT_INSN (after);
        !          2086: 
        !          2087:   NEXT_INSN (insn) = next;
        !          2088:   PREV_INSN (insn) = after;
        !          2089: 
        !          2090:   if (next)
        !          2091:     {
        !          2092:       PREV_INSN (next) = insn;
        !          2093:       if (GET_CODE (next) == INSN && GET_CODE (PATTERN (next)) == SEQUENCE)
        !          2094:        PREV_INSN (XVECEXP (PATTERN (next), 0, 0)) = insn;
        !          2095:     }
        !          2096:   else if (last_insn == after)
        !          2097:     last_insn = insn;
        !          2098:   else
        !          2099:     {
        !          2100:       struct sequence_stack *stack = sequence_stack;
        !          2101:       /* Scan all pending sequences too.  */
        !          2102:       for (; stack; stack = stack->next)
        !          2103:        if (after == stack->last)
        !          2104:          stack->last = insn;
        !          2105:     }
        !          2106: 
        !          2107:   NEXT_INSN (after) = insn;
        !          2108:   if (GET_CODE (after) == INSN && GET_CODE (PATTERN (after)) == SEQUENCE)
        !          2109:     {
        !          2110:       rtx sequence = PATTERN (after);
        !          2111:       NEXT_INSN (XVECEXP (sequence, 0, XVECLEN (sequence, 0) - 1)) = insn;
        !          2112:     }
        !          2113: }
        !          2114: 
        !          2115: /* Delete all insns made since FROM.
        !          2116:    FROM becomes the new last instruction.  */
        !          2117: 
        !          2118: void
        !          2119: delete_insns_since (from)
        !          2120:      rtx from;
        !          2121: {
        !          2122:   if (from == 0)
        !          2123:     first_insn = 0;
        !          2124:   else
        !          2125:     NEXT_INSN (from) = 0;
        !          2126:   last_insn = from;
        !          2127: }
        !          2128: 
        !          2129: /* Move a consecutive bunch of insns to a different place in the chain.
        !          2130:    The insns to be moved are those between FROM and TO.
        !          2131:    They are moved to a new position after the insn AFTER.
        !          2132:    AFTER must not be FROM or TO or any insn in between.
        !          2133: 
        !          2134:    This function does not know about SEQUENCEs and hence should not be
        !          2135:    called after delay-slot filling has been done.  */
        !          2136: 
        !          2137: void
        !          2138: reorder_insns (from, to, after)
        !          2139:      rtx from, to, after;
        !          2140: {
        !          2141:   /* Splice this bunch out of where it is now.  */
        !          2142:   if (PREV_INSN (from))
        !          2143:     NEXT_INSN (PREV_INSN (from)) = NEXT_INSN (to);
        !          2144:   if (NEXT_INSN (to))
        !          2145:     PREV_INSN (NEXT_INSN (to)) = PREV_INSN (from);
        !          2146:   if (last_insn == to)
        !          2147:     last_insn = PREV_INSN (from);
        !          2148:   if (first_insn == from)
        !          2149:     first_insn = NEXT_INSN (to);
        !          2150: 
        !          2151:   /* Make the new neighbors point to it and it to them.  */
        !          2152:   if (NEXT_INSN (after))
        !          2153:     PREV_INSN (NEXT_INSN (after)) = to;
        !          2154: 
        !          2155:   NEXT_INSN (to) = NEXT_INSN (after);
        !          2156:   PREV_INSN (from) = after;
        !          2157:   NEXT_INSN (after) = from;
        !          2158:   if (after == last_insn)
        !          2159:     last_insn = to;
        !          2160: }
        !          2161: 
        !          2162: /* Return the line note insn preceding INSN.  */
        !          2163: 
        !          2164: static rtx
        !          2165: find_line_note (insn)
        !          2166:      rtx insn;
        !          2167: {
        !          2168:   if (no_line_numbers)
        !          2169:     return 0;
        !          2170: 
        !          2171:   for (; insn; insn = PREV_INSN (insn))
        !          2172:     if (GET_CODE (insn) == NOTE
        !          2173:         && NOTE_LINE_NUMBER (insn) >= 0)
        !          2174:       break;
        !          2175: 
        !          2176:   return insn;
        !          2177: }
        !          2178: 
        !          2179: /* Like reorder_insns, but inserts line notes to preserve the line numbers
        !          2180:    of the moved insns when debugging.  This may insert a note between AFTER
        !          2181:    and FROM, and another one after TO.  */
        !          2182: 
        !          2183: void
        !          2184: reorder_insns_with_line_notes (from, to, after)
        !          2185:      rtx from, to, after;
        !          2186: {
        !          2187:   rtx from_line = find_line_note (from);
        !          2188:   rtx after_line = find_line_note (after);
        !          2189: 
        !          2190:   reorder_insns (from, to, after);
        !          2191: 
        !          2192:   if (from_line == after_line)
        !          2193:     return;
        !          2194: 
        !          2195:   if (from_line)
        !          2196:     emit_line_note_after (NOTE_SOURCE_FILE (from_line),
        !          2197:                          NOTE_LINE_NUMBER (from_line),
        !          2198:                          after);
        !          2199:   if (after_line)
        !          2200:     emit_line_note_after (NOTE_SOURCE_FILE (after_line),
        !          2201:                          NOTE_LINE_NUMBER (after_line),
        !          2202:                          to);
        !          2203: }
        !          2204: 
        !          2205: /* Emit an insn of given code and pattern
        !          2206:    at a specified place within the doubly-linked list.  */
        !          2207: 
        !          2208: /* Make an instruction with body PATTERN
        !          2209:    and output it before the instruction BEFORE.  */
        !          2210: 
        !          2211: rtx
        !          2212: emit_insn_before (pattern, before)
        !          2213:      register rtx pattern, before;
        !          2214: {
        !          2215:   register rtx insn = before;
        !          2216: 
        !          2217:   if (GET_CODE (pattern) == SEQUENCE)
        !          2218:     {
        !          2219:       register int i;
        !          2220: 
        !          2221:       for (i = 0; i < XVECLEN (pattern, 0); i++)
        !          2222:        {
        !          2223:          insn = XVECEXP (pattern, 0, i);
        !          2224:          add_insn_after (insn, PREV_INSN (before));
        !          2225:        }
        !          2226:       if (XVECLEN (pattern, 0) < SEQUENCE_RESULT_SIZE)
        !          2227:        sequence_result[XVECLEN (pattern, 0)] = pattern;
        !          2228:     }
        !          2229:   else
        !          2230:     {
        !          2231:       insn = make_insn_raw (pattern);
        !          2232:       add_insn_after (insn, PREV_INSN (before));
        !          2233:     }
        !          2234: 
        !          2235:   return insn;
        !          2236: }
        !          2237: 
        !          2238: /* Make an instruction with body PATTERN and code JUMP_INSN
        !          2239:    and output it before the instruction BEFORE.  */
        !          2240: 
        !          2241: rtx
        !          2242: emit_jump_insn_before (pattern, before)
        !          2243:      register rtx pattern, before;
        !          2244: {
        !          2245:   register rtx insn;
        !          2246: 
        !          2247:   if (GET_CODE (pattern) == SEQUENCE)
        !          2248:     insn = emit_insn_before (pattern, before);
        !          2249:   else
        !          2250:     {
        !          2251:       insn = make_jump_insn_raw (pattern);
        !          2252:       add_insn_after (insn, PREV_INSN (before));
        !          2253:     }
        !          2254: 
        !          2255:   return insn;
        !          2256: }
        !          2257: 
        !          2258: /* Make an instruction with body PATTERN and code CALL_INSN
        !          2259:    and output it before the instruction BEFORE.  */
        !          2260: 
        !          2261: rtx
        !          2262: emit_call_insn_before (pattern, before)
        !          2263:      register rtx pattern, before;
        !          2264: {
        !          2265:   rtx insn = emit_insn_before (pattern, before);
        !          2266:   PUT_CODE (insn, CALL_INSN);
        !          2267:   return insn;
        !          2268: }
        !          2269: 
        !          2270: /* Make an insn of code BARRIER
        !          2271:    and output it before the insn AFTER.  */
        !          2272: 
        !          2273: rtx
        !          2274: emit_barrier_before (before)
        !          2275:      register rtx before;
        !          2276: {
        !          2277:   register rtx insn = rtx_alloc (BARRIER);
        !          2278: 
        !          2279:   INSN_UID (insn) = cur_insn_uid++;
        !          2280: 
        !          2281:   add_insn_after (insn, PREV_INSN (before));
        !          2282:   return insn;
        !          2283: }
        !          2284: 
        !          2285: /* Emit a note of subtype SUBTYPE before the insn BEFORE.  */
        !          2286: 
        !          2287: rtx
        !          2288: emit_note_before (subtype, before)
        !          2289:      int subtype;
        !          2290:      rtx before;
        !          2291: {
        !          2292:   register rtx note = rtx_alloc (NOTE);
        !          2293:   INSN_UID (note) = cur_insn_uid++;
        !          2294:   NOTE_SOURCE_FILE (note) = 0;
        !          2295:   NOTE_LINE_NUMBER (note) = subtype;
        !          2296: 
        !          2297:   add_insn_after (note, PREV_INSN (before));
        !          2298:   return note;
        !          2299: }
        !          2300: 
        !          2301: /* Make an insn of code INSN with body PATTERN
        !          2302:    and output it after the insn AFTER.  */
        !          2303: 
        !          2304: rtx
        !          2305: emit_insn_after (pattern, after)
        !          2306:      register rtx pattern, after;
        !          2307: {
        !          2308:   register rtx insn = after;
        !          2309: 
        !          2310:   if (GET_CODE (pattern) == SEQUENCE)
        !          2311:     {
        !          2312:       register int i;
        !          2313: 
        !          2314:       for (i = 0; i < XVECLEN (pattern, 0); i++)
        !          2315:        {
        !          2316:          insn = XVECEXP (pattern, 0, i);
        !          2317:          add_insn_after (insn, after);
        !          2318:          after = insn;
        !          2319:        }
        !          2320:       if (XVECLEN (pattern, 0) < SEQUENCE_RESULT_SIZE)
        !          2321:        sequence_result[XVECLEN (pattern, 0)] = pattern;
        !          2322:     }
        !          2323:   else
        !          2324:     {
        !          2325:       insn = make_insn_raw (pattern);
        !          2326:       add_insn_after (insn, after);
        !          2327:     }
        !          2328: 
        !          2329:   return insn;
        !          2330: }
        !          2331: 
        !          2332: /* Similar to emit_insn_after, except that line notes are to be inserted so
        !          2333:    as to act as if this insn were at FROM.  */
        !          2334: 
        !          2335: void
        !          2336: emit_insn_after_with_line_notes (pattern, after, from)
        !          2337:      rtx pattern, after, from;
        !          2338: {
        !          2339:   rtx from_line = find_line_note (from);
        !          2340:   rtx after_line = find_line_note (after);
        !          2341:   rtx insn = emit_insn_after (pattern, after);
        !          2342: 
        !          2343:   if (from_line)
        !          2344:     emit_line_note_after (NOTE_SOURCE_FILE (from_line),
        !          2345:                          NOTE_LINE_NUMBER (from_line),
        !          2346:                          after);
        !          2347: 
        !          2348:   if (after_line)
        !          2349:     emit_line_note_after (NOTE_SOURCE_FILE (after_line),
        !          2350:                          NOTE_LINE_NUMBER (after_line),
        !          2351:                          insn);
        !          2352: }
        !          2353: 
        !          2354: /* Make an insn of code JUMP_INSN with body PATTERN
        !          2355:    and output it after the insn AFTER.  */
        !          2356: 
        !          2357: rtx
        !          2358: emit_jump_insn_after (pattern, after)
        !          2359:      register rtx pattern, after;
        !          2360: {
        !          2361:   register rtx insn;
        !          2362: 
        !          2363:   if (GET_CODE (pattern) == SEQUENCE)
        !          2364:     insn = emit_insn_after (pattern, after);
        !          2365:   else
        !          2366:     {
        !          2367:       insn = make_jump_insn_raw (pattern);
        !          2368:       add_insn_after (insn, after);
        !          2369:     }
        !          2370: 
        !          2371:   return insn;
        !          2372: }
        !          2373: 
        !          2374: /* Make an insn of code BARRIER
        !          2375:    and output it after the insn AFTER.  */
        !          2376: 
        !          2377: rtx
        !          2378: emit_barrier_after (after)
        !          2379:      register rtx after;
        !          2380: {
        !          2381:   register rtx insn = rtx_alloc (BARRIER);
        !          2382: 
        !          2383:   INSN_UID (insn) = cur_insn_uid++;
        !          2384: 
        !          2385:   add_insn_after (insn, after);
        !          2386:   return insn;
        !          2387: }
        !          2388: 
        !          2389: /* Emit the label LABEL after the insn AFTER.  */
        !          2390: 
        !          2391: rtx
        !          2392: emit_label_after (label, after)
        !          2393:      rtx label, after;
        !          2394: {
        !          2395:   /* This can be called twice for the same label
        !          2396:      as a result of the confusion that follows a syntax error!
        !          2397:      So make it harmless.  */
        !          2398:   if (INSN_UID (label) == 0)
        !          2399:     {
        !          2400:       INSN_UID (label) = cur_insn_uid++;
        !          2401:       add_insn_after (label, after);
        !          2402:     }
        !          2403: 
        !          2404:   return label;
        !          2405: }
        !          2406: 
        !          2407: /* Emit a note of subtype SUBTYPE after the insn AFTER.  */
        !          2408: 
        !          2409: rtx
        !          2410: emit_note_after (subtype, after)
        !          2411:      int subtype;
        !          2412:      rtx after;
        !          2413: {
        !          2414:   register rtx note = rtx_alloc (NOTE);
        !          2415:   INSN_UID (note) = cur_insn_uid++;
        !          2416:   NOTE_SOURCE_FILE (note) = 0;
        !          2417:   NOTE_LINE_NUMBER (note) = subtype;
        !          2418:   add_insn_after (note, after);
        !          2419:   return note;
        !          2420: }
        !          2421: 
        !          2422: /* Emit a line note for FILE and LINE after the insn AFTER.  */
        !          2423: 
        !          2424: rtx
        !          2425: emit_line_note_after (file, line, after)
        !          2426:      char *file;
        !          2427:      int line;
        !          2428:      rtx after;
        !          2429: {
        !          2430:   register rtx note;
        !          2431: 
        !          2432:   if (no_line_numbers && line > 0)
        !          2433:     {
        !          2434:       cur_insn_uid++;
        !          2435:       return 0;
        !          2436:     }
        !          2437: 
        !          2438:   note  = rtx_alloc (NOTE);
        !          2439:   INSN_UID (note) = cur_insn_uid++;
        !          2440:   NOTE_SOURCE_FILE (note) = file;
        !          2441:   NOTE_LINE_NUMBER (note) = line;
        !          2442:   add_insn_after (note, after);
        !          2443:   return note;
        !          2444: }
        !          2445: 
        !          2446: /* Make an insn of code INSN with pattern PATTERN
        !          2447:    and add it to the end of the doubly-linked list.
        !          2448:    If PATTERN is a SEQUENCE, take the elements of it
        !          2449:    and emit an insn for each element.
        !          2450: 
        !          2451:    Returns the last insn emitted.  */
        !          2452: 
        !          2453: rtx
        !          2454: emit_insn (pattern)
        !          2455:      rtx pattern;
        !          2456: {
        !          2457:   rtx insn = last_insn;
        !          2458: 
        !          2459:   if (GET_CODE (pattern) == SEQUENCE)
        !          2460:     {
        !          2461:       register int i;
        !          2462: 
        !          2463:       for (i = 0; i < XVECLEN (pattern, 0); i++)
        !          2464:        {
        !          2465:          insn = XVECEXP (pattern, 0, i);
        !          2466:          add_insn (insn);
        !          2467:        }
        !          2468:       if (XVECLEN (pattern, 0) < SEQUENCE_RESULT_SIZE)
        !          2469:        sequence_result[XVECLEN (pattern, 0)] = pattern;
        !          2470:     }
        !          2471:   else
        !          2472:     {
        !          2473:       insn = make_insn_raw (pattern);
        !          2474:       add_insn (insn);
        !          2475:     }
        !          2476: 
        !          2477:   return insn;
        !          2478: }
        !          2479: 
        !          2480: /* Emit the insns in a chain starting with INSN.
        !          2481:    Return the last insn emitted.  */
        !          2482: 
        !          2483: rtx
        !          2484: emit_insns (insn)
        !          2485:      rtx insn;
        !          2486: {
        !          2487:   rtx last = 0;
        !          2488: 
        !          2489:   while (insn)
        !          2490:     {
        !          2491:       rtx next = NEXT_INSN (insn);
        !          2492:       add_insn (insn);
        !          2493:       last = insn;
        !          2494:       insn = next;
        !          2495:     }
        !          2496: 
        !          2497:   return last;
        !          2498: }
        !          2499: 
        !          2500: /* Emit the insns in a chain starting with INSN and place them in front of
        !          2501:    the insn BEFORE.  Return the last insn emitted.  */
        !          2502: 
        !          2503: rtx
        !          2504: emit_insns_before (insn, before)
        !          2505:      rtx insn;
        !          2506:      rtx before;
        !          2507: {
        !          2508:   rtx last = 0;
        !          2509: 
        !          2510:   while (insn)
        !          2511:     {
        !          2512:       rtx next = NEXT_INSN (insn);
        !          2513:       add_insn_after (insn, PREV_INSN (before));
        !          2514:       last = insn;
        !          2515:       insn = next;
        !          2516:     }
        !          2517: 
        !          2518:   return last;
        !          2519: }
        !          2520: 
        !          2521: /* Emit the insns in a chain starting with FIRST and place them in back of
        !          2522:    the insn AFTER.  Return the last insn emitted.  */
        !          2523: 
        !          2524: rtx
        !          2525: emit_insns_after (first, after)
        !          2526:      register rtx first;
        !          2527:      register rtx after;
        !          2528: {
        !          2529:   register rtx last;
        !          2530:   register rtx after_after;
        !          2531: 
        !          2532:   if (!after)
        !          2533:     abort ();
        !          2534: 
        !          2535:   if (!first)
        !          2536:     return first;
        !          2537: 
        !          2538:   for (last = first; NEXT_INSN (last); last = NEXT_INSN (last))
        !          2539:     continue;
        !          2540: 
        !          2541:   after_after = NEXT_INSN (after);
        !          2542: 
        !          2543:   NEXT_INSN (after) = first;
        !          2544:   PREV_INSN (first) = after;
        !          2545:   NEXT_INSN (last) = after_after;
        !          2546:   if (after_after)
        !          2547:     PREV_INSN (after_after) = last;
        !          2548: 
        !          2549:   if (after == last_insn)
        !          2550:     last_insn = last;
        !          2551:   return last;
        !          2552: }
        !          2553: 
        !          2554: /* Make an insn of code JUMP_INSN with pattern PATTERN
        !          2555:    and add it to the end of the doubly-linked list.  */
        !          2556: 
        !          2557: rtx
        !          2558: emit_jump_insn (pattern)
        !          2559:      rtx pattern;
        !          2560: {
        !          2561:   if (GET_CODE (pattern) == SEQUENCE)
        !          2562:     return emit_insn (pattern);
        !          2563:   else
        !          2564:     {
        !          2565:       register rtx insn = make_jump_insn_raw (pattern);
        !          2566:       add_insn (insn);
        !          2567:       return insn;
        !          2568:     }
        !          2569: }
        !          2570: 
        !          2571: /* Make an insn of code CALL_INSN with pattern PATTERN
        !          2572:    and add it to the end of the doubly-linked list.  */
        !          2573: 
        !          2574: rtx
        !          2575: emit_call_insn (pattern)
        !          2576:      rtx pattern;
        !          2577: {
        !          2578:   if (GET_CODE (pattern) == SEQUENCE)
        !          2579:     return emit_insn (pattern);
        !          2580:   else
        !          2581:     {
        !          2582:       register rtx insn = make_insn_raw (pattern);
        !          2583:       add_insn (insn);
        !          2584:       PUT_CODE (insn, CALL_INSN);
        !          2585:       return insn;
        !          2586:     }
        !          2587: }
        !          2588: 
        !          2589: /* Add the label LABEL to the end of the doubly-linked list.  */
        !          2590: 
        !          2591: rtx
        !          2592: emit_label (label)
        !          2593:      rtx label;
        !          2594: {
        !          2595:   /* This can be called twice for the same label
        !          2596:      as a result of the confusion that follows a syntax error!
        !          2597:      So make it harmless.  */
        !          2598:   if (INSN_UID (label) == 0)
        !          2599:     {
        !          2600:       INSN_UID (label) = cur_insn_uid++;
        !          2601:       add_insn (label);
        !          2602:     }
        !          2603:   return label;
        !          2604: }
        !          2605: 
        !          2606: /* Make an insn of code BARRIER
        !          2607:    and add it to the end of the doubly-linked list.  */
        !          2608: 
        !          2609: rtx
        !          2610: emit_barrier ()
        !          2611: {
        !          2612:   register rtx barrier = rtx_alloc (BARRIER);
        !          2613:   INSN_UID (barrier) = cur_insn_uid++;
        !          2614:   add_insn (barrier);
        !          2615:   return barrier;
        !          2616: }
        !          2617: 
        !          2618: /* Make an insn of code NOTE
        !          2619:    with data-fields specified by FILE and LINE
        !          2620:    and add it to the end of the doubly-linked list,
        !          2621:    but only if line-numbers are desired for debugging info.  */
        !          2622: 
        !          2623: rtx
        !          2624: emit_line_note (file, line)
        !          2625:      char *file;
        !          2626:      int line;
        !          2627: {
        !          2628:   if (output_bytecode)
        !          2629:     {
        !          2630:       /* FIXME: for now we do nothing, but eventually we will have to deal with
        !          2631:         debugging information.  */
        !          2632:       return 0;
        !          2633:     }
        !          2634: 
        !          2635:   emit_filename = file;
        !          2636:   emit_lineno = line;
        !          2637: 
        !          2638: #if 0
        !          2639:   if (no_line_numbers)
        !          2640:     return 0;
        !          2641: #endif
        !          2642: 
        !          2643:   return emit_note (file, line);
        !          2644: }
        !          2645: 
        !          2646: /* Make an insn of code NOTE
        !          2647:    with data-fields specified by FILE and LINE
        !          2648:    and add it to the end of the doubly-linked list.
        !          2649:    If it is a line-number NOTE, omit it if it matches the previous one.  */
        !          2650: 
        !          2651: rtx
        !          2652: emit_note (file, line)
        !          2653:      char *file;
        !          2654:      int line;
        !          2655: {
        !          2656:   register rtx note;
        !          2657: 
        !          2658:   if (line > 0)
        !          2659:     {
        !          2660:       if (file && last_filename && !strcmp (file, last_filename)
        !          2661:          && line == last_linenum)
        !          2662:        return 0;
        !          2663:       last_filename = file;
        !          2664:       last_linenum = line;
        !          2665:     }
        !          2666: 
        !          2667:   if (no_line_numbers && line > 0)
        !          2668:     {
        !          2669:       cur_insn_uid++;
        !          2670:       return 0;
        !          2671:     }
        !          2672: 
        !          2673:   note = rtx_alloc (NOTE);
        !          2674:   INSN_UID (note) = cur_insn_uid++;
        !          2675:   NOTE_SOURCE_FILE (note) = file;
        !          2676:   NOTE_LINE_NUMBER (note) = line;
        !          2677:   add_insn (note);
        !          2678:   return note;
        !          2679: }
        !          2680: 
        !          2681: /* Emit a NOTE, and don't omit it even if LINE it the previous note.  */
        !          2682: 
        !          2683: rtx
        !          2684: emit_line_note_force (file, line)
        !          2685:      char *file;
        !          2686:      int line;
        !          2687: {
        !          2688:   last_linenum = -1;
        !          2689:   return emit_line_note (file, line);
        !          2690: }
        !          2691: 
        !          2692: /* Cause next statement to emit a line note even if the line number
        !          2693:    has not changed.  This is used at the beginning of a function.  */
        !          2694: 
        !          2695: void
        !          2696: force_next_line_note ()
        !          2697: {
        !          2698:   last_linenum = -1;
        !          2699: }
        !          2700: 
        !          2701: /* Return an indication of which type of insn should have X as a body.
        !          2702:    The value is CODE_LABEL, INSN, CALL_INSN or JUMP_INSN.  */
        !          2703: 
        !          2704: enum rtx_code
        !          2705: classify_insn (x)
        !          2706:      rtx x;
        !          2707: {
        !          2708:   if (GET_CODE (x) == CODE_LABEL)
        !          2709:     return CODE_LABEL;
        !          2710:   if (GET_CODE (x) == CALL)
        !          2711:     return CALL_INSN;
        !          2712:   if (GET_CODE (x) == RETURN)
        !          2713:     return JUMP_INSN;
        !          2714:   if (GET_CODE (x) == SET)
        !          2715:     {
        !          2716:       if (SET_DEST (x) == pc_rtx)
        !          2717:        return JUMP_INSN;
        !          2718:       else if (GET_CODE (SET_SRC (x)) == CALL)
        !          2719:        return CALL_INSN;
        !          2720:       else
        !          2721:        return INSN;
        !          2722:     }
        !          2723:   if (GET_CODE (x) == PARALLEL)
        !          2724:     {
        !          2725:       register int j;
        !          2726:       for (j = XVECLEN (x, 0) - 1; j >= 0; j--)
        !          2727:        if (GET_CODE (XVECEXP (x, 0, j)) == CALL)
        !          2728:          return CALL_INSN;
        !          2729:        else if (GET_CODE (XVECEXP (x, 0, j)) == SET
        !          2730:                 && SET_DEST (XVECEXP (x, 0, j)) == pc_rtx)
        !          2731:          return JUMP_INSN;
        !          2732:        else if (GET_CODE (XVECEXP (x, 0, j)) == SET
        !          2733:                 && GET_CODE (SET_SRC (XVECEXP (x, 0, j))) == CALL)
        !          2734:          return CALL_INSN;
        !          2735:     }
        !          2736:   return INSN;
        !          2737: }
        !          2738: 
        !          2739: /* Emit the rtl pattern X as an appropriate kind of insn.
        !          2740:    If X is a label, it is simply added into the insn chain.  */
        !          2741: 
        !          2742: rtx
        !          2743: emit (x)
        !          2744:      rtx x;
        !          2745: {
        !          2746:   enum rtx_code code = classify_insn (x);
        !          2747: 
        !          2748:   if (code == CODE_LABEL)
        !          2749:     return emit_label (x);
        !          2750:   else if (code == INSN)
        !          2751:     return emit_insn (x);
        !          2752:   else if (code == JUMP_INSN)
        !          2753:     {
        !          2754:       register rtx insn = emit_jump_insn (x);
        !          2755:       if (simplejump_p (insn) || GET_CODE (x) == RETURN)
        !          2756:        return emit_barrier ();
        !          2757:       return insn;
        !          2758:     }
        !          2759:   else if (code == CALL_INSN)
        !          2760:     return emit_call_insn (x);
        !          2761:   else
        !          2762:     abort ();
        !          2763: }
        !          2764: 
        !          2765: /* Begin emitting insns to a sequence which can be packaged in an RTL_EXPR.  */
        !          2766: 
        !          2767: void
        !          2768: start_sequence ()
        !          2769: {
        !          2770:   struct sequence_stack *tem;
        !          2771: 
        !          2772:   if (sequence_element_free_list)
        !          2773:     {
        !          2774:       /* Reuse a previously-saved struct sequence_stack.  */
        !          2775:       tem = sequence_element_free_list;
        !          2776:       sequence_element_free_list = tem->next;
        !          2777:     }
        !          2778:   else
        !          2779:     tem = (struct sequence_stack *) permalloc (sizeof (struct sequence_stack));
        !          2780: 
        !          2781:   tem->next = sequence_stack;
        !          2782:   tem->first = first_insn;
        !          2783:   tem->last = last_insn;
        !          2784:   tem->sequence_rtl_expr = sequence_rtl_expr;
        !          2785: 
        !          2786:   sequence_stack = tem;
        !          2787: 
        !          2788:   first_insn = 0;
        !          2789:   last_insn = 0;
        !          2790: }
        !          2791: 
        !          2792: /* Similarly, but indicate that this sequence will be placed in 
        !          2793:    T, an RTL_EXPR.  */
        !          2794: 
        !          2795: void
        !          2796: start_sequence_for_rtl_expr (t)
        !          2797:      tree t;
        !          2798: {
        !          2799:   start_sequence ();
        !          2800: 
        !          2801:   sequence_rtl_expr = t;
        !          2802: }
        !          2803: 
        !          2804: /* Set up the insn chain starting with FIRST
        !          2805:    as the current sequence, saving the previously current one.  */
        !          2806: 
        !          2807: void
        !          2808: push_to_sequence (first)
        !          2809:      rtx first;
        !          2810: {
        !          2811:   rtx last;
        !          2812: 
        !          2813:   start_sequence ();
        !          2814: 
        !          2815:   for (last = first; last && NEXT_INSN (last); last = NEXT_INSN (last));
        !          2816: 
        !          2817:   first_insn = first;
        !          2818:   last_insn = last;
        !          2819: }
        !          2820: 
        !          2821: /* Set up the outer-level insn chain
        !          2822:    as the current sequence, saving the previously current one.  */
        !          2823: 
        !          2824: void
        !          2825: push_topmost_sequence ()
        !          2826: {
        !          2827:   struct sequence_stack *stack, *top;
        !          2828: 
        !          2829:   start_sequence ();
        !          2830: 
        !          2831:   for (stack = sequence_stack; stack; stack = stack->next)
        !          2832:     top = stack;
        !          2833: 
        !          2834:   first_insn = top->first;
        !          2835:   last_insn = top->last;
        !          2836:   sequence_rtl_expr = top->sequence_rtl_expr;
        !          2837: }
        !          2838: 
        !          2839: /* After emitting to the outer-level insn chain, update the outer-level
        !          2840:    insn chain, and restore the previous saved state.  */
        !          2841: 
        !          2842: void
        !          2843: pop_topmost_sequence ()
        !          2844: {
        !          2845:   struct sequence_stack *stack, *top;
        !          2846: 
        !          2847:   for (stack = sequence_stack; stack; stack = stack->next)
        !          2848:     top = stack;
        !          2849: 
        !          2850:   top->first = first_insn;
        !          2851:   top->last = last_insn;
        !          2852:   /* ??? Why don't we save sequence_rtl_expr here?  */
        !          2853: 
        !          2854:   end_sequence ();
        !          2855: }
        !          2856: 
        !          2857: /* After emitting to a sequence, restore previous saved state.
        !          2858: 
        !          2859:    To get the contents of the sequence just made,
        !          2860:    you must call `gen_sequence' *before* calling here.  */
        !          2861: 
        !          2862: void
        !          2863: end_sequence ()
        !          2864: {
        !          2865:   struct sequence_stack *tem = sequence_stack;
        !          2866: 
        !          2867:   first_insn = tem->first;
        !          2868:   last_insn = tem->last;
        !          2869:   sequence_rtl_expr = tem->sequence_rtl_expr;
        !          2870:   sequence_stack = tem->next;
        !          2871: 
        !          2872:   tem->next = sequence_element_free_list;
        !          2873:   sequence_element_free_list = tem;
        !          2874: }
        !          2875: 
        !          2876: /* Return 1 if currently emitting into a sequence.  */
        !          2877: 
        !          2878: int
        !          2879: in_sequence_p ()
        !          2880: {
        !          2881:   return sequence_stack != 0;
        !          2882: }
        !          2883: 
        !          2884: /* Generate a SEQUENCE rtx containing the insns already emitted
        !          2885:    to the current sequence.
        !          2886: 
        !          2887:    This is how the gen_... function from a DEFINE_EXPAND
        !          2888:    constructs the SEQUENCE that it returns.  */
        !          2889: 
        !          2890: rtx
        !          2891: gen_sequence ()
        !          2892: {
        !          2893:   rtx result;
        !          2894:   rtx tem;
        !          2895:   rtvec newvec;
        !          2896:   int i;
        !          2897:   int len;
        !          2898: 
        !          2899:   /* Count the insns in the chain.  */
        !          2900:   len = 0;
        !          2901:   for (tem = first_insn; tem; tem = NEXT_INSN (tem))
        !          2902:     len++;
        !          2903: 
        !          2904:   /* If only one insn, return its pattern rather than a SEQUENCE.
        !          2905:      (Now that we cache SEQUENCE expressions, it isn't worth special-casing
        !          2906:      the case of an empty list.)  */
        !          2907:   if (len == 1
        !          2908:       && (GET_CODE (first_insn) == INSN
        !          2909:          || GET_CODE (first_insn) == JUMP_INSN
        !          2910:          || GET_CODE (first_insn) == CALL_INSN))
        !          2911:     return PATTERN (first_insn);
        !          2912: 
        !          2913:   /* Put them in a vector.  See if we already have a SEQUENCE of the
        !          2914:      appropriate length around.  */
        !          2915:   if (len < SEQUENCE_RESULT_SIZE && (result = sequence_result[len]) != 0)
        !          2916:     sequence_result[len] = 0;
        !          2917:   else
        !          2918:     {
        !          2919:       /* Ensure that this rtl goes in saveable_obstack, since we may be
        !          2920:         caching it.  */
        !          2921:       push_obstacks_nochange ();
        !          2922:       rtl_in_saveable_obstack ();
        !          2923:       result = gen_rtx (SEQUENCE, VOIDmode, rtvec_alloc (len));
        !          2924:       pop_obstacks ();
        !          2925:     }
        !          2926: 
        !          2927:   for (i = 0, tem = first_insn; tem; tem = NEXT_INSN (tem), i++)
        !          2928:     XVECEXP (result, 0, i) = tem;
        !          2929: 
        !          2930:   return result;
        !          2931: }
        !          2932: 
        !          2933: /* Set up regno_reg_rtx, reg_rtx_no and regno_pointer_flag
        !          2934:    according to the chain of insns starting with FIRST.
        !          2935: 
        !          2936:    Also set cur_insn_uid to exceed the largest uid in that chain.
        !          2937: 
        !          2938:    This is used when an inline function's rtl is saved
        !          2939:    and passed to rest_of_compilation later.  */
        !          2940: 
        !          2941: static void restore_reg_data_1 ();
        !          2942: 
        !          2943: void
        !          2944: restore_reg_data (first)
        !          2945:      rtx first;
        !          2946: {
        !          2947:   register rtx insn;
        !          2948:   int i;
        !          2949:   register int max_uid = 0;
        !          2950: 
        !          2951:   for (insn = first; insn; insn = NEXT_INSN (insn))
        !          2952:     {
        !          2953:       if (INSN_UID (insn) >= max_uid)
        !          2954:        max_uid = INSN_UID (insn);
        !          2955: 
        !          2956:       switch (GET_CODE (insn))
        !          2957:        {
        !          2958:        case NOTE:
        !          2959:        case CODE_LABEL:
        !          2960:        case BARRIER:
        !          2961:          break;
        !          2962: 
        !          2963:        case JUMP_INSN:
        !          2964:        case CALL_INSN:
        !          2965:        case INSN:
        !          2966:          restore_reg_data_1 (PATTERN (insn));
        !          2967:          break;
        !          2968:        }
        !          2969:     }
        !          2970: 
        !          2971:   /* Don't duplicate the uids already in use.  */
        !          2972:   cur_insn_uid = max_uid + 1;
        !          2973: 
        !          2974:   /* If any regs are missing, make them up.  
        !          2975: 
        !          2976:      ??? word_mode is not necessarily the right mode.  Most likely these REGs
        !          2977:      are never used.  At some point this should be checked.  */
        !          2978: 
        !          2979:   for (i = FIRST_PSEUDO_REGISTER; i < reg_rtx_no; i++)
        !          2980:     if (regno_reg_rtx[i] == 0)
        !          2981:       regno_reg_rtx[i] = gen_rtx (REG, word_mode, i);
        !          2982: }
        !          2983: 
        !          2984: static void
        !          2985: restore_reg_data_1 (orig)
        !          2986:      rtx orig;
        !          2987: {
        !          2988:   register rtx x = orig;
        !          2989:   register int i;
        !          2990:   register enum rtx_code code;
        !          2991:   register char *format_ptr;
        !          2992: 
        !          2993:   code = GET_CODE (x);
        !          2994: 
        !          2995:   switch (code)
        !          2996:     {
        !          2997:     case QUEUED:
        !          2998:     case CONST_INT:
        !          2999:     case CONST_DOUBLE:
        !          3000:     case SYMBOL_REF:
        !          3001:     case CODE_LABEL:
        !          3002:     case PC:
        !          3003:     case CC0:
        !          3004:     case LABEL_REF:
        !          3005:       return;
        !          3006: 
        !          3007:     case REG:
        !          3008:       if (REGNO (x) >= FIRST_PSEUDO_REGISTER)
        !          3009:        {
        !          3010:          /* Make sure regno_pointer_flag and regno_reg_rtx are large
        !          3011:             enough to have an element for this pseudo reg number.  */
        !          3012:          if (REGNO (x) >= reg_rtx_no)
        !          3013:            {
        !          3014:              reg_rtx_no = REGNO (x);
        !          3015: 
        !          3016:              if (reg_rtx_no >= regno_pointer_flag_length)
        !          3017:                {
        !          3018:                  int newlen = MAX (regno_pointer_flag_length * 2,
        !          3019:                                    reg_rtx_no + 30);
        !          3020:                  rtx *new1;
        !          3021:                  char *new = (char *) oballoc (newlen);
        !          3022:                  bzero (new, newlen);
        !          3023:                  bcopy (regno_pointer_flag, new, regno_pointer_flag_length);
        !          3024: 
        !          3025:                  new1 = (rtx *) oballoc (newlen * sizeof (rtx));
        !          3026:                  bzero (new1, newlen * sizeof (rtx));
        !          3027:                  bcopy (regno_reg_rtx, new1, regno_pointer_flag_length * sizeof (rtx));
        !          3028: 
        !          3029:                  regno_pointer_flag = new;
        !          3030:                  regno_reg_rtx = new1;
        !          3031:                  regno_pointer_flag_length = newlen;
        !          3032:                }
        !          3033:              reg_rtx_no ++;
        !          3034:            }
        !          3035:          regno_reg_rtx[REGNO (x)] = x;
        !          3036:        }
        !          3037:       return;
        !          3038: 
        !          3039:     case MEM:
        !          3040:       if (GET_CODE (XEXP (x, 0)) == REG)
        !          3041:        mark_reg_pointer (XEXP (x, 0));
        !          3042:       restore_reg_data_1 (XEXP (x, 0));
        !          3043:       return;
        !          3044:     }
        !          3045: 
        !          3046:   /* Now scan the subexpressions recursively.  */
        !          3047: 
        !          3048:   format_ptr = GET_RTX_FORMAT (code);
        !          3049: 
        !          3050:   for (i = 0; i < GET_RTX_LENGTH (code); i++)
        !          3051:     {
        !          3052:       switch (*format_ptr++)
        !          3053:        {
        !          3054:        case 'e':
        !          3055:          restore_reg_data_1 (XEXP (x, i));
        !          3056:          break;
        !          3057: 
        !          3058:        case 'E':
        !          3059:          if (XVEC (x, i) != NULL)
        !          3060:            {
        !          3061:              register int j;
        !          3062: 
        !          3063:              for (j = 0; j < XVECLEN (x, i); j++)
        !          3064:                restore_reg_data_1 (XVECEXP (x, i, j));
        !          3065:            }
        !          3066:          break;
        !          3067:        }
        !          3068:     }
        !          3069: }
        !          3070: 
        !          3071: /* Initialize data structures and variables in this file
        !          3072:    before generating rtl for each function.  */
        !          3073: 
        !          3074: void
        !          3075: init_emit ()
        !          3076: {
        !          3077:   int i;
        !          3078: 
        !          3079:   first_insn = NULL;
        !          3080:   last_insn = NULL;
        !          3081:   sequence_rtl_expr = NULL;
        !          3082:   cur_insn_uid = 1;
        !          3083:   reg_rtx_no = LAST_VIRTUAL_REGISTER + 1;
        !          3084:   last_linenum = 0;
        !          3085:   last_filename = 0;
        !          3086:   first_label_num = label_num;
        !          3087:   last_label_num = 0;
        !          3088:   sequence_stack = NULL;
        !          3089: 
        !          3090:   /* Clear the start_sequence/gen_sequence cache.  */
        !          3091:   sequence_element_free_list = 0;
        !          3092:   for (i = 0; i < SEQUENCE_RESULT_SIZE; i++)
        !          3093:     sequence_result[i] = 0;
        !          3094: 
        !          3095:   /* Init the tables that describe all the pseudo regs.  */
        !          3096: 
        !          3097:   regno_pointer_flag_length = LAST_VIRTUAL_REGISTER + 101;
        !          3098: 
        !          3099:   regno_pointer_flag 
        !          3100:     = (char *) oballoc (regno_pointer_flag_length);
        !          3101:   bzero (regno_pointer_flag, regno_pointer_flag_length);
        !          3102: 
        !          3103:   regno_reg_rtx 
        !          3104:     = (rtx *) oballoc (regno_pointer_flag_length * sizeof (rtx));
        !          3105:   bzero (regno_reg_rtx, regno_pointer_flag_length * sizeof (rtx));
        !          3106: 
        !          3107:   /* Put copies of all the virtual register rtx into regno_reg_rtx.  */
        !          3108:   regno_reg_rtx[VIRTUAL_INCOMING_ARGS_REGNUM] = virtual_incoming_args_rtx;
        !          3109:   regno_reg_rtx[VIRTUAL_STACK_VARS_REGNUM] = virtual_stack_vars_rtx;
        !          3110:   regno_reg_rtx[VIRTUAL_STACK_DYNAMIC_REGNUM] = virtual_stack_dynamic_rtx;
        !          3111:   regno_reg_rtx[VIRTUAL_OUTGOING_ARGS_REGNUM] = virtual_outgoing_args_rtx;
        !          3112: 
        !          3113:   /* Indicate that the virtual registers and stack locations are
        !          3114:      all pointers.  */
        !          3115:   REGNO_POINTER_FLAG (STACK_POINTER_REGNUM) = 1;
        !          3116:   REGNO_POINTER_FLAG (FRAME_POINTER_REGNUM) = 1;
        !          3117:   REGNO_POINTER_FLAG (ARG_POINTER_REGNUM) = 1;
        !          3118: 
        !          3119:   REGNO_POINTER_FLAG (VIRTUAL_INCOMING_ARGS_REGNUM) = 1;
        !          3120:   REGNO_POINTER_FLAG (VIRTUAL_STACK_VARS_REGNUM) = 1;
        !          3121:   REGNO_POINTER_FLAG (VIRTUAL_STACK_DYNAMIC_REGNUM) = 1;
        !          3122:   REGNO_POINTER_FLAG (VIRTUAL_OUTGOING_ARGS_REGNUM) = 1;
        !          3123: 
        !          3124: #ifdef INIT_EXPANDERS
        !          3125:   INIT_EXPANDERS;
        !          3126: #endif
        !          3127: }
        !          3128: 
        !          3129: /* Create some permanent unique rtl objects shared between all functions.
        !          3130:    LINE_NUMBERS is nonzero if line numbers are to be generated.  */
        !          3131: 
        !          3132: void
        !          3133: init_emit_once (line_numbers)
        !          3134:      int line_numbers;
        !          3135: {
        !          3136:   int i;
        !          3137:   enum machine_mode mode;
        !          3138: 
        !          3139:   no_line_numbers = ! line_numbers;
        !          3140: 
        !          3141:   sequence_stack = NULL;
        !          3142: 
        !          3143:   /* Compute the word and byte modes.  */
        !          3144: 
        !          3145:   byte_mode = VOIDmode;
        !          3146:   word_mode = VOIDmode;
        !          3147: 
        !          3148:   for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode;
        !          3149:        mode = GET_MODE_WIDER_MODE (mode))
        !          3150:     {
        !          3151:       if (GET_MODE_BITSIZE (mode) == BITS_PER_UNIT
        !          3152:          && byte_mode == VOIDmode)
        !          3153:        byte_mode = mode;
        !          3154: 
        !          3155:       if (GET_MODE_BITSIZE (mode) == BITS_PER_WORD
        !          3156:          && word_mode == VOIDmode)
        !          3157:        word_mode = mode;
        !          3158:     }
        !          3159: 
        !          3160:   /* Create the unique rtx's for certain rtx codes and operand values.  */
        !          3161: 
        !          3162:   pc_rtx = gen_rtx (PC, VOIDmode);
        !          3163:   cc0_rtx = gen_rtx (CC0, VOIDmode);
        !          3164: 
        !          3165:   /* Don't use gen_rtx here since gen_rtx in this case
        !          3166:      tries to use these variables.  */
        !          3167:   for (i = - MAX_SAVED_CONST_INT; i <= MAX_SAVED_CONST_INT; i++)
        !          3168:     {
        !          3169:       const_int_rtx[i + MAX_SAVED_CONST_INT] = rtx_alloc (CONST_INT);
        !          3170:       PUT_MODE (const_int_rtx[i + MAX_SAVED_CONST_INT], VOIDmode);
        !          3171:       INTVAL (const_int_rtx[i + MAX_SAVED_CONST_INT]) = i;
        !          3172:     }
        !          3173: 
        !          3174:   /* These four calls obtain some of the rtx expressions made above.  */
        !          3175:   const0_rtx = GEN_INT (0);
        !          3176:   const1_rtx = GEN_INT (1);
        !          3177:   const2_rtx = GEN_INT (2);
        !          3178:   constm1_rtx = GEN_INT (-1);
        !          3179: 
        !          3180:   /* This will usually be one of the above constants, but may be a new rtx.  */
        !          3181:   const_true_rtx = GEN_INT (STORE_FLAG_VALUE);
        !          3182: 
        !          3183:   dconst0 = REAL_VALUE_ATOF ("0", DFmode);
        !          3184:   dconst1 = REAL_VALUE_ATOF ("1", DFmode);
        !          3185:   dconst2 = REAL_VALUE_ATOF ("2", DFmode);
        !          3186:   dconstm1 = REAL_VALUE_ATOF ("-1", DFmode);
        !          3187: 
        !          3188:   for (i = 0; i <= 2; i++)
        !          3189:     {
        !          3190:       for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); mode != VOIDmode;
        !          3191:           mode = GET_MODE_WIDER_MODE (mode))
        !          3192:        {
        !          3193:          rtx tem = rtx_alloc (CONST_DOUBLE);
        !          3194:          union real_extract u;
        !          3195: 
        !          3196:          bzero (&u, sizeof u);  /* Zero any holes in a structure.  */
        !          3197:          u.d = i == 0 ? dconst0 : i == 1 ? dconst1 : dconst2;
        !          3198: 
        !          3199:          bcopy (&u, &CONST_DOUBLE_LOW (tem), sizeof u);
        !          3200:          CONST_DOUBLE_MEM (tem) = cc0_rtx;
        !          3201:          PUT_MODE (tem, mode);
        !          3202: 
        !          3203:          const_tiny_rtx[i][(int) mode] = tem;
        !          3204:        }
        !          3205: 
        !          3206:       const_tiny_rtx[i][(int) VOIDmode] = GEN_INT (i);
        !          3207: 
        !          3208:       for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode;
        !          3209:           mode = GET_MODE_WIDER_MODE (mode))
        !          3210:        const_tiny_rtx[i][(int) mode] = GEN_INT (i);
        !          3211: 
        !          3212:       for (mode = GET_CLASS_NARROWEST_MODE (MODE_PARTIAL_INT);
        !          3213:           mode != VOIDmode;
        !          3214:           mode = GET_MODE_WIDER_MODE (mode))
        !          3215:        const_tiny_rtx[i][(int) mode] = GEN_INT (i);
        !          3216:     }
        !          3217: 
        !          3218:   for (mode = GET_CLASS_NARROWEST_MODE (MODE_CC); mode != VOIDmode;
        !          3219:        mode = GET_MODE_WIDER_MODE (mode))
        !          3220:     const_tiny_rtx[0][(int) mode] = const0_rtx;
        !          3221: 
        !          3222:   stack_pointer_rtx = gen_rtx (REG, Pmode, STACK_POINTER_REGNUM);
        !          3223:   frame_pointer_rtx = gen_rtx (REG, Pmode, FRAME_POINTER_REGNUM);
        !          3224: 
        !          3225:   if (HARD_FRAME_POINTER_REGNUM == FRAME_POINTER_REGNUM)
        !          3226:     hard_frame_pointer_rtx = frame_pointer_rtx;
        !          3227:   else
        !          3228:     hard_frame_pointer_rtx = gen_rtx (REG, Pmode, HARD_FRAME_POINTER_REGNUM);
        !          3229:   
        !          3230:   if (FRAME_POINTER_REGNUM == ARG_POINTER_REGNUM)
        !          3231:     arg_pointer_rtx = frame_pointer_rtx;
        !          3232:   else if (HARD_FRAME_POINTER_REGNUM == ARG_POINTER_REGNUM)
        !          3233:     arg_pointer_rtx = hard_frame_pointer_rtx;
        !          3234:   else if (STACK_POINTER_REGNUM == ARG_POINTER_REGNUM)
        !          3235:     arg_pointer_rtx = stack_pointer_rtx;
        !          3236:   else
        !          3237:     arg_pointer_rtx = gen_rtx (REG, Pmode, ARG_POINTER_REGNUM);
        !          3238: 
        !          3239:   /* Create the virtual registers.  Do so here since the following objects
        !          3240:      might reference them.  */
        !          3241: 
        !          3242:   virtual_incoming_args_rtx = gen_rtx (REG, Pmode,
        !          3243:                                       VIRTUAL_INCOMING_ARGS_REGNUM);
        !          3244:   virtual_stack_vars_rtx = gen_rtx (REG, Pmode,
        !          3245:                                    VIRTUAL_STACK_VARS_REGNUM);
        !          3246:   virtual_stack_dynamic_rtx = gen_rtx (REG, Pmode,
        !          3247:                                       VIRTUAL_STACK_DYNAMIC_REGNUM);
        !          3248:   virtual_outgoing_args_rtx = gen_rtx (REG, Pmode,
        !          3249:                                       VIRTUAL_OUTGOING_ARGS_REGNUM);
        !          3250: 
        !          3251: #ifdef STRUCT_VALUE
        !          3252:   struct_value_rtx = STRUCT_VALUE;
        !          3253: #else
        !          3254:   struct_value_rtx = gen_rtx (REG, Pmode, STRUCT_VALUE_REGNUM);
        !          3255: #endif
        !          3256: 
        !          3257: #ifdef STRUCT_VALUE_INCOMING
        !          3258:   struct_value_incoming_rtx = STRUCT_VALUE_INCOMING;
        !          3259: #else
        !          3260: #ifdef STRUCT_VALUE_INCOMING_REGNUM
        !          3261:   struct_value_incoming_rtx
        !          3262:     = gen_rtx (REG, Pmode, STRUCT_VALUE_INCOMING_REGNUM);
        !          3263: #else
        !          3264:   struct_value_incoming_rtx = struct_value_rtx;
        !          3265: #endif
        !          3266: #endif
        !          3267: 
        !          3268: #ifdef STATIC_CHAIN_REGNUM
        !          3269:   static_chain_rtx = gen_rtx (REG, Pmode, STATIC_CHAIN_REGNUM);
        !          3270: 
        !          3271: #ifdef STATIC_CHAIN_INCOMING_REGNUM
        !          3272:   if (STATIC_CHAIN_INCOMING_REGNUM != STATIC_CHAIN_REGNUM)
        !          3273:     static_chain_incoming_rtx = gen_rtx (REG, Pmode, STATIC_CHAIN_INCOMING_REGNUM);
        !          3274:   else
        !          3275: #endif
        !          3276:     static_chain_incoming_rtx = static_chain_rtx;
        !          3277: #endif
        !          3278: 
        !          3279: #ifdef STATIC_CHAIN
        !          3280:   static_chain_rtx = STATIC_CHAIN;
        !          3281: 
        !          3282: #ifdef STATIC_CHAIN_INCOMING
        !          3283:   static_chain_incoming_rtx = STATIC_CHAIN_INCOMING;
        !          3284: #else
        !          3285:   static_chain_incoming_rtx = static_chain_rtx;
        !          3286: #endif
        !          3287: #endif
        !          3288: 
        !          3289: #ifdef PIC_OFFSET_TABLE_REGNUM
        !          3290:   pic_offset_table_rtx = gen_rtx (REG, Pmode, PIC_OFFSET_TABLE_REGNUM);
        !          3291: #endif
        !          3292: }

unix.superglobalmegacorp.com

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