Annotation of gcc/combine.c, revision 1.1.1.19

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

unix.superglobalmegacorp.com

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