Annotation of gcc/combine.c, revision 1.1.1.9

1.1       root        1: /* Optimize by combining instructions for GNU compiler.
1.1.1.2   root        2:    Copyright (C) 1987, 1988 Free Software Foundation, Inc.
1.1       root        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"
1.1.1.2   root       66: #include "flags.h"
1.1       root       67: #include "regs.h"
                     68: #include "basic-block.h"
                     69: #include "insn-config.h"
                     70: #include "recog.h"
                     71: 
                     72: #define max(A,B) ((A) > (B) ? (A) : (B))
                     73: #define min(A,B) ((A) < (B) ? (A) : (B))
                     74: 
1.1.1.2   root       75: /* It is not safe to use ordinary gen_lowpart in combine.
                     76:    Use gen_lowpart_for_combine instead.  See comments there.  */
                     77: #define gen_lowpart dont_use_gen_lowpart_you_dummy
                     78: 
1.1       root       79: /* Number of attempts to combine instructions in this function.  */
                     80: 
                     81: static int combine_attempts;
1.1.1.7   root       82: static int distrib_attempts;
1.1       root       83: 
                     84: /* Number of attempts that got as far as substitution in this function.  */
                     85: 
                     86: static int combine_merges;
1.1.1.7   root       87: static int distrib_merges_1, distrib_merges_2;
1.1       root       88: 
                     89: /* Number of instructions combined with added SETs in this function.  */
                     90: 
                     91: static int combine_extras;
                     92: 
                     93: /* Number of instructions combined in this function.  */
                     94: 
                     95: static int combine_successes;
1.1.1.7   root       96: static int distrib_successes;
1.1       root       97: 
                     98: /* Totals over entire compilation.  */
                     99: 
                    100: static int total_attempts, total_merges, total_extras, total_successes;
1.1.1.7   root      101: static int total_distrib_attempts, total_distrib_merges_1, total_distrib_merges_2, total_distrib_successes;
1.1       root      102: 
                    103: 
                    104: /* Vector mapping INSN_UIDs to cuids.
                    105:    The cuids are like uids but increase monononically always.
                    106:    Combine always uses cuids so that it can compare them.
                    107:    But actually renumbering the uids, which we used to do,
                    108:    proves to be a bad idea because it makes it hard to compare
                    109:    the dumps produced by earlier passes with those from later passes.  */
                    110: 
                    111: static short *uid_cuid;
                    112: 
                    113: /* Get the cuid of an insn.  */
                    114: 
                    115: #define INSN_CUID(INSN) (uid_cuid[INSN_UID (INSN)])
                    116: 
                    117: 
                    118: /* Record last point of death of (hard or pseudo) register n.  */
                    119: 
                    120: static rtx *reg_last_death;
                    121: 
                    122: /* Record last point of modification of (hard or pseudo) register n.  */
                    123: 
                    124: static rtx *reg_last_set;
                    125: 
                    126: /* Record the cuid of the last insn that invalidated memory
                    127:    (anything that writes memory, and subroutine calls).  */
                    128: 
                    129: static int mem_last_set;
                    130: 
                    131: /* Record the cuid of the last CALL_INSN
                    132:    so we can tell whether a potential combination crosses any calls.  */
                    133: 
                    134: static int last_call_cuid;
                    135: 
                    136: /* When `subst' is called, this is the insn that is being modified
                    137:    (by combining in a previous insn).  The PATTERN of this insn
                    138:    is still the old pattern partially modified and it should not be
                    139:    looked at, but this may be used to examine the successors of the insn
                    140:    to judge whether a simplification is valid.  */
                    141: 
                    142: static rtx subst_insn;
                    143: 
                    144: /* Record one modification to rtl structure
                    145:    to be undone by storing old_contents into *where.  */
                    146: 
                    147: struct undo
                    148: {
                    149:   rtx *where;
                    150:   rtx old_contents;
                    151: };
                    152: 
                    153: /* Record a bunch of changes to be undone, up to MAX_UNDO of them.
                    154:    num_undo says how many are currently recorded.
                    155:    storage is nonzero if we must undo the allocation of new storage.
                    156:    The value of storage is what to pass to obfree.  */
                    157: 
                    158: #define MAX_UNDO 10
                    159: 
                    160: struct undobuf
                    161: {
                    162:   int num_undo;
                    163:   char *storage;
                    164:   struct undo undo[MAX_UNDO];
                    165: };
                    166: 
                    167: static struct undobuf undobuf;
                    168: 
1.1.1.2   root      169: /* Number of times the pseudo being substituted for
                    170:    was found and replaced.  */
                    171: 
                    172: static int n_occurrences;
                    173: 
1.1       root      174: static void move_deaths ();
1.1.1.7   root      175: static void move_deaths_2 ();
1.1.1.4   root      176: void remove_death ();
1.1       root      177: static void record_dead_and_set_regs ();
                    178: int regno_dead_p ();
                    179: static int use_crosses_set_p ();
1.1.1.4   root      180: static int try_combine ();
1.1.1.7   root      181: static rtx try_distrib ();
1.1       root      182: static rtx subst ();
                    183: static void undo_all ();
