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

1.1     ! root        1: /* Subroutines used by or related to instruction recognition.
        !             2:    Copyright (C) 1987, 1988, 1991, 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: #include "config.h"
        !            22: #include "rtl.h"
        !            23: #include <stdio.h>
        !            24: #include "insn-config.h"
        !            25: #include "insn-attr.h"
        !            26: #include "insn-flags.h"
        !            27: #include "insn-codes.h"
        !            28: #include "recog.h"
        !            29: #include "regs.h"
        !            30: #include "hard-reg-set.h"
        !            31: #include "flags.h"
        !            32: #include "real.h"
        !            33: 
        !            34: #ifndef STACK_PUSH_CODE
        !            35: #ifdef STACK_GROWS_DOWNWARD
        !            36: #define STACK_PUSH_CODE PRE_DEC
        !            37: #else
        !            38: #define STACK_PUSH_CODE PRE_INC
        !            39: #endif
        !            40: #endif
        !            41: 
        !            42: /* Import from final.c: */
        !            43: extern rtx alter_subreg ();
        !            44: 
        !            45: int strict_memory_address_p ();
        !            46: int memory_address_p ();
        !            47: 
        !            48: /* Nonzero means allow operands to be volatile.
        !            49:    This should be 0 if you are generating rtl, such as if you are calling
        !            50:    the functions in optabs.c and expmed.c (most of the time).
        !            51:    This should be 1 if all valid insns need to be recognized,
        !            52:    such as in regclass.c and final.c and reload.c.
        !            53: 
        !            54:    init_recog and init_recog_no_volatile are responsible for setting this.  */
        !            55: 
        !            56: int volatile_ok;
        !            57: 
        !            58: /* On return from `constrain_operands', indicate which alternative
        !            59:    was satisfied.  */
        !            60: 
        !            61: int which_alternative;
        !            62: 
        !            63: /* Nonzero after end of reload pass.
        !            64:    Set to 1 or 0 by toplev.c.
        !            65:    Controls the significance of (SUBREG (MEM)).  */
        !            66: 
        !            67: int reload_completed;
        !            68: 
        !            69: /* Initialize data used by the function `recog'.
        !            70:    This must be called once in the compilation of a function
        !            71:    before any insn recognition may be done in the function.  */
        !            72: 
        !            73: void
        !            74: init_recog_no_volatile ()
        !            75: {
        !            76:   volatile_ok = 0;
        !            77: }
        !            78: 
        !            79: void
        !            80: init_recog ()
        !            81: {
        !            82:   volatile_ok = 1;
        !            83: }
        !            84: 
        !            85: /* Try recognizing the instruction INSN,
        !            86:    and return the code number that results.
        !            87:    Remeber the code so that repeated calls do not
        !            88:    need to spend the time for actual rerecognition.
        !            89: 
        !            90:    This function is the normal interface to instruction recognition.
        !            91:    The automatically-generated function `recog' is normally called
        !            92:    through this one.  (The only exception is in combine.c.)  */
        !            93: 
        !            94: int
        !            95: recog_memoized (insn)
        !            96:      rtx insn;
        !            97: {
        !            98:   if (INSN_CODE (insn) < 0)
        !            99:     INSN_CODE (insn) = recog (PATTERN (insn), insn, NULL_PTR);
        !           100:   return INSN_CODE (insn);
        !           101: }
        !           102: 
        !           103: /* Check that X is an insn-body for an `asm' with operands
        !           104:    and that the operands mentioned in it are legitimate.  */
        !           105: 
        !           106: int
        !           107: check_asm_operands (x)
        !           108:      rtx x;
        !           109: {
        !           110:   int noperands = asm_noperands (x);
        !           111:   rtx *operands;
        !           112:   int i;
        !           113: 
        !           114:   if (noperands < 0)
        !           115:     return 0;
        !           116:   if (noperands == 0)
        !           117:     return 1;
        !           118: 
        !           119:   operands = (rtx *) alloca (noperands * sizeof (rtx));
        !           120:   decode_asm_operands (x, operands, NULL_PTR, NULL_PTR, NULL_PTR);
        !           121: 
        !           122:   for (i = 0; i < noperands; i++)
        !           123:     if (!general_operand (operands[i], VOIDmode))
        !           124:       return 0;
        !           125: 
        !           126:   return 1;
        !           127: }
        !           128: 
        !           129: /* Static data for the next two routines.
        !           130: 
        !           131:    The maximum number of changes supported is defined as the maximum
        !           132:    number of operands times 5.  This allows for repeated substitutions
        !           133:    inside complex indexed address, or, alternatively, changes in up
        !           134:    to 5 insns.  */
        !           135: 
        !           136: #define MAX_CHANGE_LOCS        (MAX_RECOG_OPERANDS * 5)
        !           137: 
        !           138: static rtx change_objects[MAX_CHANGE_LOCS];
        !           139: static int change_old_codes[MAX_CHANGE_LOCS];
        !           140: static rtx *change_locs[MAX_CHANGE_LOCS];
        !           141: static rtx change_olds[MAX_CHANGE_LOCS];
        !           142: 
        !           143: static int num_changes = 0;
        !           144: 
        !           145: /* Validate a proposed change to OBJECT.  LOC is the location in the rtl for
        !           146:    at which NEW will be placed.  If OBJECT is zero, no validation is done,
        !           147:    the change is simply made.
        !           148: 
        !           149:    Two types of objects are supported:  If OBJECT is a MEM, memory_address_p
        !           150:    will be called with the address and mode as parameters.  If OBJECT is
        !           151:    an INSN, CALL_INSN, or JUMP_INSN, the insn will be re-recognized with
        !           152:    the change in place.
        !           153: 
        !           154:    IN_GROUP is non-zero if this is part of a group of changes that must be
        !           155:    performed as a group.  In that case, the changes will be stored.  The
        !           156:    function `apply_change_group' will validate and apply the changes.
        !           157: 
        !           158:    If IN_GROUP is zero, this is a single change.  Try to recognize the insn
        !           159:    or validate the memory reference with the change applied.  If the result
        !           160:    is not valid for the machine, suppress the change and return zero.
        !           161:    Otherwise, perform the change and return 1.  */
        !           162: 
        !           163: int
        !           164: validate_change (object, loc, new, in_group)
        !           165:     rtx object;
        !           166:     rtx *loc;
        !           167:     rtx new;
        !           168:     int in_group;
        !           169: {
        !           170:   rtx old = *loc;
        !           171: 
        !           172:   if (old == new || rtx_equal_p (old, new))
        !           173:     return 1;
        !           174: 
        !           175:   if (num_changes >= MAX_CHANGE_LOCS
        !           176:       || (in_group == 0 && num_changes != 0))
        !           177:     abort ();
        !           178: 
        !           179:   *loc = new;
        !           180: 
        !           181:   /* Save the information describing this change.  */
        !           182:   change_objects[num_changes] = object;
        !           183:   change_locs[num_changes] = loc;
        !           184:   change_olds[num_changes] = old;
        !           185: 
        !           186:   if (object && GET_CODE (object) != MEM)
        !           187:     {
        !           188:       /* Set INSN_CODE to force rerecognition of insn.  Save old code in
        !           189:         case invalid.  */
        !           190:       change_old_codes[num_changes] = INSN_CODE (object);
        !           191:       INSN_CODE (object) = -1;
        !           192:     }
        !           193: 
        !           194:   num_changes++;
        !           195: 
        !           196:   /* If we are making a group of changes, return 1.  Otherwise, validate the
        !           197:      change group we made.  */
        !           198: 
        !           199:   if (in_group)
        !           200:     return 1;
        !           201:   else
        !           202:     return apply_change_group ();
        !           203: }
        !           204: 
        !           205: /* Apply a group of changes previously issued with `validate_change'.
        !           206:    Return 1 if all changes are valid, zero otherwise.  */
        !           207: 
        !           208: int
        !           209: apply_change_group ()
        !           210: {
        !           211:   int i;
        !           212: 
        !           213:   /* The changes have been applied and all INSN_CODEs have been reset to force
        !           214:      rerecognition.
        !           215: 
        !           216:      The changes are valid if we aren't given an object, or if we are
        !           217:      given a MEM and it still is a valid address, or if this is in insn
        !           218:      and it is recognized.  In the latter case, if reload has completed,
        !           219:      we also require that the operands meet the constraints for
        !           220:      the insn.  We do not allow modifying an ASM_OPERANDS after reload
        !           221:      has completed because verifying the constraints is too difficult.  */
        !           222: 
        !           223:   for (i = 0; i < num_changes; i++)
        !           224:     {
        !           225:       rtx object = change_objects[i];
        !           226: 
        !           227:       if (object == 0)
        !           228:        continue;
        !           229: 
        !           230:       if (GET_CODE (object) == MEM)
        !           231:        {
        !           232:          if (! memory_address_p (GET_MODE (object), XEXP (object, 0)))
        !           233:            break;
        !           234:        }
        !           235:       else if ((recog_memoized (object) < 0
        !           236:                && (asm_noperands (PATTERN (object)) < 0
        !           237:                    || ! check_asm_operands (PATTERN (object))
        !           238:                    || reload_completed))
        !           239:               || (reload_completed
        !           240:                   && (insn_extract (object),
        !           241:                       ! constrain_operands (INSN_CODE (object), 1))))
        !           242:        {
        !           243:          rtx pat = PATTERN (object);
        !           244: 
        !           245:          /* Perhaps we couldn't recognize the insn because there were
        !           246:             extra CLOBBERs at the end.  If so, try to re-recognize
        !           247:             without the last CLOBBER (later iterations will cause each of
        !           248:             them to be eliminated, in turn).  But don't do this if we
        !           249:             have an ASM_OPERAND.  */
        !           250:          if (GET_CODE (pat) == PARALLEL
        !           251:              && GET_CODE (XVECEXP (pat, 0, XVECLEN (pat, 0) - 1)) == CLOBBER
        !           252:              && asm_noperands (PATTERN (object)) < 0)
        !           253:            {
        !           254:               rtx newpat;
        !           255: 
        !           256:               if (XVECLEN (pat, 0) == 2)
        !           257:                 newpat = XVECEXP (pat, 0, 0);
        !           258:               else
        !           259:                 {
        !           260:                   int j;
        !           261: 
        !           262:                   newpat = gen_rtx (PARALLEL, VOIDmode, 
        !           263:                                     gen_rtvec (XVECLEN (pat, 0) - 1));
        !           264:                   for (j = 0; j < XVECLEN (newpat, 0); j++)
        !           265:                     XVECEXP (newpat, 0, j) = XVECEXP (pat, 0, j);
        !           266:                 }
        !           267: 
        !           268:               /* Add a new change to this group to replace the pattern
        !           269:                  with this new pattern.  Then consider this change
        !           270:                  as having succeeded.  The change we added will
        !           271:                  cause the entire call to fail if things remain invalid.
        !           272: 
        !           273:                  Note that this can lose if a later change than the one
        !           274:                  we are processing specified &XVECEXP (PATTERN (object), 0, X)
        !           275:                  but this shouldn't occur.  */
        !           276: 
        !           277:               validate_change (object, &PATTERN (object), newpat, 1);
        !           278:             }
        !           279:          else if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER)
        !           280:            /* If this insn is a CLOBBER or USE, it is always valid, but is
        !           281:               never recognized.  */
        !           282:            continue;
        !           283:          else
        !           284:            break;
        !           285:        }
        !           286:     }
        !           287: 
        !           288:   if (i == num_changes)
        !           289:     {
        !           290:       num_changes = 0;
        !           291:       return 1;
        !           292:     }
        !           293:   else
        !           294:     {
        !           295:       cancel_changes (0);
        !           296:       return 0;
        !           297:     }
        !           298: }
        !           299: 
        !           300: /* Return the number of changes so far in the current group.   */
        !           301: 
        !           302: int
        !           303: num_validated_changes ()
        !           304: {
        !           305:   return num_changes;
        !           306: }
        !           307: 
        !           308: /* Retract the changes numbered NUM and up.  */
        !           309: 
        !           310: void
        !           311: cancel_changes (num)
        !           312:      int num;
        !           313: {
        !           314:   int i;
        !           315: 
        !           316:   /* Back out all the changes.  Do this in the opposite order in which
        !           317:      they were made.  */
        !           318:   for (i = num_changes - 1; i >= num; i--)
        !           319:     {
        !           320:       *change_locs[i] = change_olds[i];
        !           321:       if (change_objects[i] && GET_CODE (change_objects[i]) != MEM)
        !           322:        INSN_CODE (change_objects[i]) = change_old_codes[i];
        !           323:     }
        !           324:   num_changes = num;
        !           325: }
        !           326: 
        !           327: /* Replace every occurrence of FROM in X with TO.  Mark each change with
        !           328:    validate_change passing OBJECT.  */
        !           329: 
        !           330: static void
        !           331: validate_replace_rtx_1 (loc, from, to, object)
        !           332:      rtx *loc;
        !           333:      rtx from, to, object;
        !           334: {
        !           335:   register int i, j;
        !           336:   register char *fmt;
        !           337:   register rtx x = *loc;
        !           338:   enum rtx_code code = GET_CODE (x);
        !           339: 
        !           340:   /* X matches FROM if it is the same rtx or they are both referring to the
        !           341:      same register in the same mode.  Avoid calling rtx_equal_p unless the
        !           342:      operands look similar.  */
        !           343: 
        !           344:   if (x == from
        !           345:       || (GET_CODE (x) == REG && GET_CODE (from) == REG
        !           346:          && GET_MODE (x) == GET_MODE (from)
        !           347:          && REGNO (x) == REGNO (from))
        !           348:       || (GET_CODE (x) == GET_CODE (from) && GET_MODE (x) == GET_MODE (from)
        !           349:          && rtx_equal_p (x, from)))
        !           350:     {
        !           351:       validate_change (object, loc, to, 1);
        !           352:       return;
        !           353:     }
        !           354: 
        !           355:   /* For commutative or comparison operations, try replacing each argument
        !           356:      separately and seeing if we made any changes.  If so, put a constant
        !           357:      argument last.*/
        !           358:   if (GET_RTX_CLASS (code) == '<' || GET_RTX_CLASS (code) == 'c')
        !           359:     {
        !           360:       int prev_changes = num_changes;
        !           361: 
        !           362:       validate_replace_rtx_1 (&XEXP (x, 0), from, to, object);
        !           363:       validate_replace_rtx_1 (&XEXP (x, 1), from, to, object);
        !           364:       if (prev_changes != num_changes && CONSTANT_P (XEXP (x, 0)))
        !           365:        {
        !           366:          validate_change (object, loc,
        !           367:                           gen_rtx (GET_RTX_CLASS (code) == 'c' ? code
        !           368:                                    : swap_condition (code),
        !           369:                                    GET_MODE (x), XEXP (x, 1), XEXP (x, 0)),
        !           370:                           1);
        !           371:          x = *loc;
        !           372:          code = GET_CODE (x);
        !           373:        }
        !           374:     }
        !           375: 
        !           376:   switch (code)
        !           377:     {
        !           378:     case PLUS:
        !           379:       /* If we have have a PLUS whose second operand is now a CONST_INT, use
        !           380:         plus_constant to try to simplify it.  */
        !           381:       if (GET_CODE (XEXP (x, 1)) == CONST_INT && XEXP (x, 1) == to)
        !           382:        validate_change (object, loc, 
        !           383:                         plus_constant (XEXP (x, 0), INTVAL (XEXP (x, 1))), 1);
        !           384:       return;
        !           385:       
        !           386:     case ZERO_EXTEND:
        !           387:     case SIGN_EXTEND:
        !           388:       /* In these cases, the operation to be performed depends on the mode
        !           389:         of the operand.  If we are replacing the operand with a VOIDmode
        !           390:         constant, we lose the information.  So try to simplify the operation
        !           391:         in that case.  If it fails, substitute in something that we know
        !           392:         won't be recognized.  */
        !           393:       if (GET_MODE (to) == VOIDmode
        !           394:          && (XEXP (x, 0) == from
        !           395:              || (GET_CODE (XEXP (x, 0)) == REG && GET_CODE (from) == REG
        !           396:                  && GET_MODE (XEXP (x, 0)) == GET_MODE (from)
        !           397:                  && REGNO (XEXP (x, 0)) == REGNO (from))))
        !           398:        {
        !           399:          rtx new = simplify_unary_operation (code, GET_MODE (x), to,
        !           400:                                              GET_MODE (from));
        !           401:          if (new == 0)
        !           402:            new = gen_rtx (CLOBBER, GET_MODE (x), const0_rtx);
        !           403: 
        !           404:          validate_change (object, loc, new, 1);
        !           405:          return;
        !           406:        }
        !           407:       break;
        !           408:        
        !           409:     case SUBREG:
        !           410:       /* If we have a SUBREG of a register that we are replacing and we are
        !           411:         replacing it with a MEM, make a new MEM and try replacing the
        !           412:         SUBREG with it.  Don't do this if the MEM has a mode-dependent address
        !           413:         or if we would be widening it.  */
        !           414: 
        !           415:       if (SUBREG_REG (x) == from
        !           416:          && GET_CODE (from) == REG
        !           417:          && GET_CODE (to) == MEM
        !           418:          && ! mode_dependent_address_p (XEXP (to, 0))
        !           419:          && ! MEM_VOLATILE_P (to)
        !           420:          && GET_MODE_SIZE (GET_MODE (x)) <= GET_MODE_SIZE (GET_MODE (to)))
        !           421:        {
        !           422:          int offset = SUBREG_WORD (x) * UNITS_PER_WORD;
        !           423:          enum machine_mode mode = GET_MODE (x);
        !           424:          rtx new;
        !           425: 
        !           426: #if BYTES_BIG_ENDIAN
        !           427:          offset += (MIN (UNITS_PER_WORD,
        !           428:                          GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))
        !           429:                     - MIN (UNITS_PER_WORD, GET_MODE_SIZE (mode)));
        !           430: #endif
        !           431: 
        !           432:          new = gen_rtx (MEM, mode, plus_constant (XEXP (to, 0), offset));
        !           433:          MEM_VOLATILE_P (new) = MEM_VOLATILE_P (to);
        !           434:          RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (to);
        !           435:          MEM_IN_STRUCT_P (new) = MEM_IN_STRUCT_P (to);
        !           436:          validate_change (object, loc, new, 1);
        !           437:          return;
        !           438:        }
        !           439:       break;
        !           440: 
        !           441:     case ZERO_EXTRACT:
        !           442:     case SIGN_EXTRACT:
        !           443:       /* If we are replacing a register with memory, try to change the memory
        !           444:         to be the mode required for memory in extract operations (this isn't
        !           445:         likely to be an insertion operation; if it was, nothing bad will
        !           446:         happen, we might just fail in some cases).  */
        !           447: 
        !           448:       if (XEXP (x, 0) == from && GET_CODE (from) == REG && GET_CODE (to) == MEM
        !           449:          && GET_CODE (XEXP (x, 1)) == CONST_INT
        !           450:          && GET_CODE (XEXP (x, 2)) == CONST_INT
        !           451:          && ! mode_dependent_address_p (XEXP (to, 0))
        !           452:          && ! MEM_VOLATILE_P (to))
        !           453:        {
        !           454:          enum machine_mode wanted_mode = VOIDmode;
        !           455:          enum machine_mode is_mode = GET_MODE (to);
        !           456:          int width = INTVAL (XEXP (x, 1));
        !           457:          int pos = INTVAL (XEXP (x, 2));
        !           458: 
        !           459: #ifdef HAVE_extzv
        !           460:          if (code == ZERO_EXTRACT)
        !           461:            wanted_mode = insn_operand_mode[(int) CODE_FOR_extzv][1];
        !           462: #endif
        !           463: #ifdef HAVE_extv
        !           464:          if (code == SIGN_EXTRACT)
        !           465:            wanted_mode = insn_operand_mode[(int) CODE_FOR_extv][1];
        !           466: #endif
        !           467: 
        !           468:          /* If we have a narrower mode, we can do something.  */
        !           469:          if (wanted_mode != VOIDmode
        !           470:              && GET_MODE_SIZE (wanted_mode) < GET_MODE_SIZE (is_mode))
        !           471:            {
        !           472:              int offset = pos / BITS_PER_UNIT;
        !           473:              rtx newmem;
        !           474: 
        !           475:                  /* If the bytes and bits are counted differently, we
        !           476:                     must adjust the offset.  */
        !           477: #if BYTES_BIG_ENDIAN != BITS_BIG_ENDIAN
        !           478:              offset = (GET_MODE_SIZE (is_mode) - GET_MODE_SIZE (wanted_mode)
        !           479:                        - offset);
        !           480: #endif
        !           481: 
        !           482:              pos %= GET_MODE_BITSIZE (wanted_mode);
        !           483: 
        !           484:              newmem = gen_rtx (MEM, wanted_mode,
        !           485:                                plus_constant (XEXP (to, 0), offset));
        !           486:              RTX_UNCHANGING_P (newmem) = RTX_UNCHANGING_P (to);
        !           487:              MEM_VOLATILE_P (newmem) = MEM_VOLATILE_P (to);
        !           488:              MEM_IN_STRUCT_P (newmem) = MEM_IN_STRUCT_P (to);
        !           489: 
        !           490:              validate_change (object, &XEXP (x, 2), GEN_INT (pos), 1);
        !           491:              validate_change (object, &XEXP (x, 0), newmem, 1);
        !           492:            }
        !           493:        }
        !           494: 
        !           495:       break;
        !           496:     }
        !           497:       
        !           498:   fmt = GET_RTX_FORMAT (code);
        !           499:   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
        !           500:     {
        !           501:       if (fmt[i] == 'e')
        !           502:        validate_replace_rtx_1 (&XEXP (x, i), from, to, object);
        !           503:       else if (fmt[i] == 'E')
        !           504:        for (j = XVECLEN (x, i) - 1; j >= 0; j--)
        !           505:          validate_replace_rtx_1 (&XVECEXP (x, i, j), from, to, object);
        !           506:     }
        !           507: }
        !           508: 
        !           509: /* Try replacing every occurrence of FROM in INSN with TO.  After all
        !           510:    changes have been made, validate by seeing if INSN is still valid.  */
        !           511: 
        !           512: int
        !           513: validate_replace_rtx (from, to, insn)
        !           514:      rtx from, to, insn;
        !           515: {
        !           516:   validate_replace_rtx_1 (&PATTERN (insn), from, to, insn);
        !           517:   return apply_change_group ();
        !           518: }
        !           519: 
        !           520: #ifdef HAVE_cc0
        !           521: /* Return 1 if the insn using CC0 set by INSN does not contain
        !           522:    any ordered tests applied to the condition codes.
        !           523:    EQ and NE tests do not count.  */
        !           524: 
        !           525: int
        !           526: next_insn_tests_no_inequality (insn)
        !           527:      rtx insn;
        !           528: {
        !           529:   register rtx next = next_cc0_user (insn);
        !           530: 
        !           531:   /* If there is no next insn, we have to take the conservative choice.  */
        !           532:   if (next == 0)
        !           533:     return 0;
        !           534: 
        !           535:   return ((GET_CODE (next) == JUMP_INSN
        !           536:           || GET_CODE (next) == INSN
        !           537:           || GET_CODE (next) == CALL_INSN)
        !           538:          && ! inequality_comparisons_p (PATTERN (next)));
        !           539: }
        !           540: 
        !           541: #if 0  /* This is useless since the insn that sets the cc's
        !           542:          must be followed immediately by the use of them.  */
        !           543: /* Return 1 if the CC value set up by INSN is not used.  */
        !           544: 
        !           545: int
        !           546: next_insns_test_no_inequality (insn)
        !           547:      rtx insn;
        !           548: {
        !           549:   register rtx next = NEXT_INSN (insn);
        !           550: 
        !           551:   for (; next != 0; next = NEXT_INSN (next))
        !           552:     {
        !           553:       if (GET_CODE (next) == CODE_LABEL
        !           554:          || GET_CODE (next) == BARRIER)
        !           555:        return 1;
        !           556:       if (GET_CODE (next) == NOTE)
        !           557:        continue;
        !           558:       if (inequality_comparisons_p (PATTERN (next)))
        !           559:        return 0;
        !           560:       if (sets_cc0_p (PATTERN (next)) == 1)
        !           561:        return 1;
        !           562:       if (! reg_mentioned_p (cc0_rtx, PATTERN (next)))
        !           563:        return 1;
        !           564:     }
        !           565:   return 1;
        !           566: }
        !           567: #endif
        !           568: #endif
        !           569: 
        !           570: /* This is used by find_single_use to locate an rtx that contains exactly one
        !           571:    use of DEST, which is typically either a REG or CC0.  It returns a
        !           572:    pointer to the innermost rtx expression containing DEST.  Appearances of
        !           573:    DEST that are being used to totally replace it are not counted.  */
        !           574: 
        !           575: static rtx *
        !           576: find_single_use_1 (dest, loc)
        !           577:      rtx dest;
        !           578:      rtx *loc;
        !           579: {
        !           580:   rtx x = *loc;
        !           581:   enum rtx_code code = GET_CODE (x);
        !           582:   rtx *result = 0;
        !           583:   rtx *this_result;
        !           584:   int i;
        !           585:   char *fmt;
        !           586: 
        !           587:   switch (code)
        !           588:     {
        !           589:     case CONST_INT:
        !           590:     case CONST:
        !           591:     case LABEL_REF:
        !           592:     case SYMBOL_REF:
        !           593:     case CONST_DOUBLE:
        !           594:     case CLOBBER:
        !           595:       return 0;
        !           596: 
        !           597:     case SET:
        !           598:       /* If the destination is anything other than CC0, PC, a REG or a SUBREG
        !           599:         of a REG that occupies all of the REG, the insn uses DEST if
        !           600:         it is mentioned in the destination or the source.  Otherwise, we
        !           601:         need just check the source.  */
        !           602:       if (GET_CODE (SET_DEST (x)) != CC0
        !           603:          && GET_CODE (SET_DEST (x)) != PC
        !           604:          && GET_CODE (SET_DEST (x)) != REG
        !           605:          && ! (GET_CODE (SET_DEST (x)) == SUBREG
        !           606:                && GET_CODE (SUBREG_REG (SET_DEST (x))) == REG
        !           607:                && (((GET_MODE_SIZE (GET_MODE (SUBREG_REG (SET_DEST (x))))
        !           608:                      + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)
        !           609:                    == ((GET_MODE_SIZE (GET_MODE (SET_DEST (x)))
        !           610:                         + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD))))
        !           611:        break;
        !           612: 
        !           613:       return find_single_use_1 (dest, &SET_SRC (x));
        !           614: 
        !           615:     case MEM:
        !           616:     case SUBREG:
        !           617:       return find_single_use_1 (dest, &XEXP (x, 0));
        !           618:     }
        !           619: 
        !           620:   /* If it wasn't one of the common cases above, check each expression and
        !           621:      vector of this code.  Look for a unique usage of DEST.  */
        !           622: 
        !           623:   fmt = GET_RTX_FORMAT (code);
        !           624:   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
        !           625:     {
        !           626:       if (fmt[i] == 'e')
        !           627:        {
        !           628:          if (dest == XEXP (x, i)
        !           629:              || (GET_CODE (dest) == REG && GET_CODE (XEXP (x, i)) == REG
        !           630:                  && REGNO (dest) == REGNO (XEXP (x, i))))
        !           631:            this_result = loc;
        !           632:          else
        !           633:            this_result = find_single_use_1 (dest, &XEXP (x, i));
        !           634: 
        !           635:          if (result == 0)
        !           636:            result = this_result;
        !           637:          else if (this_result)
        !           638:            /* Duplicate usage.  */
        !           639:            return 0;
        !           640:        }
        !           641:       else if (fmt[i] == 'E')
        !           642:        {
        !           643:          int j;
        !           644: 
        !           645:          for (j = XVECLEN (x, i) - 1; j >= 0; j--)
        !           646:            {
        !           647:              if (XVECEXP (x, i, j) == dest
        !           648:                  || (GET_CODE (dest) == REG
        !           649:                      && GET_CODE (XVECEXP (x, i, j)) == REG
        !           650:                      && REGNO (XVECEXP (x, i, j)) == REGNO (dest)))
        !           651:                this_result = loc;
        !           652:              else
        !           653:                this_result = find_single_use_1 (dest, &XVECEXP (x, i, j));
        !           654: 
        !           655:              if (result == 0)
        !           656:                result = this_result;
        !           657:              else if (this_result)
        !           658:                return 0;
        !           659:            }
        !           660:        }
        !           661:     }
        !           662: 
        !           663:   return result;
        !           664: }
        !           665: 
        !           666: /* See if DEST, produced in INSN, is used only a single time in the
        !           667:    sequel.  If so, return a pointer to the innermost rtx expression in which
        !           668:    it is used.
        !           669: 
        !           670:    If PLOC is non-zero, *PLOC is set to the insn containing the single use.
        !           671: 
        !           672:    This routine will return usually zero either before flow is called (because
        !           673:    there will be no LOG_LINKS notes) or after reload (because the REG_DEAD
        !           674:    note can't be trusted).
        !           675: 
        !           676:    If DEST is cc0_rtx, we look only at the next insn.  In that case, we don't
        !           677:    care about REG_DEAD notes or LOG_LINKS.
        !           678: 
        !           679:    Otherwise, we find the single use by finding an insn that has a
        !           680:    LOG_LINKS pointing at INSN and has a REG_DEAD note for DEST.  If DEST is
        !           681:    only referenced once in that insn, we know that it must be the first
        !           682:    and last insn referencing DEST.  */
        !           683: 
        !           684: rtx *
        !           685: find_single_use (dest, insn, ploc)
        !           686:      rtx dest;
        !           687:      rtx insn;
        !           688:      rtx *ploc;
        !           689: {
        !           690:   rtx next;
        !           691:   rtx *result;
        !           692:   rtx link;
        !           693: 
        !           694: #ifdef HAVE_cc0
        !           695:   if (dest == cc0_rtx)
        !           696:     {
        !           697:       next = NEXT_INSN (insn);
        !           698:       if (next == 0
        !           699:          || (GET_CODE (next) != INSN && GET_CODE (next) != JUMP_INSN))
        !           700:        return 0;
        !           701: 
        !           702:       result = find_single_use_1 (dest, &PATTERN (next));
        !           703:       if (result && ploc)
        !           704:        *ploc = next;
        !           705:       return result;
        !           706:     }
        !           707: #endif
        !           708: 
        !           709:   if (reload_completed || reload_in_progress || GET_CODE (dest) != REG)
        !           710:     return 0;
        !           711: 
        !           712:   for (next = next_nonnote_insn (insn);
        !           713:        next != 0 && GET_CODE (next) != CODE_LABEL;
        !           714:        next = next_nonnote_insn (next))
        !           715:     if (GET_RTX_CLASS (GET_CODE (next)) == 'i' && dead_or_set_p (next, dest))
        !           716:       {
        !           717:        for (link = LOG_LINKS (next); link; link = XEXP (link, 1))
        !           718:          if (XEXP (link, 0) == insn)
        !           719:            break;
        !           720: 
        !           721:        if (link)
        !           722:          {
        !           723:            result = find_single_use_1 (dest, &PATTERN (next));
        !           724:            if (ploc)
        !           725:              *ploc = next;
        !           726:            return result;
        !           727:          }
        !           728:       }
        !           729: 
        !           730:   return 0;
        !           731: }
        !           732: 
        !           733: /* Return 1 if OP is a valid general operand for machine mode MODE.
        !           734:    This is either a register reference, a memory reference,
        !           735:    or a constant.  In the case of a memory reference, the address
        !           736:    is checked for general validity for the target machine.
        !           737: 
        !           738:    Register and memory references must have mode MODE in order to be valid,
        !           739:    but some constants have no machine mode and are valid for any mode.
        !           740: 
        !           741:    If MODE is VOIDmode, OP is checked for validity for whatever mode
        !           742:    it has.
        !           743: 
        !           744:    The main use of this function is as a predicate in match_operand
        !           745:    expressions in the machine description.
        !           746: 
        !           747:    For an explanation of this function's behavior for registers of
        !           748:    class NO_REGS, see the comment for `register_operand'.  */
        !           749: 
        !           750: int
        !           751: general_operand (op, mode)
        !           752:      register rtx op;
        !           753:      enum machine_mode mode;
        !           754: {
        !           755:   register enum rtx_code code = GET_CODE (op);
        !           756:   int mode_altering_drug = 0;
        !           757: 
        !           758:   if (mode == VOIDmode)
        !           759:     mode = GET_MODE (op);
        !           760: 
        !           761:   /* Don't accept CONST_INT or anything similar
        !           762:      if the caller wants something floating.  */
        !           763:   if (GET_MODE (op) == VOIDmode && mode != VOIDmode
        !           764:       && GET_MODE_CLASS (mode) != MODE_INT
        !           765:       && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT)
        !           766:     return 0;
        !           767: 
        !           768:   if (CONSTANT_P (op))
        !           769:     return ((GET_MODE (op) == VOIDmode || GET_MODE (op) == mode)
        !           770: #ifdef LEGITIMATE_PIC_OPERAND_P
        !           771:            && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op))
        !           772: #endif
        !           773:            && LEGITIMATE_CONSTANT_P (op));
        !           774: 
        !           775:   /* Except for certain constants with VOIDmode, already checked for,
        !           776:      OP's mode must match MODE if MODE specifies a mode.  */
        !           777: 
        !           778:   if (GET_MODE (op) != mode)
        !           779:     return 0;
        !           780: 
        !           781:   if (code == SUBREG)
        !           782:     {
        !           783: #ifdef INSN_SCHEDULING
        !           784:       /* On machines that have insn scheduling, we want all memory
        !           785:         reference to be explicit, so outlaw paradoxical SUBREGs.  */
        !           786:       if (GET_CODE (SUBREG_REG (op)) == MEM
        !           787:          && GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))))
        !           788:        return 0;
        !           789: #endif
        !           790: 
        !           791:       op = SUBREG_REG (op);
        !           792:       code = GET_CODE (op);
        !           793: #if 0
        !           794:       /* No longer needed, since (SUBREG (MEM...))
        !           795:         will load the MEM into a reload reg in the MEM's own mode.  */
        !           796:       mode_altering_drug = 1;
        !           797: #endif
        !           798:     }
        !           799: 
        !           800:   if (code == REG)
        !           801:     /* A register whose class is NO_REGS is not a general operand.  */
        !           802:     return (REGNO (op) >= FIRST_PSEUDO_REGISTER
        !           803:            || REGNO_REG_CLASS (REGNO (op)) != NO_REGS);
        !           804: 
        !           805:   if (code == MEM)
        !           806:     {
        !           807:       register rtx y = XEXP (op, 0);
        !           808:       if (! volatile_ok && MEM_VOLATILE_P (op))
        !           809:        return 0;
        !           810:       /* Use the mem's mode, since it will be reloaded thus.  */
        !           811:       mode = GET_MODE (op);
        !           812:       GO_IF_LEGITIMATE_ADDRESS (mode, y, win);
        !           813:     }
        !           814:   return 0;
        !           815: 
        !           816:  win:
        !           817:   if (mode_altering_drug)
        !           818:     return ! mode_dependent_address_p (XEXP (op, 0));
        !           819:   return 1;
        !           820: }
        !           821: 
        !           822: /* Return 1 if OP is a valid memory address for a memory reference
        !           823:    of mode MODE.
        !           824: 
        !           825:    The main use of this function is as a predicate in match_operand
        !           826:    expressions in the machine description.  */
        !           827: 
        !           828: int
        !           829: address_operand (op, mode)
        !           830:      register rtx op;
        !           831:      enum machine_mode mode;
        !           832: {
        !           833:   return memory_address_p (mode, op);
        !           834: }
        !           835: 
        !           836: /* Return 1 if OP is a register reference of mode MODE.
        !           837:    If MODE is VOIDmode, accept a register in any mode.
        !           838: 
        !           839:    The main use of this function is as a predicate in match_operand
        !           840:    expressions in the machine description.
        !           841: 
        !           842:    As a special exception, registers whose class is NO_REGS are
        !           843:    not accepted by `register_operand'.  The reason for this change
        !           844:    is to allow the representation of special architecture artifacts
        !           845:    (such as a condition code register) without extending the rtl
        !           846:    definitions.  Since registers of class NO_REGS cannot be used
        !           847:    as registers in any case where register classes are examined,
        !           848:    it is most consistent to keep this function from accepting them.  */
        !           849: 
        !           850: int
        !           851: register_operand (op, mode)
        !           852:      register rtx op;
        !           853:      enum machine_mode mode;
        !           854: {
        !           855:   if (GET_MODE (op) != mode && mode != VOIDmode)
        !           856:     return 0;
        !           857: 
        !           858:   if (GET_CODE (op) == SUBREG)
        !           859:     {
        !           860:       /* Before reload, we can allow (SUBREG (MEM...)) as a register operand
        !           861:         because it is guaranteed to be reloaded into one.
        !           862:         Just make sure the MEM is valid in itself.
        !           863:         (Ideally, (SUBREG (MEM)...) should not exist after reload,
        !           864:         but currently it does result from (SUBREG (REG)...) where the
        !           865:         reg went on the stack.)  */
        !           866:       if (! reload_completed && GET_CODE (SUBREG_REG (op)) == MEM)
        !           867:        return general_operand (op, mode);
        !           868:       op = SUBREG_REG (op);
        !           869:     }
        !           870: 
        !           871:   /* We don't consider registers whose class is NO_REGS
        !           872:      to be a register operand.  */
        !           873:   return (GET_CODE (op) == REG
        !           874:          && (REGNO (op) >= FIRST_PSEUDO_REGISTER
        !           875:              || REGNO_REG_CLASS (REGNO (op)) != NO_REGS));
        !           876: }
        !           877: 
        !           878: /* Return 1 if OP should match a MATCH_SCRATCH, i.e., if it is a SCRATCH
        !           879:    or a hard register.  */
        !           880: 
        !           881: int
        !           882: scratch_operand (op, mode)
        !           883:      register rtx op;
        !           884:      enum machine_mode mode;
        !           885: {
        !           886:   return (GET_MODE (op) == mode
        !           887:          && (GET_CODE (op) == SCRATCH
        !           888:              || (GET_CODE (op) == REG
        !           889:                  && REGNO (op) < FIRST_PSEUDO_REGISTER)));
        !           890: }
        !           891: 
        !           892: /* Return 1 if OP is a valid immediate operand for mode MODE.
        !           893: 
        !           894:    The main use of this function is as a predicate in match_operand
        !           895:    expressions in the machine description.  */
        !           896: 
        !           897: int
        !           898: immediate_operand (op, mode)
        !           899:      register rtx op;
        !           900:      enum machine_mode mode;
        !           901: {
        !           902:   /* Don't accept CONST_INT or anything similar
        !           903:      if the caller wants something floating.  */
        !           904:   if (GET_MODE (op) == VOIDmode && mode != VOIDmode
        !           905:       && GET_MODE_CLASS (mode) != MODE_INT
        !           906:       && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT)
        !           907:     return 0;
        !           908: 
        !           909:   return (CONSTANT_P (op)
        !           910:          && (GET_MODE (op) == mode || mode == VOIDmode
        !           911:              || GET_MODE (op) == VOIDmode)
        !           912: #ifdef LEGITIMATE_PIC_OPERAND_P
        !           913:          && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op))
        !           914: #endif
        !           915:          && LEGITIMATE_CONSTANT_P (op));
        !           916: }
        !           917: 
        !           918: /* Returns 1 if OP is an operand that is a CONST_INT.  */
        !           919: 
        !           920: int
        !           921: const_int_operand (op, mode)
        !           922:      register rtx op;
        !           923:      enum machine_mode mode;
        !           924: {
        !           925:   return GET_CODE (op) == CONST_INT;
        !           926: }
        !           927: 
        !           928: /* Returns 1 if OP is an operand that is a constant integer or constant
        !           929:    floating-point number.  */
        !           930: 
        !           931: int
        !           932: const_double_operand (op, mode)
        !           933:      register rtx op;
        !           934:      enum machine_mode mode;
        !           935: {
        !           936:   /* Don't accept CONST_INT or anything similar
        !           937:      if the caller wants something floating.  */
        !           938:   if (GET_MODE (op) == VOIDmode && mode != VOIDmode
        !           939:       && GET_MODE_CLASS (mode) != MODE_INT
        !           940:       && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT)
        !           941:     return 0;
        !           942: 
        !           943:   return ((GET_CODE (op) == CONST_DOUBLE || GET_CODE (op) == CONST_INT)
        !           944:          && (mode == VOIDmode || GET_MODE (op) == mode
        !           945:              || GET_MODE (op) == VOIDmode));
        !           946: }
        !           947: 
        !           948: /* Return 1 if OP is a general operand that is not an immediate operand.  */
        !           949: 
        !           950: int
        !           951: nonimmediate_operand (op, mode)
        !           952:      register rtx op;
        !           953:      enum machine_mode mode;
        !           954: {
        !           955:   return (general_operand (op, mode) && ! CONSTANT_P (op));
        !           956: }
        !           957: 
        !           958: /* Return 1 if OP is a register reference or immediate value of mode MODE.  */
        !           959: 
        !           960: int
        !           961: nonmemory_operand (op, mode)
        !           962:      register rtx op;
        !           963:      enum machine_mode mode;
        !           964: {
        !           965:   if (CONSTANT_P (op))
        !           966:     {
        !           967:       /* Don't accept CONST_INT or anything similar
        !           968:         if the caller wants something floating.  */
        !           969:       if (GET_MODE (op) == VOIDmode && mode != VOIDmode
        !           970:          && GET_MODE_CLASS (mode) != MODE_INT
        !           971:          && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT)
        !           972:        return 0;
        !           973: 
        !           974:       return ((GET_MODE (op) == VOIDmode || GET_MODE (op) == mode)
        !           975: #ifdef LEGITIMATE_PIC_OPERAND_P
        !           976:              && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op))
        !           977: #endif
        !           978:              && LEGITIMATE_CONSTANT_P (op));
        !           979:     }
        !           980: 
        !           981:   if (GET_MODE (op) != mode && mode != VOIDmode)
        !           982:     return 0;
        !           983: 
        !           984:   if (GET_CODE (op) == SUBREG)
        !           985:     {
        !           986:       /* Before reload, we can allow (SUBREG (MEM...)) as a register operand
        !           987:         because it is guaranteed to be reloaded into one.
        !           988:         Just make sure the MEM is valid in itself.
        !           989:         (Ideally, (SUBREG (MEM)...) should not exist after reload,
        !           990:         but currently it does result from (SUBREG (REG)...) where the
        !           991:         reg went on the stack.)  */
        !           992:       if (! reload_completed && GET_CODE (SUBREG_REG (op)) == MEM)
        !           993:        return general_operand (op, mode);
        !           994:       op = SUBREG_REG (op);
        !           995:     }
        !           996: 
        !           997:   /* We don't consider registers whose class is NO_REGS
        !           998:      to be a register operand.  */
        !           999:   return (GET_CODE (op) == REG
        !          1000:          && (REGNO (op) >= FIRST_PSEUDO_REGISTER
        !          1001:              || REGNO_REG_CLASS (REGNO (op)) != NO_REGS));
        !          1002: }
        !          1003: 
        !          1004: /* Return 1 if OP is a valid operand that stands for pushing a
        !          1005:    value of mode MODE onto the stack.
        !          1006: 
        !          1007:    The main use of this function is as a predicate in match_operand
        !          1008:    expressions in the machine description.  */
        !          1009: 
        !          1010: int
        !          1011: push_operand (op, mode)
        !          1012:      rtx op;
        !          1013:      enum machine_mode mode;
        !          1014: {
        !          1015:   if (GET_CODE (op) != MEM)
        !          1016:     return 0;
        !          1017: 
        !          1018:   if (GET_MODE (op) != mode)
        !          1019:     return 0;
        !          1020: 
        !          1021:   op = XEXP (op, 0);
        !          1022: 
        !          1023:   if (GET_CODE (op) != STACK_PUSH_CODE)
        !          1024:     return 0;
        !          1025: 
        !          1026:   return XEXP (op, 0) == stack_pointer_rtx;
        !          1027: }
        !          1028: 
        !          1029: /* Return 1 if ADDR is a valid memory address for mode MODE.  */
        !          1030: 
        !          1031: int
        !          1032: memory_address_p (mode, addr)
        !          1033:      enum machine_mode mode;
        !          1034:      register rtx addr;
        !          1035: {
        !          1036:   GO_IF_LEGITIMATE_ADDRESS (mode, addr, win);
        !          1037:   return 0;
        !          1038: 
        !          1039:  win:
        !          1040:   return 1;
        !          1041: }
        !          1042: 
        !          1043: /* Return 1 if OP is a valid memory reference with mode MODE,
        !          1044:    including a valid address.
        !          1045: 
        !          1046:    The main use of this function is as a predicate in match_operand
        !          1047:    expressions in the machine description.  */
        !          1048: 
        !          1049: int
        !          1050: memory_operand (op, mode)
        !          1051:      register rtx op;
        !          1052:      enum machine_mode mode;
        !          1053: {
        !          1054:   rtx inner;
        !          1055: 
        !          1056:   if (! reload_completed)
        !          1057:     /* Note that no SUBREG is a memory operand before end of reload pass,
        !          1058:        because (SUBREG (MEM...)) forces reloading into a register.  */
        !          1059:     return GET_CODE (op) == MEM && general_operand (op, mode);
        !          1060: 
        !          1061:   if (mode != VOIDmode && GET_MODE (op) != mode)
        !          1062:     return 0;
        !          1063: 
        !          1064:   inner = op;
        !          1065: #ifdef MACHO_PIC
        !          1066:   if (GET_CODE (inner) == CONST)
        !          1067:     inner = XEXP (inner, 0);
        !          1068: #endif
        !          1069:   if (GET_CODE (inner) == SUBREG)
        !          1070:     inner = SUBREG_REG (inner);
        !          1071: 
        !          1072:   return (GET_CODE (inner) == MEM && general_operand (op, mode));
        !          1073: }
        !          1074: 
        !          1075: /* Return 1 if OP is a valid indirect memory reference with mode MODE;
        !          1076:    that is, a memory reference whose address is a general_operand.  */
        !          1077: 
        !          1078: int
        !          1079: indirect_operand (op, mode)
        !          1080:      register rtx op;
        !          1081:      enum machine_mode mode;
        !          1082: {
        !          1083:   /* Before reload, a SUBREG isn't in memory (see memory_operand, above).  */
        !          1084:   if (! reload_completed
        !          1085:       && GET_CODE (op) == SUBREG && GET_CODE (SUBREG_REG (op)) == MEM)
        !          1086:     {
        !          1087:       register int offset = SUBREG_WORD (op) * UNITS_PER_WORD;
        !          1088:       rtx inner = SUBREG_REG (op);
        !          1089: 
        !          1090: #if BYTES_BIG_ENDIAN
        !          1091:       offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (op)))
        !          1092:                 - MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (inner))));
        !          1093: #endif
        !          1094: 
        !          1095:       /* The only way that we can have a general_operand as the resulting
        !          1096:         address is if OFFSET is zero and the address already is an operand
        !          1097:         or if the address is (plus Y (const_int -OFFSET)) and Y is an
        !          1098:         operand.  */
        !          1099: 
        !          1100:       return ((offset == 0 && general_operand (XEXP (inner, 0), Pmode))
        !          1101:              || (GET_CODE (XEXP (inner, 0)) == PLUS
        !          1102:                  && GET_CODE (XEXP (XEXP (inner, 0), 1)) == CONST_INT
        !          1103:                  && INTVAL (XEXP (XEXP (inner, 0), 1)) == -offset
        !          1104:                  && general_operand (XEXP (XEXP (inner, 0), 0), Pmode)));
        !          1105:     }
        !          1106: 
        !          1107:   return (GET_CODE (op) == MEM
        !          1108:          && memory_operand (op, mode)
        !          1109:          && general_operand (XEXP (op, 0), Pmode));
        !          1110: }
        !          1111: 
        !          1112: /* Return 1 if this is a comparison operator.  This allows the use of
        !          1113:    MATCH_OPERATOR to recognize all the branch insns.  */
        !          1114: 
        !          1115: int
        !          1116: comparison_operator (op, mode)
        !          1117:     register rtx op;
        !          1118:     enum machine_mode mode;
        !          1119: {
        !          1120:   return ((mode == VOIDmode || GET_MODE (op) == mode)
        !          1121:          && GET_RTX_CLASS (GET_CODE (op)) == '<');
        !          1122: }
        !          1123: 
        !          1124: /* If BODY is an insn body that uses ASM_OPERANDS,
        !          1125:    return the number of operands (both input and output) in the insn.
        !          1126:    Otherwise return -1.  */
        !          1127: 
        !          1128: int
        !          1129: asm_noperands (body)
        !          1130:      rtx body;
        !          1131: {
        !          1132:   if (GET_CODE (body) == ASM_OPERANDS)
        !          1133:     /* No output operands: return number of input operands.  */
        !          1134:     return ASM_OPERANDS_INPUT_LENGTH (body);
        !          1135:   if (GET_CODE (body) == SET && GET_CODE (SET_SRC (body)) == ASM_OPERANDS)
        !          1136:     /* Single output operand: BODY is (set OUTPUT (asm_operands ...)).  */
        !          1137:     return ASM_OPERANDS_INPUT_LENGTH (SET_SRC (body)) + 1;
        !          1138:   else if (GET_CODE (body) == PARALLEL
        !          1139:           && GET_CODE (XVECEXP (body, 0, 0)) == SET
        !          1140:           && GET_CODE (SET_SRC (XVECEXP (body, 0, 0))) == ASM_OPERANDS)
        !          1141:     {
        !          1142:       /* Multiple output operands, or 1 output plus some clobbers:
        !          1143:         body is [(set OUTPUT (asm_operands ...))... (clobber (reg ...))...].  */
        !          1144:       int i;
        !          1145:       int n_sets;
        !          1146: 
        !          1147:       /* Count backwards through CLOBBERs to determine number of SETs.  */
        !          1148:       for (i = XVECLEN (body, 0); i > 0; i--)
        !          1149:        {
        !          1150:          if (GET_CODE (XVECEXP (body, 0, i - 1)) == SET)
        !          1151:            break;
        !          1152:          if (GET_CODE (XVECEXP (body, 0, i - 1)) != CLOBBER)
        !          1153:            return -1;
        !          1154:        }
        !          1155: 
        !          1156:       /* N_SETS is now number of output operands.  */
        !          1157:       n_sets = i;
        !          1158: 
        !          1159:       /* Verify that all the SETs we have
        !          1160:         came from a single original asm_operands insn
        !          1161:         (so that invalid combinations are blocked).  */
        !          1162:       for (i = 0; i < n_sets; i++)
        !          1163:        {
        !          1164:          rtx elt = XVECEXP (body, 0, i);
        !          1165:          if (GET_CODE (elt) != SET)
        !          1166:            return -1;
        !          1167:          if (GET_CODE (SET_SRC (elt)) != ASM_OPERANDS)
        !          1168:            return -1;
        !          1169:          /* If these ASM_OPERANDS rtx's came from different original insns
        !          1170:             then they aren't allowed together.  */
        !          1171:          if (ASM_OPERANDS_INPUT_VEC (SET_SRC (elt))
        !          1172:              != ASM_OPERANDS_INPUT_VEC (SET_SRC (XVECEXP (body, 0, 0))))
        !          1173:            return -1;
        !          1174:        }
        !          1175:       return (ASM_OPERANDS_INPUT_LENGTH (SET_SRC (XVECEXP (body, 0, 0)))
        !          1176:              + n_sets);
        !          1177:     }
        !          1178:   else if (GET_CODE (body) == PARALLEL
        !          1179:           && GET_CODE (XVECEXP (body, 0, 0)) == ASM_OPERANDS)
        !          1180:     {
        !          1181:       /* 0 outputs, but some clobbers:
        !          1182:         body is [(asm_operands ...) (clobber (reg ...))...].  */
        !          1183:       int i;
        !          1184: 
        !          1185:       /* Make sure all the other parallel things really are clobbers.  */
        !          1186:       for (i = XVECLEN (body, 0) - 1; i > 0; i--)
        !          1187:        if (GET_CODE (XVECEXP (body, 0, i)) != CLOBBER)
        !          1188:          return -1;
        !          1189: 
        !          1190:       return ASM_OPERANDS_INPUT_LENGTH (XVECEXP (body, 0, 0));
        !          1191:     }
        !          1192:   else
        !          1193:     return -1;
        !          1194: }
        !          1195: 
        !          1196: /* Assuming BODY is an insn body that uses ASM_OPERANDS,
        !          1197:    copy its operands (both input and output) into the vector OPERANDS,
        !          1198:    the locations of the operands within the insn into the vector OPERAND_LOCS,
        !          1199:    and the constraints for the operands into CONSTRAINTS.
        !          1200:    Write the modes of the operands into MODES.
        !          1201:    Return the assembler-template.
        !          1202: 
        !          1203:    If MODES, OPERAND_LOCS, CONSTRAINTS or OPERANDS is 0,
        !          1204:    we don't store that info.  */
        !          1205: 
        !          1206: char *
        !          1207: decode_asm_operands (body, operands, operand_locs, constraints, modes)
        !          1208:      rtx body;
        !          1209:      rtx *operands;
        !          1210:      rtx **operand_locs;
        !          1211:      char **constraints;
        !          1212:      enum machine_mode *modes;
        !          1213: {
        !          1214:   register int i;
        !          1215:   int noperands;
        !          1216:   char *template = 0;
        !          1217: 
        !          1218:   if (GET_CODE (body) == SET && GET_CODE (SET_SRC (body)) == ASM_OPERANDS)
        !          1219:     {
        !          1220:       rtx asmop = SET_SRC (body);
        !          1221:       /* Single output operand: BODY is (set OUTPUT (asm_operands ....)).  */
        !          1222: 
        !          1223:       noperands = ASM_OPERANDS_INPUT_LENGTH (asmop) + 1;
        !          1224: 
        !          1225:       for (i = 1; i < noperands; i++)
        !          1226:        {
        !          1227:          if (operand_locs)
        !          1228:            operand_locs[i] = &ASM_OPERANDS_INPUT (asmop, i - 1);
        !          1229:          if (operands)
        !          1230:            operands[i] = ASM_OPERANDS_INPUT (asmop, i - 1);
        !          1231:          if (constraints)
        !          1232:            constraints[i] = ASM_OPERANDS_INPUT_CONSTRAINT (asmop, i - 1);
        !          1233:          if (modes)
        !          1234:            modes[i] = ASM_OPERANDS_INPUT_MODE (asmop, i - 1);
        !          1235:        }
        !          1236: 
        !          1237:       /* The output is in the SET.
        !          1238:         Its constraint is in the ASM_OPERANDS itself.  */
        !          1239:       if (operands)
        !          1240:        operands[0] = SET_DEST (body);
        !          1241:       if (operand_locs)
        !          1242:        operand_locs[0] = &SET_DEST (body);
        !          1243:       if (constraints)
        !          1244:        constraints[0] = ASM_OPERANDS_OUTPUT_CONSTRAINT (asmop);
        !          1245:       if (modes)
        !          1246:        modes[0] = GET_MODE (SET_DEST (body));
        !          1247:       template = ASM_OPERANDS_TEMPLATE (asmop);
        !          1248:     }
        !          1249:   else if (GET_CODE (body) == ASM_OPERANDS)
        !          1250:     {
        !          1251:       rtx asmop = body;
        !          1252:       /* No output operands: BODY is (asm_operands ....).  */
        !          1253: 
        !          1254:       noperands = ASM_OPERANDS_INPUT_LENGTH (asmop);
        !          1255: 
        !          1256:       /* The input operands are found in the 1st element vector.  */
        !          1257:       /* Constraints for inputs are in the 2nd element vector.  */
        !          1258:       for (i = 0; i < noperands; i++)
        !          1259:        {
        !          1260:          if (operand_locs)
        !          1261:            operand_locs[i] = &ASM_OPERANDS_INPUT (asmop, i);
        !          1262:          if (operands)
        !          1263:            operands[i] = ASM_OPERANDS_INPUT (asmop, i);
        !          1264:          if (constraints)
        !          1265:            constraints[i] = ASM_OPERANDS_INPUT_CONSTRAINT (asmop, i);
        !          1266:          if (modes)
        !          1267:            modes[i] = ASM_OPERANDS_INPUT_MODE (asmop, i);
        !          1268:        }
        !          1269:       template = ASM_OPERANDS_TEMPLATE (asmop);
        !          1270:     }
        !          1271:   else if (GET_CODE (body) == PARALLEL
        !          1272:           && GET_CODE (XVECEXP (body, 0, 0)) == SET)
        !          1273:     {
        !          1274:       rtx asmop = SET_SRC (XVECEXP (body, 0, 0));
        !          1275:       int nparallel = XVECLEN (body, 0); /* Includes CLOBBERs.  */
        !          1276:       int nin = ASM_OPERANDS_INPUT_LENGTH (asmop);
        !          1277:       int nout = 0;            /* Does not include CLOBBERs.  */
        !          1278: 
        !          1279:       /* At least one output, plus some CLOBBERs.  */
        !          1280: 
        !          1281:       /* The outputs are in the SETs.
        !          1282:         Their constraints are in the ASM_OPERANDS itself.  */
        !          1283:       for (i = 0; i < nparallel; i++)
        !          1284:        {
        !          1285:          if (GET_CODE (XVECEXP (body, 0, i)) == CLOBBER)
        !          1286:            break;              /* Past last SET */
        !          1287:          
        !          1288:          if (operands)
        !          1289:            operands[i] = SET_DEST (XVECEXP (body, 0, i));
        !          1290:          if (operand_locs)
        !          1291:            operand_locs[i] = &SET_DEST (XVECEXP (body, 0, i));
        !          1292:          if (constraints)
        !          1293:            constraints[i] = XSTR (SET_SRC (XVECEXP (body, 0, i)), 1);
        !          1294:          if (modes)
        !          1295:            modes[i] = GET_MODE (SET_DEST (XVECEXP (body, 0, i)));
        !          1296:          nout++;
        !          1297:        }
        !          1298: 
        !          1299:       for (i = 0; i < nin; i++)
        !          1300:        {
        !          1301:          if (operand_locs)
        !          1302:            operand_locs[i + nout] = &ASM_OPERANDS_INPUT (asmop, i);
        !          1303:          if (operands)
        !          1304:            operands[i + nout] = ASM_OPERANDS_INPUT (asmop, i);
        !          1305:          if (constraints)
        !          1306:            constraints[i + nout] = ASM_OPERANDS_INPUT_CONSTRAINT (asmop, i);
        !          1307:          if (modes)
        !          1308:            modes[i + nout] = ASM_OPERANDS_INPUT_MODE (asmop, i);
        !          1309:        }
        !          1310: 
        !          1311:       template = ASM_OPERANDS_TEMPLATE (asmop);
        !          1312:     }
        !          1313:   else if (GET_CODE (body) == PARALLEL
        !          1314:           && GET_CODE (XVECEXP (body, 0, 0)) == ASM_OPERANDS)
        !          1315:     {
        !          1316:       /* No outputs, but some CLOBBERs.  */
        !          1317: 
        !          1318:       rtx asmop = XVECEXP (body, 0, 0);
        !          1319:       int nin = ASM_OPERANDS_INPUT_LENGTH (asmop);
        !          1320: 
        !          1321:       for (i = 0; i < nin; i++)
        !          1322:        {
        !          1323:          if (operand_locs)
        !          1324:            operand_locs[i] = &ASM_OPERANDS_INPUT (asmop, i);
        !          1325:          if (operands)
        !          1326:            operands[i] = ASM_OPERANDS_INPUT (asmop, i);
        !          1327:          if (constraints)
        !          1328:            constraints[i] = ASM_OPERANDS_INPUT_CONSTRAINT (asmop, i);
        !          1329:          if (modes)
        !          1330:            modes[i] = ASM_OPERANDS_INPUT_MODE (asmop, i);
        !          1331:        }
        !          1332: 
        !          1333:       template = ASM_OPERANDS_TEMPLATE (asmop);
        !          1334:     }
        !          1335: 
        !          1336:   return template;
        !          1337: }
        !          1338: 
        !          1339: /* Given an rtx *P, if it is a sum containing an integer constant term,
        !          1340:    return the location (type rtx *) of the pointer to that constant term.
        !          1341:    Otherwise, return a null pointer.  */
        !          1342: 
        !          1343: static rtx *
        !          1344: find_constant_term_loc (p)
        !          1345:      rtx *p;
        !          1346: {
        !          1347:   register rtx *tem;
        !          1348:   register enum rtx_code code = GET_CODE (*p);
        !          1349: 
        !          1350:   /* If *P IS such a constant term, P is its location.  */
        !          1351: 
        !          1352:   if (code == CONST_INT || code == SYMBOL_REF || code == LABEL_REF
        !          1353:       || code == CONST)
        !          1354:     return p;
        !          1355: 
        !          1356:   /* Otherwise, if not a sum, it has no constant term.  */
        !          1357: 
        !          1358:   if (GET_CODE (*p) != PLUS)
        !          1359:     return 0;
        !          1360: 
        !          1361:   /* If one of the summands is constant, return its location.  */
        !          1362: 
        !          1363:   if (XEXP (*p, 0) && CONSTANT_P (XEXP (*p, 0))
        !          1364:       && XEXP (*p, 1) && CONSTANT_P (XEXP (*p, 1)))
        !          1365:     return p;
        !          1366: 
        !          1367:   /* Otherwise, check each summand for containing a constant term.  */
        !          1368: 
        !          1369:   if (XEXP (*p, 0) != 0)
        !          1370:     {
        !          1371:       tem = find_constant_term_loc (&XEXP (*p, 0));
        !          1372:       if (tem != 0)
        !          1373:        return tem;
        !          1374:     }
        !          1375: 
        !          1376:   if (XEXP (*p, 1) != 0)
        !          1377:     {
        !          1378:       tem = find_constant_term_loc (&XEXP (*p, 1));
        !          1379:       if (tem != 0)
        !          1380:        return tem;
        !          1381:     }
        !          1382: 
        !          1383:   return 0;
        !          1384: }
        !          1385: 
        !          1386: /* Return 1 if OP is a memory reference
        !          1387:    whose address contains no side effects
        !          1388:    and remains valid after the addition
        !          1389:    of a positive integer less than the
        !          1390:    size of the object being referenced.
        !          1391: 
        !          1392:    We assume that the original address is valid and do not check it.
        !          1393: 
        !          1394:    This uses strict_memory_address_p as a subroutine, so
        !          1395:    don't use it before reload.  */
        !          1396: 
        !          1397: int
        !          1398: offsettable_memref_p (op)
        !          1399:      rtx op;
        !          1400: {
        !          1401:   return ((GET_CODE (op) == MEM)
        !          1402:          && offsettable_address_p (1, GET_MODE (op), XEXP (op, 0)));
        !          1403: }
        !          1404: 
        !          1405: /* Similar, but don't require a strictly valid mem ref:
        !          1406:    consider pseudo-regs valid as index or base regs.  */
        !          1407: 
        !          1408: int
        !          1409: offsettable_nonstrict_memref_p (op)
        !          1410:      rtx op;
        !          1411: {
        !          1412:   return ((GET_CODE (op) == MEM)
        !          1413:          && offsettable_address_p (0, GET_MODE (op), XEXP (op, 0)));
        !          1414: }
        !          1415: 
        !          1416: /* Return 1 if Y is a memory address which contains no side effects
        !          1417:    and would remain valid after the addition of a positive integer
        !          1418:    less than the size of that mode.
        !          1419: 
        !          1420:    We assume that the original address is valid and do not check it.
        !          1421:    We do check that it is valid for narrower modes.
        !          1422: 
        !          1423:    If STRICTP is nonzero, we require a strictly valid address,
        !          1424:    for the sake of use in reload.c.  */
        !          1425: 
        !          1426: int
        !          1427: offsettable_address_p (strictp, mode, y)
        !          1428:      int strictp;
        !          1429:      enum machine_mode mode;
        !          1430:      register rtx y;
        !          1431: {
        !          1432:   register enum rtx_code ycode = GET_CODE (y);
        !          1433:   register rtx z;
        !          1434:   rtx y1 = y;
        !          1435:   rtx *y2;
        !          1436:   int (*addressp) () = (strictp ? strict_memory_address_p : memory_address_p);
        !          1437: 
        !          1438:   if (CONSTANT_ADDRESS_P (y))
        !          1439:     return 1;
        !          1440: 
        !          1441:   /* Adjusting an offsettable address involves changing to a narrower mode.
        !          1442:      Make sure that's OK.  */
        !          1443: 
        !          1444:   if (mode_dependent_address_p (y))
        !          1445:     return 0;
        !          1446: 
        !          1447:   /* If the expression contains a constant term,
        !          1448:      see if it remains valid when max possible offset is added.  */
        !          1449: 
        !          1450:   if ((ycode == PLUS) && (y2 = find_constant_term_loc (&y1)))
        !          1451:     {
        !          1452:       int good;
        !          1453: 
        !          1454:       y1 = *y2;
        !          1455:       *y2 = plus_constant (*y2, GET_MODE_SIZE (mode) - 1);
        !          1456:       /* Use QImode because an odd displacement may be automatically invalid
        !          1457:         for any wider mode.  But it should be valid for a single byte.  */
        !          1458:       good = (*addressp) (QImode, y);
        !          1459: 
        !          1460:       /* In any case, restore old contents of memory.  */
        !          1461:       *y2 = y1;
        !          1462:       return good;
        !          1463:     }
        !          1464: 
        !          1465:   if (ycode == PRE_DEC || ycode == PRE_INC
        !          1466:       || ycode == POST_DEC || ycode == POST_INC)
        !          1467:     return 0;
        !          1468: 
        !          1469:   /* The offset added here is chosen as the maximum offset that
        !          1470:      any instruction could need to add when operating on something
        !          1471:      of the specified mode.  We assume that if Y and Y+c are
        !          1472:      valid addresses then so is Y+d for all 0<d<c.  */
        !          1473: 
        !          1474:   z = plus_constant_for_output (y, GET_MODE_SIZE (mode) - 1);
        !          1475: 
        !          1476:   /* Use QImode because an odd displacement may be automatically invalid
        !          1477:      for any wider mode.  But it should be valid for a single byte.  */
        !          1478:   return (*addressp) (QImode, z);
        !          1479: }
        !          1480: 
        !          1481: /* Return 1 if ADDR is an address-expression whose effect depends
        !          1482:    on the mode of the memory reference it is used in.
        !          1483: 
        !          1484:    Autoincrement addressing is a typical example of mode-dependence
        !          1485:    because the amount of the increment depends on the mode.  */
        !          1486: 
        !          1487: int
        !          1488: mode_dependent_address_p (addr)
        !          1489:      rtx addr;
        !          1490: {
        !          1491:   GO_IF_MODE_DEPENDENT_ADDRESS (addr, win);
        !          1492:   return 0;
        !          1493:  win:
        !          1494:   return 1;
        !          1495: }
        !          1496: 
        !          1497: /* Return 1 if OP is a general operand
        !          1498:    other than a memory ref with a mode dependent address.  */
        !          1499: 
        !          1500: int
        !          1501: mode_independent_operand (op, mode)
        !          1502:      enum machine_mode mode;
        !          1503:      rtx op;
        !          1504: {
        !          1505:   rtx addr;
        !          1506: 
        !          1507:   if (! general_operand (op, mode))
        !          1508:     return 0;
        !          1509: 
        !          1510:   if (GET_CODE (op) != MEM)
        !          1511:     return 1;
        !          1512: 
        !          1513:   addr = XEXP (op, 0);
        !          1514:   GO_IF_MODE_DEPENDENT_ADDRESS (addr, lose);
        !          1515:   return 1;
        !          1516:  lose:
        !          1517:   return 0;
        !          1518: }
        !          1519: 
        !          1520: /* Given an operand OP that is a valid memory reference
        !          1521:    which satisfies offsettable_memref_p,
        !          1522:    return a new memory reference whose address has been adjusted by OFFSET.
        !          1523:    OFFSET should be positive and less than the size of the object referenced.
        !          1524: */
        !          1525: 
        !          1526: rtx
        !          1527: adj_offsettable_operand (op, offset)
        !          1528:      rtx op;
        !          1529:      int offset;
        !          1530: {
        !          1531:   register enum rtx_code code = GET_CODE (op);
        !          1532: 
        !          1533:   if (code == MEM) 
        !          1534:     {
        !          1535:       register rtx y = XEXP (op, 0);
        !          1536:       register rtx new;
        !          1537: 
        !          1538:       if (CONSTANT_ADDRESS_P (y))
        !          1539:        {
        !          1540:          new = gen_rtx (MEM, GET_MODE (op), plus_constant_for_output (y, offset));
        !          1541:          RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (op);
        !          1542:          return new;
        !          1543:        }
        !          1544: 
        !          1545:       if (GET_CODE (y) == PLUS)
        !          1546:        {
        !          1547:          rtx z = y;
        !          1548:          register rtx *const_loc;
        !          1549: 
        !          1550:          op = copy_rtx (op);
        !          1551:          z = XEXP (op, 0);
        !          1552:          const_loc = find_constant_term_loc (&z);
        !          1553:          if (const_loc)
        !          1554:            {
        !          1555:              *const_loc = plus_constant_for_output (*const_loc, offset);
        !          1556:              return op;
        !          1557:            }
        !          1558:        }
        !          1559: 
        !          1560:       new = gen_rtx (MEM, GET_MODE (op), plus_constant_for_output (y, offset));
        !          1561:       RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (op);
        !          1562:       return new;
        !          1563:     }
        !          1564:   abort ();
        !          1565: }
        !          1566: 
        !          1567: #ifdef REGISTER_CONSTRAINTS
        !          1568: 
        !          1569: /* Check the operands of an insn (found in recog_operands)
        !          1570:    against the insn's operand constraints (found via INSN_CODE_NUM)
        !          1571:    and return 1 if they are valid.
        !          1572: 
        !          1573:    WHICH_ALTERNATIVE is set to a number which indicates which
        !          1574:    alternative of constraints was matched: 0 for the first alternative,
        !          1575:    1 for the next, etc.
        !          1576: 
        !          1577:    In addition, when two operands are match
        !          1578:    and it happens that the output operand is (reg) while the
        !          1579:    input operand is --(reg) or ++(reg) (a pre-inc or pre-dec),
        !          1580:    make the output operand look like the input.
        !          1581:    This is because the output operand is the one the template will print.
        !          1582: 
        !          1583:    This is used in final, just before printing the assembler code and by
        !          1584:    the routines that determine an insn's attribute.
        !          1585: 
        !          1586:    If STRICT is a positive non-zero value, it means that we have been
        !          1587:    called after reload has been completed.  In that case, we must
        !          1588:    do all checks strictly.  If it is zero, it means that we have been called
        !          1589:    before reload has completed.  In that case, we first try to see if we can
        !          1590:    find an alternative that matches strictly.  If not, we try again, this
        !          1591:    time assuming that reload will fix up the insn.  This provides a "best
        !          1592:    guess" for the alternative and is used to compute attributes of insns prior
        !          1593:    to reload.  A negative value of STRICT is used for this internal call.  */
        !          1594: 
        !          1595: struct funny_match
        !          1596: {
        !          1597:   int this, other;
        !          1598: };
        !          1599: 
        !          1600: int
        !          1601: constrain_operands (insn_code_num, strict)
        !          1602:      int insn_code_num;
        !          1603:      int strict;
        !          1604: {
        !          1605:   char *constraints[MAX_RECOG_OPERANDS];
        !          1606:   int matching_operands[MAX_RECOG_OPERANDS];
        !          1607:   enum op_type {OP_IN, OP_OUT, OP_INOUT} op_types[MAX_RECOG_OPERANDS];
        !          1608:   int earlyclobber[MAX_RECOG_OPERANDS];
        !          1609:   register int c;
        !          1610:   int noperands = insn_n_operands[insn_code_num];
        !          1611: 
        !          1612:   struct funny_match funny_match[MAX_RECOG_OPERANDS];
        !          1613:   int funny_match_index;
        !          1614:   int nalternatives = insn_n_alternatives[insn_code_num];
        !          1615: 
        !          1616:   if (noperands == 0 || nalternatives == 0)
        !          1617:     return 1;
        !          1618: 
        !          1619:   for (c = 0; c < noperands; c++)
        !          1620:     {
        !          1621:       constraints[c] = insn_operand_constraint[insn_code_num][c];
        !          1622:       matching_operands[c] = -1;
        !          1623:       op_types[c] = OP_IN;
        !          1624:     }
        !          1625: 
        !          1626:   which_alternative = 0;
        !          1627: 
        !          1628:   while (which_alternative < nalternatives)
        !          1629:     {
        !          1630:       register int opno;
        !          1631:       int lose = 0;
        !          1632:       funny_match_index = 0;
        !          1633: 
        !          1634:       for (opno = 0; opno < noperands; opno++)
        !          1635:        {
        !          1636:          register rtx op = recog_operand[opno];
        !          1637:          enum machine_mode mode = GET_MODE (op);
        !          1638:          register char *p = constraints[opno];
        !          1639:          int offset = 0;
        !          1640:          int win = 0;
        !          1641:          int val;
        !          1642: 
        !          1643:          earlyclobber[opno] = 0;
        !          1644: 
        !          1645:          if (GET_CODE (op) == SUBREG)
        !          1646:            {
        !          1647:              if (GET_CODE (SUBREG_REG (op)) == REG
        !          1648:                  && REGNO (SUBREG_REG (op)) < FIRST_PSEUDO_REGISTER)
        !          1649:                offset = SUBREG_WORD (op);
        !          1650:              op = SUBREG_REG (op);
        !          1651:            }
        !          1652: 
        !          1653:          /* An empty constraint or empty alternative
        !          1654:             allows anything which matched the pattern.  */
        !          1655:          if (*p == 0 || *p == ',')
        !          1656:            win = 1;
        !          1657: 
        !          1658:          while (*p && (c = *p++) != ',')
        !          1659:            switch (c)
        !          1660:              {
        !          1661:              case '?':
        !          1662:              case '#':
        !          1663:              case '!':
        !          1664:              case '*':
        !          1665:              case '%':
        !          1666:                break;
        !          1667: 
        !          1668:              case '=':
        !          1669:                op_types[opno] = OP_OUT;
        !          1670:                break;
        !          1671: 
        !          1672:              case '+':
        !          1673:                op_types[opno] = OP_INOUT;
        !          1674:                break;
        !          1675: 
        !          1676:              case '&':
        !          1677:                earlyclobber[opno] = 1;
        !          1678:                break;
        !          1679: 
        !          1680:              case '0':
        !          1681:              case '1':
        !          1682:              case '2':
        !          1683:              case '3':
        !          1684:              case '4':
        !          1685:                /* This operand must be the same as a previous one.
        !          1686:                   This kind of constraint is used for instructions such
        !          1687:                   as add when they take only two operands.
        !          1688: 
        !          1689:                   Note that the lower-numbered operand is passed first.
        !          1690: 
        !          1691:                   If we are not testing strictly, assume that this constraint
        !          1692:                   will be satisfied.  */
        !          1693:                if (strict < 0)
        !          1694:                  val = 1;
        !          1695:                else
        !          1696:                  val = operands_match_p (recog_operand[c - '0'],
        !          1697:                                          recog_operand[opno]);
        !          1698: 
        !          1699:                matching_operands[opno] = c - '0';
        !          1700:                matching_operands[c - '0'] = opno;
        !          1701: 
        !          1702:                if (val != 0)
        !          1703:                  win = 1;
        !          1704:                /* If output is *x and input is *--x,
        !          1705:                   arrange later to change the output to *--x as well,
        !          1706:                   since the output op is the one that will be printed.  */
        !          1707:                if (val == 2 && strict > 0)
        !          1708:                  {
        !          1709:                    funny_match[funny_match_index].this = opno;
        !          1710:                    funny_match[funny_match_index++].other = c - '0';
        !          1711:                  }
        !          1712:                break;
        !          1713: 
        !          1714:              case 'p':
        !          1715:                /* p is used for address_operands.  When we are called by
        !          1716:                   gen_input_reload, no one will have checked that the
        !          1717:                   address is strictly valid, i.e., that all pseudos
        !          1718:                   requiring hard regs have gotten them.  */
        !          1719:                if (strict <= 0
        !          1720:                    || (strict_memory_address_p
        !          1721:                        (insn_operand_mode[insn_code_num][opno], op)))
        !          1722:                  win = 1;
        !          1723:                break;
        !          1724: 
        !          1725:                /* No need to check general_operand again;
        !          1726:                   it was done in insn-recog.c.  */
        !          1727:              case 'g':
        !          1728:                /* Anything goes unless it is a REG and really has a hard reg
        !          1729:                   but the hard reg is not in the class GENERAL_REGS.  */
        !          1730:                if (strict < 0
        !          1731:                    || GENERAL_REGS == ALL_REGS
        !          1732:                    || GET_CODE (op) != REG
        !          1733:                    || (reload_in_progress
        !          1734:                        && REGNO (op) >= FIRST_PSEUDO_REGISTER)
        !          1735:                    || reg_fits_class_p (op, GENERAL_REGS, offset, mode))
        !          1736:                  win = 1;
        !          1737:                break;
        !          1738: 
        !          1739:              case 'r':
        !          1740:                if (strict < 0
        !          1741:                    || (strict == 0
        !          1742:                        && GET_CODE (op) == REG
        !          1743:                        && REGNO (op) >= FIRST_PSEUDO_REGISTER)
        !          1744:                    || (strict == 0 && GET_CODE (op) == SCRATCH)
        !          1745:                    || (GET_CODE (op) == REG
        !          1746:                        && ((GENERAL_REGS == ALL_REGS
        !          1747:                             && REGNO (op) < FIRST_PSEUDO_REGISTER)
        !          1748:                            || reg_fits_class_p (op, GENERAL_REGS,
        !          1749:                                                 offset, mode))))
        !          1750:                  win = 1;
        !          1751:                break;
        !          1752: 
        !          1753:              case 'X':
        !          1754:                /* This is used for a MATCH_SCRATCH in the cases when we
        !          1755:                   don't actually need anything.  So anything goes any time. */
        !          1756:                win = 1;
        !          1757:                break;
        !          1758: 
        !          1759:              case 'm':
        !          1760:                if (GET_CODE (op) == MEM
        !          1761:                    /* Before reload, accept what reload can turn into mem.  */
        !          1762:                    || (strict < 0 && CONSTANT_P (op))
        !          1763:                    /* During reload, accept a pseudo  */
        !          1764:                    || (reload_in_progress && GET_CODE (op) == REG
        !          1765:                        && REGNO (op) >= FIRST_PSEUDO_REGISTER))
        !          1766:                  win = 1;
        !          1767:                break;
        !          1768: 
        !          1769:              case '<':
        !          1770:                if (GET_CODE (op) == MEM
        !          1771:                    && (GET_CODE (XEXP (op, 0)) == PRE_DEC
        !          1772:                        || GET_CODE (XEXP (op, 0)) == POST_DEC))
        !          1773:                  win = 1;
        !          1774:                break;
        !          1775: 
        !          1776:              case '>':
        !          1777:                if (GET_CODE (op) == MEM
        !          1778:                    && (GET_CODE (XEXP (op, 0)) == PRE_INC
        !          1779:                        || GET_CODE (XEXP (op, 0)) == POST_INC))
        !          1780:                  win = 1;
        !          1781:                break;
        !          1782: 
        !          1783:              case 'E':
        !          1784:                /* Match any CONST_DOUBLE, but only if
        !          1785:                   we can examine the bits of it reliably.  */
        !          1786:                if ((HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
        !          1787:                     || HOST_BITS_PER_WIDE_INT != BITS_PER_WORD)
        !          1788:                    && GET_MODE (op) != VOIDmode && ! flag_pretend_float)
        !          1789:                  break;
        !          1790:                if (GET_CODE (op) == CONST_DOUBLE)
        !          1791:                  win = 1;
        !          1792:                break;
        !          1793: 
        !          1794:              case 'F':
        !          1795:                if (GET_CODE (op) == CONST_DOUBLE)
        !          1796:                  win = 1;
        !          1797:                break;
        !          1798: 
        !          1799:              case 'G':
        !          1800:              case 'H':
        !          1801:                if (GET_CODE (op) == CONST_DOUBLE
        !          1802:                    && CONST_DOUBLE_OK_FOR_LETTER_P (op, c))
        !          1803:                  win = 1;
        !          1804:                break;
        !          1805: 
        !          1806:              case 's':
        !          1807:                if (GET_CODE (op) == CONST_INT
        !          1808:                    || (GET_CODE (op) == CONST_DOUBLE
        !          1809:                        && GET_MODE (op) == VOIDmode))
        !          1810:                  break;
        !          1811:              case 'i':
        !          1812:                if (CONSTANT_P (op))
        !          1813:                  win = 1;
        !          1814:                break;
        !          1815: 
        !          1816:              case 'n':
        !          1817:                if (GET_CODE (op) == CONST_INT
        !          1818:                    || (GET_CODE (op) == CONST_DOUBLE
        !          1819:                        && GET_MODE (op) == VOIDmode))
        !          1820:                  win = 1;
        !          1821:                break;
        !          1822: 
        !          1823:              case 'I':
        !          1824:              case 'J':
        !          1825:              case 'K':
        !          1826:              case 'L':
        !          1827:              case 'M':
        !          1828:              case 'N':
        !          1829:              case 'O':
        !          1830:              case 'P':
        !          1831:                if (GET_CODE (op) == CONST_INT
        !          1832:                    && CONST_OK_FOR_LETTER_P (INTVAL (op), c))
        !          1833:                  win = 1;
        !          1834:                break;
        !          1835: 
        !          1836: #ifdef EXTRA_CONSTRAINT
        !          1837:               case 'Q':
        !          1838:               case 'R':
        !          1839:               case 'S':
        !          1840:               case 'T':
        !          1841:               case 'U':
        !          1842:                if (EXTRA_CONSTRAINT (op, c))
        !          1843:                  win = 1;
        !          1844:                break;
        !          1845: #endif
        !          1846: 
        !          1847:              case 'V':
        !          1848:                if (GET_CODE (op) == MEM
        !          1849:                    && ! offsettable_memref_p (op))
        !          1850:                  win = 1;
        !          1851:                break;
        !          1852: 
        !          1853:              case 'o':
        !          1854:                if ((strict > 0 && offsettable_memref_p (op))
        !          1855:                    || (strict == 0 && offsettable_nonstrict_memref_p (op))
        !          1856:                    /* Before reload, accept what reload can handle.  */
        !          1857:                    || (strict < 0
        !          1858:                        && (CONSTANT_P (op) || GET_CODE (op) == MEM))
        !          1859:                    /* During reload, accept a pseudo  */
        !          1860:                    || (reload_in_progress && GET_CODE (op) == REG
        !          1861:                        && REGNO (op) >= FIRST_PSEUDO_REGISTER))
        !          1862:                  win = 1;
        !          1863:                break;
        !          1864: 
        !          1865:              default:
        !          1866:                if (strict < 0
        !          1867:                    || (strict == 0
        !          1868:                        && GET_CODE (op) == REG
        !          1869:                        && REGNO (op) >= FIRST_PSEUDO_REGISTER)
        !          1870:                    || (strict == 0 && GET_CODE (op) == SCRATCH)
        !          1871:                    || (GET_CODE (op) == REG
        !          1872:                        && reg_fits_class_p (op, REG_CLASS_FROM_LETTER (c),
        !          1873:                                             offset, mode)))
        !          1874:                  win = 1;
        !          1875:              }
        !          1876: 
        !          1877:          constraints[opno] = p;
        !          1878:          /* If this operand did not win somehow,
        !          1879:             this alternative loses.  */
        !          1880:          if (! win)
        !          1881:            lose = 1;
        !          1882:        }
        !          1883:       /* This alternative won; the operands are ok.
        !          1884:         Change whichever operands this alternative says to change.  */
        !          1885:       if (! lose)
        !          1886:        {
        !          1887:          int opno, eopno;
        !          1888: 
        !          1889:          /* See if any earlyclobber operand conflicts with some other
        !          1890:             operand.  */
        !          1891: 
        !          1892:          if (strict > 0)
        !          1893:            for (eopno = 0; eopno < noperands; eopno++)
        !          1894:              /* Ignore earlyclobber operands now in memory,
        !          1895:                 because we would often report failure when we have
        !          1896:                 two memory operands, one of which was formerly a REG.  */
        !          1897:              if (earlyclobber[eopno]
        !          1898:                  && GET_CODE (recog_operand[eopno]) == REG)
        !          1899:                for (opno = 0; opno < noperands; opno++)
        !          1900:                  if ((GET_CODE (recog_operand[opno]) == MEM
        !          1901:                       || op_types[opno] != OP_OUT)
        !          1902:                      && opno != eopno
        !          1903:                      /* Ignore things like match_operator operands. */
        !          1904:                      && *constraints[opno] != 0
        !          1905:                      && ! (matching_operands[opno] == eopno
        !          1906:                            && rtx_equal_p (recog_operand[opno],
        !          1907:                                            recog_operand[eopno]))
        !          1908:                      && ! safe_from_earlyclobber (recog_operand[opno],
        !          1909:                                                   recog_operand[eopno]))
        !          1910:                    lose = 1;
        !          1911: 
        !          1912:          if (! lose)
        !          1913:            {
        !          1914:              while (--funny_match_index >= 0)
        !          1915:                {
        !          1916:                  recog_operand[funny_match[funny_match_index].other]
        !          1917:                    = recog_operand[funny_match[funny_match_index].this];
        !          1918:                }
        !          1919: 
        !          1920:              return 1;
        !          1921:            }
        !          1922:        }
        !          1923: 
        !          1924:       which_alternative++;
        !          1925:     }
        !          1926: 
        !          1927:   /* If we are about to reject this, but we are not to test strictly,
        !          1928:      try a very loose test.  Only return failure if it fails also.  */
        !          1929:   if (strict == 0)
        !          1930:     return constrain_operands (insn_code_num, -1);
        !          1931:   else
        !          1932:     return 0;
        !          1933: }
        !          1934: 
        !          1935: /* Return 1 iff OPERAND (assumed to be a REG rtx)
        !          1936:    is a hard reg in class CLASS when its regno is offsetted by OFFSET
        !          1937:    and changed to mode MODE.
        !          1938:    If REG occupies multiple hard regs, all of them must be in CLASS.  */
        !          1939: 
        !          1940: int
        !          1941: reg_fits_class_p (operand, class, offset, mode)
        !          1942:      rtx operand;
        !          1943:      register enum reg_class class;
        !          1944:      int offset;
        !          1945:      enum machine_mode mode;
        !          1946: {
        !          1947:   register int regno = REGNO (operand);
        !          1948:   if (regno < FIRST_PSEUDO_REGISTER
        !          1949:       && TEST_HARD_REG_BIT (reg_class_contents[(int) class],
        !          1950:                            regno + offset))
        !          1951:     {
        !          1952:       register int sr;
        !          1953:       regno += offset;
        !          1954:       for (sr = HARD_REGNO_NREGS (regno, mode) - 1;
        !          1955:           sr > 0; sr--)
        !          1956:        if (! TEST_HARD_REG_BIT (reg_class_contents[(int) class],
        !          1957:                                 regno + sr))
        !          1958:          break;
        !          1959:       return sr == 0;
        !          1960:     }
        !          1961: 
        !          1962:   return 0;
        !          1963: }
        !          1964: 
        !          1965: #endif /* REGISTER_CONSTRAINTS */

unix.superglobalmegacorp.com

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