Annotation of gcc/combine.c, revision 1.1

1.1     ! root        1: /* Optimize by combining instructions for GNU compiler.
        !             2:    Copyright (C) 1987 Free Software Foundation, Inc.
        !             3: 
        !             4: This file is part of GNU CC.
        !             5: 
        !             6: GNU CC is distributed in the hope that it will be useful,
        !             7: but WITHOUT ANY WARRANTY.  No author or distributor
        !             8: accepts responsibility to anyone for the consequences of using it
        !             9: or for whether it serves any particular purpose or works at all,
        !            10: unless he says so in writing.  Refer to the GNU CC General Public
        !            11: License for full details.
        !            12: 
        !            13: Everyone is granted permission to copy, modify and redistribute
        !            14: GNU CC, but only under the conditions described in the
        !            15: GNU CC General Public License.   A copy of this license is
        !            16: supposed to have been given to you along with GNU CC so you
        !            17: can know your rights and responsibilities.  It should be in a
        !            18: file named COPYING.  Among other things, the copyright notice
        !            19: and this notice must be preserved on all copies.  */
        !            20: 
        !            21: 
        !            22: /* This module is essentially the "combiner" phase of the U. of Arizona
        !            23:    Portable Optimizer, but redone to work on our list-structured
        !            24:    representation for RTL instead of their string representation.
        !            25: 
        !            26:    The LOG_LINKS of each insn identify the most recent assignment
        !            27:    to each REG used in the insn.  It is a list of previous insns,
        !            28:    each of which contains a SET for a REG that is used in this insn
        !            29:    and not used or set in between.  LOG_LINKs never cross basic blocks.
        !            30:    They were set up by the preceding pass (lifetime analysis).
        !            31: 
        !            32:    We try to combine each pair of insns joined by a logical link.
        !            33:    We also try to combine triples of insns A, B and C when
        !            34:    C has a link back to B and B has a link back to A.
        !            35: 
        !            36:    LOG_LINKS does not have links for use of the CC0.  They don't
        !            37:    need to, because the insn that sets the CC0 is always immediately
        !            38:    before the insn that tests it.  So we always regard a branch
        !            39:    insn as having a logical link to the preceding insn.
        !            40: 
        !            41:    We check (with use_crosses_set_p) to avoid combining in such a way
        !            42:    as to move a computation to a place where its value would be different.
        !            43: 
        !            44:    Combination is done by mathematically substituting the previous
        !            45:    insn(s) values for the regs they set into the expressions in
        !            46:    the later insns that refer to these regs.  If the result is a valid insn
        !            47:    for our target machine, according to the machine description,
        !            48:    we install it, delete the earlier insns, and update the data flow
        !            49:    information (LOG_LINKS and REG_NOTES) for what we did.
        !            50: 
        !            51:    To simplify substitution, we combine only when the earlier insn(s)
        !            52:    consist of only a single assignment.  To simplify updating afterward,
        !            53:    we never combine when a subroutine call appears in the middle.
        !            54: 
        !            55:    Since we do not represent assignments to CC0 explicitly except when that
        !            56:    is all an insn does, there is no LOG_LINKS entry in an insn that uses
        !            57:    the condition code for the insn that set the condition code.
        !            58:    Fortunately, these two insns must be consecutive.
        !            59:    Therefore, every JUMP_INSN is taken to have an implicit logical link
        !            60:    to the preceding insn.  This is not quite right, since non-jumps can
        !            61:    also use the condition code; but in practice such insns would not
        !            62:    combine anyway.  */
        !            63: 
        !            64: #include "config.h"
        !            65: #include "rtl.h"
        !            66: #include "regs.h"
        !            67: #include "basic-block.h"
        !            68: #include "insn-config.h"
        !            69: #include "recog.h"
        !            70: 
        !            71: #define max(A,B) ((A) > (B) ? (A) : (B))
        !            72: #define min(A,B) ((A) < (B) ? (A) : (B))
        !            73: 
        !            74: /* Number of attempts to combine instructions in this function.  */
        !            75: 
        !            76: static int combine_attempts;
        !            77: 
        !            78: /* Number of attempts that got as far as substitution in this function.  */
        !            79: 
        !            80: static int combine_merges;
        !            81: 
        !            82: /* Number of instructions combined with added SETs in this function.  */
        !            83: 
        !            84: static int combine_extras;
        !            85: 
        !            86: /* Number of instructions combined in this function.  */
        !            87: 
        !            88: static int combine_successes;
        !            89: 
        !            90: /* Totals over entire compilation.  */
        !            91: 
        !            92: static int total_attempts, total_merges, total_extras, total_successes;
        !            93: 
        !            94: 
        !            95: /* Vector mapping INSN_UIDs to cuids.
        !            96:    The cuids are like uids but increase monononically always.
        !            97:    Combine always uses cuids so that it can compare them.
        !            98:    But actually renumbering the uids, which we used to do,
        !            99:    proves to be a bad idea because it makes it hard to compare
        !           100:    the dumps produced by earlier passes with those from later passes.  */
        !           101: 
        !           102: static short *uid_cuid;
        !           103: 
        !           104: /* Get the cuid of an insn.  */
        !           105: 
        !           106: #define INSN_CUID(INSN) (uid_cuid[INSN_UID (INSN)])
        !           107: 
        !           108: 
        !           109: /* Record last point of death of (hard or pseudo) register n.  */
        !           110: 
        !           111: static rtx *reg_last_death;
        !           112: 
        !           113: /* Record last point of modification of (hard or pseudo) register n.  */
        !           114: 
        !           115: static rtx *reg_last_set;
        !           116: 
        !           117: /* Record the cuid of the last insn that invalidated memory
        !           118:    (anything that writes memory, and subroutine calls).  */
        !           119: 
        !           120: static int mem_last_set;
        !           121: 
        !           122: /* Record the cuid of the last CALL_INSN
        !           123:    so we can tell whether a potential combination crosses any calls.  */
        !           124: 
        !           125: static int last_call_cuid;
        !           126: 
        !           127: /* When `subst' is called, this is the insn that is being modified
        !           128:    (by combining in a previous insn).  The PATTERN of this insn
        !           129:    is still the old pattern partially modified and it should not be
        !           130:    looked at, but this may be used to examine the successors of the insn
        !           131:    to judge whether a simplification is valid.  */
        !           132: 
        !           133: static rtx subst_insn;
        !           134: 
        !           135: /* Record one modification to rtl structure
        !           136:    to be undone by storing old_contents into *where.  */
        !           137: 
        !           138: struct undo
        !           139: {
        !           140:   rtx *where;
        !           141:   rtx old_contents;
        !           142: };
        !           143: 
        !           144: /* Record a bunch of changes to be undone, up to MAX_UNDO of them.
        !           145:    num_undo says how many are currently recorded.
        !           146:    storage is nonzero if we must undo the allocation of new storage.
        !           147:    The value of storage is what to pass to obfree.  */
        !           148: 
        !           149: #define MAX_UNDO 10
        !           150: 
        !           151: struct undobuf
        !           152: {
        !           153:   int num_undo;
        !           154:   char *storage;
        !           155:   struct undo undo[MAX_UNDO];
        !           156: };
        !           157: 
        !           158: static struct undobuf undobuf;
        !           159: 
        !           160: static void move_deaths ();
        !           161: static void remove_death ();
        !           162: static void record_dead_and_set_regs ();
        !           163: int regno_dead_p ();
        !           164: static int reg_set_in_range_p ();
        !           165: static int use_crosses_set_p ();
        !           166: static rtx subst ();
        !           167: static void undo_all ();
        !           168: static void add_links ();
        !           169: static void add_incs ();
        !           170: static int adjacent_insns_p ();
        !           171: static rtx simplify_and_const_int ();
        !           172: static rtx gen_lowpart_for_combine ();
        !           173: static void simplify_set_cc0_and ();
        !           174: 
        !           175: /* Main entry point for combiner.  F is the first insn of the function.
        !           176:    NREGS is the first unused pseudo-reg number.  */
        !           177: 
        !           178: void
        !           179: combine_instructions (f, nregs)
        !           180:      rtx f;
        !           181:      int nregs;
        !           182: {
        !           183:   register rtx insn;
        !           184:   register int i;
        !           185:   register rtx links, nextlinks;
        !           186:   rtx prev;
        !           187: 
        !           188:   combine_attempts = 0;
        !           189:   combine_merges = 0;
        !           190:   combine_extras = 0;
        !           191:   combine_successes = 0;
        !           192: 
        !           193:   reg_last_death = (rtx *) alloca (nregs * sizeof (rtx));
        !           194:   reg_last_set = (rtx *) alloca (nregs * sizeof (rtx));
        !           195:   bzero (reg_last_death, nregs * sizeof (rtx));
        !           196:   bzero (reg_last_set, nregs * sizeof (rtx));
        !           197: 
        !           198:   init_recog ();
        !           199: 
        !           200:   /* Compute maximum uid value so uid_cuid can be allocated.  */
        !           201: 
        !           202:   for (insn = f, i = 0; insn; insn = NEXT_INSN (insn))
        !           203:     if (INSN_UID (insn) > i)
        !           204:       i = INSN_UID (insn);
        !           205: 
        !           206:   uid_cuid = (short *) alloca ((i + 1) * sizeof (short));
        !           207: 
        !           208:   /* Compute the mapping from uids to cuids.
        !           209:      Cuids are numbers assigned to insns, like uids,
        !           210:      except that cuids increase monotonically through the code.  */
        !           211: 
        !           212:   for (insn = f, i = 0; insn; insn = NEXT_INSN (insn))
        !           213:     INSN_CUID (insn) = ++i;
        !           214: 
        !           215:   /* Now scan all the insns in forward order.  */
        !           216: 
        !           217:   last_call_cuid = 0;
        !           218:   mem_last_set = 0;
        !           219:   prev = 0;
        !           220: 
        !           221:   for (insn = f; insn; insn = NEXT_INSN (insn))
        !           222:     {
        !           223:       if (GET_CODE (insn) == INSN
        !           224:          || GET_CODE (insn) == CALL_INSN
        !           225:          || GET_CODE (insn) == JUMP_INSN)
        !           226:        {
        !           227:        retry:
        !           228:          /* Try this insn with each insn it links back to.  */
        !           229: 
        !           230:          for (links = LOG_LINKS (insn); links; links = XEXP (links, 1))
        !           231:            if (try_combine (insn, XEXP (links, 0), 0))
        !           232:              goto retry;
        !           233: 
        !           234:          /* Try each sequence of three linked insns ending with this one.  */
        !           235: 
        !           236:          for (links = LOG_LINKS (insn); links; links = XEXP (links, 1))
        !           237:            if (GET_CODE (XEXP (links, 0)) != NOTE)
        !           238:              for (nextlinks = LOG_LINKS (XEXP (links, 0)); nextlinks;
        !           239:                   nextlinks = XEXP (nextlinks, 1))
        !           240:                if (try_combine (insn, XEXP (links, 0), XEXP (nextlinks, 0)))
        !           241:                  goto retry;
        !           242: 
        !           243:          /* Try to combine a jump insn that uses CC0
        !           244:             with a preceding insn that sets CC0, and maybe with its
        !           245:             logical predecessor as well.
        !           246:             This is how we make decrement-and-branch insns.
        !           247:             We need this special code because data flow connections
        !           248:             via CC0 do not get entered in LOG_LINKS.  */
        !           249: 
        !           250:          if (GET_CODE (insn) == JUMP_INSN
        !           251:              && prev != 0
        !           252:              && GET_CODE (prev) == INSN
        !           253:              && GET_CODE (PATTERN (prev)) == SET
        !           254:              && GET_CODE (SET_DEST (PATTERN (prev))) == CC0)
        !           255:            {
        !           256:              if (try_combine (insn, prev, 0))
        !           257:                  goto retry;
        !           258: 
        !           259:              if (GET_CODE (prev) != NOTE)
        !           260:                for (nextlinks = LOG_LINKS (prev); nextlinks;
        !           261:                     nextlinks = XEXP (nextlinks, 1))
        !           262:                  if (try_combine (insn, prev, XEXP (nextlinks, 0)))
        !           263:                    goto retry;
        !           264:            }
        !           265: #if 0
        !           266: /* Turned off because on 68020 it takes four insns to make
        !           267:    something like (a[b / 32] & (1 << (31 - (b % 32)))) != 0
        !           268:    that could actually be optimized, and that's an unlikely piece of code.  */
        !           269:          /* If an insn gets or sets a bit field, try combining it
        !           270:             with two different insns whose results it uses.  */
        !           271:          if (GET_CODE (insn) == INSN
        !           272:              && GET_CODE (PATTERN (insn)) == SET
        !           273:              && (GET_CODE (SET_DEST (PATTERN (insn))) == ZERO_EXTRACT
        !           274:                  || GET_CODE (SET_DEST (PATTERN (insn))) == SIGN_EXTRACT
        !           275:                  || GET_CODE (SET_SRC (PATTERN (insn))) == ZERO_EXTRACT
        !           276:                  || GET_CODE (SET_SRC (PATTERN (insn))) == SIGN_EXTRACT))
        !           277:            {
        !           278:              for (links = LOG_LINKS (insn); links; links = XEXP (links, 1))
        !           279:                if (GET_CODE (XEXP (links, 0)) != NOTE)
        !           280:                  for (nextlinks = XEXP (links, 1); nextlinks;
        !           281:                       nextlinks = XEXP (nextlinks, 1))
        !           282:                    if (try_combine (insn, XEXP (links, 0), XEXP (nextlinks, 0)))
        !           283:                      goto retry;
        !           284:            }
        !           285: #endif
        !           286:          record_dead_and_set_regs (insn);
        !           287:          prev = insn;
        !           288:        }
        !           289:       else if (GET_CODE (insn) != NOTE)
        !           290:        prev = 0;
        !           291:     }
        !           292:   total_attempts += combine_attempts;
        !           293:   total_merges += combine_merges;
        !           294:   total_extras += combine_extras;
        !           295:   total_successes += combine_successes;
        !           296: }
        !           297: 
        !           298: /* Try to combine the insns I1 and I2 into I3.
        !           299:    Here I1 appears earlier than I2, which is earlier than I3.
        !           300:    I1 can be zero; then we combine just I2 into I3.
        !           301:  
        !           302:    Return 1 if successful; if that happens, I1 and I2 are pseudo-deleted
        !           303:    by turning them into NOTEs, and I3 is modified.
        !           304:    Return 0 if the combination does not work.  Then nothing is changed.  */
        !           305: 
        !           306: static int
        !           307: try_combine (i3, i2, i1)
        !           308:      register rtx i3, i2, i1;
        !           309: {
        !           310:   register rtx newpat;
        !           311:   int added_sets_1 = 0;
        !           312:   int added_sets_2 = 0;
        !           313:   int total_sets;
        !           314:   int i2_is_used;
        !           315:   register rtx link;
        !           316:   int insn_code_number;
        !           317:   int recog_flags = 0;
        !           318:   rtx i2dest, i2src;
        !           319:   rtx i1dest, i1src;
        !           320: 
        !           321:   combine_attempts++;
        !           322: 
        !           323:   /* Don't combine with something already used up by combination.  */
        !           324: 
        !           325:   if (GET_CODE (i2) == NOTE
        !           326:       || (i1 && GET_CODE (i1) == NOTE))
        !           327:     return 0;
        !           328: 
        !           329:   /* Don't combine across a CALL_INSN, because that would possibly
        !           330:      change whether the life span of some REGs crosses calls or not,
        !           331:      and it is a pain to update that information.  */
        !           332: 
        !           333:   if (INSN_CUID (i2) < last_call_cuid
        !           334:       || (i1 && INSN_CUID (i1) < last_call_cuid))
        !           335:     return 0;
        !           336: 
        !           337:   /* Can combine only if previous insn is a SET of a REG, a SUBREG or CC0.
        !           338:      That REG must be either set or dead by the final instruction
        !           339:      (so that we can safely forget about setting it).
        !           340:      Also test use_crosses_set_p to make sure that the value
        !           341:      that is to be substituted for the register
        !           342:      does not use any registers whose values alter in between.
        !           343:      Do not try combining with moves from one register to another
        !           344:      since it is better to let them be tied by register allocation.
        !           345: 
        !           346:      A set of a SUBREG is considered as if it were a set from
        !           347:      SUBREG.  Thus, (SET (SUBREG:X (REG:Y...)) (something:X...))
        !           348:      is handled by substituting (SUBREG:Y (something:X...)) for (REG:Y...).  */
        !           349: 
        !           350:   if (GET_CODE (PATTERN (i2)) != SET)
        !           351:     return 0;
        !           352:   i2dest = SET_DEST (PATTERN (i2));
        !           353:   i2src = SET_SRC (PATTERN (i2));
        !           354:   if (GET_CODE (i2dest) == SUBREG)
        !           355:     {
        !           356:       i2dest = SUBREG_REG (i2dest);
        !           357:       i2src = gen_rtx (SUBREG, GET_MODE (i2dest), i2src, 0);
        !           358:     }
        !           359:   if (GET_CODE (i2dest) != CC0
        !           360:       && (GET_CODE (i2dest) != REG
        !           361:          || GET_CODE (i2src) == REG
        !           362:          || use_crosses_set_p (i2src, INSN_CUID (i2))))
        !           363:     return 0;
        !           364: 
        !           365:   if (i1 != 0)
        !           366:     {
        !           367:       if (GET_CODE (PATTERN (i1)) != SET)
        !           368:        return 0;
        !           369:       i1dest = SET_DEST (PATTERN (i1));
        !           370:       i1src = SET_SRC (PATTERN (i1));
        !           371:       if (GET_CODE (i1dest) == SUBREG)
        !           372:        {
        !           373:          i1dest = SUBREG_REG (i1dest);
        !           374:          i1src = gen_rtx (SUBREG, GET_MODE (i1dest), i1src, 0);
        !           375:        }
        !           376:       if (GET_CODE (i1dest) != CC0
        !           377:          && (GET_CODE (i1dest) != REG
        !           378:              || GET_CODE (i1src) == REG
        !           379:              || use_crosses_set_p (i1src, INSN_CUID (i1))))
        !           380:        return 0;
        !           381:     }
        !           382: 
        !           383:   /* If I1 or I2 contains an autoincrement or autodecrement,
        !           384:      make sure that register is not used between there and I3.
        !           385:      Also insist that I3 not be a jump; if it were one
        !           386:      and the incremented register were spilled, we would lose.  */
        !           387:   for (link = REG_NOTES (i2); link; link = XEXP (link, 1))
        !           388:     if ((enum reg_note) GET_MODE (link) == REG_INC)
        !           389:       if (GET_CODE (i3) == JUMP_INSN
        !           390:          || reg_used_between_p (XEXP (link, 0), i2, i3))
        !           391:        return 0;
        !           392: 
        !           393:   if (i1)
        !           394:     for (link = REG_NOTES (i1); link; link = XEXP (link, 1))
        !           395:       if ((enum reg_note) GET_MODE (link) == REG_INC)
        !           396:        if (GET_CODE (i3) == JUMP_INSN
        !           397:            || reg_used_between_p (XEXP (link, 0), i1, i3))
        !           398:          return 0;
        !           399: 
        !           400:   /* See if the SETs in i1 or i2 need to be kept around in the merged
        !           401:      instruction: whenever the value set there is still needed past i3.  */
        !           402:   added_sets_2 = (GET_CODE (i2dest) != CC0
        !           403:                  && ! dead_or_set_p (i3, i2dest));
        !           404:   if (i1)
        !           405:     added_sets_1 = ! (dead_or_set_p (i3, i1dest)
        !           406:                      || dead_or_set_p (i2, i1dest));
        !           407: 
        !           408:   combine_merges++;
        !           409: 
        !           410:   undobuf.num_undo = 0;
        !           411:   undobuf.storage = 0;
        !           412: 
        !           413:   /* Substitute in the latest insn for the regs set by the earlier ones.  */
        !           414: 
        !           415:   subst_insn = i3;
        !           416:   newpat = subst (PATTERN (i3), i2dest, i2src);
        !           417:   /* Record whether i2's body now appears within i3's body.  */
        !           418:   i2_is_used = undobuf.num_undo;
        !           419: 
        !           420:   if (i1)
        !           421:     newpat = subst (newpat, i1dest, i1src);
        !           422: 
        !           423:   if (GET_CODE (PATTERN (i3)) == SET
        !           424:       && SET_DEST (PATTERN (i3)) == cc0_rtx
        !           425:       && GET_CODE (SET_SRC (PATTERN (i3))) == AND
        !           426:       && next_insn_tests_no_inequality (i3))
        !           427:     simplify_set_cc0_and (i3);
        !           428: 
        !           429:   /* If the actions of the earler insns must be kept
        !           430:      in addition to substituting them into the latest one,
        !           431:      we must make a new PARALLEL for the latest insn
        !           432:      to hold additional the SETs.  */
        !           433: 
        !           434:   if (added_sets_1 || added_sets_2)
        !           435:     {
        !           436:       combine_extras++;
        !           437: 
        !           438:       /* Arrange to free later what we allocate now
        !           439:         if we don't accept this combination.  */
        !           440:       if (!undobuf.storage)
        !           441:        undobuf.storage = (char *) oballoc (0);
        !           442: 
        !           443:       if (GET_CODE (newpat) == PARALLEL)
        !           444:        {
        !           445:          total_sets = XVECLEN (newpat, 0) + added_sets_1 + added_sets_2;
        !           446:          newpat = gen_rtx (PARALLEL, VOIDmode,
        !           447:                            gen_rtvec_v (total_sets,
        !           448:                                         &XVECEXP (newpat, 0, 0)));
        !           449:        }
        !           450:       else
        !           451:        {
        !           452:          total_sets = 1 + added_sets_1 + added_sets_2;
        !           453:          newpat = gen_rtx (PARALLEL, VOIDmode,
        !           454:                            gen_rtvec (total_sets, newpat));
        !           455:        }
        !           456:      if (added_sets_1)
        !           457:        {
        !           458:          XVECEXP (newpat, 0, --total_sets) = PATTERN (i1);
        !           459:        }
        !           460:      if (added_sets_2)
        !           461:        {
        !           462:          /* If there is no I1, use I2's body as is.  */
        !           463:          if (i1 == 0
        !           464:          /* If I2 was stuck into I3, then anything within it has
        !           465:             already had I1 substituted into it when that was done to I3.  */
        !           466:              || i2_is_used)
        !           467:            {
        !           468:              XVECEXP (newpat, 0, --total_sets) = PATTERN (i2);
        !           469:            }
        !           470:          else
        !           471:            XVECEXP (newpat, 0, --total_sets)
        !           472:              = subst (PATTERN (i2), i1dest, i1src);
        !           473:        }
        !           474:     }
        !           475: 
        !           476:   /* Is the result of combination a valid instruction?  */
        !           477:   insn_code_number = recog (newpat, i3);
        !           478: 
        !           479:   if (insn_code_number >= 0)
        !           480:     {
        !           481:       /* Yes.  Install it.  */
        !           482:       register int regno;
        !           483:       INSN_CODE (i3) = insn_code_number;
        !           484:       PATTERN (i3) = newpat;
        !           485:       /* Most REGs that previously died in I2 now die in I3.  */ 
        !           486:       move_deaths (i2src, INSN_CUID (i2), i3);
        !           487:       if (GET_CODE (i2dest) == REG)
        !           488:        {
        !           489:          /* If the reg formerly set in I2 died only once and that was in I3,
        !           490:             zero its use count so it won't make `reload' do any work.  */
        !           491:          regno = REGNO (i2dest);
        !           492:          if (! added_sets_2)
        !           493:            reg_n_sets[regno]--;
        !           494:          if (reg_n_sets[regno] == 0 && regno_dead_p (regno, i3))
        !           495:            reg_n_refs[regno] = 0;
        !           496:          /* If a ref to REGNO was substituted into I3 from I2,
        !           497:             then it still dies there if it previously did.
        !           498:             Otherwise either REGNO never did die in I3 so remove_death is safe
        !           499:             or this entire life of REGNO is gone so remove its death.  */
        !           500:          if (!added_sets_2
        !           501:              && ! reg_mentioned_p (i2dest, PATTERN (i3)))
        !           502:            remove_death (regno, i3);
        !           503:        }
        !           504:       /* The data flowing into I2 now flows into I3.
        !           505:         But we cannot always move I2's LOG_LINKS into I3,
        !           506:         since they must go to a setting of a REG from the
        !           507:         first use following.  If I2 was the first use following a set,
        !           508:         I3 is now a use, but it is not the first use
        !           509:         if some instruction between I2 and I3 is also a use.
        !           510:         Here, for simplicity, we move the links only if
        !           511:         there are no real insns between I2 and I3.  */
        !           512:       if (adjacent_insns_p (i2, i3))
        !           513:        add_links (i3, LOG_LINKS (i2));
        !           514:       /* Any registers previously autoincremented in I2
        !           515:         are now incremented in I3.  */
        !           516:       add_incs (i3, REG_NOTES (i2));
        !           517:       /* Get rid of I2.  */
        !           518:       LOG_LINKS (i2) = 0;
        !           519:       PUT_CODE (i2, NOTE);
        !           520:       NOTE_LINE_NUMBER (i2) = NOTE_INSN_DELETED;
        !           521:       NOTE_SOURCE_FILE (i2) = 0;
        !           522:       if (i1)
        !           523:        {
        !           524:          /* Likewise, merge the info from I1 and get rid of it.  */
        !           525:          move_deaths (i1src, INSN_CUID (i1), i3);
        !           526:          if (GET_CODE (i1dest) == REG)
        !           527:            {
        !           528:              regno = REGNO (i1dest);
        !           529:              if (! added_sets_1)
        !           530:                reg_n_sets[regno]--;
        !           531:              if (reg_n_sets[regno] == 0 && regno_dead_p (regno, i3))
        !           532:                reg_n_refs[regno] = 0;
        !           533:              /* If a ref to REGNO was substituted into I3 from I1,
        !           534:                 then it still dies there if it previously did.
        !           535:                 Else either REGNO never did die in I3 so remove_death is safe
        !           536:                 or this entire life of REGNO is gone so remove its death.  */
        !           537:              if (! added_sets_1
        !           538:                  && ! reg_mentioned_p (i1dest, PATTERN (i3)))
        !           539:                remove_death (regno, i3);
        !           540:            }
        !           541:          if (adjacent_insns_p (i2, i3))
        !           542:            add_links (i3, LOG_LINKS (i1));
        !           543:          add_incs (i3, REG_NOTES (i1));
        !           544:          LOG_LINKS (i1) = 0;
        !           545:          PUT_CODE (i1, NOTE);
        !           546:          NOTE_LINE_NUMBER (i1) = NOTE_INSN_DELETED;
        !           547:          NOTE_SOURCE_FILE (i1) = 0;
        !           548:        }
        !           549: 
        !           550:       combine_successes++;
        !           551:       return 1;
        !           552:     }
        !           553: 
        !           554:   /* Failure: change I3 back the way it was.  */
        !           555:   undo_all ();
        !           556: 
        !           557:   return 0;
        !           558: }
        !           559: 
        !           560: /* Undo all the modifications recorded in undobuf.  */
        !           561: 
        !           562: static void
        !           563: undo_all ()
        !           564: {
        !           565:   register int i;
        !           566:   if (undobuf.num_undo > MAX_UNDO)
        !           567:     undobuf.num_undo = MAX_UNDO;
        !           568:   for (i = undobuf.num_undo - 1; i >= 0; i--)
        !           569:     *undobuf.undo[i].where = undobuf.undo[i].old_contents;
        !           570:   if (undobuf.storage)
        !           571:     obfree (undobuf.storage);
        !           572:   undobuf.num_undo = 0;
        !           573:   undobuf.storage = 0;
        !           574: }
        !           575: 
        !           576: /* Throughout X, replace FROM with TO, and return the result.
        !           577:    The result is TO if X is FROM;
        !           578:    otherwise the result is X, but its contents may have been modified.
        !           579:    If they were modified, a record was made in undobuf so that
        !           580:    undo_all will (among other things) return X to its original state.
        !           581: 
        !           582:    If the number of changes necessary is too much to record to undo,
        !           583:    the excess changes are not made, so the result is invalid.
        !           584:    The changes already made can still be undone.
        !           585:    undobuf.num_undo is incremented for such changes, so by testing that
        !           586:    the caller can tell whether the result is valid.  */
        !           587: 
        !           588: static rtx
        !           589: subst (x, from, to)
        !           590:      register rtx x, from, to;
        !           591: {
        !           592:   register char *fmt;
        !           593:   register int len, i;
        !           594:   register enum rtx_code code;
        !           595: 
        !           596:   /* THIS_TO is used to replace FROM if it appears exactly one
        !           597:      level down in X.  Simplifications often work by changing
        !           598:      THIS_TO after observing that FROM appears in a specific way
        !           599:      one level down in X.  Since only THIS_TO is changed, and TO
        !           600:      is left alone, further occurrences of FROM within the operands
        !           601:      of X are replaced normally.  */
        !           602:   rtx this_to;
        !           603: 
        !           604:   if (x == from)
        !           605:     return to;
        !           606: 
        !           607:   code = GET_CODE (x);
        !           608:   this_to = to;
        !           609: 
        !           610:   /* A little bit of algebraic simplification here.  */
        !           611:   switch (code)
        !           612:     {
        !           613:       /* This case has no effect except to speed things up.  */
        !           614:     case REG:
        !           615:     case CONST_INT:
        !           616:     case CONST:
        !           617:     case SYMBOL_REF:
        !           618:     case LABEL_REF:
        !           619:     case PC:
        !           620:     case CC0:
        !           621:       return x;
        !           622: 
        !           623:     case NOT:
        !           624:     case NEG:
        !           625:       /* Don't let substitution introduce double-negatives.  */
        !           626:       if (XEXP (x, 0) == from
        !           627:          && GET_CODE (to) == code)
        !           628:        return XEXP (to, 0);
        !           629:       break;
        !           630: 
        !           631:     case PLUS:
        !           632:       /* In (plus <foo> (ashift <bar> <n>))
        !           633:         change the shift to a multiply so we can recognize
        !           634:         scaled indexed addresses.  */
        !           635:       if ((XEXP (x, 0) == from
        !           636:           || XEXP (x, 1) == from)
        !           637:          && GET_CODE (to) == ASHIFT
        !           638:          && GET_CODE (XEXP (to, 1)) == CONST_INT)
        !           639:        {
        !           640:          if (!undobuf.storage)
        !           641:            undobuf.storage = (char *) oballoc (0);
        !           642:          this_to = gen_rtx (MULT, GET_MODE (to),
        !           643:                             XEXP (to, 0),
        !           644:                             gen_rtx (CONST_INT, VOIDmode,
        !           645:                                      1 << INTVAL (XEXP (to, 1))));
        !           646:        }
        !           647:       /* If we have something (putative index) being added to a sum,
        !           648:         associate it so that any constant term is outermost.
        !           649:         That's because that's the way indexed addresses are
        !           650:         now supposed to appear.  */
        !           651:       if (((XEXP (x, 0) == from && GET_CODE (XEXP (x, 1)) == PLUS)
        !           652:           || (XEXP (x, 1) == from && GET_CODE (XEXP (x, 0)) == PLUS))
        !           653:          ||
        !           654:          ((XEXP (x, 0) == from || XEXP (x, 1) == from)
        !           655:           && GET_CODE (this_to) == PLUS))
        !           656:        {
        !           657:          rtx offset = 0, base, index;
        !           658:          if (GET_CODE (this_to) != PLUS)
        !           659:            {
        !           660:              index = this_to;
        !           661:              base = XEXP (x, 0) == from ? XEXP (x, 1) : XEXP (x, 0);
        !           662:            }
        !           663:          else
        !           664:            {
        !           665:              index = XEXP (x, 0) == from ? XEXP (x, 1) : XEXP (x, 0);
        !           666:              base = this_to;
        !           667:            }
        !           668:          if (CONSTANT_ADDRESS_P (XEXP (base, 0)))
        !           669:            {
        !           670:              offset = XEXP (base, 0);
        !           671:              base = XEXP (base, 1);
        !           672:            }
        !           673:          else if (CONSTANT_ADDRESS_P (XEXP (base, 1)))
        !           674:            {
        !           675:              offset = XEXP (base, 1);
        !           676:              base = XEXP (base, 0);
        !           677:            }
        !           678:          if (offset != 0)
        !           679:            {
        !           680:              if (!undobuf.storage)
        !           681:                undobuf.storage = (char *) oballoc (0);
        !           682:              return gen_rtx (PLUS, GET_MODE (index), offset,
        !           683:                              gen_rtx (PLUS, GET_MODE (index),
        !           684:                                       index, base));
        !           685:            }
        !           686:        }
        !           687:       break;
        !           688: 
        !           689:     case MINUS:
        !           690:       /* Can simplify (minus:VOIDmode (zero/sign_extend FOO) CONST)
        !           691:         (which is a compare instruction, not a subtract instruction)
        !           692:         to (minus FOO CONST) if CONST fits in FOO's mode
        !           693:         and we are only testing equality.
        !           694:         In fact, this is valid for zero_extend if what follows is an
        !           695:         unsigned comparison, and for sign_extend with a signed comparison.  */
        !           696:       if (GET_MODE (x) == VOIDmode
        !           697:          && XEXP (x, 0) == from
        !           698:          && (GET_CODE (to) == ZERO_EXTEND || GET_CODE (to) == SIGN_EXTEND)
        !           699:          && next_insn_tests_no_inequality (subst_insn)
        !           700:          && GET_CODE (XEXP (x, 1)) == CONST_INT
        !           701:          && ((unsigned) INTVAL (XEXP (x, 1))
        !           702:              < (1 << (BITS_PER_UNIT * GET_MODE_SIZE (GET_MODE (XEXP (to, 0)))))))
        !           703:        this_to = XEXP (to, 0);
        !           704:       break;
        !           705: 
        !           706:     case EQ:
        !           707:     case NE:
        !           708:       /* If comparing a subreg against zero, discard the subreg.  */
        !           709:       if (XEXP (x, 0) == from
        !           710:          && GET_CODE (to) == SUBREG
        !           711:          && SUBREG_WORD (to) == 0
        !           712:          && XEXP (x, 1) == const0_rtx)
        !           713:        this_to = SUBREG_REG (to);
        !           714: 
        !           715:       /* If comparing a ZERO_EXTRACT against zero,
        !           716:         canonicalize to a SIGN_EXTRACT,
        !           717:         since the two are equivalent here.  */
        !           718:       if (XEXP (x, 0) == from
        !           719:          && GET_CODE (this_to) == ZERO_EXTRACT
        !           720:          && XEXP (x, 1) == const0_rtx)
        !           721:        {
        !           722:          if (!undobuf.storage)
        !           723:            undobuf.storage = (char *) oballoc (0);
        !           724:          this_to = gen_rtx (SIGN_EXTRACT, GET_MODE (this_to),
        !           725:                             XEXP (this_to, 0), XEXP (this_to, 1),
        !           726:                             XEXP (this_to, 2));
        !           727:        }
        !           728:       /* If we are putting (ASHIFT 1 x) into (EQ (AND ... y) 0),
        !           729:         arrange to return (EQ (SIGN_EXTRACT y 1 x) 0),
        !           730:         which is what jump-on-bit instructions are written with.  */
        !           731:       else if (XEXP (x, 1) == const0_rtx
        !           732:               && GET_CODE (XEXP (x, 0)) == AND
        !           733:               && (XEXP (XEXP (x, 0), 0) == from
        !           734:                   || XEXP (XEXP (x, 0), 1) == from)
        !           735:               && GET_CODE (this_to) == ASHIFT
        !           736:               && XEXP (this_to, 0) == const1_rtx)
        !           737:        {
        !           738:          register rtx y = XEXP (XEXP (x, 0),
        !           739:                                 XEXP (XEXP (x, 0), 0) == from);
        !           740:          if (!undobuf.storage)
        !           741:            undobuf.storage = (char *) oballoc (0);
        !           742:          this_to = gen_rtx (SIGN_EXTRACT, GET_MODE (this_to),
        !           743:                             y,
        !           744:                             const1_rtx, XEXP (this_to, 1));
        !           745:          from = XEXP (x, 0);
        !           746:        }
        !           747: 
        !           748:       break;
        !           749: 
        !           750:     case ZERO_EXTEND:
        !           751:       if (XEXP (x, 0) == from
        !           752:          && GET_CODE (to) == ZERO_EXTEND)
        !           753:        this_to = XEXP (to, 0);
        !           754:       /* Zero-extending the result of an and with a constant can be done
        !           755:         with a wider and.  */
        !           756:       if (XEXP (x, 0) == from
        !           757:          && GET_CODE (to) == AND
        !           758:          && GET_CODE (XEXP (to, 1)) == CONST_INT
        !           759:          && (GET_CODE (XEXP (to, 0)) == REG
        !           760:              || offsetable_address_p (XEXP (to, 0)))
        !           761:          /* Avoid getting wrong result if the constant has high bits set
        !           762:             that are irrelevant in the narrow mode where it is being used.  */
        !           763:          && ((INTVAL (XEXP (to, 1))
        !           764:               & (-1 << (GET_MODE_SIZE (GET_MODE (to)) * BITS_PER_UNIT)))
        !           765:              == 0))
        !           766:        {
        !           767:          if (!undobuf.storage)
        !           768:            undobuf.storage = (char *) oballoc (0);
        !           769:          return gen_rtx (AND, GET_MODE (x),
        !           770:                          gen_lowpart (GET_MODE (x), XEXP (to, 0)),
        !           771:                          XEXP (to, 1));
        !           772:         } 
        !           773:       break;
        !           774: 
        !           775:     case SIGN_EXTEND:
        !           776:       if (XEXP (x, 0) == from
        !           777:          && GET_CODE (to) == SIGN_EXTEND)
        !           778:        this_to = XEXP (to, 0);
        !           779:       /* Sign-extending the result of an and with a constant can be done
        !           780:         with a wider and, provided the high bit of the constant is 0.  */
        !           781:       if (XEXP (x, 0) == from
        !           782:          && GET_CODE (to) == AND
        !           783:          && GET_CODE (XEXP (to, 1)) == CONST_INT
        !           784:          && (GET_CODE (XEXP (to, 0)) == REG
        !           785:              || offsetable_address_p (XEXP (to, 0)))
        !           786:          && ((INTVAL (XEXP (to, 1))
        !           787:               & (-1 << (GET_MODE_SIZE (GET_MODE (to)) * BITS_PER_UNIT - 1)))
        !           788:              == 0))
        !           789:        {
        !           790:          if (!undobuf.storage)
        !           791:            undobuf.storage = (char *) oballoc (0);
        !           792:          return gen_rtx (AND, GET_MODE (x),
        !           793:                          gen_lowpart (GET_MODE (x), XEXP (to, 0)),
        !           794:                          XEXP (to, 1));
        !           795:         } 
        !           796:       break;
        !           797: 
        !           798:     case SET:
        !           799:       /* In (set (zero-extract <x> <1> <y>) (and <foo> <1>))
        !           800:         the `and' can be deleted.  This can happen when storing a bit
        !           801:         that came from a set-flag insn followed by masking to one bit.
        !           802:         There is probably no need to optimize other field widths similarly
        !           803:         because on machines with bit-field insns `and' is not needed
        !           804:         to extract the fields.  */
        !           805:       if (GET_CODE (XEXP (x, 0)) == ZERO_EXTRACT
        !           806:          && XEXP (XEXP (x, 0), 1) == const1_rtx
        !           807:          && XEXP (x, 1) == from
        !           808:          && GET_CODE (to) == AND
        !           809:          && XEXP (to, 1) == const1_rtx)
        !           810:        {
        !           811:          this_to = XEXP (to, 0);
        !           812:         } 
        !           813:       break;
        !           814: 
        !           815:     case AND:
        !           816:       if (GET_CODE (XEXP (x, 1)) == CONST_INT)
        !           817:        {
        !           818:          rtx tem = simplify_and_const_int (x, from, to);
        !           819:          if (tem)
        !           820:            return tem;
        !           821:        }
        !           822:       break;
        !           823: 
        !           824:     case FLOAT:
        !           825:       /* (float (sign_extend <X>)) = (float <X>).  */
        !           826:       if (XEXP (x, 0) == from
        !           827:          && GET_CODE (to) == SIGN_EXTEND)
        !           828:        this_to = XEXP (to, 0);
        !           829:       break;
        !           830: 
        !           831:     case ZERO_EXTRACT:
        !           832:       /* Extracting a single bit from the result of a shift:
        !           833:         see which bit it was before the shift and extract that directly.  */
        !           834:       if (XEXP (x, 0) == from
        !           835:          && (GET_CODE (to) == ASHIFTRT || GET_CODE (to) == LSHIFTRT
        !           836:              || GET_CODE (to) == ASHIFT || GET_CODE (to) == LSHIFT)
        !           837:          && GET_CODE (XEXP (to, 1)) == CONST_INT
        !           838:          && XEXP (x, 1) == const1_rtx
        !           839:          && GET_CODE (XEXP (x, 2)) == CONST_INT)
        !           840:        {
        !           841:          int shift = INTVAL (XEXP (to, 1));
        !           842:          int newpos;
        !           843:          if (GET_CODE (to) == ASHIFT || GET_CODE (to) == LSHIFT)
        !           844:            shift = - shift;
        !           845: #ifdef BITS_BIG_ENDIAN
        !           846:          shift = - shift;
        !           847: #endif
        !           848:          newpos = INTVAL (XEXP (x, 2)) + shift;
        !           849:          if (newpos >= 0 &&
        !           850:              newpos < BITS_PER_UNIT * GET_MODE_SIZE (GET_MODE (from)))
        !           851:            {
        !           852:              if (!undobuf.storage)
        !           853:                undobuf.storage = (char *) oballoc (0);
        !           854:              return gen_rtx (ZERO_EXTRACT, GET_MODE (x),
        !           855:                              XEXP (to, 0), const1_rtx,
        !           856:                              gen_rtx (CONST_INT, VOIDmode, newpos));
        !           857:            }
        !           858:        }
        !           859:       break;
        !           860: 
        !           861:     case LSHIFTRT:
        !           862:     case ASHIFTRT:
        !           863:     case ROTATE:
        !           864:     case ROTATERT:
        !           865: #ifdef SHIFT_COUNT_TRUNCATED
        !           866:       /* (lshift <X> (sign_extend <Y>)) = (lshift <X> <Y>) (most machines).
        !           867:         True for all kinds of shifts and also for zero_extend.  */
        !           868:       if (XEXP (x, 1) == from
        !           869:          && (GET_CODE (to) == SIGN_EXTEND
        !           870:              || GET_CODE (to) == ZERO_EXTEND))
        !           871:        {
        !           872:          if (!undobuf.storage)
        !           873:            undobuf.storage = (char *) oballoc (0);
        !           874:          this_to = gen_rtx (SUBREG, GET_MODE (to), XEXP (to, 0), 0);
        !           875:        }
        !           876: #endif
        !           877:       /* Two shifts in a row of same kind
        !           878:         in same direction with constant counts
        !           879:         may be combined.  */
        !           880:       if (XEXP (x, 0) == from
        !           881:          && GET_CODE (to) == GET_CODE (x)
        !           882:          && GET_CODE (XEXP (x, 1)) == CONST_INT
        !           883:          && GET_CODE (XEXP (to, 1)) == CONST_INT
        !           884:          && INTVAL (XEXP (to, 1)) > 0
        !           885:          && INTVAL (XEXP (x, 1)) > 0
        !           886:          && (INTVAL (XEXP (x, 1)) + INTVAL (XEXP (to, 1))
        !           887:              < BITS_PER_UNIT * GET_MODE_SIZE (GET_MODE (x))))
        !           888:        {
        !           889:          if (!undobuf.storage)
        !           890:            undobuf.storage = (char *) oballoc (0);
        !           891:          return gen_rtx (GET_CODE (x), GET_MODE (x),
        !           892:                          XEXP (to, 0),
        !           893:                          gen_rtx (CONST_INT, VOIDmode,
        !           894:                                   INTVAL (XEXP (x, 1))
        !           895:                                   + INTVAL (XEXP (to, 1))));
        !           896:        }
        !           897:       break;
        !           898: 
        !           899:     case LSHIFT:
        !           900:     case ASHIFT:
        !           901: #ifdef SHIFT_COUNT_TRUNCATED
        !           902:       /* (lshift <X> (sign_extend <Y>)) = (lshift <X> <Y>) (most machines).
        !           903:         True for all kinds of shifts and also for zero_extend.  */
        !           904:       if (XEXP (x, 1) == from
        !           905:          && (GET_CODE (to) == SIGN_EXTEND
        !           906:              || GET_CODE (to) == ZERO_EXTEND))
        !           907:        {
        !           908:          if (!undobuf.storage)
        !           909:            undobuf.storage = (char *) oballoc (0);
        !           910:          this_to = gen_rtx (SUBREG, GET_MODE (to), XEXP (to, 0), 0);
        !           911:        }
        !           912: #endif
        !           913:       /* (lshift (and (lshiftrt <foo> <X>) <Y>) <X>)
        !           914:         happens copying between bit fields in similar structures.
        !           915:         It can be replaced by one and instruction.
        !           916:         It does not matter whether the shifts are logical or arithmetic.  */
        !           917:       if (GET_CODE (XEXP (x, 0)) == AND
        !           918:          && GET_CODE (XEXP (x, 1)) == CONST_INT
        !           919:          && INTVAL (XEXP (x, 1)) > 0
        !           920:          && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
        !           921:          && XEXP (XEXP (x, 0), 0) == from
        !           922:          && (GET_CODE (to) == LSHIFTRT
        !           923:              || GET_CODE (to) == ASHIFTRT)
        !           924: #if 0
        !           925: /* I now believe this restriction is unnecessary.
        !           926:    The outer shift will discard those bits in any case, right?  */
        !           927: 
        !           928:              /* If inner shift is arithmetic, either it shifts left or
        !           929:                 the bits it shifts the sign into are zeroed by the and.  */
        !           930:                  && (INTVAL (XEXP (x, 1)) < 0
        !           931:                      || ((unsigned) INTVAL (XEXP (XEXP (x, 0), 1))
        !           932:                          < 1 << (GET_MODE_BITSIZE (GET_MODE (x))
        !           933:                                  - INTVAL (XEXP (x, 0)))))
        !           934: #endif
        !           935:          && GET_CODE (XEXP (to, 1)) == CONST_INT
        !           936:          && INTVAL (XEXP (x, 1)) == INTVAL (XEXP (to, 1)))
        !           937:        {
        !           938:          if (!undobuf.storage)
        !           939:            undobuf.storage = (char *) oballoc (0);
        !           940:          /* The constant in the new `and' is <Y> << <X>
        !           941:             but clear out all bits that don't belong in our mode.  */
        !           942:          return gen_rtx (AND, GET_MODE (x), XEXP (to, 0),
        !           943:                          gen_rtx (CONST_INT, VOIDmode,
        !           944:                                   (GET_MODE_MASK (GET_MODE (x))
        !           945:                                    & ((GET_MODE_MASK (GET_MODE (x))
        !           946:                                        & INTVAL (XEXP (XEXP (x, 0), 1)))
        !           947:                                       << INTVAL (XEXP (x, 1))))));
        !           948:        } 
        !           949:       /* Two shifts in a row in same direction with constant counts
        !           950:         may be combined.  */
        !           951:       if (XEXP (x, 0) == from
        !           952:          && (GET_CODE (to) == ASHIFT || GET_CODE (to) == LSHIFT)
        !           953:          && GET_CODE (XEXP (x, 1)) == CONST_INT
        !           954:          && GET_CODE (XEXP (to, 1)) == CONST_INT
        !           955:          && INTVAL (XEXP (to, 1)) > 0
        !           956:          && INTVAL (XEXP (x, 1)) > 0
        !           957:          && (INTVAL (XEXP (x, 1)) + INTVAL (XEXP (to, 1))
        !           958:              < BITS_PER_UNIT * GET_MODE_SIZE (GET_MODE (x))))
        !           959:        {
        !           960:          if (!undobuf.storage)
        !           961:            undobuf.storage = (char *) oballoc (0);
        !           962:          return gen_rtx (GET_CODE (x), GET_MODE (x),
        !           963:                          XEXP (to, 0),
        !           964:                          gen_rtx (CONST_INT, VOIDmode,
        !           965:                                   INTVAL (XEXP (x, 1))
        !           966:                                   + INTVAL (XEXP (to, 1))));
        !           967:        }
        !           968:       /* (ashift (ashiftrt <foo> <X>) <X>)
        !           969:         (or, on some machines, (ashift (ashift <foo> <-X>) <X>) instead)
        !           970:         happens if you divide by 2**N and then multiply by 2**N.
        !           971:         It can be replaced by one `and' instruction.
        !           972:         It does not matter whether the shifts are logical or arithmetic.  */
        !           973:       if (GET_CODE (XEXP (x, 1)) == CONST_INT
        !           974:          && INTVAL (XEXP (x, 1)) > 0
        !           975:          && XEXP (x, 0) == from
        !           976:          && (((GET_CODE (to) == LSHIFTRT || GET_CODE (to) == ASHIFTRT)
        !           977:               && GET_CODE (XEXP (to, 1)) == CONST_INT
        !           978:               && INTVAL (XEXP (x, 1)) == INTVAL (XEXP (to, 1)))
        !           979:              ||
        !           980:              ((GET_CODE (to) == LSHIFT || GET_CODE (to) == ASHIFT)
        !           981:               && GET_CODE (XEXP (to, 1)) == CONST_INT
        !           982:               && INTVAL (XEXP (x, 1)) == - INTVAL (XEXP (to, 1)))))
        !           983:        {
        !           984:          if (!undobuf.storage)
        !           985:            undobuf.storage = (char *) oballoc (0);
        !           986:          /* The constant in the new `and' is <Y> << <X>
        !           987:             but clear out all bits that don't belong in our mode.  */
        !           988:          return gen_rtx (AND, GET_MODE (x), XEXP (to, 0),
        !           989:                          gen_rtx (CONST_INT, VOIDmode,
        !           990:                                   (GET_MODE_MASK (GET_MODE (x))
        !           991:                                    & (GET_MODE_MASK (GET_MODE (x))
        !           992:                                       << INTVAL (XEXP (x, 1))))));
        !           993:        } 
        !           994: 
        !           995:     }
        !           996: 
        !           997:   len = GET_RTX_LENGTH (code);
        !           998:   fmt = GET_RTX_FORMAT (code);
        !           999: 
        !          1000:   /* Don't replace FROM where it is being stored in rather than used.  */
        !          1001:   if (code == SET && SET_DEST (x) == from)
        !          1002:     fmt = "ie";
        !          1003: 
        !          1004:   for (i = 0; i < len; i++)
        !          1005:     {
        !          1006:       if (fmt[i] == 'E')
        !          1007:        {
        !          1008:          register int j;
        !          1009:          for (j = XVECLEN (x, i) - 1; j >= 0; j--)
        !          1010:            {
        !          1011:              register rtx new;
        !          1012:              if (XVECEXP (x, i, j) == from)
        !          1013:                new = this_to;
        !          1014:              else
        !          1015:                new = subst (XVECEXP (x, i, j), from, to);
        !          1016:              if (new != XVECEXP (x, i, j))
        !          1017:                {
        !          1018:                  if (undobuf.num_undo < MAX_UNDO)
        !          1019:                    {
        !          1020:                      undobuf.undo[undobuf.num_undo].where = &XVECEXP (x, i, j);
        !          1021:                      undobuf.undo[undobuf.num_undo].old_contents = XVECEXP (x, i, j);
        !          1022:                      XVECEXP (x, i, j) = new;
        !          1023:                    }
        !          1024:                  undobuf.num_undo++;
        !          1025:                }
        !          1026:            }
        !          1027:        }
        !          1028:       else if (fmt[i] == 'e')
        !          1029:        {
        !          1030:          register rtx new;
        !          1031: 
        !          1032:          if (XEXP (x, i) == from)
        !          1033:            new = this_to;
        !          1034:          else
        !          1035:            new = subst (XEXP (x, i), from, to);
        !          1036: 
        !          1037:          if (new != XEXP (x, i))
        !          1038:            {
        !          1039:              if (undobuf.num_undo < MAX_UNDO)
        !          1040:                {
        !          1041:                  undobuf.undo[undobuf.num_undo].where = &XEXP (x, i);
        !          1042:                  undobuf.undo[undobuf.num_undo].old_contents = XEXP (x, i);
        !          1043:                  XEXP (x, i) = new;
        !          1044:                }
        !          1045:              undobuf.num_undo++;
        !          1046:            }
        !          1047:        }
        !          1048:     }
        !          1049:   return x;
        !          1050: }
        !          1051: 
        !          1052: /* This is the AND case of the function subst.  */
        !          1053: 
        !          1054: static rtx
        !          1055: simplify_and_const_int (x, from, to)
        !          1056:      rtx x, from, to;
        !          1057: {
        !          1058:   register rtx varop = XEXP (x, 0);
        !          1059:   register int constop = INTVAL (XEXP (x, 1));
        !          1060: 
        !          1061:   /* (and (subreg (and <foo> <constant>) 0) <constant>)
        !          1062:      results from an andsi followed by an andqi,
        !          1063:      which happens frequently when storing bit-fields
        !          1064:      on something whose result comes from an andsi.  */
        !          1065:   if (GET_CODE (varop) == SUBREG
        !          1066:       && XEXP (varop, 0) == from
        !          1067:       && subreg_lowpart_p (varop)
        !          1068:       && GET_CODE (to) == AND
        !          1069:       && GET_CODE (XEXP (to, 1)) == CONST_INT
        !          1070:       /* Verify that the result of the outer `and'
        !          1071:         is not affected by any bits not defined in the inner `and'.
        !          1072:         True if the outer mode is narrower, or if the outer constant
        !          1073:         masks to zero all the bits that the inner mode doesn't have.  */
        !          1074:       && (GET_MODE_SIZE (GET_MODE (x)) < GET_MODE_SIZE (GET_MODE (from))
        !          1075:          || constop & (-1 << (BITS_PER_UNIT * GET_MODE_SIZE (GET_MODE (from)))) == 0))
        !          1076:     {
        !          1077:       if (!undobuf.storage)
        !          1078:        undobuf.storage = (char *) oballoc (0);
        !          1079:       return gen_rtx (AND, GET_MODE (x),
        !          1080:                      gen_lowpart (GET_MODE (x), XEXP (to, 0)),
        !          1081:                      gen_rtx (CONST_INT, VOIDmode,
        !          1082:                               constop
        !          1083:                               /* Remember that the bits outside that mode
        !          1084:                                  are not being changed, so the effect
        !          1085:                                  is as if they were all 1.  */
        !          1086:                               & INTVAL (XEXP (to, 1))));
        !          1087:     } 
        !          1088:   /* (and (zero_extend <foo>) <constant>)
        !          1089:      often results from storing in a bit-field something
        !          1090:      that was calculated as a short.  Replace with a single `and'
        !          1091:      in whose constant all bits not in <foo>'s mode are zero.  */
        !          1092:   if (varop == from
        !          1093:       && GET_CODE (to) == ZERO_EXTEND)
        !          1094:     {
        !          1095:       if (!undobuf.storage)
        !          1096:        undobuf.storage = (char *) oballoc (0);
        !          1097:       return gen_rtx (AND, GET_MODE (x),
        !          1098:                      gen_rtx (SUBREG, GET_MODE (x),
        !          1099:                               XEXP (to, 0), 0),
        !          1100:                      gen_rtx (CONST_INT, VOIDmode,
        !          1101:                               constop
        !          1102:                               & ((1 << (BITS_PER_UNIT * GET_MODE_SIZE (GET_MODE (XEXP (to, 0))))) - 1)));
        !          1103:     }
        !          1104:   /* (and (sign_extend <foo>) <constant>)
        !          1105:      can be replaced with (and (subreg <foo>) <constant>)
        !          1106:      if <constant> is narrower than <foo>'s mode,
        !          1107:      or with (zero_extend <foo>) if <constant> is a mask for that mode.  */
        !          1108:   if (varop == from
        !          1109:       && GET_CODE (to) == SIGN_EXTEND
        !          1110:       && ((unsigned) constop
        !          1111:          <= ((1 << (BITS_PER_UNIT
        !          1112:                     * GET_MODE_SIZE (GET_MODE (XEXP (to, 0)))))
        !          1113:              - 1)))
        !          1114:     {
        !          1115:       if (!undobuf.storage)
        !          1116:        undobuf.storage = (char *) oballoc (0);
        !          1117:       if (constop == ((1 << (BITS_PER_UNIT
        !          1118:                             * GET_MODE_SIZE (GET_MODE (XEXP (to, 0)))))
        !          1119:                      - 1))
        !          1120:        return gen_rtx (ZERO_EXTEND, GET_MODE (x), XEXP (to, 0));
        !          1121:       return gen_rtx (AND, GET_MODE (x),
        !          1122:                      gen_rtx (SUBREG, GET_MODE (x),
        !          1123:                               XEXP (to, 0), 0),
        !          1124:                      XEXP (x, 1));
        !          1125:     }
        !          1126:   /* (and (and <foo> <constant>) <constant>)
        !          1127:      comes from two and instructions in a row.  */
        !          1128:   if (varop == from
        !          1129:       && GET_CODE (to) == AND
        !          1130:       && GET_CODE (XEXP (to, 1)) == CONST_INT)
        !          1131:     {
        !          1132:       if (!undobuf.storage)
        !          1133:        undobuf.storage = (char *) oballoc (0);
        !          1134:       return gen_rtx (AND, GET_MODE (x),
        !          1135:                      XEXP (to, 0),
        !          1136:                      gen_rtx (CONST_INT, VOIDmode,
        !          1137:                               constop
        !          1138:                               & INTVAL (XEXP (to, 1))));
        !          1139:     }
        !          1140:   /* (and (ashiftrt (ashift FOO N) N) CONST)
        !          1141:      may be simplified to (and FOO CONST) if CONST masks off the bits
        !          1142:      changed by the two shifts.  */
        !          1143:   if (GET_CODE (varop) == ASHIFTRT
        !          1144:       && GET_CODE (XEXP (varop, 1)) == CONST_INT
        !          1145:       && XEXP (varop, 0) == from
        !          1146:       && GET_CODE (to) == ASHIFT
        !          1147:       && GET_CODE (XEXP (to, 1)) == CONST_INT
        !          1148:       && INTVAL (XEXP (varop, 1)) == INTVAL (XEXP (to, 1))
        !          1149:       && ((unsigned) constop >> INTVAL (XEXP (varop, 1))) == 0)
        !          1150:     {
        !          1151:       if (!undobuf.storage)
        !          1152:        undobuf.storage = (char *) oballoc (0);
        !          1153:       /* If CONST is a mask for the low byte,
        !          1154:         change this into a zero-extend instruction
        !          1155:         from just the low byte of FOO.  */
        !          1156:       if (constop == (1 << BITS_PER_UNIT) - 1)
        !          1157:        {
        !          1158:          rtx temp = gen_lowpart_for_combine (QImode, XEXP (to, 0));
        !          1159:          if (temp)
        !          1160:            return gen_rtx (ZERO_EXTEND, GET_MODE (x), temp);
        !          1161:        }
        !          1162:       return gen_rtx (AND, GET_MODE (x),
        !          1163:                      XEXP (to, 0), XEXP (x, 1));
        !          1164:     }
        !          1165: 
        !          1166:   /* No simplification applies.  */
        !          1167:   return 0;
        !          1168: }
        !          1169: 
        !          1170: /* Like gen_lowpart but for use by combine.  In combine it is not possible
        !          1171:    to create any new pseudoregs.  However, it is safe to create
        !          1172:    invalid memory addresses, because combine will try to recognize
        !          1173:    them and all they will do is make the combine attempt fail.
        !          1174: 
        !          1175:    Also, return zero if we don't see a way to make a lowpart.  */
        !          1176: 
        !          1177: static rtx
        !          1178: gen_lowpart_for_combine (mode, x)
        !          1179:      enum machine_mode mode;
        !          1180:      register rtx x;
        !          1181: {
        !          1182:   if (GET_CODE (x) == SUBREG || GET_CODE (x) == REG)
        !          1183:     return gen_lowpart (mode, x);
        !          1184:   if (GET_MODE (x) == mode)
        !          1185:     return 0;
        !          1186:   if (GET_CODE (x) == VOLATILE)
        !          1187:     return 0;
        !          1188:   if (GET_CODE (x) == MEM)
        !          1189:     {
        !          1190:       register int offset = 0;
        !          1191: #ifdef WORDS_BIG_ENDIAN
        !          1192:       offset = (max (GET_MODE_SIZE (GET_MODE (x)), UNITS_PER_WORD)
        !          1193:                - max (GET_MODE_SIZE (mode), UNITS_PER_WORD));
        !          1194: #endif
        !          1195: #ifdef BYTES_BIG_ENDIAN
        !          1196:       if (GET_MODE_SIZE (mode) < UNITS_PER_WORD)
        !          1197:        offset -= (GET_MODE_SIZE (mode)
        !          1198:                   - min (UNITS_PER_WORD,
        !          1199:                          GET_MODE_SIZE (GET_MODE (x))));
        !          1200: #endif
        !          1201:       return gen_rtx (MEM, mode, plus_constant (XEXP (x, 0),
        !          1202:                                                offset));
        !          1203:     }
        !          1204:   else
        !          1205:     return 0;
        !          1206: }
        !          1207: 
        !          1208: /* After substitution, if the resulting pattern looks like
        !          1209:    (set (cc0) (and ...)), this function is called to simplify the
        !          1210:    pattern into a bit-field operation if possible.  */
        !          1211: 
        !          1212: static void
        !          1213: simplify_set_cc0_and (insn)
        !          1214:      rtx insn;
        !          1215: {
        !          1216:   register rtx value = XEXP (PATTERN (insn), 1);
        !          1217:   register rtx op0 = XEXP (value, 0);
        !          1218:   register rtx op1 = XEXP (value, 1);
        !          1219:   int offset = 0;
        !          1220:   rtx var = 0;
        !          1221:   rtx bitnum = 0;
        !          1222:   int temp;
        !          1223:   int unit;
        !          1224: 
        !          1225:   /* Look for a constant power of 2 or a shifted 1
        !          1226:      on either side of the AND.  Set VAR to the other side.
        !          1227:      Set BITNUM to the shift count of the 1 (as an rtx).
        !          1228:      Or, if bit number is constant, set OFFSET to the bit number.  */
        !          1229: 
        !          1230:   switch (GET_CODE (op0))
        !          1231:     {
        !          1232:     case CONST_INT:
        !          1233:       temp = exact_log2 (INTVAL (op0));
        !          1234:       if (temp < 0)
        !          1235:        return;
        !          1236:       offset = temp;
        !          1237:       var = op1;
        !          1238:       break;
        !          1239: 
        !          1240:     case ASHIFT:
        !          1241:     case LSHIFT:
        !          1242:       if (XEXP (op0, 0) == const1_rtx)
        !          1243:        {
        !          1244:          bitnum = XEXP (op0, 1);
        !          1245:          var = op1;
        !          1246:        }
        !          1247:     }
        !          1248:   if (var == 0)
        !          1249:     switch (GET_CODE (op1))
        !          1250:       {
        !          1251:       case CONST_INT:
        !          1252:        temp = exact_log2 (INTVAL (op1));
        !          1253:        if (temp < 0)
        !          1254:          return;
        !          1255:        offset = temp;
        !          1256:        var = op0;
        !          1257:        break;
        !          1258: 
        !          1259:       case ASHIFT:
        !          1260:       case LSHIFT:
        !          1261:        if (XEXP (op1, 0) == const1_rtx)
        !          1262:          {
        !          1263:            bitnum = XEXP (op1, 1);
        !          1264:            var = op0;
        !          1265:          }
        !          1266:       }
        !          1267: 
        !          1268:   /* If VAR is 0, we didn't find something recognizable.  */
        !          1269:   if (var == 0)
        !          1270:     return;
        !          1271: 
        !          1272:   if (!undobuf.storage)
        !          1273:     undobuf.storage = (char *) oballoc (0);
        !          1274: 
        !          1275:   /* If the bit position is currently exactly 0,
        !          1276:      extract a right-shift from the variable portion.  */
        !          1277:   if (offset == 0
        !          1278:       && (GET_CODE (var) == ASHIFTRT || GET_CODE (var) == LSHIFTRT))
        !          1279:     {
        !          1280:       bitnum = XEXP (var, 1);
        !          1281:       var = XEXP (var, 0);
        !          1282:     }
        !          1283: 
        !          1284: #ifdef BITS_BIG_ENDIAN
        !          1285:   unit = GET_MODE_SIZE (GET_MODE (var)) * BITS_PER_UNIT - 1;
        !          1286: 
        !          1287:   if (bitnum != 0)
        !          1288:     bitnum = gen_rtx (MINUS, SImode,
        !          1289:                      gen_rtx (CONST_INT, VOIDmode, unit), bitnum);
        !          1290:   else
        !          1291:     offset = unit - offset;
        !          1292: #endif
        !          1293: 
        !          1294:   if (bitnum == 0)
        !          1295:     bitnum = gen_rtx (CONST_INT, VOIDmode, offset);
        !          1296: 
        !          1297:   if (GET_CODE (var) == SUBREG && SUBREG_WORD (var) == 0)
        !          1298:     var = SUBREG_REG (var);
        !          1299: 
        !          1300:   if (undobuf.num_undo < MAX_UNDO)
        !          1301:     {
        !          1302:       undobuf.undo[undobuf.num_undo].where = &XEXP (PATTERN (insn), 1);
        !          1303:       undobuf.undo[undobuf.num_undo].old_contents = value;
        !          1304:       XEXP (PATTERN (insn), 1)
        !          1305:        = gen_rtx (ZERO_EXTRACT, VOIDmode, var, const1_rtx, bitnum);
        !          1306:     }
        !          1307:   undobuf.num_undo++;
        !          1308: }
        !          1309: 
        !          1310: /* Update the records of when each REG was most recently set or killed
        !          1311:    for the things done by INSN.  This is the last thing done in processing
        !          1312:    INSN in the combiner loop.
        !          1313: 
        !          1314:    We update reg_last_set, reg_last_death, and also the similar information
        !          1315:    mem_last_set (which insn most recently modified memory)
        !          1316:    and last_call_cuid (which insn was the most recent subroutine call).  */
        !          1317: 
        !          1318: static void
        !          1319: record_dead_and_set_regs (insn)
        !          1320:      rtx insn;
        !          1321: {
        !          1322:   register rtx link;
        !          1323:   for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
        !          1324:     {
        !          1325:       if ((enum reg_note) GET_MODE (link) == REG_DEAD)
        !          1326:        reg_last_death[REGNO (XEXP (link, 0))] = insn;
        !          1327:       else if ((enum reg_note) GET_MODE (link) == REG_INC)
        !          1328:        reg_last_set[REGNO (XEXP (link, 0))] = insn;
        !          1329:     }
        !          1330: 
        !          1331:   if (GET_CODE (insn) == CALL_INSN)
        !          1332:     last_call_cuid = mem_last_set = INSN_CUID (insn);
        !          1333: 
        !          1334:   if (GET_CODE (PATTERN (insn)) == PARALLEL)
        !          1335:     {
        !          1336:       register int i;
        !          1337:       for (i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--)
        !          1338:        {
        !          1339:          register rtx elt = XVECEXP (PATTERN (insn), 0, i);
        !          1340:          register enum rtx_code code = GET_CODE (elt);
        !          1341:          if (code == SET || code == CLOBBER)
        !          1342:            {
        !          1343:              if (GET_CODE (XEXP (elt, 0)) == REG)
        !          1344:                reg_last_set[REGNO (XEXP (elt, 0))] = insn;
        !          1345:              else if (GET_CODE (XEXP (elt, 0)) == MEM)
        !          1346:                mem_last_set = INSN_CUID (insn);
        !          1347:            }
        !          1348:        }
        !          1349:     }
        !          1350:   else if (GET_CODE (PATTERN (insn)) == SET
        !          1351:           || GET_CODE (PATTERN (insn)) == CLOBBER)
        !          1352:     {
        !          1353:       register rtx x = XEXP (PATTERN (insn), 0);
        !          1354:       if (GET_CODE (x) == REG)
        !          1355:        reg_last_set[REGNO (x)] = insn;
        !          1356:       else if (GET_CODE (x) == MEM)
        !          1357:        mem_last_set = INSN_CUID (insn);
        !          1358:     }
        !          1359: }
        !          1360: 
        !          1361: /* Return nonzero if expression X refers to a REG or to memory
        !          1362:    that is set in an instruction more recent than FROM_CUID.  */
        !          1363: 
        !          1364: static int
        !          1365: use_crosses_set_p (x, from_cuid)
        !          1366:      register rtx x;
        !          1367:      int from_cuid;
        !          1368: {
        !          1369:   register char *fmt;
        !          1370:   register int i;
        !          1371:   register enum rtx_code code = GET_CODE (x);
        !          1372: 
        !          1373:   if (code == REG)
        !          1374:     {
        !          1375:       register int regno = REGNO (x);
        !          1376:       return (reg_last_set[regno]
        !          1377:              && INSN_CUID (reg_last_set[regno]) > from_cuid);
        !          1378:     }
        !          1379: 
        !          1380:   if (code == MEM && mem_last_set > from_cuid)
        !          1381:     return 1;
        !          1382: 
        !          1383:   fmt = GET_RTX_FORMAT (code);
        !          1384: 
        !          1385:   for (i = GET_RTX_LENGTH (code); i >= 0; i--)
        !          1386:     {
        !          1387:       if (fmt[i] == 'E')
        !          1388:        {
        !          1389:          register int j;
        !          1390:          for (j = XVECLEN (x, i) - 1; j >= 0; j--)
        !          1391:            if (use_crosses_set_p (XVECEXP (x, i, j), from_cuid))
        !          1392:              return 1;
        !          1393:        }
        !          1394:       else if (fmt[i] == 'e'
        !          1395:               && use_crosses_set_p (XEXP (x, i), from_cuid))
        !          1396:        return 1;
        !          1397:     }
        !          1398:   return 0;
        !          1399: }
        !          1400: 
        !          1401: /* Return nonzero if reg REGNO is marked as dying in INSN.  */
        !          1402: 
        !          1403: int
        !          1404: regno_dead_p (regno, insn)
        !          1405:      int regno;
        !          1406:      rtx insn;
        !          1407: {
        !          1408:   register rtx link;
        !          1409: 
        !          1410:   for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
        !          1411:     if (REGNO (XEXP (link, 0)) == regno
        !          1412:        && ((enum reg_note) GET_MODE (link) == REG_DEAD
        !          1413:            || (enum reg_note) GET_MODE (link) == REG_INC))
        !          1414:       return 1;
        !          1415: 
        !          1416:   return 0;
        !          1417: }
        !          1418: 
        !          1419: /* Remove register number REGNO from the dead registers list of INSN.  */
        !          1420: 
        !          1421: static void
        !          1422: remove_death (regno, insn)
        !          1423:      int regno;
        !          1424:      rtx insn;
        !          1425: {
        !          1426:   register rtx link, next;
        !          1427:   while ((link = REG_NOTES (insn))
        !          1428:         && REGNO (XEXP (link, 0)) == regno
        !          1429:         && (enum reg_note) GET_MODE (link) == REG_DEAD)
        !          1430:     REG_NOTES (insn) = XEXP (link, 1);
        !          1431: 
        !          1432:   if (link)
        !          1433:     while (next = XEXP (link, 1))
        !          1434:       {
        !          1435:        if (REGNO (XEXP (next, 0)) == regno
        !          1436:            && (enum reg_note) GET_MODE (next) == REG_DEAD)
        !          1437:          XEXP (link, 1) = XEXP (next, 1);
        !          1438:        else
        !          1439:          link = next;
        !          1440:       }
        !          1441: }
        !          1442: 
        !          1443: /* Return nonzero if J is the first insn following I,
        !          1444:    not counting labels, line numbers, etc.
        !          1445:    We assume that J follows I.  */
        !          1446: 
        !          1447: static int
        !          1448: adjacent_insns_p (i, j)
        !          1449:      rtx i, j;
        !          1450: {
        !          1451:   register rtx insn;
        !          1452:   for (insn = NEXT_INSN (i); insn != j; insn = NEXT_INSN (insn))
        !          1453:     if (GET_CODE (insn) == INSN
        !          1454:        || GET_CODE (insn) == CALL_INSN
        !          1455:        || GET_CODE (insn) == JUMP_INSN)
        !          1456:       return 0;
        !          1457:   return 1;
        !          1458: }
        !          1459: 
        !          1460: /* Concatenate the list of logical links LINKS
        !          1461:    into INSN's list of logical links.
        !          1462:    Modifies LINKS destructively.  */
        !          1463: 
        !          1464: static void
        !          1465: add_links (insn, links)
        !          1466:      rtx insn, links;
        !          1467: {
        !          1468:   if (LOG_LINKS (insn) == 0)
        !          1469:     LOG_LINKS (insn) = links;
        !          1470:   else
        !          1471:     {
        !          1472:       register rtx next, prev = LOG_LINKS (insn);
        !          1473:       while (next = XEXP (prev, 1))
        !          1474:        prev = next;
        !          1475:       XEXP (prev, 1) = links;
        !          1476:     }
        !          1477: }
        !          1478: 
        !          1479: /* Concatenate the any elements of the list of reg-notes INCS
        !          1480:    which are of type REG_INC
        !          1481:    into INSN's list of reg-notes.  */
        !          1482: 
        !          1483: static void
        !          1484: add_incs (insn, incs)
        !          1485:      rtx insn, incs;
        !          1486: {
        !          1487:   register rtx tail;
        !          1488: 
        !          1489:   for (tail = incs; tail; tail = XEXP (tail, 1))
        !          1490:     if ((enum reg_note) GET_MODE (tail) == REG_INC)
        !          1491:       REG_NOTES (insn)
        !          1492:        = gen_rtx (EXPR_LIST, REG_INC, XEXP (tail, 0), REG_NOTES (insn));
        !          1493: }
        !          1494: 
        !          1495: /* For each register (hardware or pseudo) used within expression X,
        !          1496:    if its death is in an instruction with cuid
        !          1497:    between FROM_CUID (inclusive) and TO_INSN (exclusive),
        !          1498:    mark it as dead in TO_INSN instead.
        !          1499: 
        !          1500:    This is done when X is being merged by combination into TO_INSN.  */
        !          1501: 
        !          1502: static void
        !          1503: move_deaths (x, from_cuid, to_insn)
        !          1504:      rtx x;
        !          1505:      int from_cuid;
        !          1506:      rtx to_insn;
        !          1507: {
        !          1508:   register char *fmt;
        !          1509:   register int len, i;
        !          1510:   register enum rtx_code code = GET_CODE (x);
        !          1511: 
        !          1512:   if (code == REG)
        !          1513:     {
        !          1514:       register rtx where_dead = reg_last_death[REGNO (x)];
        !          1515: 
        !          1516:       if (where_dead && INSN_CUID (where_dead) >= from_cuid
        !          1517:          && INSN_CUID (where_dead) < INSN_CUID (to_insn))
        !          1518:        {
        !          1519:          remove_death (REGNO (x), reg_last_death[REGNO (x)]);
        !          1520:          if (! dead_or_set_p (to_insn, x))
        !          1521:            REG_NOTES (to_insn)
        !          1522:              = gen_rtx (EXPR_LIST, REG_DEAD, x, REG_NOTES (to_insn));
        !          1523:        }
        !          1524:       return;
        !          1525:     }
        !          1526: 
        !          1527:   len = GET_RTX_LENGTH (code);
        !          1528:   fmt = GET_RTX_FORMAT (code);
        !          1529: 
        !          1530:   for (i = 0; i < len; i++)
        !          1531:     {
        !          1532:       if (fmt[i] == 'E')
        !          1533:        {
        !          1534:          register int j;
        !          1535:          for (j = XVECLEN (x, i) - 1; j >= 0; j--)
        !          1536:            move_deaths (XVECEXP (x, i, j), from_cuid, to_insn);
        !          1537:        }
        !          1538:       else if (fmt[i] == 'e')
        !          1539:        move_deaths (XEXP (x, i), from_cuid, to_insn);
        !          1540:     }
        !          1541: }
        !          1542: 
        !          1543: dump_combine_stats (file)
        !          1544:      char *file;
        !          1545: {
        !          1546:   fprintf
        !          1547:     (file,
        !          1548:      ";; Combiner statistics: %d attempts, %d substitutions (%d requiring new space),\n;; %d successes.\n\n"
        !          1549:      , combine_attempts, combine_merges, combine_extras, combine_successes);
        !          1550: }
        !          1551: 
        !          1552: dump_combine_total_stats (file)
        !          1553:      char *file;
        !          1554: {
        !          1555:   fprintf
        !          1556:     (file,
        !          1557:      "\n;; Combiner totals: %d attempts, %d substitutions (%d requiring new space),\n;; %d successes.\n",
        !          1558:      total_attempts, total_merges, total_extras, total_successes);
        !          1559: }

unix.superglobalmegacorp.com

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