1.1.1.2   root      184: static void copy_substitutions ();
1.1       root      185: static void add_links ();
1.1.1.7   root      186: static void remove_links ();
1.1       root      187: static void add_incs ();
1.1.1.2   root      188: static int insn_has_inc_p ();
1.1       root      189: static int adjacent_insns_p ();
                    190: static rtx simplify_and_const_int ();
                    191: static rtx gen_lowpart_for_combine ();
                    192: static void simplify_set_cc0_and ();
                    193: 
                    194: /* Main entry point for combiner.  F is the first insn of the function.
                    195:    NREGS is the first unused pseudo-reg number.  */
                    196: 
                    197: void
                    198: combine_instructions (f, nregs)
                    199:      rtx f;
                    200:      int nregs;
                    201: {
                    202:   register rtx insn;
                    203:   register int i;
                    204:   register rtx links, nextlinks;
                    205:   rtx prev;
                    206: 
                    207:   combine_attempts = 0;
                    208:   combine_merges = 0;
                    209:   combine_extras = 0;
                    210:   combine_successes = 0;
1.1.1.7   root      211:   distrib_attempts = 0;
                    212:   distrib_merges_1 = 0;
                    213:   distrib_merges_2 = 0;
                    214:   distrib_successes = 0;
1.1       root      215: 
                    216:   reg_last_death = (rtx *) alloca (nregs * sizeof (rtx));
                    217:   reg_last_set = (rtx *) alloca (nregs * sizeof (rtx));
                    218:   bzero (reg_last_death, nregs * sizeof (rtx));
                    219:   bzero (reg_last_set, nregs * sizeof (rtx));
                    220: 
                    221:   init_recog ();
                    222: 
                    223:   /* Compute maximum uid value so uid_cuid can be allocated.  */
                    224: 
                    225:   for (insn = f, i = 0; insn; insn = NEXT_INSN (insn))
                    226:     if (INSN_UID (insn) > i)
                    227:       i = INSN_UID (insn);
                    228: 
                    229:   uid_cuid = (short *) alloca ((i + 1) * sizeof (short));
                    230: 
                    231:   /* Compute the mapping from uids to cuids.
                    232:      Cuids are numbers assigned to insns, like uids,
                    233:      except that cuids increase monotonically through the code.  */
                    234: 
                    235:   for (insn = f, i = 0; insn; insn = NEXT_INSN (insn))
                    236:     INSN_CUID (insn) = ++i;
                    237: 
                    238:   /* Now scan all the insns in forward order.  */
                    239: 
                    240:   last_call_cuid = 0;
                    241:   mem_last_set = 0;
                    242:   prev = 0;
                    243: 
                    244:   for (insn = f; insn; insn = NEXT_INSN (insn))
                    245:     {
                    246:       if (GET_CODE (insn) == INSN
                    247:          || GET_CODE (insn) == CALL_INSN
                    248:          || GET_CODE (insn) == JUMP_INSN)
                    249:        {
                    250:        retry:
                    251:          /* Try this insn with each insn it links back to.  */
                    252: 
                    253:          for (links = LOG_LINKS (insn); links; links = XEXP (links, 1))
                    254:            if (try_combine (insn, XEXP (links, 0), 0))
                    255:              goto retry;
                    256: 
                    257:          /* Try each sequence of three linked insns ending with this one.  */
                    258: 
                    259:          for (links = LOG_LINKS (insn); links; links = XEXP (links, 1))
                    260:            if (GET_CODE (XEXP (links, 0)) != NOTE)
                    261:              for (nextlinks = LOG_LINKS (XEXP (links, 0)); nextlinks;
                    262:                   nextlinks = XEXP (nextlinks, 1))
                    263:                if (try_combine (insn, XEXP (links, 0), XEXP (nextlinks, 0)))
                    264:                  goto retry;
                    265: 
                    266:          /* Try to combine a jump insn that uses CC0
                    267:             with a preceding insn that sets CC0, and maybe with its
                    268:             logical predecessor as well.
                    269:             This is how we make decrement-and-branch insns.
                    270:             We need this special code because data flow connections
                    271:             via CC0 do not get entered in LOG_LINKS.  */
                    272: 
                    273:          if (GET_CODE (insn) == JUMP_INSN
                    274:              && prev != 0
                    275:              && GET_CODE (prev) == INSN
                    276:              && GET_CODE (PATTERN (prev)) == SET
                    277:              && GET_CODE (SET_DEST (PATTERN (prev))) == CC0)
                    278:            {
                    279:              if (try_combine (insn, prev, 0))
                    280:                  goto retry;
                    281: 
                    282:              if (GET_CODE (prev) != NOTE)
                    283:                for (nextlinks = LOG_LINKS (prev); nextlinks;
                    284:                     nextlinks = XEXP (nextlinks, 1))
                    285:                  if (try_combine (insn, prev, XEXP (nextlinks, 0)))
                    286:                    goto retry;
                    287:            }
1.1.1.7   root      288: 
                    289:          /* Try to apply the distributive law to this insn
                    290:             and two insns that compute the operands of this one.  */
                    291:          for (links = LOG_LINKS (insn); links; links = XEXP (links, 1))
                    292:            if (GET_CODE (XEXP (links, 0)) != NOTE)
                    293:              for (nextlinks = XEXP (links, 1); nextlinks; nextlinks = XEXP (nextlinks, 1))
                    294:                if (GET_CODE (XEXP (nextlinks, 0)) != NOTE)
                    295:                  {
                    296:                    rtx try_from = 0;
                    297: 
                    298:                    if (GET_CODE (PATTERN (XEXP (links, 0))) == SET
                    299:                        && find_reg_note (insn, REG_DEAD, SET_DEST (PATTERN (XEXP (links, 0))))
                    300:                        && GET_CODE (PATTERN (XEXP (nextlinks, 0))) == SET
                    301:                        && find_reg_note (insn, REG_DEAD, SET_DEST (PATTERN (XEXP (nextlinks, 0)))))
                    302:                      try_from = try_distrib (insn, XEXP (links, 0), XEXP (nextlinks, 0));
                    303:                    if (try_from != 0)
                    304:                      {
                    305:                        insn = try_from;
                    306:                        goto retry;
                    307:                      }
                    308:                  }
1.1       root      309: #if 0
                    310: /* Turned off because on 68020 it takes four insns to make
                    311:    something like (a[b / 32] & (1 << (31 - (b % 32)))) != 0
                    312:    that could actually be optimized, and that's an unlikely piece of code.  */
                    313:          /* If an insn gets or sets a bit field, try combining it
                    314:             with two different insns whose results it uses.  */
                    315:          if (GET_CODE (insn) == INSN
                    316:              && GET_CODE (PATTERN (insn)) == SET
                    317:              && (GET_CODE (SET_DEST (PATTERN (insn))) == ZERO_EXTRACT
                    318:                  || GET_CODE (SET_DEST (PATTERN (insn))) == SIGN_EXTRACT
                    319:                  || GET_CODE (SET_SRC (PATTERN (insn))) == ZERO_EXTRACT
                    320:                  || GET_CODE (SET_SRC (PATTERN (insn))) == SIGN_EXTRACT))
                    321:            {
                    322:              for (links = LOG_LINKS (insn); links; links = XEXP (links, 1))
                    323:                if (GET_CODE (XEXP (links, 0)) != NOTE)
                    324:                  for (nextlinks = XEXP (links, 1); nextlinks;
                    325:                       nextlinks = XEXP (nextlinks, 1))
                    326:                    if (try_combine (insn, XEXP (links, 0), XEXP (nextlinks, 0)))
                    327:                      goto retry;
                    328:            }
                    329: #endif
                    330:          record_dead_and_set_regs (insn);
                    331:          prev = insn;
                    332:        }
                    333:       else if (GET_CODE (insn) != NOTE)
                    334:        prev = 0;
                    335:     }
                    336:   total_attempts += combine_attempts;
                    337:   total_merges += combine_merges;
                    338:   total_extras += combine_extras;
                    339:   total_successes += combine_successes;
                    340: }
                    341: 
                    342: /* Try to combine the insns I1 and I2 into I3.
                    343:    Here I1 appears earlier than I2, which is earlier than I3.
                    344:    I1 can be zero; then we combine just I2 into I3.
                    345:  
                    346:    Return 1 if successful; if that happens, I1 and I2 are pseudo-deleted
                    347:    by turning them into NOTEs, and I3 is modified.
                    348:    Return 0 if the combination does not work.  Then nothing is changed.  */
                    349: 
                    350: static int
                    351: try_combine (i3, i2, i1)
                    352:      register rtx i3, i2, i1;
                    353: {
                    354:   register rtx newpat;
                    355:   int added_sets_1 = 0;
                    356:   int added_sets_2 = 0;
                    357:   int total_sets;
                    358:   int i2_is_used;
                    359:   register rtx link;
                    360:   int insn_code_number;
                    361:   rtx i2dest, i2src;
                    362:   rtx i1dest, i1src;
1.1.1.2   root      363:   int maxreg;
1.1       root      364: 
                    365:   combine_attempts++;
                    366: 
                    367:   /* Don't combine with something already used up by combination.  */
                    368: 
                    369:   if (GET_CODE (i2) == NOTE
                    370:       || (i1 && GET_CODE (i1) == NOTE))
                    371:     return 0;
                    372: 
                    373:   /* Don't combine across a CALL_INSN, because that would possibly
                    374:      change whether the life span of some REGs crosses calls or not,
                    375:      and it is a pain to update that information.  */
                    376: 
                    377:   if (INSN_CUID (i2) < last_call_cuid
                    378:       || (i1 && INSN_CUID (i1) < last_call_cuid))
                    379:     return 0;
                    380: 
                    381:   /* Can combine only if previous insn is a SET of a REG, a SUBREG or CC0.
                    382:      That REG must be either set or dead by the final instruction
                    383:      (so that we can safely forget about setting it).
                    384:      Also test use_crosses_set_p to make sure that the value
                    385:      that is to be substituted for the register
                    386:      does not use any registers whose values alter in between.
                    387:      Do not try combining with moves from one register to another
                    388:      since it is better to let them be tied by register allocation.
1.1.1.2   root      389:      (There is a switch to permit such combination; except the insns
                    390:      that copy a function value into another register are never combined
                    391:      because moving that too far away from the function call could cause
                    392:      something else to be stored in that register in the interim.)
1.1       root      393: 
                    394:      A set of a SUBREG is considered as if it were a set from
                    395:      SUBREG.  Thus, (SET (SUBREG:X (REG:Y...)) (something:X...))
                    396:      is handled by substituting (SUBREG:Y (something:X...)) for (REG:Y...).  */
                    397: 
                    398:   if (GET_CODE (PATTERN (i2)) != SET)
                    399:     return 0;
                    400:   i2dest = SET_DEST (PATTERN (i2));
                    401:   i2src = SET_SRC (PATTERN (i2));
                    402:   if (GET_CODE (i2dest) == SUBREG)
                    403:     {
                    404:       i2dest = SUBREG_REG (i2dest);
                    405:       i2src = gen_rtx (SUBREG, GET_MODE (i2dest), i2src, 0);
                    406:     }
1.1.1.4   root      407:   /* Don't eliminate a store in the stack pointer.  */
                    408:   if (i2dest == stack_pointer_rtx)
                    409:     return 0;
1.1       root      410:   if (GET_CODE (i2dest) != CC0
                    411:       && (GET_CODE (i2dest) != REG
1.1.1.2   root      412:          || (GET_CODE (i2src) == REG
                    413:              && (!flag_combine_regs
1.1.1.5   root      414:                  /* Don't substitute a function value reg for any other.  */
1.1.1.9 ! root      415:                  || FUNCTION_VALUE_REGNO_P (REGNO (i2src))))
1.1.1.2   root      416:          || GET_CODE (i2src) == CALL
1.1.1.9 ! root      417:          /* Don't substitute into an incremented register.  */
        !           418:          || find_reg_note (i3, REG_INC, i2dest)
1.1       root      419:          || use_crosses_set_p (i2src, INSN_CUID (i2))))
                    420:     return 0;
                    421: 
                    422:   if (i1 != 0)
                    423:     {
                    424:       if (GET_CODE (PATTERN (i1)) != SET)
                    425:        return 0;
                    426:       i1dest = SET_DEST (PATTERN (i1));
                    427:       i1src = SET_SRC (PATTERN (i1));
                    428:       if (GET_CODE (i1dest) == SUBREG)
                    429:        {
                    430:          i1dest = SUBREG_REG (i1dest);
                    431:          i1src = gen_rtx (SUBREG, GET_MODE (i1dest), i1src, 0);
                    432:        }
1.1.1.4   root      433:       if (i1dest == stack_pointer_rtx)
                    434:        return 0;
1.1       root      435:       if (GET_CODE (i1dest) != CC0
                    436:          && (GET_CODE (i1dest) != REG
1.1.1.2   root      437:              || (GET_CODE (i1src) == REG
                    438:                  && (!flag_combine_regs
1.1.1.9 ! root      439:                      || FUNCTION_VALUE_REGNO_P (REGNO (i1src))))
1.1.1.2   root      440:              || GET_CODE (i1src) == CALL
1.1.1.9 ! root      441:              || find_reg_note (i3, REG_INC, i1dest)
        !           442:              || find_reg_note (i2, REG_INC, i1dest)
1.1       root      443:              || use_crosses_set_p (i1src, INSN_CUID (i1))))
                    444:        return 0;
                    445:     }
                    446: 
                    447:   /* If I1 or I2 contains an autoincrement or autodecrement,
                    448:      make sure that register is not used between there and I3.
                    449:      Also insist that I3 not be a jump; if it were one
                    450:      and the incremented register were spilled, we would lose.  */
1.1.1.5   root      451:   for (link = REG_NOTES (i2); link; link = XEXP (link, 1))
                    452:     if (REG_NOTE_KIND (link) == REG_INC
                    453:        && (GET_CODE (i3) == JUMP_INSN
                    454:            || reg_used_between_p (XEXP (link, 0), i2, i3)
                    455:            || reg_mentioned_p (XEXP (link, 0), i3)))
                    456:       return 0;
1.1       root      457: 
1.1.1.5   root      458:   if (i1)
                    459:     for (link = REG_NOTES (i1); link; link = XEXP (link, 1))
                    460:       if (REG_NOTE_KIND (link) == REG_INC
                    461:          && (GET_CODE (i3) == JUMP_INSN
                    462:              || reg_used_between_p (XEXP (link, 0), i1, i3)
                    463:              || reg_mentioned_p (XEXP (link, 0), i3)))
                    464:        return 0;
1.1       root      465: 
                    466:   /* See if the SETs in i1 or i2 need to be kept around in the merged
                    467:      instruction: whenever the value set there is still needed past i3.  */
                    468:   added_sets_2 = (GET_CODE (i2dest) != CC0
                    469:                  && ! dead_or_set_p (i3, i2dest));
                    470:   if (i1)
                    471:     added_sets_1 = ! (dead_or_set_p (i3, i1dest)
                    472:                      || dead_or_set_p (i2, i1dest));
                    473: 
                    474:   combine_merges++;
                    475: 
                    476:   undobuf.num_undo = 0;
                    477:   undobuf.storage = 0;
                    478: 
                    479:   /* Substitute in the latest insn for the regs set by the earlier ones.  */
                    480: 
1.1.1.2   root      481:   maxreg = max_reg_num ();
                    482: 
1.1       root      483:   subst_insn = i3;
1.1.1.2   root      484:   n_occurrences = 0;           /* `subst' counts here */
                    485: 
1.1       root      486:   newpat = subst (PATTERN (i3), i2dest, i2src);
                    487:   /* Record whether i2's body now appears within i3's body.  */
1.1.1.2   root      488:   i2_is_used = n_occurrences;
1.1       root      489: 
                    490:   if (i1)
1.1.1.2   root      491:     {
                    492:       n_occurrences = 0;
                    493:       newpat = subst (newpat, i1dest, i1src);
                    494:     }
1.1       root      495: 
                    496:   if (GET_CODE (PATTERN (i3)) == SET
                    497:       && SET_DEST (PATTERN (i3)) == cc0_rtx
1.1.1.2   root      498:       && (GET_CODE (SET_SRC (PATTERN (i3))) == AND
                    499:          || GET_CODE (SET_SRC (PATTERN (i3))) == LSHIFTRT)
1.1       root      500:       && next_insn_tests_no_inequality (i3))
                    501:     simplify_set_cc0_and (i3);
                    502: 
1.1.1.2   root      503:   if (max_reg_num () != maxreg)
                    504:     abort ();
                    505: 
1.1       root      506:   /* If the actions of the earler insns must be kept
                    507:      in addition to substituting them into the latest one,
                    508:      we must make a new PARALLEL for the latest insn
                    509:      to hold additional the SETs.  */
                    510: 
                    511:   if (added_sets_1 || added_sets_2)
                    512:     {
                    513:       combine_extras++;
                    514: 
                    515:       /* Arrange to free later what we allocate now
                    516:         if we don't accept this combination.  */
                    517:       if (!undobuf.storage)
                    518:        undobuf.storage = (char *) oballoc (0);
                    519: 
                    520:       if (GET_CODE (newpat) == PARALLEL)
                    521:        {
1.1.1.2   root      522:          rtvec old = XVEC (newpat, 0);
1.1       root      523:          total_sets = XVECLEN (newpat, 0) + added_sets_1 + added_sets_2;
1.1.1.2   root      524:          newpat = gen_rtx (PARALLEL, VOIDmode, rtvec_alloc (total_sets));
                    525:          bcopy (&old->elem[0], &XVECEXP (newpat, 0, 0),
                    526:                 sizeof (old->elem[0]) * old->num_elem);
1.1       root      527:        }
                    528:       else
                    529:        {
1.1.1.2   root      530:          rtx old = newpat;
1.1       root      531:          total_sets = 1 + added_sets_1 + added_sets_2;
1.1.1.2   root      532:          newpat = gen_rtx (PARALLEL, VOIDmode, rtvec_alloc (total_sets));
                    533:          XVECEXP (newpat, 0, 0) = old;
1.1       root      534:        }
                    535:      if (added_sets_1)
                    536:        {
                    537:          XVECEXP (newpat, 0, --total_sets) = PATTERN (i1);
                    538:        }
                    539:      if (added_sets_2)
                    540:        {
                    541:          /* If there is no I1, use I2's body as is.  */
                    542:          if (i1 == 0
                    543:          /* If I2 was stuck into I3, then anything within it has
                    544:             already had I1 substituted into it when that was done to I3.  */
                    545:              || i2_is_used)
                    546:            {
                    547:              XVECEXP (newpat, 0, --total_sets) = PATTERN (i2);
                    548:            }
                    549:          else
                    550:            XVECEXP (newpat, 0, --total_sets)
                    551:              = subst (PATTERN (i2), i1dest, i1src);
                    552:        }
                    553:     }
                    554: 
1.1.1.2   root      555:   /* Fail if an autoincrement side-effect has been duplicated.  */
                    556:   if ((i2_is_used > 1 && find_reg_note (i2, REG_INC, 0) != 0)
                    557:       || (i1 != 0 && n_occurrences > 1 && find_reg_note (i1, REG_INC, 0) != 0))
                    558:     {
                    559:       undo_all ();
                    560:       return 0;
                    561:     }
                    562: 
1.1       root      563:   /* Is the result of combination a valid instruction?  */
                    564:   insn_code_number = recog (newpat, i3);
                    565: 
                    566:   if (insn_code_number >= 0)
                    567:     {
                    568:       /* Yes.  Install it.  */
                    569:       register int regno;
                    570:       INSN_CODE (i3) = insn_code_number;
                    571:       PATTERN (i3) = newpat;
1.1.1.2   root      572:       /* If anything was substituted more than once,
                    573:         copy it to avoid invalid shared rtl structure.  */
                    574:       copy_substitutions ();
                    575:       /* The data flowing into I2 now flows into I3.
                    576:         But we cannot always move all of I2's LOG_LINKS into I3,
                    577:         since they must go to a setting of a REG from the
                    578:         first use following.  If I2 was the first use following a set,
                    579:         I3 is now a use, but it is not the first use
                    580:         if some instruction between I2 and I3 is also a use.
                    581:         Here, for simplicity, we move all the links only if
                    582:         there are no real insns between I2 and I3.
                    583:         Otherwise, we move only links that correspond to regs
                    584:         that used to die in I2.  They are always safe to move.  */
                    585:       add_links (i3, i2, adjacent_insns_p (i2, i3));
1.1       root      586:       /* Most REGs that previously died in I2 now die in I3.  */ 
                    587:       move_deaths (i2src, INSN_CUID (i2), i3);
                    588:       if (GET_CODE (i2dest) == REG)
                    589:        {
                    590:          /* If the reg formerly set in I2 died only once and that was in I3,
                    591:             zero its use count so it won't make `reload' do any work.  */
                    592:          regno = REGNO (i2dest);
                    593:          if (! added_sets_2)
1.1.1.2   root      594:            {
                    595:              reg_n_sets[regno]--;
                    596:              /* Used to check  && regno_dead_p (regno, i3)  also here.  */
                    597:              if (reg_n_sets[regno] == 0
                    598:                  && ! (basic_block_live_at_start[0][regno / HOST_BITS_PER_INT]
                    599:                        & (1 << (regno % HOST_BITS_PER_INT))))
                    600:                reg_n_refs[regno] = 0;
                    601:            }
1.1       root      602:          /* If a ref to REGNO was substituted into I3 from I2,
                    603:             then it still dies there if it previously did.
                    604:             Otherwise either REGNO never did die in I3 so remove_death is safe
                    605:             or this entire life of REGNO is gone so remove its death.  */
                    606:          if (!added_sets_2
                    607:              && ! reg_mentioned_p (i2dest, PATTERN (i3)))
                    608:            remove_death (regno, i3);
                    609:        }
                    610:       /* Any registers previously autoincremented in I2
                    611:         are now incremented in I3.  */
                    612:       add_incs (i3, REG_NOTES (i2));
                    613:       if (i1)
                    614:        {
                    615:          /* Likewise, merge the info from I1 and get rid of it.  */
1.1.1.2   root      616:          add_links (i3, i1,
                    617:                     adjacent_insns_p (i1, i2) && adjacent_insns_p (i2, i3));
1.1       root      618:          move_deaths (i1src, INSN_CUID (i1), i3);
                    619:          if (GET_CODE (i1dest) == REG)
                    620:            {
                    621:              regno = REGNO (i1dest);
                    622:              if (! added_sets_1)
1.1.1.2   root      623:                {
                    624:                  reg_n_sets[regno]--;
                    625:                  /* Used to also check  && regno_dead_p (regno, i3) here.  */
                    626: 
                    627:                  if (reg_n_sets[regno] == 0
                    628:                      && ! (basic_block_live_at_start[0][regno / HOST_BITS_PER_INT]
                    629:                            & (1 << (regno % HOST_BITS_PER_INT))))
                    630: 
                    631:                    reg_n_refs[regno] = 0;
                    632:                }
1.1       root      633:              /* If a ref to REGNO was substituted into I3 from I1,
                    634:                 then it still dies there if it previously did.
                    635:                 Else either REGNO never did die in I3 so remove_death is safe
                    636:                 or this entire life of REGNO is gone so remove its death.  */
                    637:              if (! added_sets_1
                    638:                  && ! reg_mentioned_p (i1dest, PATTERN (i3)))
                    639:                remove_death (regno, i3);
                    640:            }
                    641:          add_incs (i3, REG_NOTES (i1));
                    642:          LOG_LINKS (i1) = 0;
                    643:          PUT_CODE (i1, NOTE);
                    644:          NOTE_LINE_NUMBER (i1) = NOTE_INSN_DELETED;
                    645:          NOTE_SOURCE_FILE (i1) = 0;
                    646:        }
1.1.1.2   root      647:       /* Get rid of I2.  */
                    648:       LOG_LINKS (i2) = 0;
                    649:       PUT_CODE (i2, NOTE);
                    650:       NOTE_LINE_NUMBER (i2) = NOTE_INSN_DELETED;
                    651:       NOTE_SOURCE_FILE (i2) = 0;
1.1       root      652: 
                    653:       combine_successes++;
                    654:       return 1;
                    655:     }
                    656: 
                    657:   /* Failure: change I3 back the way it was.  */
                    658:   undo_all ();
                    659: 
                    660:   return 0;
                    661: }
                    662: 
                    663: /* Undo all the modifications recorded in undobuf.  */
                    664: 
                    665: static void
                    666: undo_all ()
                    667: {
                    668:   register int i;
                    669:   if (undobuf.num_undo > MAX_UNDO)
                    670:     undobuf.num_undo = MAX_UNDO;
                    671:   for (i = undobuf.num_undo - 1; i >= 0; i--)
                    672:     *undobuf.undo[i].where = undobuf.undo[i].old_contents;
                    673:   if (undobuf.storage)
                    674:     obfree (undobuf.storage);
                    675:   undobuf.num_undo = 0;
                    676:   undobuf.storage = 0;
                    677: }
                    678: 
1.1.1.2   root      679: /* If this insn had more than one substitution,
                    680:    copy all but one, so that no invalid shared substructure is introduced.  */
                    681: 
                    682: static void
                    683: copy_substitutions ()
                    684: {
                    685:   register int i;
                    686:   if (undobuf.num_undo > 1)
                    687:     {
                    688:       for (i = undobuf.num_undo - 1; i >= 1; i--)
                    689:        *undobuf.undo[i].where = copy_rtx (*undobuf.undo[i].where);
                    690:     }
                    691: }
                    692: 
1.1       root      693: /* Throughout X, replace FROM with TO, and return the result.
                    694:    The result is TO if X is FROM;
                    695:    otherwise the result is X, but its contents may have been modified.
                    696:    If they were modified, a record was made in undobuf so that
                    697:    undo_all will (among other things) return X to its original state.
                    698: 
                    699:    If the number of changes necessary is too much to record to undo,
                    700:    the excess changes are not made, so the result is invalid.
                    701:    The changes already made can still be undone.
                    702:    undobuf.num_undo is incremented for such changes, so by testing that
1.1.1.2   root      703:    the caller can tell whether the result is valid.
                    704: 
                    705:    `n_occurrences' is incremented each time FROM is replaced.  */
1.1       root      706: 
                    707: static rtx
                    708: subst (x, from, to)
                    709:      register rtx x, from, to;
                    710: {
                    711:   register char *fmt;
                    712:   register int len, i;
                    713:   register enum rtx_code code;
1.1.1.2   root      714:   char was_replaced[2];
1.1       root      715: 
1.1.1.2   root      716: #define SUBST(INTO, NEWVAL)  \
                    717:  do { if (undobuf.num_undo < MAX_UNDO)                                 \
                    718:        {                                                               \
                    719:          undobuf.undo[undobuf.num_undo].where = &INTO;                 \
                    720:          undobuf.undo[undobuf.num_undo].old_contents = INTO;           \
                    721:          INTO = NEWVAL;                                                \
                    722:        }                                                               \
                    723:       undobuf.num_undo++; } while (0)
                    724: 
                    725: /* FAKE_EXTEND_SAFE_P (MODE, FROM) is 1 if (subreg:MODE FROM 0) is a safe
                    726:    replacement for (zero_extend:MODE FROM) or (sign_extend:MODE FROM).
1.1.1.6   root      727:    If it is 0, that cannot be done.  We can now do this for any MEM
                    728:    because (SUBREG (MEM...)) is guaranteed to cause the MEM to be reloaded.
                    729:    If not for that, MEM's would very rarely be safe.  */
1.1.1.2   root      730: 
1.1.1.9 ! root      731: /* Reject MODEs bigger than a word, because we might not be able
        !           732:    to reference a two-register group starting with an arbitrary register
        !           733:    (and currently gen_lowpart might crash for a SUBREG).  */
        !           734: 
1.1.1.7   root      735: #define FAKE_EXTEND_SAFE_P(MODE, FROM) \
1.1.1.9 ! root      736:   (GET_MODE_SIZE (MODE) <= UNITS_PER_WORD                      \
        !           737:    && (GET_CODE (FROM) == REG || GET_CODE (FROM) == SUBREG     \
        !           738:        || GET_CODE (FROM) == MEM))
1.1       root      739: 
                    740:   if (x == from)
                    741:     return to;
                    742: 
1.1.1.2   root      743:   /* It is possible to have a subexpression appear twice in the insn.
                    744:      Suppose that FROM is a register that appears within TO.
                    745:      Then, after that subexpression has been scanned once by `subst',
                    746:      the second time it is scanned, TO may be found.  If we were
                    747:      to scan TO here, we would find FROM within it and create a
                    748:      self-referent rtl structure which is completely wrong.  */
                    749:   if (x == to)
                    750:     return to;
                    751: 
1.1       root      752:   code = GET_CODE (x);
                    753: 
                    754:   /* A little bit of algebraic simplification here.  */
                    755:   switch (code)
                    756:     {
                    757:       /* This case has no effect except to speed things up.  */
                    758:     case REG:
                    759:     case CONST_INT:
                    760:     case CONST:
                    761:     case SYMBOL_REF:
                    762:     case LABEL_REF:
                    763:     case PC:
                    764:     case CC0:
                    765:       return x;
1.1.1.2   root      766:     }
                    767: 
                    768:   was_replaced[0] = 0;
                    769:   was_replaced[1] = 0;
                    770: 
                    771:   len = GET_RTX_LENGTH (code);
                    772:   fmt = GET_RTX_FORMAT (code);
                    773: 
                    774:   /* Don't replace FROM where it is being stored in rather than used.  */
                    775:   if (code == SET && SET_DEST (x) == from)
                    776:     fmt = "ie";
                    777:   if (code == SET && GET_CODE (SET_DEST (x)) == SUBREG
                    778:       && SUBREG_REG (SET_DEST (x)) == from)
                    779:     fmt = "ie";
                    780: 
                    781:   for (i = 0; i < len; i++)
                    782:     {
                    783:       if (fmt[i] == 'E')
                    784:        {
                    785:          register int j;
                    786:          for (j = XVECLEN (x, i) - 1; j >= 0; j--)
                    787:            {
                    788:              register rtx new;
                    789:              if (XVECEXP (x, i, j) == from)
                    790:                new = to, n_occurrences++;
                    791:              else
                    792:                new = subst (XVECEXP (x, i, j), from, to);
                    793:              if (new != XVECEXP (x, i, j))
                    794:                SUBST (XVECEXP (x, i, j), new);
                    795:            }
                    796:        }
                    797:       else if (fmt[i] == 'e')
                    798:        {
                    799:          register rtx new;
                    800: 
                    801:          if (XEXP (x, i) == from)
                    802:            {
                    803:              new = to;
                    804:              n_occurrences++;
                    805:              if (i < 2)
                    806:                was_replaced[i] = 1;
                    807:            }
                    808:          else
                    809:            new = subst (XEXP (x, i), from, to);
                    810: 
                    811:          if (new != XEXP (x, i))
                    812:            SUBST (XEXP (x, i), new);
                    813:        }
                    814:     }
                    815: 
                    816:   /* A little bit of algebraic simplification here.  */
                    817:   switch (code)
                    818:     {
                    819:     case SUBREG:
                    820:       /* Changing mode twice with SUBREG => just change it once,
                    821:         or not at all if changing back to starting mode.  */
                    822:       if (SUBREG_REG (x) == to
                    823:          && GET_CODE (to) == SUBREG
                    824:          && SUBREG_WORD (x) == 0
                    825:          && SUBREG_WORD (to) == 0)
                    826:        {
                    827:          if (GET_MODE (x) == GET_MODE (SUBREG_REG (to)))
                    828:            return SUBREG_REG (to);
                    829:          SUBST (SUBREG_REG (x), SUBREG_REG (to));
                    830:        }
1.1.1.4   root      831:       /* (subreg (sign_extend X)) is X, if it has same mode as X.  */
                    832:       if (SUBREG_REG (x) == to
                    833:          && (GET_CODE (to) == SIGN_EXTEND || GET_CODE (to) == ZERO_EXTEND)
                    834:          && SUBREG_WORD (x) == 0
                    835:          && GET_MODE (x) == GET_MODE (XEXP (to, 0)))
                    836:        return XEXP (to, 0);
1.1.1.2   root      837:       break;
1.1       root      838: 
                    839:     case NOT:
1.1.1.4   root      840:       /* (not (minus X 1)) can become (neg X).  */
                    841:       if (was_replaced[0]
                    842:          && ((GET_CODE (to) == PLUS && INTVAL (XEXP (to, 1)) == -1)
                    843:              || (GET_CODE (to) == MINUS && XEXP (to, 1) == const1_rtx)))
                    844:        return gen_rtx (NEG, GET_MODE (to), XEXP (to, 0));
                    845:       /* Don't let substitution introduce double-negatives.  */
                    846:       if (was_replaced[0]
                    847:           && GET_CODE (to) == code)
                    848:         return XEXP (to, 0);
                    849:       break;
                    850: 
1.1       root      851:     case NEG:
1.1.1.4   root      852:       /* (neg (minus X Y)) can become (minus Y X).  */
                    853:       if (was_replaced[0] && GET_CODE (to) == MINUS)
                    854:           return gen_rtx (MINUS, GET_MODE (to),
                    855:                           XEXP (to, 1), XEXP (to, 0));
1.1       root      856:       /* Don't let substitution introduce double-negatives.  */
1.1.1.2   root      857:       if (was_replaced[0]
1.1       root      858:          && GET_CODE (to) == code)
                    859:        return XEXP (to, 0);
                    860:       break;
                    861: 
1.1.1.2   root      862:     case FLOAT_TRUNCATE:
                    863:       /* (float_truncate:SF (float_extend:DF foo:SF)) = foo:SF.  */
                    864:       if (was_replaced[0]
                    865:          && GET_CODE (to) == FLOAT_EXTEND
                    866:          && GET_MODE (XEXP (to, 0)) == GET_MODE (x))
                    867:        return XEXP (to, 0);
                    868:       break;
                    869: 
1.1       root      870:     case PLUS:
                    871:       /* In (plus <foo> (ashift <bar> <n>))
                    872:         change the shift to a multiply so we can recognize
                    873:         scaled indexed addresses.  */
1.1.1.2   root      874:       if ((was_replaced[0]
                    875:           || was_replaced[1])
1.1       root      876:          && GET_CODE (to) == ASHIFT
1.1.1.2   root      877:          && GET_CODE (XEXP (to, 1)) == CONST_INT
                    878:          && INTVAL (XEXP (to, 1)) < HOST_BITS_PER_INT)
                    879:        {
                    880:          rtx temp;
                    881:          if (!undobuf.storage)
                    882:            undobuf.storage = (char *) oballoc (0);
                    883:          temp = gen_rtx (MULT, GET_MODE (to),
                    884:                          XEXP (to, 0),
                    885:                          gen_rtx (CONST_INT, VOIDmode,
                    886:                                   1 << INTVAL (XEXP (to, 1))));
                    887:          if (was_replaced[0])
                    888:            SUBST (XEXP (x, 0), temp);
                    889:          else
                    890:            SUBST (XEXP (x, 1), temp);
                    891:        }
                    892:       /* (plus X (neg Y)) becomes (minus X Y).  */
                    893:       if (GET_CODE (XEXP (x, 1)) == NEG)
                    894:        {
                    895:          if (!undobuf.storage)
                    896:            undobuf.storage = (char *) oballoc (0);
                    897:          return gen_rtx (MINUS, GET_MODE (x),
                    898:                          XEXP (x, 0), XEXP (XEXP (x, 1), 0));
                    899:        }
                    900:       /* (plus (neg X) Y) becomes (minus Y X).  */
                    901:       if (GET_CODE (XEXP (x, 0)) == NEG)
1.1       root      902:        {
                    903:          if (!undobuf.storage)
                    904:            undobuf.storage = (char *) oballoc (0);
1.1.1.2   root      905:          return gen_rtx (MINUS, GET_MODE (x),
                    906:                          XEXP (x, 1), XEXP (XEXP (x, 0), 0));
                    907:        }
                    908:       /* (plus (plus x c1) c2) => (plus x c1+c2) */
                    909:       if (GET_CODE (XEXP (x, 1)) == CONST_INT
                    910:          && GET_CODE (XEXP (x, 0)) == PLUS
                    911:          && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
                    912:        {
                    913:          int sum = (INTVAL (XEXP (x, 1))
                    914:                     + INTVAL (XEXP (XEXP (x, 0), 1)));
                    915:          if (sum == 0)
                    916:            return XEXP (XEXP (x, 0), 0);
                    917:          if (!undobuf.storage)
                    918:            undobuf.storage = (char *) oballoc (0);
                    919:          SUBST (XEXP (x, 1), gen_rtx (CONST_INT, VOIDmode, sum));
                    920:          SUBST (XEXP (x, 0), XEXP (XEXP (x, 0), 0));
                    921:          break;
1.1       root      922:        }
                    923:       /* If we have something (putative index) being added to a sum,
                    924:         associate it so that any constant term is outermost.
                    925:         That's because that's the way indexed addresses are
                    926:         now supposed to appear.  */
1.1.1.2   root      927:       if (((was_replaced[0] && GET_CODE (XEXP (x, 1)) == PLUS)
                    928:           || (was_replaced[1] && GET_CODE (XEXP (x, 0)) == PLUS))
1.1       root      929:          ||
1.1.1.2   root      930:          ((was_replaced[0] || was_replaced[1])
                    931:           && GET_CODE (to) == PLUS))
1.1       root      932:        {
                    933:          rtx offset = 0, base, index;
1.1.1.2   root      934:          if (GET_CODE (to) != PLUS)
1.1       root      935:            {
1.1.1.2   root      936:              index = to;
                    937:              base = was_replaced[0] ? XEXP (x, 1) : XEXP (x, 0);
1.1       root      938:            }
                    939:          else
                    940:            {
1.1.1.2   root      941:              index = was_replaced[0] ? XEXP (x, 1) : XEXP (x, 0);
                    942:              base = to;
1.1       root      943:            }
                    944:          if (CONSTANT_ADDRESS_P (XEXP (base, 0)))
                    945:            {
                    946:              offset = XEXP (base, 0);
                    947:              base = XEXP (base, 1);
                    948:            }
                    949:          else if (CONSTANT_ADDRESS_P (XEXP (base, 1)))
                    950:            {
                    951:              offset = XEXP (base, 1);
                    952:              base = XEXP (base, 0);
                    953:            }
                    954:          if (offset != 0)
                    955:            {
                    956:              if (!undobuf.storage)
                    957:                undobuf.storage = (char *) oballoc (0);
1.1.1.2   root      958:              if (GET_CODE (offset) == CONST_INT)
                    959:                return plus_constant (gen_rtx (PLUS, GET_MODE (index),
                    960:                                               base, index),
                    961:                                      INTVAL (offset));
                    962:              if (GET_CODE (index) == CONST_INT)
                    963:                return plus_constant (gen_rtx (PLUS, GET_MODE (offset),
                    964:                                               base, offset),
                    965:                                      INTVAL (index));
                    966:              return gen_rtx (PLUS, GET_MODE (index),
1.1       root      967:                              gen_rtx (PLUS, GET_MODE (index),
1.1.1.2   root      968:                                       base, index),
                    969:                              offset);
1.1       root      970:            }
                    971:        }
                    972:       break;
                    973: 
                    974:     case MINUS:
                    975:       /* Can simplify (minus:VOIDmode (zero/sign_extend FOO) CONST)
                    976:         (which is a compare instruction, not a subtract instruction)
                    977:         to (minus FOO CONST) if CONST fits in FOO's mode
                    978:         and we are only testing equality.
                    979:         In fact, this is valid for zero_extend if what follows is an
                    980:         unsigned comparison, and for sign_extend with a signed comparison.  */
                    981:       if (GET_MODE (x) == VOIDmode
1.1.1.2   root      982:          && was_replaced[0]
1.1       root      983:          && (GET_CODE (to) == ZERO_EXTEND || GET_CODE (to) == SIGN_EXTEND)
                    984:          && next_insn_tests_no_inequality (subst_insn)
                    985:          && GET_CODE (XEXP (x, 1)) == CONST_INT
1.1.1.2   root      986:          /* This is overly cautious by one bit, but saves worrying about
                    987:             whether it is zero-extension or sign extension.  */
1.1       root      988:          && ((unsigned) INTVAL (XEXP (x, 1))
1.1.1.2   root      989:              < (1 << (GET_MODE_BITSIZE (GET_MODE (XEXP (to, 0))) - 1))))
                    990:        SUBST (XEXP (x, 0), XEXP (to, 0));
1.1       root      991:       break;
                    992: 
                    993:     case EQ:
                    994:     case NE:
                    995:       /* If comparing a subreg against zero, discard the subreg.  */
1.1.1.2   root      996:       if (was_replaced[0]
1.1       root      997:          && GET_CODE (to) == SUBREG
                    998:          && SUBREG_WORD (to) == 0
                    999:          && XEXP (x, 1) == const0_rtx)
1.1.1.2   root     1000:        SUBST (XEXP (x, 0), SUBREG_REG (to));
1.1       root     1001: 
                   1002:       /* If comparing a ZERO_EXTRACT against zero,
                   1003:         canonicalize to a SIGN_EXTRACT,
                   1004:         since the two are equivalent here.  */
1.1.1.2   root     1005:       if (was_replaced[0]
                   1006:          && GET_CODE (to) == ZERO_EXTRACT
1.1       root     1007:          && XEXP (x, 1) == const0_rtx)
                   1008:        {
                   1009:          if (!undobuf.storage)
                   1010:            undobuf.storage = (char *) oballoc (0);
1.1.1.2   root     1011:          SUBST (XEXP (x, 0),
                   1012:                 gen_rtx (SIGN_EXTRACT, GET_MODE (to),
                   1013:                          XEXP (to, 0), XEXP (to, 1),
                   1014:                          XEXP (to, 2)));
1.1       root     1015:        }
                   1016:       /* If we are putting (ASHIFT 1 x) into (EQ (AND ... y) 0),
                   1017:         arrange to return (EQ (SIGN_EXTRACT y 1 x) 0),
                   1018:         which is what jump-on-bit instructions are written with.  */
                   1019:       else if (XEXP (x, 1) == const0_rtx
                   1020:               && GET_CODE (XEXP (x, 0)) == AND
1.1.1.2   root     1021:               && (XEXP (XEXP (x, 0), 0) == to
                   1022:                   || XEXP (XEXP (x, 0), 1) == to)
                   1023:               && GET_CODE (to) == ASHIFT
                   1024:               && XEXP (to, 0) == const1_rtx)
1.1       root     1025:        {
                   1026:          register rtx y = XEXP (XEXP (x, 0),
1.1.1.2   root     1027:                                 XEXP (XEXP (x, 0), 0) == to);
1.1       root     1028:          if (!undobuf.storage)
                   1029:            undobuf.storage = (char *) oballoc (0);
1.1.1.2   root     1030:          SUBST (XEXP (x, 0),
                   1031:                 gen_rtx (SIGN_EXTRACT, GET_MODE (to),
                   1032:                          y,
                   1033:                          const1_rtx, XEXP (to, 1)));
1.1       root     1034:        }
                   1035: 
                   1036:       break;
                   1037: 
                   1038:     case ZERO_EXTEND:
1.1.1.7   root     1039:       /* Nested zero-extends are equivalent to just one.  */
1.1.1.2   root     1040:       if (was_replaced[0]
1.1       root     1041:          && GET_CODE (to) == ZERO_EXTEND)
1.1.1.2   root     1042:        SUBST (XEXP (x, 0), XEXP (to, 0));
1.1.1.7   root     1043:       /* Zero extending a constant int can be replaced
                   1044:         by a zero-extended constant.  */
                   1045:       if (was_replaced[0]
                   1046:          && HOST_BITS_PER_INT >= GET_MODE_BITSIZE (GET_MODE (from))
                   1047:          && GET_CODE (to) == CONST_INT)
                   1048:        {
                   1049:          int intval = INTVAL (to) & GET_MODE_MASK (GET_MODE (from));
                   1050:          if (!undobuf.storage)
                   1051:            undobuf.storage = (char *) oballoc (0);
                   1052:          return gen_rtx (CONST_INT, VOIDmode, intval);
                   1053:        }
1.1       root     1054:       /* Zero-extending the result of an and with a constant can be done
                   1055:         with a wider and.  */
1.1.1.2   root     1056:       if (was_replaced[0]
1.1       root     1057:          && GET_CODE (to) == AND
                   1058:          && GET_CODE (XEXP (to, 1)) == CONST_INT
1.1.1.2   root     1059:          && FAKE_EXTEND_SAFE_P (GET_MODE (x), XEXP (to, 0))
1.1       root     1060:          /* Avoid getting wrong result if the constant has high bits set
                   1061:             that are irrelevant in the narrow mode where it is being used.  */
1.1.1.2   root     1062:          && 0 == (INTVAL (XEXP (to, 1))
                   1063:                   & ~ GET_MODE_MASK (GET_MODE (to))))
1.1       root     1064:        {
                   1065:          if (!undobuf.storage)
                   1066:            undobuf.storage = (char *) oballoc (0);
                   1067:          return gen_rtx (AND, GET_MODE (x),
1.1.1.2   root     1068:                          gen_lowpart_for_combine (GET_MODE (x), XEXP (to, 0)),
1.1       root     1069:                          XEXP (to, 1));
1.1.1.2   root     1070:        } 
                   1071:       /* Change (zero_extend:M (subreg:N (zero_extract:M ...) 0))
                   1072:         to (zero_extract:M ...) if the field extracted fits in mode N.  */
                   1073:       if (GET_CODE (XEXP (x, 0)) == SUBREG
                   1074:          && GET_CODE (XEXP (XEXP (x, 0), 0)) == ZERO_EXTRACT
                   1075:          && GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)) == CONST_INT
                   1076:          && (INTVAL (XEXP (XEXP (XEXP (x, 0), 0), 1))
                   1077:              <= GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0)))))
                   1078:        {
                   1079:          return XEXP (XEXP (x, 0), 0);
                   1080:        }
1.1.1.7   root     1081:       /* Change (zero_extend:M (subreg:N (and:M ... <const>) 0))
                   1082:         to (and:M ...) if the significant bits fit in mode N.  */
                   1083:       if (GET_CODE (XEXP (x, 0)) == SUBREG
                   1084:          && SUBREG_REG (XEXP (x, 0)) == to
                   1085:          && SUBREG_WORD (XEXP (x, 0)) == 0
                   1086:          && GET_CODE (to) == AND
                   1087:          && GET_CODE (XEXP (to, 1)) == CONST_INT
                   1088:          && FAKE_EXTEND_SAFE_P (GET_MODE (x), XEXP (to, 0))
                   1089:          /* Avoid getting wrong result if the constant has high bits set
                   1090:             that are irrelevant in the narrow mode where it is being used.  */
                   1091:          && 0 == (INTVAL (XEXP (to, 1))
                   1092:                   & ~ GET_MODE_MASK (GET_MODE (to))))
                   1093:        {
                   1094:          if (!undobuf.storage)
                   1095:            undobuf.storage = (char *) oballoc (0);
                   1096:          return gen_rtx (AND, GET_MODE (x),
                   1097:                          gen_lowpart_for_combine (GET_MODE (x), XEXP (to, 0)),
                   1098:                          XEXP (to, 1));
                   1099:        }
                   1100:       /* In (zero_extend:M (subreg:N (lshiftrt:M (zero_extend:M (any:N ...)))))
                   1101:         remove the outer zero extension.  */
                   1102:       if (GET_CODE (XEXP (x, 0)) == SUBREG
                   1103:          && SUBREG_REG (XEXP (x, 0)) == to
                   1104:          && SUBREG_WORD (XEXP (x, 0)) == 0
                   1105:          && GET_CODE (to) == LSHIFTRT)
                   1106:        {
                   1107:          rtx tmp = XEXP (to, 0);
                   1108: 
                   1109:          if (GET_CODE (tmp) == REG)
                   1110:            if (reg_n_sets[REGNO (tmp)] == 1)
                   1111:              tmp = SET_SRC (PATTERN (reg_last_set[REGNO (tmp)]));
                   1112:            else
                   1113:              break;
                   1114: 
                   1115:          if (GET_CODE (tmp) == ZERO_EXTEND
                   1116:              && GET_MODE (tmp) == GET_MODE (x)
                   1117:              && GET_MODE (XEXP (tmp, 0)) == GET_MODE (XEXP (x, 0)))
                   1118:            return SUBREG_REG (XEXP (x, 0));
                   1119:        }
1.1       root     1120:       break;
                   1121: 
                   1122:     case SIGN_EXTEND:
1.1.1.7   root     1123:       /* Nested sign-extends are equivalent to just one.  */
1.1.1.2   root     1124:       if (was_replaced[0]
1.1       root     1125:          && GET_CODE (to) == SIGN_EXTEND)
1.1.1.2   root     1126:        SUBST (XEXP (x, 0), XEXP (to, 0));
1.1.1.7   root     1127:       /* Sign extending a constant int can be replaced
                   1128:         by a sign-extended constant.  */
                   1129:       if (was_replaced[0]
                   1130:          && HOST_BITS_PER_INT >= GET_MODE_BITSIZE (GET_MODE (from))
                   1131:          && GET_CODE (to) == CONST_INT)
                   1132:        {
                   1133:          int intval = INTVAL (to);
                   1134:          if (!undobuf.storage)
                   1135:            undobuf.storage = (char *) oballoc (0);
                   1136:          if (intval > 0
                   1137:              && (intval & (1 << (GET_MODE_BITSIZE (GET_MODE (from)) - 1))))
                   1138:            intval |= ~ GET_MODE_MASK (GET_MODE (from));
                   1139:          return gen_rtx (CONST_INT, VOIDmode, intval);
                   1140:        }
1.1       root     1141:       /* Sign-extending the result of an and with a constant can be done
                   1142:         with a wider and, provided the high bit of the constant is 0.  */
1.1.1.2   root     1143:       if (was_replaced[0]
1.1       root     1144:          && GET_CODE (to) == AND
                   1145:          && GET_CODE (XEXP (to, 1)) == CONST_INT
1.1.1.2   root     1146:          && FAKE_EXTEND_SAFE_P (GET_MODE (x), XEXP (to, 0))
1.1       root     1147:          && ((INTVAL (XEXP (to, 1))
1.1.1.2   root     1148:               & (-1 << (GET_MODE_BITSIZE (GET_MODE (to)) - 1)))
1.1       root     1149:              == 0))
                   1150:        {
                   1151:          if (!undobuf.storage)
                   1152:            undobuf.storage = (char *) oballoc (0);
                   1153:          return gen_rtx (AND, GET_MODE (x),
1.1.1.2   root     1154:                          gen_lowpart_for_combine (GET_MODE (x), XEXP (to, 0)),
1.1       root     1155:                          XEXP (to, 1));
                   1156:         } 
1.1.1.7   root     1157:       /* hacks added by tiemann.  */
                   1158:       /* Change (sign_extend:M (subreg:N (and:M ... <const>) 0))
                   1159:         to (and:M ...), provided the result fits in mode N,
                   1160:         and the high bit of the constant is 0.  */
                   1161:       if (GET_CODE (XEXP (x, 0)) == SUBREG
                   1162:          && SUBREG_REG (XEXP (x, 0)) == to
                   1163:          && SUBREG_WORD (XEXP (x, 0)) == 0
                   1164:          && GET_CODE (to) == AND
                   1165:          && GET_CODE (XEXP (to, 1)) == CONST_INT
                   1166:          && FAKE_EXTEND_SAFE_P (GET_MODE (x), XEXP (to, 0))
                   1167:          && ((INTVAL (XEXP (to, 1))
                   1168:               & (-1 << (GET_MODE_BITSIZE (GET_MODE (to)) - 1)))
                   1169:              == 0))
                   1170:        {
                   1171:          if (!undobuf.storage)
                   1172:            undobuf.storage = (char *) oballoc (0);
                   1173:          return gen_rtx (AND, GET_MODE (x),
                   1174:                          gen_lowpart_for_combine (GET_MODE (x), XEXP (to, 0)),
                   1175:                          XEXP (to, 1));
                   1176:        } 
                   1177:       /* In (sign_extend:M (subreg:N (ashiftrt:M (sign_extend:M (any:N ...)))))
                   1178:         remove the outer sign extension.  */
                   1179:       if (GET_CODE (XEXP (x, 0)) == SUBREG
                   1180:          && SUBREG_REG (XEXP (x, 0)) == to
                   1181:          && SUBREG_WORD (XEXP (x, 0)) == 0
                   1182:          && GET_CODE (to) == ASHIFTRT)
                   1183:        {
                   1184:          rtx tmp = XEXP (to, 0);
                   1185: 
                   1186:          if (GET_CODE (tmp) == REG)
                   1187:            if (reg_n_sets[REGNO (tmp)] == 1)
                   1188:              tmp = SET_SRC (PATTERN (reg_last_set[REGNO (tmp)]));
                   1189:            else
                   1190:              break;
                   1191: 
                   1192:          if (GET_CODE (tmp) == SIGN_EXTEND
                   1193:              && GET_MODE (tmp) == GET_MODE (x)
                   1194:              && GET_MODE (XEXP (tmp, 0)) == GET_MODE (XEXP (x, 0)))
                   1195:            return SUBREG_REG (XEXP (x, 0));
                   1196:        }
1.1       root     1197:       break;
                   1198: 
                   1199:     case SET:
1.1.1.2   root     1200:       /* In (set (zero-extract <x> <n> <y>) (and <foo> <(2**n-1) | anything>))
1.1       root     1201:         the `and' can be deleted.  This can happen when storing a bit
1.1.1.2   root     1202:         that came from a set-flag insn followed by masking to one bit.  */
1.1       root     1203:       if (GET_CODE (XEXP (x, 0)) == ZERO_EXTRACT
1.1.1.2   root     1204:          && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
                   1205:          && was_replaced[1]
1.1       root     1206:          && GET_CODE (to) == AND
1.1.1.2   root     1207:          && GET_CODE (XEXP (to, 1)) == CONST_INT
                   1208:          && 0 == (((1 << INTVAL (XEXP (XEXP (x, 0), 1))) - 1)
                   1209:                   & ~ INTVAL (XEXP (to, 1))))
1.1       root     1210:        {
1.1.1.2   root     1211:          SUBST (XEXP (x, 1), XEXP (to, 0));
                   1212:        } 
                   1213:       /* In (set (zero-extract <x> <n> <y>)
                   1214:                 (subreg (and <foo> <(2**n-1) | anything>)))
                   1215:         the `and' can be deleted.  */
                   1216:       if (GET_CODE (XEXP (x, 0)) == ZERO_EXTRACT
                   1217:          && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
                   1218:          && GET_CODE (XEXP (x, 1)) == SUBREG
                   1219:          && SUBREG_WORD (XEXP (x, 1)) == 0
                   1220:          && GET_CODE (SUBREG_REG (XEXP (x, 1))) == AND
                   1221:          && GET_CODE (XEXP (SUBREG_REG (XEXP (x, 1)), 1)) == CONST_INT
                   1222:          && 0 == (((1 << INTVAL (XEXP (XEXP (x, 0), 1))) - 1)
                   1223:                   & ~ INTVAL (XEXP (SUBREG_REG (XEXP (x, 1)), 1))))
                   1224:        {
                   1225:          SUBST (SUBREG_REG (XEXP (x, 1)), XEXP (SUBREG_REG (XEXP (x, 1)), 0));
                   1226:        } 
                   1227:       /* (set (zero_extract ...) (and/or/xor (zero_extract ...) const)),
1.1.1.5   root     1228:         if both zero_extracts have the same location, size and position,
1.1.1.2   root     1229:         can be changed to avoid the byte extracts.  */
                   1230:       if ((GET_CODE (XEXP (x, 0)) == ZERO_EXTRACT
                   1231:           || GET_CODE (XEXP (x, 0)) == SIGN_EXTRACT)
                   1232:          && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
                   1233:          && (GET_CODE (XEXP (x, 1)) == AND
                   1234:              || GET_CODE (XEXP (x, 1)) == IOR
                   1235:              || GET_CODE (XEXP (x, 1)) == XOR)
1.1.1.5   root     1236:          && rtx_equal_p (XEXP (x, 0), XEXP (XEXP (x, 1), 0))
1.1.1.2   root     1237:          && GET_CODE (XEXP (XEXP (x, 1), 0)) == GET_CODE (XEXP (x, 0))
                   1238:          && GET_CODE (XEXP (XEXP (x, 1), 1)) == CONST_INT)
                   1239:        {
                   1240: #ifdef BITS_BIG_ENDIAN
                   1241:          int shiftcount
                   1242:            = GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (x, 0), 0)))
                   1243:              - INTVAL (XEXP (XEXP (x, 0), 1)) - INTVAL (XEXP (XEXP (x, 0), 2));
                   1244: #else
                   1245:          int shiftcount
                   1246:            = INTVAL (XEXP (XEXP (x, 0), 2));
                   1247: #endif
                   1248:          if (!undobuf.storage)
                   1249:            undobuf.storage = (char *) oballoc (0);
                   1250:          return
                   1251:            gen_rtx (SET, VOIDmode,
                   1252:                     XEXP (XEXP (x, 0), 0),
                   1253:                     gen_rtx (GET_CODE (XEXP (x, 1)),
                   1254:                              GET_MODE (XEXP (XEXP (x, 0), 0)),
                   1255:                              XEXP (XEXP (XEXP (x, 1), 0), 0),
                   1256:                              gen_rtx (CONST_INT, VOIDmode,
                   1257:                                       (INTVAL (XEXP (XEXP (x, 1), 1))
                   1258:                                        << shiftcount)
                   1259:                                       + (GET_CODE (XEXP (x, 1)) == AND
                   1260:                                          ? (1 << shiftcount) - 1
                   1261:                                          : 0))));
                   1262:        }
1.1       root     1263:       break;
                   1264: 
                   1265:     case AND:
                   1266:       if (GET_CODE (XEXP (x, 1)) == CONST_INT)
                   1267:        {
1.1.1.2   root     1268:          rtx tem = simplify_and_const_int (x, to);
1.1       root     1269:          if (tem)
                   1270:            return tem;
                   1271:        }
                   1272:       break;
                   1273: 
                   1274:     case FLOAT:
                   1275:       /* (float (sign_extend <X>)) = (float <X>).  */
1.1.1.2   root     1276:       if (was_replaced[0]
1.1       root     1277:          && GET_CODE (to) == SIGN_EXTEND)
1.1.1.2   root     1278:        SUBST (XEXP (x, 0), XEXP (to, 0));
1.1       root     1279:       break;
                   1280: 
                   1281:     case ZERO_EXTRACT:
1.1.1.2   root     1282:       /* (ZERO_EXTRACT (TRUNCATE x)...)
                   1283:         can become (ZERO_EXTRACT x ...).  */
                   1284:       if (was_replaced[0]
                   1285:          && GET_CODE (to) == TRUNCATE)
                   1286:        {
                   1287: #ifdef BITS_BIG_ENDIAN
                   1288:          if (GET_CODE (XEXP (x, 2)) == CONST_INT)
                   1289:            {
                   1290:              if (!undobuf.storage)
                   1291:                undobuf.storage = (char *) oballoc (0);
                   1292:              /* On a big-endian machine, must increment the bit-number
                   1293:                 since sign bit is farther away in the pre-truncated value.  */
                   1294:              return gen_rtx (ZERO_EXTRACT, GET_MODE (x),
                   1295:                              XEXP (to, 0),
                   1296:                              XEXP (x, 1),
                   1297:                              gen_rtx (CONST_INT, VOIDmode,
                   1298:                                       (INTVAL (XEXP (x, 2))
                   1299:                                        + GET_MODE_BITSIZE (GET_MODE (XEXP (to, 0)))
                   1300:                                        - GET_MODE_BITSIZE (GET_MODE (to)))));
                   1301:            }
                   1302: #else
                   1303:          SUBST (XEXP (x, 0), XEXP (to, 0));
                   1304: #endif
                   1305:        }
1.1       root     1306:       /* Extracting a single bit from the result of a shift:
                   1307:         see which bit it was before the shift and extract that directly.  */
1.1.1.2   root     1308:       if (was_replaced[0]
1.1       root     1309:          && (GET_CODE (to) == ASHIFTRT || GET_CODE (to) == LSHIFTRT
                   1310:              || GET_CODE (to) == ASHIFT || GET_CODE (to) == LSHIFT)
                   1311:          && GET_CODE (XEXP (to, 1)) == CONST_INT
                   1312:          && XEXP (x, 1) == const1_rtx
                   1313:          && GET_CODE (XEXP (x, 2)) == CONST_INT)
                   1314:        {
                   1315:          int shift = INTVAL (XEXP (to, 1));
                   1316:          int newpos;
                   1317:          if (GET_CODE (to) == ASHIFT || GET_CODE (to) == LSHIFT)
                   1318:            shift = - shift;
                   1319: #ifdef BITS_BIG_ENDIAN
                   1320:          shift = - shift;
                   1321: #endif
                   1322:          newpos = INTVAL (XEXP (x, 2)) + shift;
                   1323:          if (newpos >= 0 &&
1.1.1.2   root     1324:              newpos < GET_MODE_BITSIZE (GET_MODE (to)))
1.1       root     1325:            {
                   1326:              if (!undobuf.storage)
                   1327:                undobuf.storage = (char *) oballoc (0);
                   1328:              return gen_rtx (ZERO_EXTRACT, GET_MODE (x),
                   1329:                              XEXP (to, 0), const1_rtx,
                   1330:                              gen_rtx (CONST_INT, VOIDmode, newpos));
                   1331:            }
                   1332:        }
                   1333:       break;
                   1334: 
                   1335:     case LSHIFTRT:
                   1336:     case ASHIFTRT:
                   1337:     case ROTATE:
                   1338:     case ROTATERT:
                   1339: #ifdef SHIFT_COUNT_TRUNCATED
                   1340:       /* (lshift <X> (sign_extend <Y>)) = (lshift <X> <Y>) (most machines).
                   1341:         True for all kinds of shifts and also for zero_extend.  */
1.1.1.2   root     1342:       if (was_replaced[1]
1.1       root     1343:          && (GET_CODE (to) == SIGN_EXTEND
1.1.1.2   root     1344:              || GET_CODE (to) == ZERO_EXTEND)
                   1345:          && FAKE_EXTEND_SAFE_P (GET_MODE (to), XEXP (to, 0)))
1.1       root     1346:        {
                   1347:          if (!undobuf.storage)
                   1348:            undobuf.storage = (char *) oballoc (0);
1.1.1.2   root     1349:          SUBST (XEXP (x, 1),
                   1350:                 /* This is a perverse SUBREG, wider than its base.  */
                   1351:                 gen_lowpart_for_combine (GET_MODE (to), XEXP (to, 0)));
1.1       root     1352:        }
                   1353: #endif
                   1354:       /* Two shifts in a row of same kind
                   1355:         in same direction with constant counts
                   1356:         may be combined.  */
1.1.1.2   root     1357:       if (was_replaced[0]
1.1       root     1358:          && GET_CODE (to) == GET_CODE (x)
                   1359:          && GET_CODE (XEXP (x, 1)) == CONST_INT
                   1360:          && GET_CODE (XEXP (to, 1)) == CONST_INT
                   1361:          && INTVAL (XEXP (to, 1)) > 0
                   1362:          && INTVAL (XEXP (x, 1)) > 0
                   1363:          && (INTVAL (XEXP (x, 1)) + INTVAL (XEXP (to, 1))
1.1.1.2   root     1364:              < GET_MODE_BITSIZE (GET_MODE (x))))
1.1       root     1365:        {
                   1366:          if (!undobuf.storage)
                   1367:            undobuf.storage = (char *) oballoc (0);
                   1368:          return gen_rtx (GET_CODE (x), GET_MODE (x),
                   1369:                          XEXP (to, 0),
                   1370:                          gen_rtx (CONST_INT, VOIDmode,
                   1371:                                   INTVAL (XEXP (x, 1))
                   1372:                                   + INTVAL (XEXP (to, 1))));
                   1373:        }
                   1374:       break;
                   1375: 
                   1376:     case LSHIFT:
                   1377:     case ASHIFT:
                   1378: #ifdef SHIFT_COUNT_TRUNCATED
                   1379:       /* (lshift <X> (sign_extend <Y>)) = (lshift <X> <Y>) (most machines).
                   1380:         True for all kinds of shifts and also for zero_extend.  */
1.1.1.2   root     1381:       if (was_replaced[1]
1.1       root     1382:          && (GET_CODE (to) == SIGN_EXTEND
1.1.1.4   root     1383:              || GET_CODE (to) == ZERO_EXTEND)
                   1384:          && GET_CODE (to) == REG)
1.1       root     1385:        {
                   1386:          if (!undobuf.storage)
                   1387:            undobuf.storage = (char *) oballoc (0);
1.1.1.2   root     1388:          SUBST (XEXP (x, 1), gen_rtx (SUBREG, GET_MODE (to), XEXP (to, 0), 0));
1.1       root     1389:        }
                   1390: #endif
                   1391:       /* (lshift (and (lshiftrt <foo> <X>) <Y>) <X>)
                   1392:         happens copying between bit fields in similar structures.
                   1393:         It can be replaced by one and instruction.
                   1394:         It does not matter whether the shifts are logical or arithmetic.  */
                   1395:       if (GET_CODE (XEXP (x, 0)) == AND
                   1396:          && GET_CODE (XEXP (x, 1)) == CONST_INT
                   1397:          && INTVAL (XEXP (x, 1)) > 0
                   1398:          && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
1.1.1.2   root     1399:          && XEXP (XEXP (x, 0), 0) == to
1.1       root     1400:          && (GET_CODE (to) == LSHIFTRT
                   1401:              || GET_CODE (to) == ASHIFTRT)
                   1402: #if 0
                   1403: /* I now believe this restriction is unnecessary.
                   1404:    The outer shift will discard those bits in any case, right?  */
                   1405: 
                   1406:              /* If inner shift is arithmetic, either it shifts left or
                   1407:                 the bits it shifts the sign into are zeroed by the and.  */
                   1408:                  && (INTVAL (XEXP (x, 1)) < 0
                   1409:                      || ((unsigned) INTVAL (XEXP (XEXP (x, 0), 1))
                   1410:                          < 1 << (GET_MODE_BITSIZE (GET_MODE (x))
                   1411:                                  - INTVAL (XEXP (x, 0)))))
                   1412: #endif
                   1413:          && GET_CODE (XEXP (to, 1)) == CONST_INT
                   1414:          && INTVAL (XEXP (x, 1)) == INTVAL (XEXP (to, 1)))
                   1415:        {
                   1416:          if (!undobuf.storage)
                   1417:            undobuf.storage = (char *) oballoc (0);
                   1418:          /* The constant in the new `and' is <Y> << <X>
                   1419:             but clear out all bits that don't belong in our mode.  */
                   1420:          return gen_rtx (AND, GET_MODE (x), XEXP (to, 0),
                   1421:                          gen_rtx (CONST_INT, VOIDmode,
                   1422:                                   (GET_MODE_MASK (GET_MODE (x))
                   1423:                                    & ((GET_MODE_MASK (GET_MODE (x))
                   1424:                                        & INTVAL (XEXP (XEXP (x, 0), 1)))
                   1425:                                       << INTVAL (XEXP (x, 1))))));
                   1426:        } 
                   1427:       /* Two shifts in a row in same direction with constant counts
                   1428:         may be combined.  */
1.1.1.2   root     1429:       if (was_replaced[0]
1.1       root     1430:          && (GET_CODE (to) == ASHIFT || GET_CODE (to) == LSHIFT)
                   1431:          && GET_CODE (XEXP (x, 1)) == CONST_INT
                   1432:          && GET_CODE (XEXP (to, 1)) == CONST_INT
                   1433:          && INTVAL (XEXP (to, 1)) > 0
                   1434:          && INTVAL (XEXP (x, 1)) > 0
                   1435:          && (INTVAL (XEXP (x, 1)) + INTVAL (XEXP (to, 1))
1.1.1.2   root     1436:              < GET_MODE_BITSIZE (GET_MODE (x))))
1.1       root     1437:        {
                   1438:          if (!undobuf.storage)
                   1439:            undobuf.storage = (char *) oballoc (0);
                   1440:          return gen_rtx (GET_CODE (x), GET_MODE (x),
                   1441:                          XEXP (to, 0),
                   1442:                          gen_rtx (CONST_INT, VOIDmode,
                   1443:                                   INTVAL (XEXP (x, 1))
                   1444:                                   + INTVAL (XEXP (to, 1))));
                   1445:        }
                   1446:       /* (ashift (ashiftrt <foo> <X>) <X>)
                   1447:         (or, on some machines, (ashift (ashift <foo> <-X>) <X>) instead)
                   1448:         happens if you divide by 2**N and then multiply by 2**N.
                   1449:         It can be replaced by one `and' instruction.
                   1450:         It does not matter whether the shifts are logical or arithmetic.  */
                   1451:       if (GET_CODE (XEXP (x, 1)) == CONST_INT
                   1452:          && INTVAL (XEXP (x, 1)) > 0
1.1.1.2   root     1453:          && was_replaced[0]
1.1       root     1454:          && (((GET_CODE (to) == LSHIFTRT || GET_CODE (to) == ASHIFTRT)
                   1455:               && GET_CODE (XEXP (to, 1)) == CONST_INT
                   1456:               && INTVAL (XEXP (x, 1)) == INTVAL (XEXP (to, 1)))
                   1457:              ||
                   1458:              ((GET_CODE (to) == LSHIFT || GET_CODE (to) == ASHIFT)
                   1459:               && GET_CODE (XEXP (to, 1)) == CONST_INT
                   1460:               && INTVAL (XEXP (x, 1)) == - INTVAL (XEXP (to, 1)))))
                   1461:        {
                   1462:          if (!undobuf.storage)
                   1463:            undobuf.storage = (char *) oballoc (0);
1.1.1.2   root     1464:          /* The constant in the new `and' is -1 << <X>
1.1       root     1465:             but clear out all bits that don't belong in our mode.  */
                   1466:          return gen_rtx (AND, GET_MODE (x), XEXP (to, 0),
                   1467:                          gen_rtx (CONST_INT, VOIDmode,
                   1468:                                   (GET_MODE_MASK (GET_MODE (x))
                   1469:                                    & (GET_MODE_MASK (GET_MODE (x))
                   1470:                                       << INTVAL (XEXP (x, 1))))));
                   1471:        } 
                   1472: 
                   1473:     }
                   1474: 
                   1475:   return x;
                   1476: }
                   1477: 
                   1478: /* This is the AND case of the function subst.  */
                   1479: 
                   1480: static rtx
1.1.1.2   root     1481: simplify_and_const_int (x, to)
                   1482:      rtx x, to;
1.1       root     1483: {
                   1484:   register rtx varop = XEXP (x, 0);
                   1485:   register int constop = INTVAL (XEXP (x, 1));
                   1486: 
                   1487:   /* (and (subreg (and <foo> <constant>) 0) <constant>)
                   1488:      results from an andsi followed by an andqi,
                   1489:      which happens frequently when storing bit-fields
                   1490:      on something whose result comes from an andsi.  */
                   1491:   if (GET_CODE (varop) == SUBREG
1.1.1.2   root     1492:       && XEXP (varop, 0) == to
1.1       root     1493:       && subreg_lowpart_p (varop)
                   1494:       && GET_CODE (to) == AND
                   1495:       && GET_CODE (XEXP (to, 1)) == CONST_INT
                   1496:       /* Verify that the result of the outer `and'
                   1497:         is not affected by any bits not defined in the inner `and'.
                   1498:         True if the outer mode is narrower, or if the outer constant
                   1499:         masks to zero all the bits that the inner mode doesn't have.  */
1.1.1.2   root     1500:       && (GET_MODE_SIZE (GET_MODE (x)) < GET_MODE_SIZE (GET_MODE (to))
                   1501:          || (constop & ~ GET_MODE_MASK (GET_MODE (to))) == 0))
1.1       root     1502:     {
                   1503:       if (!undobuf.storage)
                   1504:        undobuf.storage = (char *) oballoc (0);
                   1505:       return gen_rtx (AND, GET_MODE (x),
1.1.1.2   root     1506:                      gen_lowpart_for_combine (GET_MODE (x), XEXP (to, 0)),
1.1       root     1507:                      gen_rtx (CONST_INT, VOIDmode,
                   1508:                               constop
                   1509:                               /* Remember that the bits outside that mode
                   1510:                                  are not being changed, so the effect
                   1511:                                  is as if they were all 1.  */
                   1512:                               & INTVAL (XEXP (to, 1))));
                   1513:     } 
1.1.1.2   root     1514:   /* (and:SI (zero_extract:SI ...) <constant>)
                   1515:      results from an andsi following a byte-fetch on risc machines.
                   1516:      When the constant includes all bits extracted, eliminate the `and'.  */
                   1517:   if (GET_CODE (varop) == ZERO_EXTRACT
                   1518:       && GET_CODE (XEXP (varop, 1)) == CONST_INT
                   1519:       /* The `and' must not clear any bits that the extract can give.  */
                   1520:       && (~ constop & ((1 << INTVAL (XEXP (varop, 1))) - 1)) == 0)
                   1521:     return varop;
1.1       root     1522:   /* (and (zero_extend <foo>) <constant>)
                   1523:      often results from storing in a bit-field something
                   1524:      that was calculated as a short.  Replace with a single `and'
                   1525:      in whose constant all bits not in <foo>'s mode are zero.  */
1.1.1.2   root     1526:   if (varop == to
                   1527:       && GET_CODE (to) == ZERO_EXTEND
                   1528:       && FAKE_EXTEND_SAFE_P (GET_MODE (x), XEXP (to, 0)))
1.1       root     1529:     {
                   1530:       if (!undobuf.storage)
                   1531:        undobuf.storage = (char *) oballoc (0);
                   1532:       return gen_rtx (AND, GET_MODE (x),
1.1.1.2   root     1533:                      /* This is a perverse SUBREG, wider than its base.  */
                   1534:                      gen_lowpart_for_combine (GET_MODE (x), XEXP (to, 0)),
1.1       root     1535:                      gen_rtx (CONST_INT, VOIDmode,
1.1.1.2   root     1536:                               constop & GET_MODE_MASK (GET_MODE (XEXP (to, 0)))));
1.1       root     1537:     }
                   1538:   /* (and (sign_extend <foo>) <constant>)
                   1539:      can be replaced with (and (subreg <foo>) <constant>)
                   1540:      if <constant> is narrower than <foo>'s mode,
                   1541:      or with (zero_extend <foo>) if <constant> is a mask for that mode.  */
1.1.1.2   root     1542:   if (varop == to
1.1       root     1543:       && GET_CODE (to) == SIGN_EXTEND
1.1.1.2   root     1544:       && ((unsigned) constop <= GET_MODE_MASK (GET_MODE (XEXP (to, 0))))
                   1545:       && FAKE_EXTEND_SAFE_P (GET_MODE (x), XEXP (to, 0)))
1.1       root     1546:     {
                   1547:       if (!undobuf.storage)
                   1548:        undobuf.storage = (char *) oballoc (0);
1.1.1.2   root     1549:       if (constop == GET_MODE_MASK (GET_MODE (XEXP (to, 0))))
1.1       root     1550:        return gen_rtx (ZERO_EXTEND, GET_MODE (x), XEXP (to, 0));
                   1551:       return gen_rtx (AND, GET_MODE (x),
1.1.1.2   root     1552:                      /* This is a perverse SUBREG, wider than its base.  */
                   1553:                      gen_lowpart_for_combine (GET_MODE (x), XEXP (to, 0)),
1.1       root     1554:                      XEXP (x, 1));
                   1555:     }
                   1556:   /* (and (and <foo> <constant>) <constant>)
                   1557:      comes from two and instructions in a row.  */
1.1.1.2   root     1558:   if (varop == to
1.1       root     1559:       && GET_CODE (to) == AND
                   1560:       && GET_CODE (XEXP (to, 1)) == CONST_INT)
                   1561:     {
                   1562:       if (!undobuf.storage)
                   1563:        undobuf.storage = (char *) oballoc (0);
                   1564:       return gen_rtx (AND, GET_MODE (x),
                   1565:                      XEXP (to, 0),
                   1566:                      gen_rtx (CONST_INT, VOIDmode,
                   1567:                               constop
                   1568:                               & INTVAL (XEXP (to, 1))));
                   1569:     }
                   1570:   /* (and (ashiftrt (ashift FOO N) N) CONST)
                   1571:      may be simplified to (and FOO CONST) if CONST masks off the bits
                   1572:      changed by the two shifts.  */
                   1573:   if (GET_CODE (varop) == ASHIFTRT
                   1574:       && GET_CODE (XEXP (varop, 1)) == CONST_INT
1.1.1.2   root     1575:       && XEXP (varop, 0) == to
1.1       root     1576:       && GET_CODE (to) == ASHIFT
                   1577:       && GET_CODE (XEXP (to, 1)) == CONST_INT
                   1578:       && INTVAL (XEXP (varop, 1)) == INTVAL (XEXP (to, 1))
                   1579:       && ((unsigned) constop >> INTVAL (XEXP (varop, 1))) == 0)
                   1580:     {
                   1581:       if (!undobuf.storage)
                   1582:        undobuf.storage = (char *) oballoc (0);
                   1583:       /* If CONST is a mask for the low byte,
                   1584:         change this into a zero-extend instruction
                   1585:         from just the low byte of FOO.  */
1.1.1.2   root     1586:       if (constop == GET_MODE_MASK (QImode))
1.1       root     1587:        {
                   1588:          rtx temp = gen_lowpart_for_combine (QImode, XEXP (to, 0));
1.1.1.2   root     1589:          if (GET_CODE (temp) != CLOBBER)
1.1       root     1590:            return gen_rtx (ZERO_EXTEND, GET_MODE (x), temp);
                   1591:        }
                   1592:       return gen_rtx (AND, GET_MODE (x),
                   1593:                      XEXP (to, 0), XEXP (x, 1));
                   1594:     }
1.1.1.2   root     1595:   /* (and x const) may be converted to (zero_extend (subreg x 0)).  */
1.1.1.4   root     1596:   if (constop == GET_MODE_MASK (QImode)
                   1597:       && GET_CODE (varop) == REG)
1.1.1.2   root     1598:     {
                   1599:       if (!undobuf.storage)
                   1600:        undobuf.storage = (char *) oballoc (0);
                   1601:       return gen_rtx (ZERO_EXTEND, GET_MODE (x),
                   1602:                      gen_rtx (SUBREG, QImode, varop, 0));
                   1603:     }
1.1.1.4   root     1604:   if (constop == GET_MODE_MASK (HImode)
                   1605:       && GET_CODE (varop) == REG)
1.1.1.2   root     1606:     {
                   1607:       if (!undobuf.storage)
                   1608:        undobuf.storage = (char *) oballoc (0);
                   1609:       return gen_rtx (ZERO_EXTEND, GET_MODE (x),
                   1610:                      gen_rtx (SUBREG, HImode, varop, 0));
                   1611:     }
1.1       root     1612:   /* No simplification applies.  */
                   1613:   return 0;
                   1614: }
                   1615: 
                   1616: /* Like gen_lowpart but for use by combine.  In combine it is not possible
                   1617:    to create any new pseudoregs.  However, it is safe to create
                   1618:    invalid memory addresses, because combine will try to recognize
                   1619:    them and all they will do is make the combine attempt fail.
                   1620: 
1.1.1.2   root     1621:    If for some reason this cannot do its job, an rtx
                   1622:    (clobber (const_int 0)) is returned.
                   1623:    An insn containing that will not be recognized.  */
                   1624: 
                   1625: #undef gen_lowpart
1.1       root     1626: 
                   1627: static rtx
                   1628: gen_lowpart_for_combine (mode, x)
                   1629:      enum machine_mode mode;
                   1630:      register rtx x;
                   1631: {
                   1632:   if (GET_CODE (x) == SUBREG || GET_CODE (x) == REG)
                   1633:     return gen_lowpart (mode, x);
1.1.1.9 ! root     1634:   if (GET_MODE (x) == mode)
1.1.1.2   root     1635:     return gen_rtx (CLOBBER, VOIDmode, const0_rtx);
1.1       root     1636:   if (GET_CODE (x) == MEM)
                   1637:     {
                   1638:       register int offset = 0;
1.1.1.7   root     1639: 
1.1.1.9 ! root     1640:       /* Refuse to work on a volatile memory ref.  */
        !          1641:       if (MEM_VOLATILE_P (x))
        !          1642:        return gen_rtx (CLOBBER, VOIDmode, const0_rtx);
        !          1643: 
1.1.1.7   root     1644:       /* If we want to refer to something bigger than the original memref,
                   1645:         generate a perverse subreg instead.  That will force a reload
                   1646:         of the original memref X.  */
                   1647:       if (GET_MODE_SIZE (GET_MODE (x)) < GET_MODE_SIZE (mode))
                   1648:        return gen_rtx (SUBREG, mode, x, 0);
                   1649: 
1.1       root     1650: #ifdef WORDS_BIG_ENDIAN
                   1651:       offset = (max (GET_MODE_SIZE (GET_MODE (x)), UNITS_PER_WORD)
                   1652:                - max (GET_MODE_SIZE (mode), UNITS_PER_WORD));
                   1653: #endif
                   1654: #ifdef BYTES_BIG_ENDIAN
1.1.1.2   root     1655:       /* Adjust the address so that the address-after-the-data
                   1656:         is unchanged.  */
                   1657:       offset -= (min (UNITS_PER_WORD, GET_MODE_SIZE (mode))
                   1658:                 - min (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (x))));
1.1       root     1659: #endif
                   1660:       return gen_rtx (MEM, mode, plus_constant (XEXP (x, 0),
                   1661:                                                offset));
                   1662:     }
                   1663:   else
1.1.1.2   root     1664:     return gen_rtx (CLOBBER, VOIDmode, const0_rtx);
1.1       root     1665: }
                   1666: 
                   1667: /* After substitution, if the resulting pattern looks like
1.1.1.2   root     1668:    (set (cc0) (and ...)) or (set (cc0) (lshiftrt ...)),
                   1669:    this function is called to simplify the
1.1       root     1670:    pattern into a bit-field operation if possible.  */
                   1671: 
                   1672: static void
                   1673: simplify_set_cc0_and (insn)
                   1674:      rtx insn;
                   1675: {
                   1676:   register rtx value = XEXP (PATTERN (insn), 1);
                   1677:   register rtx op0 = XEXP (value, 0);
                   1678:   register rtx op1 = XEXP (value, 1);
                   1679:   int offset = 0;
                   1680:   rtx var = 0;
                   1681:   rtx bitnum = 0;
                   1682:   int temp;
                   1683:   int unit;
1.1.1.2   root     1684:   rtx newpat;
                   1685: 
                   1686:   if (GET_CODE (value) == AND)
                   1687:     {
                   1688:       op0 = XEXP (value, 0);
                   1689:       op1 = XEXP (value, 1);
                   1690:     }
                   1691:   else if (GET_CODE (value) == LSHIFTRT)
                   1692:     {
                   1693:       /* If there is no AND, but there is a shift that discards
                   1694:         all but the sign bit, we can pretend that the shift result
                   1695:         is ANDed with 1.  Otherwise we cannot handle just a shift.  */
                   1696:       if (GET_CODE (XEXP (value, 1)) == CONST_INT
                   1697:          && (INTVAL (XEXP (value, 1))
                   1698:              == GET_MODE_BITSIZE (GET_MODE (value)) - 1))
                   1699:        {
                   1700:          op0 = value;
                   1701:          op1 = const1_rtx;
                   1702:        }
                   1703:       else
                   1704:        return;
                   1705:     }
                   1706:   else
                   1707:     abort ();
1.1       root     1708: 
                   1709:   /* Look for a constant power of 2 or a shifted 1
                   1710:      on either side of the AND.  Set VAR to the other side.
                   1711:      Set BITNUM to the shift count of the 1 (as an rtx).
                   1712:      Or, if bit number is constant, set OFFSET to the bit number.  */
                   1713: 
                   1714:   switch (GET_CODE (op0))
                   1715:     {
                   1716:     case CONST_INT:
                   1717:       temp = exact_log2 (INTVAL (op0));
                   1718:       if (temp < 0)
                   1719:        return;
                   1720:       offset = temp;
                   1721:       var = op1;
                   1722:       break;
                   1723: 
                   1724:     case ASHIFT:
                   1725:     case LSHIFT:
                   1726:       if (XEXP (op0, 0) == const1_rtx)
                   1727:        {
                   1728:          bitnum = XEXP (op0, 1);
                   1729:          var = op1;
                   1730:        }
                   1731:     }
                   1732:   if (var == 0)
                   1733:     switch (GET_CODE (op1))
                   1734:       {
                   1735:       case CONST_INT:
                   1736:        temp = exact_log2 (INTVAL (op1));
                   1737:        if (temp < 0)
                   1738:          return;
                   1739:        offset = temp;
                   1740:        var = op0;
                   1741:        break;
                   1742: 
                   1743:       case ASHIFT:
                   1744:       case LSHIFT:
                   1745:        if (XEXP (op1, 0) == const1_rtx)
                   1746:          {
                   1747:            bitnum = XEXP (op1, 1);
                   1748:            var = op0;
                   1749:          }
                   1750:       }
                   1751: 
                   1752:   /* If VAR is 0, we didn't find something recognizable.  */
                   1753:   if (var == 0)
                   1754:     return;
                   1755: 
                   1756:   if (!undobuf.storage)
                   1757:     undobuf.storage = (char *) oballoc (0);
                   1758: 
                   1759:   /* If the bit position is currently exactly 0,
                   1760:      extract a right-shift from the variable portion.  */
                   1761:   if (offset == 0
                   1762:       && (GET_CODE (var) == ASHIFTRT || GET_CODE (var) == LSHIFTRT))
                   1763:     {
                   1764:       bitnum = XEXP (var, 1);
                   1765:       var = XEXP (var, 0);
                   1766:     }
                   1767: 
1.1.1.2   root     1768:   if (GET_CODE (var) == SUBREG && SUBREG_WORD (var) == 0)
                   1769:     var = SUBREG_REG (var);
                   1770: 
                   1771:   /* Note that BITNUM and OFFSET are always little-endian thru here
                   1772:      even on a big-endian machine.  */
                   1773: 
1.1       root     1774: #ifdef BITS_BIG_ENDIAN
1.1.1.2   root     1775:   unit = GET_MODE_BITSIZE (GET_MODE (var)) - 1;
1.1       root     1776: 
                   1777:   if (bitnum != 0)
                   1778:     bitnum = gen_rtx (MINUS, SImode,
                   1779:                      gen_rtx (CONST_INT, VOIDmode, unit), bitnum);
                   1780:   else
                   1781:     offset = unit - offset;
                   1782: #endif
                   1783: 
                   1784:   if (bitnum == 0)
                   1785:     bitnum = gen_rtx (CONST_INT, VOIDmode, offset);
                   1786: 
1.1.1.2   root     1787:   newpat = gen_rtx (SET, VOIDmode, cc0_rtx,
                   1788:                    gen_rtx (ZERO_EXTRACT, VOIDmode, var, const1_rtx, bitnum));
                   1789:   if (recog (newpat, insn) >= 0)
1.1       root     1790:     {
1.1.1.2   root     1791:       if (undobuf.num_undo < MAX_UNDO)
                   1792:        {
                   1793:          undobuf.undo[undobuf.num_undo].where = &XEXP (PATTERN (insn), 1);
                   1794:          undobuf.undo[undobuf.num_undo].old_contents = value;
                   1795:          XEXP (PATTERN (insn), 1) = XEXP (newpat, 1);
                   1796:        }
                   1797:       undobuf.num_undo++;
1.1       root     1798:     }
                   1799: }
                   1800: 
                   1801: /* Update the records of when each REG was most recently set or killed
                   1802:    for the things done by INSN.  This is the last thing done in processing
                   1803:    INSN in the combiner loop.
                   1804: 
                   1805:    We update reg_last_set, reg_last_death, and also the similar information
                   1806:    mem_last_set (which insn most recently modified memory)
                   1807:    and last_call_cuid (which insn was the most recent subroutine call).  */
                   1808: 
                   1809: static void
                   1810: record_dead_and_set_regs (insn)
                   1811:      rtx insn;
                   1812: {
                   1813:   register rtx link;
                   1814:   for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
                   1815:     {
1.1.1.2   root     1816:       if (REG_NOTE_KIND (link) == REG_DEAD)
1.1       root     1817:        reg_last_death[REGNO (XEXP (link, 0))] = insn;
1.1.1.2   root     1818:       else if (REG_NOTE_KIND (link) == REG_INC)
1.1       root     1819:        reg_last_set[REGNO (XEXP (link, 0))] = insn;
                   1820:     }
                   1821: 
                   1822:   if (GET_CODE (insn) == CALL_INSN)
                   1823:     last_call_cuid = mem_last_set = INSN_CUID (insn);
                   1824: 
                   1825:   if (GET_CODE (PATTERN (insn)) == PARALLEL)
                   1826:     {
                   1827:       register int i;
                   1828:       for (i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--)
                   1829:        {
                   1830:          register rtx elt = XVECEXP (PATTERN (insn), 0, i);
                   1831:          register enum rtx_code code = GET_CODE (elt);
                   1832:          if (code == SET || code == CLOBBER)
                   1833:            {
                   1834:              if (GET_CODE (XEXP (elt, 0)) == REG)
                   1835:                reg_last_set[REGNO (XEXP (elt, 0))] = insn;
1.1.1.2   root     1836:              if (GET_CODE (XEXP (elt, 0)) == SUBREG
                   1837:                  && GET_CODE (SUBREG_REG (XEXP (elt, 0))) == REG)
                   1838:                reg_last_set[REGNO (SUBREG_REG (XEXP (elt, 0)))] = insn;
1.1       root     1839:              else if (GET_CODE (XEXP (elt, 0)) == MEM)
                   1840:                mem_last_set = INSN_CUID (insn);
                   1841:            }
                   1842:        }
                   1843:     }
                   1844:   else if (GET_CODE (PATTERN (insn)) == SET
                   1845:           || GET_CODE (PATTERN (insn)) == CLOBBER)
                   1846:     {
                   1847:       register rtx x = XEXP (PATTERN (insn), 0);
                   1848:       if (GET_CODE (x) == REG)
                   1849:        reg_last_set[REGNO (x)] = insn;
1.1.1.2   root     1850:       if (GET_CODE (x) == SUBREG
                   1851:          && GET_CODE (SUBREG_REG (x)) == REG)
                   1852:        reg_last_set[REGNO (SUBREG_REG (x))] = insn;
1.1       root     1853:       else if (GET_CODE (x) == MEM)
                   1854:        mem_last_set = INSN_CUID (insn);
                   1855:     }
                   1856: }
                   1857: 
                   1858: /* Return nonzero if expression X refers to a REG or to memory
                   1859:    that is set in an instruction more recent than FROM_CUID.  */
                   1860: 
                   1861: static int
                   1862: use_crosses_set_p (x, from_cuid)
                   1863:      register rtx x;
                   1864:      int from_cuid;
                   1865: {
                   1866:   register char *fmt;
                   1867:   register int i;
                   1868:   register enum rtx_code code = GET_CODE (x);
                   1869: 
                   1870:   if (code == REG)
                   1871:     {
                   1872:       register int regno = REGNO (x);
                   1873:       return (reg_last_set[regno]
                   1874:              && INSN_CUID (reg_last_set[regno]) > from_cuid);
                   1875:     }
                   1876: 
                   1877:   if (code == MEM && mem_last_set > from_cuid)
                   1878:     return 1;
                   1879: 
                   1880:   fmt = GET_RTX_FORMAT (code);
                   1881: 
1.1.1.9 ! root     1882:   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
1.1       root     1883:     {
                   1884:       if (fmt[i] == 'E')
                   1885:        {
                   1886:          register int j;
                   1887:          for (j = XVECLEN (x, i) - 1; j >= 0; j--)
                   1888:            if (use_crosses_set_p (XVECEXP (x, i, j), from_cuid))
                   1889:              return 1;
                   1890:        }
                   1891:       else if (fmt[i] == 'e'
                   1892:               && use_crosses_set_p (XEXP (x, i), from_cuid))
                   1893:        return 1;
                   1894:     }
                   1895:   return 0;
                   1896: }
                   1897: 
                   1898: /* Return nonzero if reg REGNO is marked as dying in INSN.  */
                   1899: 
                   1900: int
                   1901: regno_dead_p (regno, insn)
                   1902:      int regno;
                   1903:      rtx insn;
                   1904: {
                   1905:   register rtx link;
                   1906: 
                   1907:   for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
1.1.1.2   root     1908:     if ((REG_NOTE_KIND (link) == REG_DEAD
                   1909:         || REG_NOTE_KIND (link) == REG_INC)
                   1910:        && REGNO (XEXP (link, 0)) == regno)
1.1       root     1911:       return 1;
                   1912: 
                   1913:   return 0;
                   1914: }
                   1915: 
                   1916: /* Return nonzero if J is the first insn following I,
                   1917:    not counting labels, line numbers, etc.
                   1918:    We assume that J follows I.  */
                   1919: 
                   1920: static int
                   1921: adjacent_insns_p (i, j)
                   1922:      rtx i, j;
                   1923: {
                   1924:   register rtx insn;
                   1925:   for (insn = NEXT_INSN (i); insn != j; insn = NEXT_INSN (insn))
                   1926:     if (GET_CODE (insn) == INSN
                   1927:        || GET_CODE (insn) == CALL_INSN
                   1928:        || GET_CODE (insn) == JUMP_INSN)
                   1929:       return 0;
                   1930:   return 1;
                   1931: }
                   1932: 
1.1.1.2   root     1933: /* Concatenate the list of logical links of OINSN
1.1       root     1934:    into INSN's list of logical links.
1.1.1.2   root     1935:    Modifies OINSN destructively.
                   1936: 
                   1937:    If ALL_LINKS is nonzero, move all the links that OINSN has.
                   1938:    Otherwise, move only those that point to insns that set regs
                   1939:    that die in the insn OINSN.
                   1940:    Other links are clobbered so that they are no longer effective.  */
1.1       root     1941: 
                   1942: static void
1.1.1.2   root     1943: add_links (insn, oinsn, all_links)
                   1944:      rtx insn, oinsn;
                   1945:      int all_links;
1.1       root     1946: {
1.1.1.2   root     1947:   register rtx links = LOG_LINKS (oinsn);
                   1948:   if (! all_links)
                   1949:     {
                   1950:       rtx tail;
                   1951:       for (tail = links; tail; tail = XEXP (tail, 1))
                   1952:        {
                   1953:          rtx target = XEXP (tail, 0);
                   1954:          if (GET_CODE (target) != INSN
                   1955:              || GET_CODE (PATTERN (target)) != SET
                   1956:              || GET_CODE (SET_DEST (PATTERN (target))) != REG
                   1957:              || ! dead_or_set_p (oinsn, SET_DEST (PATTERN (target))))
                   1958:            /* OINSN is going to become a NOTE 
                   1959:               so a link pointing there will have no effect.  */
                   1960:            XEXP (tail, 0) = oinsn;
                   1961:        }
                   1962:     }
1.1       root     1963:   if (LOG_LINKS (insn) == 0)
                   1964:     LOG_LINKS (insn) = links;
                   1965:   else
                   1966:     {
                   1967:       register rtx next, prev = LOG_LINKS (insn);
                   1968:       while (next = XEXP (prev, 1))
                   1969:        prev = next;
                   1970:       XEXP (prev, 1) = links;
                   1971:     }
                   1972: }
1.1.1.7   root     1973:   
                   1974: /* Delete any LOG_LINKS of INSN which point at OINSN.  */
                   1975: 
                   1976: static void
                   1977: remove_links (insn, oinsn)
                   1978:      rtx insn, oinsn;
                   1979: {
                   1980:   register rtx next = LOG_LINKS (insn), prev = 0;
                   1981:   while (next)
                   1982:     {
                   1983:       if (XEXP (next, 0) == oinsn)
                   1984:        {
                   1985:          if (prev)
                   1986:            XEXP (prev, 1) = XEXP (next, 1);
                   1987:          else
                   1988:            LOG_LINKS (insn) = XEXP (next, 1);
                   1989:        }
                   1990:       else
                   1991:        prev = next;
                   1992:       next = XEXP (next, 1);
                   1993:     }
                   1994: }
1.1       root     1995: 
                   1996: /* Concatenate the any elements of the list of reg-notes INCS
                   1997:    which are of type REG_INC
                   1998:    into INSN's list of reg-notes.  */
                   1999: 
                   2000: static void
                   2001: add_incs (insn, incs)
                   2002:      rtx insn, incs;
                   2003: {
                   2004:   register rtx tail;
                   2005: 
                   2006:   for (tail = incs; tail; tail = XEXP (tail, 1))
1.1.1.2   root     2007:     if (REG_NOTE_KIND (tail) == REG_INC)
1.1       root     2008:       REG_NOTES (insn)
                   2009:        = gen_rtx (EXPR_LIST, REG_INC, XEXP (tail, 0), REG_NOTES (insn));
                   2010: }
1.1.1.7   root     2011: 
                   2012: /* Remove register number REGNO from the dead registers list of INSN.  */
                   2013: 
                   2014: void
                   2015: remove_death (regno, insn)
                   2016:      int regno;
                   2017:      rtx insn;
                   2018: {
                   2019:   register rtx link, next;
                   2020:   while ((link = REG_NOTES (insn))
                   2021:         && REG_NOTE_KIND (link) == REG_DEAD
                   2022:         && REGNO (XEXP (link, 0)) == regno)
                   2023:     REG_NOTES (insn) = XEXP (link, 1);
                   2024: 
                   2025:   if (link)
                   2026:     while (next = XEXP (link, 1))
                   2027:       {
                   2028:        if (REG_NOTE_KIND (next) == REG_DEAD
                   2029:            && REGNO (XEXP (next, 0)) == regno)
                   2030:          XEXP (link, 1) = XEXP (next, 1);
                   2031:        else
                   2032:          link = next;
                   2033:       }
                   2034: }
1.1       root     2035: 
                   2036: /* For each register (hardware or pseudo) used within expression X,
                   2037:    if its death is in an instruction with cuid
                   2038:    between FROM_CUID (inclusive) and TO_INSN (exclusive),
                   2039:    mark it as dead in TO_INSN instead.
                   2040: 
                   2041:    This is done when X is being merged by combination into TO_INSN.  */
                   2042: 
                   2043: static void
                   2044: move_deaths (x, from_cuid, to_insn)
                   2045:      rtx x;
                   2046:      int from_cuid;
                   2047:      rtx to_insn;
                   2048: {
                   2049:   register char *fmt;
                   2050:   register int len, i;
                   2051:   register enum rtx_code code = GET_CODE (x);
                   2052: 
                   2053:   if (code == REG)
                   2054:     {
                   2055:       register rtx where_dead = reg_last_death[REGNO (x)];
                   2056: 
                   2057:       if (where_dead && INSN_CUID (where_dead) >= from_cuid
                   2058:          && INSN_CUID (where_dead) < INSN_CUID (to_insn))
                   2059:        {
                   2060:          remove_death (REGNO (x), reg_last_death[REGNO (x)]);
                   2061:          if (! dead_or_set_p (to_insn, x))
                   2062:            REG_NOTES (to_insn)
                   2063:              = gen_rtx (EXPR_LIST, REG_DEAD, x, REG_NOTES (to_insn));
                   2064:        }
                   2065:       return;
                   2066:     }
                   2067: 
                   2068:   len = GET_RTX_LENGTH (code);
                   2069:   fmt = GET_RTX_FORMAT (code);
                   2070: 
                   2071:   for (i = 0; i < len; i++)
                   2072:     {
                   2073:       if (fmt[i] == 'E')
                   2074:        {
                   2075:          register int j;
                   2076:          for (j = XVECLEN (x, i) - 1; j >= 0; j--)
                   2077:            move_deaths (XVECEXP (x, i, j), from_cuid, to_insn);
                   2078:        }
                   2079:       else if (fmt[i] == 'e')
                   2080:        move_deaths (XEXP (x, i), from_cuid, to_insn);
                   2081:     }
                   2082: }
                   2083: 
1.1.1.7   root     2084: /* Like move_deaths, but deaths are moving both forward
                   2085:    (from FROM_CUID to TO_INSN), and backwards
                   2086:    (from FROM_INSN to TO_INSN).  This is what happens
                   2087:    when an insn is removed after applying the distributive law.  */
                   2088: 
                   2089: static void
                   2090: move_deaths_2 (x, from_cuid, from_insn, to_insn)
                   2091:      rtx x;
                   2092:      int from_cuid;
                   2093:      rtx from_insn, to_insn;
                   2094: {
                   2095:   register char *fmt;
                   2096:   register int len, i;
                   2097:   register enum rtx_code code = GET_CODE (x);
                   2098: 
                   2099:   if (code == REG)
                   2100:     {
                   2101:       register rtx where_dead = reg_last_death[REGNO (x)];
                   2102: 
                   2103:       if (where_dead && INSN_CUID (where_dead) >= from_cuid
                   2104:          && INSN_CUID (where_dead) < INSN_CUID (to_insn))
                   2105:        {
                   2106:          remove_death (REGNO (x), reg_last_death[REGNO (x)]);
                   2107:          if (! dead_or_set_p (to_insn, x))
                   2108:            REG_NOTES (to_insn)
                   2109:              = gen_rtx (EXPR_LIST, REG_DEAD, x, REG_NOTES (to_insn));
                   2110:        }
                   2111:       /* Can't use where_dead for from_insn because it has
                   2112:         not been computed yet.  */
                   2113:       else if (dead_or_set_p (from_insn, x))
                   2114:        {
                   2115:          remove_death (REGNO (x), from_insn);
                   2116:          if (! dead_or_set_p (to_insn, x))
                   2117:            REG_NOTES (to_insn)
                   2118:              = gen_rtx (EXPR_LIST, REG_DEAD, x, REG_NOTES (to_insn));
                   2119:        }
                   2120:       return;
                   2121:     }
                   2122: 
                   2123:   len = GET_RTX_LENGTH (code);
                   2124:   fmt = GET_RTX_FORMAT (code);
                   2125: 
                   2126:   for (i = 0; i < len; i++)
                   2127:     {
                   2128:       if (fmt[i] == 'E')
                   2129:        {
                   2130:          register int j;
                   2131:          for (j = XVECLEN (x, i) - 1; j >= 0; j--)
                   2132:            move_deaths_2 (XVECEXP (x, i, j), from_cuid, from_insn, to_insn);
                   2133:        }
                   2134:       else if (fmt[i] == 'e')
                   2135:        move_deaths_2 (XEXP (x, i), from_cuid, from_insn, to_insn);
                   2136:     }
                   2137: }
                   2138: 
                   2139: /* The distrib combiner rewrites groups of insns so that optimizations
                   2140:    can be more easily recognized.  The front-end does not know how to
                   2141:    group certain kinds of operations for efficient execution, and the
                   2142:    resulting code can be quite poor.  For example, on a machine without
                   2143:    bitfield instructions, bitfield references look like
                   2144: 
                   2145:        (and (lshiftrt ... n) m)
                   2146: 
                   2147:    When combining two bitfield operations, such as with ||, this can
                   2148:    yield code like
                   2149: 
                   2150:        (set z
                   2151:             (or (and (lshiftrt x n) 1)
                   2152:                 (and (lshiftrt y n) 1)))
                   2153: 
                   2154:    which can be more efficiently executed as
                   2155: 
                   2156:        (set z
                   2157:             (lshiftrt (and (or x y)
                   2158:                            (1 << m)) n))
                   2159: 
                   2160:    From there, the combiner attempts to rewrite the insns,
                   2161:    keeping flow information accurate for later passes,
                   2162:    and reducing the total number of insns executed.
                   2163: 
                   2164:    This function returns the point at which we should try
                   2165:    looking for more simplifications.  This will be before
                   2166:    INSN if the call succeeds.  We do not need to fear
                   2167:    infinite loops, since this function is guaranteed to
                   2168:    eliminate at least one (non-note) instruction if it returns
                   2169:    successfully.  */
                   2170: 
                   2171: static rtx
                   2172: try_distrib (insn, xprev1, xprev2)
                   2173:      rtx insn, xprev1, xprev2;
                   2174: {
                   2175:   rtx pat = PATTERN (insn);
                   2176:   rtx prev1, prev2, pat1, pat2, src1, src2;
                   2177:   rtx to_prev, to_insn;
                   2178:   enum rtx_code code;
1.1.1.9 ! root     2179:   int insn_code_number, prev_code_number, regno;
1.1.1.7   root     2180:   rtx new_insn_pat, new_prev_pat;
                   2181: 
                   2182:   distrib_attempts++;
                   2183: 
                   2184:   /* ??? Need to implement a test that PREV2 and PREV1
                   2185:      are completely independent.  Right now their
                   2186:      recognition ability is sufficiently limited that
                   2187:      it should not be necessary, but better safe than sorry.  */
                   2188: 
                   2189:   /* Let PREV1 be the later of the two insns, and PREV2 the earlier.  */
                   2190:   if (INSN_CUID (xprev1) > INSN_CUID (xprev2))
                   2191:     {
                   2192:       prev1 = xprev1;
                   2193:       prev2 = xprev2;
                   2194:     }
                   2195:   else
                   2196:     {
                   2197:       prev1 = xprev2;
                   2198:       prev2 = xprev1;
                   2199:     }
                   2200: 
                   2201:   pat1 = PATTERN (prev1);
                   2202:   pat2 = PATTERN (prev2);
                   2203: 
                   2204:   /* First, see if INSN, PREV1, and PREV2 have patterns we can expect
                   2205:      to simplify.  */
                   2206: 
                   2207:   if (GET_CODE (pat) != SET
                   2208:       || GET_CODE (pat1) != SET
                   2209:       || GET_CODE (pat2) != SET)
                   2210:     return 0;
                   2211: 
                   2212:   code = GET_CODE (SET_SRC (pat));
                   2213:   src1 = SET_SRC (pat1);
                   2214:   src2 = SET_SRC (pat2);
                   2215: 
1.1.1.8   root     2216:   if (GET_CODE (SET_DEST (pat1)) != REG
                   2217:       || GET_CODE (SET_DEST (pat2)) != REG)
                   2218:     return 0;
                   2219: 
1.1.1.7   root     2220:   switch (code)
                   2221:     {
                   2222:     default:
                   2223:       return 0;
                   2224: 
                   2225:     case IOR:
                   2226:     case AND:
                   2227:     case XOR:
                   2228:     case PLUS:
                   2229:       ;
                   2230:     }
                   2231: 
1.1.1.8   root     2232:   /* Insns PREV1 and PREV2 must provide the two operands of the arithmetic
                   2233:      that is done in INSN.  */
                   2234:   if (! ((XEXP (SET_SRC (pat), 0) == SET_DEST (pat1)
                   2235:          && XEXP (SET_SRC (pat), 1) == SET_DEST (pat2))
                   2236:         ||
                   2237:         (XEXP (SET_SRC (pat), 0) == SET_DEST (pat2)
                   2238:          && XEXP (SET_SRC (pat), 1) == SET_DEST (pat1))))
                   2239:     return 0;
                   2240: 
                   2241:   /* They must not be used in any other way in INSN.
                   2242:      In particular, they must not be used in a result memory address.  */
                   2243:   if (reg_mentioned_p (SET_DEST (pat1), SET_DEST (pat))
                   2244:       || reg_mentioned_p (SET_DEST (pat2), SET_DEST (pat)))
                   2245:     return 0;
                   2246: 
                   2247:   /* Give up if the two operands' modes don't match.  */
1.1.1.7   root     2248:   if (GET_MODE (src1) != GET_MODE (src2))
                   2249:     return 0;
                   2250: 
                   2251:   /* PREV1 and PREV2 must compute the same operation.
                   2252:      Actually, there are other cases that could be handled,
                   2253:      but are not implemented.  For example:
                   2254: 
                   2255:      (set (reg:SI 94)
                   2256:          (and:SI (reg:SI 73)
                   2257:                  (const_int 223)))
                   2258: 
                   2259:      (set (reg:SI 95)
                   2260:          (zero_extend:SI (subreg:QI (reg:SI 91) 0)))
                   2261: 
                   2262:      (set (reg:SI 96)
                   2263:          (ior:SI (reg:SI 94)
                   2264:                  (reg:SI 95)))
                   2265: 
                   2266:      In this case, we know that because (reg:SI 94) has
                   2267:      been anded with 223, there is no need to zero_extend
                   2268:      (reg:SI 91), and we could eliminate (reg:SI 95).  */
                   2269: 
                   2270:   if (GET_CODE (src1) != GET_CODE (src2))
                   2271:     return 0;
                   2272: 
                   2273:   /* The SETs in PREV1 and PREV2 do not need to be kept around.  */
                   2274: 
                   2275:   undobuf.num_undo = 0;
                   2276:   undobuf.storage = 0;
                   2277: 
                   2278:   /* Substitute in the latest insn for the regs set by the earlier ones.  */
                   2279:   subst_insn = insn;
                   2280:   n_occurrences = 0;   /* `subst' counts here */
                   2281: 
                   2282:   switch (GET_CODE (src1))
                   2283:     {
                   2284:     case LSHIFTRT:
                   2285:     case ASHIFTRT:
1.1.1.9 ! root     2286:       /* Right-shift can't distribute through addition
        !          2287:         since the round-off would happen differently.  */
        !          2288:     case AND:
        !          2289:     case IOR:
        !          2290:     case XOR:
        !          2291:       /* Boolean ops don't distribute through addition.  */
1.1.1.7   root     2292:       if (code == PLUS)
                   2293:        return 0;
                   2294: 
                   2295:     case LSHIFT:
                   2296:     case ASHIFT:
1.1.1.9 ! root     2297:       /* Left shifts are multiplication; they distribute through
        !          2298:         addition.  Also, since they work bitwise, they
        !          2299:         distribute through boolean operations.  */
        !          2300:       goto do_distrib;
        !          2301: 
        !          2302:     case MULT:
        !          2303:       /* Multiplication distributes through addition only.  */
        !          2304:       if (code != PLUS)
        !          2305:        return 0;
        !          2306: 
        !          2307:     do_distrib:
        !          2308:       /* Try changing (+ (* x c) (* y c)) to (* (+ x y) c).  */
1.1.1.7   root     2309: 
                   2310:       if (GET_CODE (XEXP (src1, 1)) != CONST_INT
                   2311:          || GET_CODE (XEXP (src2, 1)) != CONST_INT
                   2312:          || INTVAL (XEXP (src1, 1)) != INTVAL (XEXP (src2, 1)))
                   2313:        return 0;
                   2314:       to_prev = gen_rtx (code, GET_MODE (src1),
                   2315:                         XEXP (src1, 0), XEXP (src2, 0));
                   2316:       to_insn = gen_rtx (GET_CODE (src1), GET_MODE (src1), SET_DEST (pat1), XEXP (src1, 1));
                   2317:       break;
                   2318: 
                   2319:     case ZERO_EXTEND:
                   2320:     case SIGN_EXTEND:
1.1.1.9 ! root     2321:       /* Extension can't distribute through addition;
        !          2322:         the carries could be changed.  */
        !          2323:       if (code == PLUS)
        !          2324:        return 0;
1.1.1.7   root     2325:       {
                   2326:        rtx inner1 = XEXP (src1, 0), inner2 = XEXP (src2, 0);
                   2327:        int subreg_needed = 0;
                   2328: 
1.1.1.9 ! root     2329:        /* Try changing (+ (extend x) (extend y)) to (extend (+ x y)).  */
1.1.1.7   root     2330:        /* But keep extend insns together with their subregs.  */
                   2331:        if (GET_CODE (inner1) == SUBREG)
                   2332:          if (SUBREG_WORD (inner1) != 0)
                   2333:            return 0;
                   2334:          else
                   2335:            {
                   2336:              subreg_needed = 1;
                   2337:              inner1 = SUBREG_REG (inner1);
                   2338:            }
                   2339: 
                   2340:        if (GET_CODE (inner2) == SUBREG)
                   2341:          if (SUBREG_WORD (inner2) != 0)
                   2342:            return 0;
                   2343:          else
                   2344:            {
                   2345:              subreg_needed = 1;
                   2346:              inner2 = SUBREG_REG (inner2);
                   2347:            }
                   2348: 
                   2349:        to_prev = gen_rtx (code, GET_MODE (src1), inner1, inner2);
                   2350:        to_insn = gen_rtx (GET_CODE (src1), GET_MODE (src1),
                   2351:                           subreg_needed
                   2352:                           ? gen_rtx (SUBREG, GET_MODE (XEXP (src1, 0)),
                   2353:                                      SET_DEST (pat1), 0)
                   2354:                           : SET_DEST (pat1));
                   2355:       }
                   2356:       break;
                   2357: 
                   2358:     default:
                   2359:       return 0;
                   2360:     }
                   2361: 
                   2362:   /* Are the results of this "substitution" a valid instruction?  */
                   2363: 
                   2364:   new_insn_pat = subst (PATTERN (insn), SET_SRC (PATTERN (insn)), to_insn);
                   2365:   distrib_merges_1++;
                   2366: 
                   2367:   insn_code_number = recog (new_insn_pat, insn);
                   2368:   if (insn_code_number < 0)
                   2369:     {
                   2370:       undo_all ();
                   2371:       return 0;
                   2372:     }
                   2373: 
                   2374:   subst_insn = prev1;
                   2375:   new_prev_pat = subst (pat1, src1, to_prev);
                   2376:   distrib_merges_2++;
                   2377: 
                   2378:   prev_code_number = recog (new_prev_pat, prev1);
                   2379:   if (prev_code_number < 0)
                   2380:     {
                   2381:       undo_all ();
                   2382:       return 0;
                   2383:     }
                   2384: 
                   2385:   /* Everything worked; install the new patterns.  */
                   2386:   INSN_CODE (insn) = insn_code_number;
                   2387:   PATTERN (insn) = new_insn_pat;
                   2388: 
                   2389:   INSN_CODE (prev1) = prev_code_number;
                   2390:   PATTERN (prev1) = new_prev_pat;
                   2391: 
                   2392:   /* Need to change LOG_LINKS around...PREV1 now gets
                   2393:      whatever flowed into PREV2.  PREV2 is going to
                   2394:      become a NOTE, so we clear out its LOG_LINKS.  */
                   2395:   remove_links (insn, prev2);
                   2396:   add_links (prev1, prev2, adjacent_insns_p (prev2, prev1));
                   2397: 
                   2398:   /* Registers which died in PREV2 now die in PREV1.
                   2399:      Also, registers born in PREV2 dying in INSN now die in PREV1.  */
                   2400:   move_deaths_2 (src2, INSN_CUID (prev2), insn, prev1);
                   2401: 
                   2402:   regno = REGNO (SET_DEST (pat2));
                   2403: 
                   2404:   reg_n_sets[regno]--;
                   2405:   if (reg_n_sets[regno] == 0
                   2406:       && ! (basic_block_live_at_start[0][regno / HOST_BITS_PER_INT]
                   2407:            & (1 << (regno % HOST_BITS_PER_INT))))
                   2408:     reg_n_refs[regno] = 0;
                   2409:   remove_death (regno, insn);
                   2410: 
                   2411:   PUT_CODE (prev2, NOTE);
                   2412:   NOTE_LINE_NUMBER (prev2) = NOTE_INSN_DELETED;
                   2413:   NOTE_SOURCE_FILE (prev2) = 0;
                   2414: 
                   2415:   distrib_successes++;
                   2416:   return prev1;
                   2417: }
                   2418: 
1.1.1.2   root     2419: void
1.1       root     2420: dump_combine_stats (file)
                   2421:      char *file;
                   2422: {
                   2423:   fprintf
                   2424:     (file,
1.1.1.7   root     2425:      ";; Combiner statistics: %d attempts, %d substitutions (%d requiring new space),\n;; %d successes.\n\n",
                   2426:      combine_attempts, combine_merges, combine_extras, combine_successes);
                   2427:   fprintf
                   2428:     (file,
                   2429:      ";; Distributer statistics: %d attempts, %d:%d substitutions,\n;; %d successes.\n\n",
                   2430:      distrib_attempts, distrib_merges_1,
                   2431:      distrib_merges_2, distrib_successes);
1.1       root     2432: }
                   2433: 
1.1.1.2   root     2434: void
1.1       root     2435: dump_combine_total_stats (file)
                   2436:      char *file;
                   2437: {
                   2438:   fprintf
                   2439:     (file,
                   2440:      "\n;; Combiner totals: %d attempts, %d substitutions (%d requiring new space),\n;; %d successes.\n",
                   2441:      total_attempts, total_merges, total_extras, total_successes);
1.1.1.7   root     2442:   fprintf
                   2443:     (file,
                   2444:      "\n;; Distributer totals: %d attempts, %d:%d substitutions,\n;; %d successes.\n",
                   2445:      total_distrib_attempts, total_distrib_merges_1,
                   2446:      total_distrib_merges_2, total_distrib_successes);
1.1       root     2447: }

unix.superglobalmegacorp.com

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