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

1.1     ! root        1: /* Optimize jump instructions, for GNU compiler.
        !             2:    Copyright (C) 1987, 88, 89, 91, 92, 1993 Free Software Foundation, Inc.
        !             3: 
        !             4: This file is part of GNU CC.
        !             5: 
        !             6: GNU CC is free software; you can redistribute it and/or modify
        !             7: it under the terms of the GNU General Public License as published by
        !             8: the Free Software Foundation; either version 2, or (at your option)
        !             9: any later version.
        !            10: 
        !            11: GNU CC is distributed in the hope that it will be useful,
        !            12: but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            14: GNU General Public License for more details.
        !            15: 
        !            16: You should have received a copy of the GNU General Public License
        !            17: along with GNU CC; see the file COPYING.  If not, write to
        !            18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
        !            19: 
        !            20: 
        !            21: /* This is the jump-optimization pass of the compiler.
        !            22:    It is run two or three times: once before cse, sometimes once after cse,
        !            23:    and once after reload (before final).
        !            24: 
        !            25:    jump_optimize deletes unreachable code and labels that are not used.
        !            26:    It also deletes jumps that jump to the following insn,
        !            27:    and simplifies jumps around unconditional jumps and jumps
        !            28:    to unconditional jumps.
        !            29: 
        !            30:    Each CODE_LABEL has a count of the times it is used
        !            31:    stored in the LABEL_NUSES internal field, and each JUMP_INSN
        !            32:    has one label that it refers to stored in the
        !            33:    JUMP_LABEL internal field.  With this we can detect labels that
        !            34:    become unused because of the deletion of all the jumps that
        !            35:    formerly used them.  The JUMP_LABEL info is sometimes looked
        !            36:    at by later passes.
        !            37: 
        !            38:    Optionally, cross-jumping can be done.  Currently it is done
        !            39:    only the last time (when after reload and before final).
        !            40:    In fact, the code for cross-jumping now assumes that register
        !            41:    allocation has been done, since it uses `rtx_renumbered_equal_p'.
        !            42: 
        !            43:    Jump optimization is done after cse when cse's constant-propagation
        !            44:    causes jumps to become unconditional or to be deleted.
        !            45: 
        !            46:    Unreachable loops are not detected here, because the labels
        !            47:    have references and the insns appear reachable from the labels.
        !            48:    find_basic_blocks in flow.c finds and deletes such loops.
        !            49: 
        !            50:    The subroutines delete_insn, redirect_jump, and invert_jump are used
        !            51:    from other passes as well.  */
        !            52: 
        !            53: #include "config.h"
        !            54: #include "rtl.h"
        !            55: #include "flags.h"
        !            56: #include "hard-reg-set.h"
        !            57: #include "regs.h"
        !            58: #include "expr.h"
        !            59: #include "insn-config.h"
        !            60: #include "insn-flags.h"
        !            61: #include "real.h"
        !            62: 
        !            63: /* ??? Eventually must record somehow the labels used by jumps
        !            64:    from nested functions.  */
        !            65: /* Pre-record the next or previous real insn for each label?
        !            66:    No, this pass is very fast anyway.  */
        !            67: /* Condense consecutive labels?
        !            68:    This would make life analysis faster, maybe.  */
        !            69: /* Optimize jump y; x: ... y: jumpif... x?
        !            70:    Don't know if it is worth bothering with.  */
        !            71: /* Optimize two cases of conditional jump to conditional jump?
        !            72:    This can never delete any instruction or make anything dead,
        !            73:    or even change what is live at any point.
        !            74:    So perhaps let combiner do it.  */
        !            75: 
        !            76: /* Vector indexed by uid.
        !            77:    For each CODE_LABEL, index by its uid to get first unconditional jump
        !            78:    that jumps to the label.
        !            79:    For each JUMP_INSN, index by its uid to get the next unconditional jump
        !            80:    that jumps to the same label.
        !            81:    Element 0 is the start of a chain of all return insns.
        !            82:    (It is safe to use element 0 because insn uid 0 is not used.  */
        !            83: 
        !            84: static rtx *jump_chain;
        !            85: 
        !            86: /* List of labels referred to from initializers.
        !            87:    These can never be deleted.  */
        !            88: rtx forced_labels;
        !            89: 
        !            90: /* Maximum index in jump_chain.  */
        !            91: 
        !            92: static int max_jump_chain;
        !            93: 
        !            94: /* Set nonzero by jump_optimize if control can fall through
        !            95:    to the end of the function.  */
        !            96: int can_reach_end;
        !            97: 
        !            98: /* Indicates whether death notes are significant in cross jump analysis.
        !            99:    Normally they are not significant, because of A and B jump to C,
        !           100:    and R dies in A, it must die in B.  But this might not be true after
        !           101:    stack register conversion, and we must compare death notes in that
        !           102:    case. */
        !           103: 
        !           104: static int cross_jump_death_matters = 0;
        !           105: 
        !           106: static int duplicate_loop_exit_test ();
        !           107: void redirect_tablejump ();
        !           108: static int delete_labelref_insn ();
        !           109: static void mark_jump_label ();
        !           110: void delete_jump ();
        !           111: void delete_computation ();
        !           112: static void delete_from_jump_chain ();
        !           113: static int tension_vector_labels ();
        !           114: static void find_cross_jump ();
        !           115: static void do_cross_jump ();
        !           116: static int jump_back_p ();
        !           117: 
        !           118: extern rtx gen_jump ();
        !           119: 
        !           120: /* Delete no-op jumps and optimize jumps to jumps
        !           121:    and jumps around jumps.
        !           122:    Delete unused labels and unreachable code.
        !           123: 
        !           124:    If CROSS_JUMP is 1, detect matching code
        !           125:    before a jump and its destination and unify them.
        !           126:    If CROSS_JUMP is 2, do cross-jumping, but pay attention to death notes.
        !           127: 
        !           128:    If NOOP_MOVES is nonzero, delete no-op move insns.
        !           129: 
        !           130:    If AFTER_REGSCAN is nonzero, then this jump pass is being run immediately
        !           131:    after regscan, and it is safe to use regno_first_uid and regno_last_uid.
        !           132: 
        !           133:    If `optimize' is zero, don't change any code,
        !           134:    just determine whether control drops off the end of the function.
        !           135:    This case occurs when we have -W and not -O.
        !           136:    It works because `delete_insn' checks the value of `optimize'
        !           137:    and refrains from actually deleting when that is 0.  */
        !           138: 
        !           139: void
        !           140: jump_optimize (f, cross_jump, noop_moves, after_regscan)
        !           141:      rtx f;
        !           142:      int cross_jump;
        !           143:      int noop_moves;
        !           144:      int after_regscan;
        !           145: {
        !           146:   register rtx insn, next;
        !           147:   int changed;
        !           148:   int first = 1;
        !           149:   int max_uid = 0;
        !           150:   rtx last_insn;
        !           151: 
        !           152:   cross_jump_death_matters = (cross_jump == 2);
        !           153: 
        !           154:   /* Initialize LABEL_NUSES and JUMP_LABEL fields.  */
        !           155: 
        !           156:   for (insn = f; insn; insn = NEXT_INSN (insn))
        !           157:     {
        !           158:       if (GET_CODE (insn) == CODE_LABEL)
        !           159:        LABEL_NUSES (insn) = (LABEL_PRESERVE_P (insn) != 0);
        !           160:       else if (GET_CODE (insn) == JUMP_INSN)
        !           161:        JUMP_LABEL (insn) = 0;
        !           162:       if (INSN_UID (insn) > max_uid)
        !           163:        max_uid = INSN_UID (insn);
        !           164:     }
        !           165: 
        !           166:   max_uid++;
        !           167: 
        !           168:   /* Delete insns following barriers, up to next label.  */
        !           169: 
        !           170:   for (insn = f; insn;)
        !           171:     {
        !           172:       if (GET_CODE (insn) == BARRIER)
        !           173:        {
        !           174:          insn = NEXT_INSN (insn);
        !           175:          while (insn != 0 && GET_CODE (insn) != CODE_LABEL)
        !           176:            {
        !           177:              if (GET_CODE (insn) == NOTE
        !           178:                  && NOTE_LINE_NUMBER (insn) != NOTE_INSN_FUNCTION_END)
        !           179:                insn = NEXT_INSN (insn);
        !           180:              else
        !           181:                insn = delete_insn (insn);
        !           182:            }
        !           183:          /* INSN is now the code_label.  */
        !           184:        }
        !           185:       else
        !           186:        insn = NEXT_INSN (insn);
        !           187:     }
        !           188: 
        !           189:   /* Leave some extra room for labels and duplicate exit test insns
        !           190:      we make.  */
        !           191:   max_jump_chain = max_uid * 14 / 10;
        !           192:   jump_chain = (rtx *) alloca (max_jump_chain * sizeof (rtx));
        !           193:   bzero (jump_chain, max_jump_chain * sizeof (rtx));
        !           194: 
        !           195:   /* Mark the label each jump jumps to.
        !           196:      Combine consecutive labels, and count uses of labels.
        !           197: 
        !           198:      For each label, make a chain (using `jump_chain')
        !           199:      of all the *unconditional* jumps that jump to it;
        !           200:      also make a chain of all returns.  */
        !           201: 
        !           202:   for (insn = f; insn; insn = NEXT_INSN (insn))
        !           203:     if ((GET_CODE (insn) == JUMP_INSN || GET_CODE (insn) == INSN
        !           204:         || GET_CODE (insn) == CALL_INSN)
        !           205:        && ! INSN_DELETED_P (insn))
        !           206:       {
        !           207:        mark_jump_label (PATTERN (insn), insn, cross_jump);
        !           208:        if (GET_CODE (insn) == JUMP_INSN)
        !           209:          {
        !           210:            if (JUMP_LABEL (insn) != 0 && simplejump_p (insn))
        !           211:              {
        !           212:                jump_chain[INSN_UID (insn)]
        !           213:                  = jump_chain[INSN_UID (JUMP_LABEL (insn))];
        !           214:                jump_chain[INSN_UID (JUMP_LABEL (insn))] = insn;
        !           215:              }
        !           216:            if (GET_CODE (PATTERN (insn)) == RETURN)
        !           217:              {
        !           218:                jump_chain[INSN_UID (insn)] = jump_chain[0];
        !           219:                jump_chain[0] = insn;
        !           220:              }
        !           221:          }
        !           222:       }
        !           223: 
        !           224:   /* Keep track of labels used from static data;
        !           225:      they cannot ever be deleted.  */
        !           226: 
        !           227:   for (insn = forced_labels; insn; insn = XEXP (insn, 1))
        !           228:     LABEL_NUSES (XEXP (insn, 0))++;
        !           229: 
        !           230:   /* Delete all labels already not referenced.
        !           231:      Also find the last insn.  */
        !           232: 
        !           233:   last_insn = 0;
        !           234:   for (insn = f; insn; )
        !           235:     {
        !           236:       if (GET_CODE (insn) == CODE_LABEL && LABEL_NUSES (insn) == 0)
        !           237:        insn = delete_insn (insn);
        !           238:       else
        !           239:        {
        !           240:          last_insn = insn;
        !           241:          insn = NEXT_INSN (insn);
        !           242:        }
        !           243:     }
        !           244: 
        !           245:   if (!optimize)
        !           246:     {
        !           247:       /* See if there is still a NOTE_INSN_FUNCTION_END in this function.
        !           248:         If so record that this function can drop off the end.  */
        !           249: 
        !           250:       insn = last_insn;
        !           251:       {
        !           252:        int n_labels = 1;
        !           253:        while (insn
        !           254:               /* One label can follow the end-note: the return label.  */
        !           255:               && ((GET_CODE (insn) == CODE_LABEL && n_labels-- > 0)
        !           256:                   /* Ordinary insns can follow it if returning a structure.  */
        !           257:                   || GET_CODE (insn) == INSN
        !           258:                   /* If machine uses explicit RETURN insns, no epilogue,
        !           259:                      then one of them follows the note.  */
        !           260:                   || (GET_CODE (insn) == JUMP_INSN
        !           261:                       && GET_CODE (PATTERN (insn)) == RETURN)
        !           262:                   /* Other kinds of notes can follow also.  */
        !           263:                   || (GET_CODE (insn) == NOTE
        !           264:                       && NOTE_LINE_NUMBER (insn) != NOTE_INSN_FUNCTION_END)))
        !           265:          insn = PREV_INSN (insn);
        !           266:       }
        !           267: 
        !           268:       /* Report if control can fall through at the end of the function.  */
        !           269:       if (insn && GET_CODE (insn) == NOTE
        !           270:          && NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_END
        !           271:          && ! INSN_DELETED_P (insn))
        !           272:        can_reach_end = 1;
        !           273: 
        !           274:       /* Zero the "deleted" flag of all the "deleted" insns.  */
        !           275:       for (insn = f; insn; insn = NEXT_INSN (insn))
        !           276:        INSN_DELETED_P (insn) = 0;
        !           277:       return;
        !           278:     }
        !           279: 
        !           280: #ifdef HAVE_return
        !           281:   if (HAVE_return)
        !           282:     {
        !           283:       /* If we fall through to the epilogue, see if we can insert a RETURN insn
        !           284:         in front of it.  If the machine allows it at this point (we might be
        !           285:         after reload for a leaf routine), it will improve optimization for it
        !           286:         to be there.  */
        !           287:       insn = get_last_insn ();
        !           288:       while (insn && GET_CODE (insn) == NOTE)
        !           289:        insn = PREV_INSN (insn);
        !           290: 
        !           291:       if (insn && GET_CODE (insn) != BARRIER)
        !           292:        {
        !           293:          emit_jump_insn (gen_return ());
        !           294:          emit_barrier ();
        !           295:        }
        !           296:     }
        !           297: #endif
        !           298: 
        !           299:   if (noop_moves)
        !           300:     for (insn = f; insn; )
        !           301:       {
        !           302:        next = NEXT_INSN (insn);
        !           303: 
        !           304:        if (GET_CODE (insn) == INSN)
        !           305:          {
        !           306:            register rtx body = PATTERN (insn);
        !           307: 
        !           308: /* Combine stack_adjusts with following push_insns.  */
        !           309: #ifdef PUSH_ROUNDING
        !           310:            if (GET_CODE (body) == SET
        !           311:                && SET_DEST (body) == stack_pointer_rtx
        !           312:                && GET_CODE (SET_SRC (body)) == PLUS
        !           313:                && XEXP (SET_SRC (body), 0) == stack_pointer_rtx
        !           314:                && GET_CODE (XEXP (SET_SRC (body), 1)) == CONST_INT
        !           315:                && INTVAL (XEXP (SET_SRC (body), 1)) > 0)
        !           316:              {
        !           317:                rtx p;
        !           318:                rtx stack_adjust_insn = insn;
        !           319:                int stack_adjust_amount = INTVAL (XEXP (SET_SRC (body), 1));
        !           320:                int total_pushed = 0;
        !           321:                int pushes = 0;
        !           322: 
        !           323:                /* Find all successive push insns.  */
        !           324:                p = insn;
        !           325:                /* Don't convert more than three pushes;
        !           326:                   that starts adding too many displaced addresses
        !           327:                   and the whole thing starts becoming a losing
        !           328:                   proposition.  */
        !           329:                while (pushes < 3)
        !           330:                  {
        !           331:                    rtx pbody, dest;
        !           332:                    p = next_nonnote_insn (p);
        !           333:                    if (p == 0 || GET_CODE (p) != INSN)
        !           334:                      break;
        !           335:                    pbody = PATTERN (p);
        !           336:                    if (GET_CODE (pbody) != SET)
        !           337:                      break;
        !           338:                    dest = SET_DEST (pbody);
        !           339:                    /* Allow a no-op move between the adjust and the push.  */
        !           340:                    if (GET_CODE (dest) == REG
        !           341:                        && GET_CODE (SET_SRC (pbody)) == REG
        !           342:                        && REGNO (dest) == REGNO (SET_SRC (pbody)))
        !           343:                      continue;
        !           344:                    if (! (GET_CODE (dest) == MEM
        !           345:                           && GET_CODE (XEXP (dest, 0)) == POST_INC
        !           346:                           && XEXP (XEXP (dest, 0), 0) == stack_pointer_rtx))
        !           347:                      break;
        !           348:                    pushes++;
        !           349:                    if (total_pushed + GET_MODE_SIZE (GET_MODE (SET_DEST (pbody)))
        !           350:                        > stack_adjust_amount)
        !           351:                      break;
        !           352:                    total_pushed += GET_MODE_SIZE (GET_MODE (SET_DEST (pbody)));
        !           353:                  }
        !           354: 
        !           355:                /* Discard the amount pushed from the stack adjust;
        !           356:                   maybe eliminate it entirely.  */
        !           357:                if (total_pushed >= stack_adjust_amount)
        !           358:                  {
        !           359:                    delete_insn (stack_adjust_insn);
        !           360:                    total_pushed = stack_adjust_amount;
        !           361:                  }
        !           362:                else
        !           363:                  XEXP (SET_SRC (PATTERN (stack_adjust_insn)), 1)
        !           364:                    = GEN_INT (stack_adjust_amount - total_pushed);
        !           365: 
        !           366:                /* Change the appropriate push insns to ordinary stores.  */
        !           367:                p = insn;
        !           368:                while (total_pushed > 0)
        !           369:                  {
        !           370:                    rtx pbody, dest;
        !           371:                    p = next_nonnote_insn (p);
        !           372:                    if (GET_CODE (p) != INSN)
        !           373:                      break;
        !           374:                    pbody = PATTERN (p);
        !           375:                    if (GET_CODE (pbody) == SET)
        !           376:                      break;
        !           377:                    dest = SET_DEST (pbody);
        !           378:                    if (! (GET_CODE (dest) == MEM
        !           379:                           && GET_CODE (XEXP (dest, 0)) == POST_INC
        !           380:                           && XEXP (XEXP (dest, 0), 0) == stack_pointer_rtx))
        !           381:                      break;
        !           382:                    total_pushed -= GET_MODE_SIZE (GET_MODE (SET_DEST (pbody)));
        !           383:                    /* If this push doesn't fully fit in the space
        !           384:                       of the stack adjust that we deleted,
        !           385:                       make another stack adjust here for what we
        !           386:                       didn't use up.  There should be peepholes
        !           387:                       to recognize the resulting sequence of insns.  */
        !           388:                    if (total_pushed < 0)
        !           389:                      {
        !           390:                        emit_insn_before (gen_add2_insn (stack_pointer_rtx,
        !           391:                                                         GEN_INT (- total_pushed)),
        !           392:                                          p);
        !           393:                        break;
        !           394:                      }
        !           395:                    XEXP (dest, 0)
        !           396:                      = plus_constant (stack_pointer_rtx, total_pushed);
        !           397:                  }
        !           398:              }
        !           399: #endif
        !           400: 
        !           401:            /* Detect and delete no-op move instructions
        !           402:               resulting from not allocating a parameter in a register.  */
        !           403: 
        !           404:            if (GET_CODE (body) == SET
        !           405:                && (SET_DEST (body) == SET_SRC (body)
        !           406:                    || (GET_CODE (SET_DEST (body)) == MEM
        !           407:                        && GET_CODE (SET_SRC (body)) == MEM
        !           408:                        && rtx_equal_p (SET_SRC (body), SET_DEST (body))))
        !           409:                && ! (GET_CODE (SET_DEST (body)) == MEM
        !           410:                      && MEM_VOLATILE_P (SET_DEST (body)))
        !           411:                && ! (GET_CODE (SET_SRC (body)) == MEM
        !           412:                      && MEM_VOLATILE_P (SET_SRC (body))))
        !           413:              delete_insn (insn);
        !           414: 
        !           415:            /* Detect and ignore no-op move instructions
        !           416:               resulting from smart or fortuitous register allocation.  */
        !           417: 
        !           418:            else if (GET_CODE (body) == SET)
        !           419:              {
        !           420:                int sreg = true_regnum (SET_SRC (body));
        !           421:                int dreg = true_regnum (SET_DEST (body));
        !           422: 
        !           423:                if (sreg == dreg && sreg >= 0)
        !           424:                  delete_insn (insn);
        !           425:                else if (sreg >= 0 && dreg >= 0)
        !           426:                  {
        !           427:                    rtx trial;
        !           428:                    rtx tem = find_equiv_reg (NULL_RTX, insn, 0,
        !           429:                                              sreg, NULL_PTR, dreg,
        !           430:                                              GET_MODE (SET_SRC (body)));
        !           431: 
        !           432: #ifdef PRESERVE_DEATH_INFO_REGNO_P
        !           433:                    /* Deleting insn could lose a death-note for SREG or DREG
        !           434:                       so don't do it if final needs accurate death-notes.  */
        !           435:                    if (! PRESERVE_DEATH_INFO_REGNO_P (sreg)
        !           436:                        && ! PRESERVE_DEATH_INFO_REGNO_P (dreg))
        !           437: #endif
        !           438:                      {
        !           439:                        /* DREG may have been the target of a REG_DEAD note in
        !           440:                           the insn which makes INSN redundant.  If so, reorg
        !           441:                           would still think it is dead.  So search for such a
        !           442:                           note and delete it if we find it.  */
        !           443:                        for (trial = prev_nonnote_insn (insn);
        !           444:                             trial && GET_CODE (trial) != CODE_LABEL;
        !           445:                             trial = prev_nonnote_insn (trial))
        !           446:                          if (find_regno_note (trial, REG_DEAD, dreg))
        !           447:                            {
        !           448:                              remove_death (dreg, trial);
        !           449:                              break;
        !           450:                            }
        !           451: 
        !           452:                        if (tem != 0
        !           453:                            && GET_MODE (tem) == GET_MODE (SET_DEST (body)))
        !           454:                          delete_insn (insn);
        !           455:                      }
        !           456:                  }
        !           457:                else if (dreg >= 0 && CONSTANT_P (SET_SRC (body))
        !           458:                         && find_equiv_reg (SET_SRC (body), insn, 0, dreg,
        !           459:                                            NULL_PTR, 0,
        !           460:                                            GET_MODE (SET_DEST (body))))
        !           461:                  {
        !           462:                    /* This handles the case where we have two consecutive
        !           463:                       assignments of the same constant to pseudos that didn't
        !           464:                       get a hard reg.  Each SET from the constant will be
        !           465:                       converted into a SET of the spill register and an
        !           466:                       output reload will be made following it.  This produces
        !           467:                       two loads of the same constant into the same spill
        !           468:                       register.  */
        !           469: 
        !           470:                    rtx in_insn = insn;
        !           471: 
        !           472:                    /* Look back for a death note for the first reg.
        !           473:                       If there is one, it is no longer accurate.  */
        !           474:                    while (in_insn && GET_CODE (in_insn) != CODE_LABEL)
        !           475:                      {
        !           476:                        if ((GET_CODE (in_insn) == INSN
        !           477:                             || GET_CODE (in_insn) == JUMP_INSN)
        !           478:                            && find_regno_note (in_insn, REG_DEAD, dreg))
        !           479:                          {
        !           480:                            remove_death (dreg, in_insn);
        !           481:                            break;
        !           482:                          }
        !           483:                        in_insn = PREV_INSN (in_insn);
        !           484:                      }
        !           485: 
        !           486:                    /* Delete the second load of the value.  */
        !           487:                    delete_insn (insn);
        !           488:                  }
        !           489:              }
        !           490:            else if (GET_CODE (body) == PARALLEL)
        !           491:              {
        !           492:                /* If each part is a set between two identical registers or
        !           493:                   a USE or CLOBBER, delete the insn. */
        !           494:                int i, sreg, dreg;
        !           495:                rtx tem;
        !           496: 
        !           497:                for (i = XVECLEN (body, 0) - 1; i >= 0; i--)
        !           498:                  {
        !           499:                    tem = XVECEXP (body, 0, i);
        !           500:                    if (GET_CODE (tem) == USE || GET_CODE (tem) == CLOBBER)
        !           501:                      continue;
        !           502: 
        !           503:                    if (GET_CODE (tem) != SET
        !           504:                        || (sreg = true_regnum (SET_SRC (tem))) < 0
        !           505:                        || (dreg = true_regnum (SET_DEST (tem))) < 0
        !           506:                        || dreg != sreg)
        !           507:                      break;
        !           508:                  }
        !           509:                  
        !           510:                if (i < 0)
        !           511:                  delete_insn (insn);
        !           512:              }
        !           513: #if !BYTES_BIG_ENDIAN /* Not worth the hair to detect this
        !           514:                         in the big-endian case.  */
        !           515:            /* Also delete insns to store bit fields if they are no-ops.  */
        !           516:            else if (GET_CODE (body) == SET
        !           517:                     && GET_CODE (SET_DEST (body)) == ZERO_EXTRACT
        !           518:                     && XEXP (SET_DEST (body), 2) == const0_rtx
        !           519:                     && XEXP (SET_DEST (body), 0) == SET_SRC (body)
        !           520:                     && ! (GET_CODE (SET_SRC (body)) == MEM
        !           521:                           && MEM_VOLATILE_P (SET_SRC (body))))
        !           522:              delete_insn (insn);
        !           523: #endif /* not BYTES_BIG_ENDIAN */
        !           524:          }
        !           525:       insn = next;
        !           526:     }
        !           527: 
        !           528:   /* If we haven't yet gotten to reload and we have just run regscan,
        !           529:      delete any insn that sets a register that isn't used elsewhere.
        !           530:      This helps some of the optimizations below by having less insns
        !           531:      being jumped around.  */
        !           532: 
        !           533:   if (! reload_completed && after_regscan)
        !           534:     for (insn = f; insn; insn = next)
        !           535:       {
        !           536:        rtx set = single_set (insn);
        !           537: 
        !           538:        next = NEXT_INSN (insn);
        !           539: 
        !           540:        if (set && GET_CODE (SET_DEST (set)) == REG
        !           541:            && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER
        !           542:            && regno_first_uid[REGNO (SET_DEST (set))] == INSN_UID (insn)
        !           543:            /* We use regno_last_note_uid so as not to delete the setting
        !           544:               of a reg that's used in notes.  A subsequent optimization
        !           545:               might arrange to use that reg for real.  */             
        !           546:            && regno_last_note_uid[REGNO (SET_DEST (set))] == INSN_UID (insn)
        !           547:            && ! side_effects_p (SET_SRC (set)))
        !           548:          delete_insn (insn);
        !           549:       }
        !           550: 
        !           551:   /* Now iterate optimizing jumps until nothing changes over one pass.  */
        !           552:   changed = 1;
        !           553:   while (changed)
        !           554:     {
        !           555:       changed = 0;
        !           556: 
        !           557:       for (insn = f; insn; insn = next)
        !           558:        {
        !           559:          rtx reallabelprev;
        !           560:          rtx temp, temp1, temp2, temp3, temp4, temp5, temp6;
        !           561:          rtx nlabel;
        !           562:          int this_is_simplejump, this_is_condjump, reversep;
        !           563: #if 0
        !           564:          /* If NOT the first iteration, if this is the last jump pass
        !           565:             (just before final), do the special peephole optimizations.
        !           566:             Avoiding the first iteration gives ordinary jump opts
        !           567:             a chance to work before peephole opts.  */
        !           568: 
        !           569:          if (reload_completed && !first && !flag_no_peephole)
        !           570:            if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN)
        !           571:              peephole (insn);
        !           572: #endif
        !           573: 
        !           574:          /* That could have deleted some insns after INSN, so check now
        !           575:             what the following insn is.  */
        !           576: 
        !           577:          next = NEXT_INSN (insn);
        !           578: 
        !           579:          /* See if this is a NOTE_INSN_LOOP_BEG followed by an unconditional
        !           580:             jump.  Try to optimize by duplicating the loop exit test if so.
        !           581:             This is only safe immediately after regscan, because it uses
        !           582:             the values of regno_first_uid and regno_last_uid.  */
        !           583:          if (after_regscan && GET_CODE (insn) == NOTE
        !           584:              && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG
        !           585:              && (temp1 = next_nonnote_insn (insn)) != 0
        !           586:              && simplejump_p (temp1))
        !           587:            {
        !           588:              temp = PREV_INSN (insn);
        !           589:              if (duplicate_loop_exit_test (insn))
        !           590:                {
        !           591:                  changed = 1;
        !           592:                  next = NEXT_INSN (temp);
        !           593:                  continue;
        !           594:                }
        !           595:            }
        !           596: 
        !           597:          if (GET_CODE (insn) != JUMP_INSN)
        !           598:            continue;
        !           599: 
        !           600:          this_is_simplejump = simplejump_p (insn);
        !           601:          this_is_condjump = condjump_p (insn);
        !           602: 
        !           603:          /* Tension the labels in dispatch tables.  */
        !           604: 
        !           605:          if (GET_CODE (PATTERN (insn)) == ADDR_VEC)
        !           606:            changed |= tension_vector_labels (PATTERN (insn), 0);
        !           607:          if (GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
        !           608:            changed |= tension_vector_labels (PATTERN (insn), 1);
        !           609: 
        !           610:          /* If a dispatch table always goes to the same place,
        !           611:             get rid of it and replace the insn that uses it.  */
        !           612: 
        !           613:          if (GET_CODE (PATTERN (insn)) == ADDR_VEC
        !           614:              || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
        !           615:            {
        !           616:              int i;
        !           617:              rtx pat = PATTERN (insn);
        !           618:              int diff_vec_p = GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC;
        !           619:              int len = XVECLEN (pat, diff_vec_p);
        !           620:              rtx dispatch = prev_real_insn (insn);
        !           621: 
        !           622:              for (i = 0; i < len; i++)
        !           623:                if (XEXP (XVECEXP (pat, diff_vec_p, i), 0)
        !           624:                    != XEXP (XVECEXP (pat, diff_vec_p, 0), 0))
        !           625:                  break;
        !           626:              if (i == len
        !           627:                  && dispatch != 0
        !           628:                  && GET_CODE (dispatch) == JUMP_INSN
        !           629:                  && JUMP_LABEL (dispatch) != 0
        !           630:                  /* Don't mess with a casesi insn.  */
        !           631:                  && !(GET_CODE (PATTERN (dispatch)) == SET
        !           632:                       && (GET_CODE (SET_SRC (PATTERN (dispatch)))
        !           633:                           == IF_THEN_ELSE))
        !           634:                  && next_real_insn (JUMP_LABEL (dispatch)) == insn)
        !           635:                {
        !           636:                  redirect_tablejump (dispatch,
        !           637:                                      XEXP (XVECEXP (pat, diff_vec_p, 0), 0));
        !           638:                  changed = 1;
        !           639:                }
        !           640:            }
        !           641: 
        !           642:          reallabelprev = prev_active_insn (JUMP_LABEL (insn));
        !           643: 
        !           644:          /* If a jump references the end of the function, try to turn
        !           645:             it into a RETURN insn, possibly a conditional one.  */
        !           646:          if (JUMP_LABEL (insn)
        !           647:              && (next_active_insn (JUMP_LABEL (insn)) == 0
        !           648:                  || GET_CODE (PATTERN (next_active_insn (JUMP_LABEL (insn))))
        !           649:                      == RETURN))
        !           650:            changed |= redirect_jump (insn, NULL_RTX);
        !           651: 
        !           652:          /* Detect jump to following insn.  */
        !           653:          if (reallabelprev == insn && condjump_p (insn))
        !           654:            {
        !           655:              delete_jump (insn);
        !           656:              changed = 1;
        !           657:              continue;
        !           658:            }
        !           659: 
        !           660:          /* If we have an unconditional jump preceded by a USE, try to put
        !           661:             the USE before the target and jump there.  This simplifies many
        !           662:             of the optimizations below since we don't have to worry about
        !           663:             dealing with these USE insns.  We only do this if the label
        !           664:             being branch to already has the identical USE or if code
        !           665:             never falls through to that label.  */
        !           666: 
        !           667:          if (this_is_simplejump
        !           668:              && (temp = prev_nonnote_insn (insn)) != 0
        !           669:              && GET_CODE (temp) == INSN && GET_CODE (PATTERN (temp)) == USE
        !           670:              && (temp1 = prev_nonnote_insn (JUMP_LABEL (insn))) != 0
        !           671:              && (GET_CODE (temp1) == BARRIER
        !           672:                  || (GET_CODE (temp1) == INSN
        !           673:                      && rtx_equal_p (PATTERN (temp), PATTERN (temp1)))))
        !           674:            {
        !           675:              if (GET_CODE (temp1) == BARRIER)
        !           676:                {
        !           677:                  emit_insn_after (PATTERN (temp), temp1);
        !           678:                  temp1 = NEXT_INSN (temp1);
        !           679:                }
        !           680: 
        !           681:              delete_insn (temp);
        !           682:              redirect_jump (insn, get_label_before (temp1));
        !           683:              reallabelprev = prev_real_insn (temp1);
        !           684:              changed = 1;
        !           685:            }
        !           686: 
        !           687:          /* Simplify   if (...) x = a; else x = b; by converting it
        !           688:             to         x = b; if (...) x = a;
        !           689:             if B is sufficiently simple, the test doesn't involve X,
        !           690:             and nothing in the test modifies B or X.
        !           691: 
        !           692:             If we have small register classes, we also can't do this if X
        !           693:             is a hard register.
        !           694: 
        !           695:             If the "x = b;" insn has any REG_NOTES, we don't do this because
        !           696:             of the possibility that we are running after CSE and there is a
        !           697:             REG_EQUAL note that is only valid if the branch has already been
        !           698:             taken.  If we move the insn with the REG_EQUAL note, we may
        !           699:             fold the comparison to always be false in a later CSE pass.
        !           700:             (We could also delete the REG_NOTES when moving the insn, but it
        !           701:             seems simpler to not move it.)  An exception is that we can move
        !           702:             the insn if the only note is a REG_EQUAL or REG_EQUIV whose
        !           703:             value is the same as "b".
        !           704: 
        !           705:             INSN is the branch over the `else' part. 
        !           706: 
        !           707:             We set:
        !           708: 
        !           709:             TEMP to the jump insn preceding "x = a;"
        !           710:             TEMP1 to X
        !           711:             TEMP2 to the insn that sets "x = b;"
        !           712:             TEMP3 to the insn that sets "x = a;"
        !           713:             TEMP4 to the set of "x = b";  */
        !           714: 
        !           715:          if (this_is_simplejump
        !           716:              && (temp3 = prev_active_insn (insn)) != 0
        !           717:              && GET_CODE (temp3) == INSN
        !           718:              && (temp4 = single_set (temp3)) != 0
        !           719:              && GET_CODE (temp1 = SET_DEST (temp4)) == REG
        !           720: #ifdef SMALL_REGISTER_CLASSES
        !           721:              && REGNO (temp1) >= FIRST_PSEUDO_REGISTER
        !           722: #endif
        !           723:              && (temp2 = next_active_insn (insn)) != 0
        !           724:              && GET_CODE (temp2) == INSN
        !           725:              && (temp4 = single_set (temp2)) != 0
        !           726:              && rtx_equal_p (SET_DEST (temp4), temp1)
        !           727:              && (GET_CODE (SET_SRC (temp4)) == REG
        !           728:                  || GET_CODE (SET_SRC (temp4)) == SUBREG
        !           729:                  || CONSTANT_P (SET_SRC (temp4)))
        !           730:              && (REG_NOTES (temp2) == 0
        !           731:                  || ((REG_NOTE_KIND (REG_NOTES (temp2)) == REG_EQUAL
        !           732:                       || REG_NOTE_KIND (REG_NOTES (temp2)) == REG_EQUIV)
        !           733:                      && XEXP (REG_NOTES (temp2), 1) == 0
        !           734:                      && rtx_equal_p (XEXP (REG_NOTES (temp2), 0),
        !           735:                                      SET_SRC (temp4))))
        !           736:              && (temp = prev_active_insn (temp3)) != 0
        !           737:              && condjump_p (temp) && ! simplejump_p (temp)
        !           738:              /* TEMP must skip over the "x = a;" insn */
        !           739:              && prev_real_insn (JUMP_LABEL (temp)) == insn
        !           740:              && no_labels_between_p (insn, JUMP_LABEL (temp))
        !           741:              /* There must be no other entries to the "x = b;" insn.  */
        !           742:              && no_labels_between_p (JUMP_LABEL (temp), temp2)
        !           743:              /* INSN must either branch to the insn after TEMP2 or the insn
        !           744:                 after TEMP2 must branch to the same place as INSN.  */
        !           745:              && (reallabelprev == temp2
        !           746:                  || ((temp5 = next_active_insn (temp2)) != 0
        !           747:                      && simplejump_p (temp5)
        !           748:                      && JUMP_LABEL (temp5) == JUMP_LABEL (insn))))
        !           749:            {
        !           750:              /* The test expression, X, may be a complicated test with
        !           751:                 multiple branches.  See if we can find all the uses of
        !           752:                 the label that TEMP branches to without hitting a CALL_INSN
        !           753:                 or a jump to somewhere else.  */
        !           754:              rtx target = JUMP_LABEL (temp);
        !           755:              int nuses = LABEL_NUSES (target);
        !           756:              rtx p, q;
        !           757: 
        !           758:              /* Set P to the first jump insn that goes around "x = a;".  */
        !           759:              for (p = temp; nuses && p; p = prev_nonnote_insn (p))
        !           760:                {
        !           761:                  if (GET_CODE (p) == JUMP_INSN)
        !           762:                    {
        !           763:                      if (condjump_p (p) && ! simplejump_p (p)
        !           764:                          && JUMP_LABEL (p) == target)
        !           765:                        {
        !           766:                          nuses--;
        !           767:                          if (nuses == 0)
        !           768:                            break;
        !           769:                        }
        !           770:                      else
        !           771:                        break;
        !           772:                    }
        !           773:                  else if (GET_CODE (p) == CALL_INSN)
        !           774:                    break;
        !           775:                }
        !           776: 
        !           777: #ifdef HAVE_cc0
        !           778:              /* We cannot insert anything between a set of cc and its use
        !           779:                 so if P uses cc0, we must back up to the previous insn.  */
        !           780:              q = prev_nonnote_insn (p);
        !           781:              if (q && GET_RTX_CLASS (GET_CODE (q)) == 'i'
        !           782:                  && sets_cc0_p (PATTERN (q)))
        !           783:                p = q;
        !           784: #endif
        !           785: 
        !           786:              if (p)
        !           787:                p = PREV_INSN (p);
        !           788: 
        !           789:              /* If we found all the uses and there was no data conflict, we
        !           790:                 can move the assignment unless we can branch into the middle
        !           791:                 from somewhere.  */
        !           792:              if (nuses == 0 && p
        !           793:                  && no_labels_between_p (p, insn)
        !           794:                  && ! reg_referenced_between_p (temp1, p, NEXT_INSN (temp3))
        !           795:                  && ! reg_set_between_p (temp1, p, temp3)
        !           796:                  && (GET_CODE (SET_SRC (temp4)) == CONST_INT
        !           797:                      || ! reg_set_between_p (SET_SRC (temp4), p, temp2)))
        !           798:                {
        !           799:                  emit_insn_after_with_line_notes (PATTERN (temp2), p, temp2);
        !           800:                  delete_insn (temp2);
        !           801: 
        !           802:                  /* Set NEXT to an insn that we know won't go away.  */
        !           803:                  next = next_active_insn (insn);
        !           804: 
        !           805:                  /* Delete the jump around the set.  Note that we must do
        !           806:                     this before we redirect the test jumps so that it won't
        !           807:                     delete the code immediately following the assignment
        !           808:                     we moved (which might be a jump).  */
        !           809: 
        !           810:                  delete_insn (insn);
        !           811: 
        !           812:                  /* We either have two consecutive labels or a jump to
        !           813:                     a jump, so adjust all the JUMP_INSNs to branch to where
        !           814:                     INSN branches to.  */
        !           815:                  for (p = NEXT_INSN (p); p != next; p = NEXT_INSN (p))
        !           816:                    if (GET_CODE (p) == JUMP_INSN)
        !           817:                      redirect_jump (p, target);
        !           818: 
        !           819:                  changed = 1;
        !           820:                  continue;
        !           821:                }
        !           822:            }
        !           823: 
        !           824: #ifndef HAVE_cc0
        !           825:          /* If we have if (...) x = exp;  and branches are expensive,
        !           826:             EXP is a single insn, does not have any side effects, cannot
        !           827:             trap, and is not too costly, convert this to
        !           828:             t = exp; if (...) x = t;
        !           829: 
        !           830:             Don't do this when we have CC0 because it is unlikely to help
        !           831:             and we'd need to worry about where to place the new insn and
        !           832:             the potential for conflicts.  We also can't do this when we have
        !           833:             notes on the insn for the same reason as above.
        !           834: 
        !           835:             We set:
        !           836: 
        !           837:             TEMP to the "x = exp;" insn.
        !           838:             TEMP1 to the single set in the "x = exp; insn.
        !           839:             TEMP2 to "x".  */
        !           840: 
        !           841:          if (! reload_completed
        !           842:              && this_is_condjump && ! this_is_simplejump
        !           843:              && BRANCH_COST >= 3
        !           844:              && (temp = next_nonnote_insn (insn)) != 0
        !           845:              && GET_CODE (temp) == INSN
        !           846:              && REG_NOTES (temp) == 0
        !           847:              && (reallabelprev == temp
        !           848:                  || ((temp2 = next_active_insn (temp)) != 0
        !           849:                      && simplejump_p (temp2)
        !           850:                      && JUMP_LABEL (temp2) == JUMP_LABEL (insn)))
        !           851:              && (temp1 = single_set (temp)) != 0
        !           852:              && (temp2 = SET_DEST (temp1), GET_CODE (temp2) == REG)
        !           853:              && GET_MODE_CLASS (GET_MODE (temp2)) == MODE_INT
        !           854: #ifdef SMALL_REGISTER_CLASSES
        !           855:              && REGNO (temp2) >= FIRST_PSEUDO_REGISTER
        !           856: #endif
        !           857:              && GET_CODE (SET_SRC (temp1)) != REG
        !           858:              && GET_CODE (SET_SRC (temp1)) != SUBREG
        !           859:              && GET_CODE (SET_SRC (temp1)) != CONST_INT
        !           860:              && ! side_effects_p (SET_SRC (temp1))
        !           861:              && ! may_trap_p (SET_SRC (temp1))
        !           862:              && rtx_cost (SET_SRC (temp1)) < 10)
        !           863:            {
        !           864:              rtx new = gen_reg_rtx (GET_MODE (temp2));
        !           865: 
        !           866:              if (validate_change (temp, &SET_DEST (temp1), new, 0))
        !           867:                {
        !           868:                  next = emit_insn_after (gen_move_insn (temp2, new), insn);
        !           869:                  emit_insn_after_with_line_notes (PATTERN (temp), 
        !           870:                                                   PREV_INSN (insn), temp);
        !           871:                  delete_insn (temp);
        !           872:                }
        !           873:            }
        !           874: 
        !           875:          /* Similarly, if it takes two insns to compute EXP but they
        !           876:             have the same destination.  Here TEMP3 will be the second
        !           877:             insn and TEMP4 the SET from that insn.  */
        !           878: 
        !           879:          if (! reload_completed
        !           880:              && this_is_condjump && ! this_is_simplejump
        !           881:              && BRANCH_COST >= 4
        !           882:              && (temp = next_nonnote_insn (insn)) != 0
        !           883:              && GET_CODE (temp) == INSN
        !           884:              && REG_NOTES (temp) == 0
        !           885:              && (temp3 = next_nonnote_insn (temp)) != 0
        !           886:              && GET_CODE (temp3) == INSN
        !           887:              && REG_NOTES (temp3) == 0
        !           888:              && (reallabelprev == temp3
        !           889:                  || ((temp2 = next_active_insn (temp3)) != 0
        !           890:                      && simplejump_p (temp2)
        !           891:                      && JUMP_LABEL (temp2) == JUMP_LABEL (insn)))
        !           892:              && (temp1 = single_set (temp)) != 0
        !           893:              && (temp2 = SET_DEST (temp1), GET_CODE (temp2) == REG)
        !           894:              && GET_MODE_CLASS (GET_MODE (temp2)) == MODE_INT
        !           895: #ifdef SMALL_REGISTER_CLASSES
        !           896:              && REGNO (temp2) >= FIRST_PSEUDO_REGISTER
        !           897: #endif
        !           898:              && ! side_effects_p (SET_SRC (temp1))
        !           899:              && ! may_trap_p (SET_SRC (temp1))
        !           900:              && rtx_cost (SET_SRC (temp1)) < 10
        !           901:              && (temp4 = single_set (temp3)) != 0
        !           902:              && rtx_equal_p (SET_DEST (temp4), temp2)
        !           903:              && ! side_effects_p (SET_SRC (temp4))
        !           904:              && ! may_trap_p (SET_SRC (temp4))
        !           905:              && rtx_cost (SET_SRC (temp4)) < 10)
        !           906:            {
        !           907:              rtx new = gen_reg_rtx (GET_MODE (temp2));
        !           908: 
        !           909:              if (validate_change (temp, &SET_DEST (temp1), new, 0))
        !           910:                {
        !           911:                  next = emit_insn_after (gen_move_insn (temp2, new), insn);
        !           912:                  emit_insn_after_with_line_notes (PATTERN (temp),
        !           913:                                                   PREV_INSN (insn), temp);
        !           914:                  emit_insn_after_with_line_notes
        !           915:                    (replace_rtx (PATTERN (temp3), temp2, new),
        !           916:                     PREV_INSN (insn), temp3);
        !           917:                  delete_insn (temp);
        !           918:                  delete_insn (temp3);
        !           919:                }
        !           920:            }
        !           921: 
        !           922:          /* Finally, handle the case where two insns are used to 
        !           923:             compute EXP but a temporary register is used.  Here we must
        !           924:             ensure that the temporary register is not used anywhere else. */
        !           925: 
        !           926:          if (! reload_completed
        !           927:              && after_regscan
        !           928:              && this_is_condjump && ! this_is_simplejump
        !           929:              && BRANCH_COST >= 4
        !           930:              && (temp = next_nonnote_insn (insn)) != 0
        !           931:              && GET_CODE (temp) == INSN
        !           932:              && REG_NOTES (temp) == 0
        !           933:              && (temp3 = next_nonnote_insn (temp)) != 0
        !           934:              && GET_CODE (temp3) == INSN
        !           935:              && REG_NOTES (temp3) == 0
        !           936:              && (reallabelprev == temp3
        !           937:                  || ((temp2 = next_active_insn (temp3)) != 0
        !           938:                      && simplejump_p (temp2)
        !           939:                      && JUMP_LABEL (temp2) == JUMP_LABEL (insn)))
        !           940:              && (temp1 = single_set (temp)) != 0
        !           941:              && (temp5 = SET_DEST (temp1), GET_CODE (temp5) == REG)
        !           942:              && REGNO (temp5) >= FIRST_PSEUDO_REGISTER
        !           943:              && regno_first_uid[REGNO (temp5)] == INSN_UID (temp)
        !           944:              && regno_last_uid[REGNO (temp5)] == INSN_UID (temp3)
        !           945:              && ! side_effects_p (SET_SRC (temp1))
        !           946:              && ! may_trap_p (SET_SRC (temp1))
        !           947:              && rtx_cost (SET_SRC (temp1)) < 10
        !           948:              && (temp4 = single_set (temp3)) != 0
        !           949:              && (temp2 = SET_DEST (temp4), GET_CODE (temp2) == REG)
        !           950:              && GET_MODE_CLASS (GET_MODE (temp2)) == MODE_INT
        !           951: #ifdef SMALL_REGISTER_CLASSES
        !           952:              && REGNO (temp2) >= FIRST_PSEUDO_REGISTER
        !           953: #endif
        !           954:              && rtx_equal_p (SET_DEST (temp4), temp2)
        !           955:              && ! side_effects_p (SET_SRC (temp4))
        !           956:              && ! may_trap_p (SET_SRC (temp4))
        !           957:              && rtx_cost (SET_SRC (temp4)) < 10)
        !           958:            {
        !           959:              rtx new = gen_reg_rtx (GET_MODE (temp2));
        !           960: 
        !           961:              if (validate_change (temp3, &SET_DEST (temp4), new, 0))
        !           962:                {
        !           963:                  next = emit_insn_after (gen_move_insn (temp2, new), insn);
        !           964:                  emit_insn_after_with_line_notes (PATTERN (temp),
        !           965:                                                   PREV_INSN (insn), temp);
        !           966:                  emit_insn_after_with_line_notes (PATTERN (temp3),
        !           967:                                                   PREV_INSN (insn), temp3);
        !           968:                  delete_insn (temp);
        !           969:                  delete_insn (temp3);
        !           970:                }
        !           971:            }
        !           972: #endif /* HAVE_cc0 */
        !           973: 
        !           974:          /* We deal with four cases:
        !           975: 
        !           976:             1) x = a; if (...) x = b; and either A or B is zero,
        !           977:             2) if (...) x = 0; and jumps are expensive,
        !           978:             3) x = a; if (...) x = b; and A and B are constants where all the
        !           979:                set bits in A are also set in B and jumps are expensive, and
        !           980:             4) x = a; if (...) x = b; and A and B non-zero, and jumps are
        !           981:                more expensive.
        !           982:             5) if (...) x = b; if jumps are even more expensive.
        !           983: 
        !           984:             In each of these try to use a store-flag insn to avoid the jump.
        !           985:             (If the jump would be faster, the machine should not have
        !           986:             defined the scc insns!).  These cases are often made by the
        !           987:             previous optimization.
        !           988: 
        !           989:             INSN here is the jump around the store.  We set:
        !           990: 
        !           991:             TEMP to the "x = b;" insn.
        !           992:             TEMP1 to X.
        !           993:             TEMP2 to B (const0_rtx in the second case).
        !           994:             TEMP3 to A (X in the second case).
        !           995:             TEMP4 to the condition being tested.
        !           996:             TEMP5 to the earliest insn used to find the condition.  */
        !           997: 
        !           998:          if (/* We can't do this after reload has completed.  */
        !           999:              ! reload_completed
        !          1000:              && this_is_condjump && ! this_is_simplejump
        !          1001:              /* Set TEMP to the "x = b;" insn.  */
        !          1002:              && (temp = next_nonnote_insn (insn)) != 0
        !          1003:              && GET_CODE (temp) == INSN
        !          1004:              && GET_CODE (PATTERN (temp)) == SET
        !          1005:              && GET_CODE (temp1 = SET_DEST (PATTERN (temp))) == REG
        !          1006: #ifdef SMALL_REGISTER_CLASSES
        !          1007:              && REGNO (temp1) >= FIRST_PSEUDO_REGISTER
        !          1008: #endif
        !          1009:              && GET_MODE_CLASS (GET_MODE (temp1)) == MODE_INT
        !          1010:              && (GET_CODE (temp2 = SET_SRC (PATTERN (temp))) == REG
        !          1011:                  || GET_CODE (temp2) == SUBREG
        !          1012:                  || GET_CODE (temp2) == CONST_INT)
        !          1013:              /* Allow either form, but prefer the former if both apply. 
        !          1014:                 There is no point in using the old value of TEMP1 if
        !          1015:                 it is a register, since cse will alias them.  It can
        !          1016:                 lose if the old value were a hard register since CSE
        !          1017:                 won't replace hard registers.  */
        !          1018:              && (((temp3 = reg_set_last (temp1, insn)) != 0
        !          1019:                   && GET_CODE (temp3) == CONST_INT)
        !          1020:                  /* Make the latter case look like  x = x; if (...) x = 0;  */
        !          1021:                  || (temp3 = temp1,
        !          1022:                      ((BRANCH_COST >= 2
        !          1023:                        && temp2 == const0_rtx)
        !          1024: #ifdef HAVE_conditional_move
        !          1025:                       || 1
        !          1026: #endif
        !          1027:                       || BRANCH_COST >= 3)))
        !          1028:              /* INSN must either branch to the insn after TEMP or the insn
        !          1029:                 after TEMP must branch to the same place as INSN.  */
        !          1030:              && (reallabelprev == temp
        !          1031:                  || ((temp4 = next_active_insn (temp)) != 0
        !          1032:                      && simplejump_p (temp4)
        !          1033:                      && JUMP_LABEL (temp4) == JUMP_LABEL (insn)))
        !          1034:              && (temp4 = get_condition (insn, &temp5)) != 0
        !          1035:              /* We must be comparing objects whose modes imply the size.
        !          1036:                 We could handle BLKmode if (1) emit_store_flag could
        !          1037:                 and (2) we could find the size reliably.  */
        !          1038:              && GET_MODE (XEXP (temp4, 0)) != BLKmode
        !          1039: 
        !          1040:              /* If B is zero, OK; if A is zero, can only do (1) if we
        !          1041:                 can reverse the condition.  See if (3) applies possibly
        !          1042:                 by reversing the condition.  Prefer reversing to (4) when
        !          1043:                 branches are very expensive.  */
        !          1044:              && ((reversep = 0, temp2 == const0_rtx)
        !          1045:                  || (temp3 == const0_rtx
        !          1046:                      && (reversep = can_reverse_comparison_p (temp4, insn)))
        !          1047:                  || (BRANCH_COST >= 2
        !          1048:                      && GET_CODE (temp2) == CONST_INT
        !          1049:                      && GET_CODE (temp3) == CONST_INT
        !          1050:                      && ((INTVAL (temp2) & INTVAL (temp3)) == INTVAL (temp2)
        !          1051:                          || ((INTVAL (temp2) & INTVAL (temp3)) == INTVAL (temp3)
        !          1052:                              && (reversep = can_reverse_comparison_p (temp4,
        !          1053:                                                                       insn)))))
        !          1054: #ifdef HAVE_conditional_move
        !          1055:                  || 1
        !          1056: #endif
        !          1057:                  || BRANCH_COST >= 3)
        !          1058: #ifdef HAVE_cc0
        !          1059:              /* If the previous insn sets CC0 and something else, we can't
        !          1060:                 do this since we are going to delete that insn.  */
        !          1061: 
        !          1062:              && ! ((temp6 = prev_nonnote_insn (insn)) != 0
        !          1063:                    && GET_CODE (temp6) == INSN
        !          1064:                    && (sets_cc0_p (PATTERN (temp6)) == -1
        !          1065:                        || (sets_cc0_p (PATTERN (temp6)) == 1
        !          1066:                            && FIND_REG_INC_NOTE (temp6, NULL_RTX))))
        !          1067: #endif
        !          1068:              )
        !          1069:            {
        !          1070:              enum rtx_code code = GET_CODE (temp4);
        !          1071:              rtx uval, cval, var = temp1;
        !          1072:              int normalizep;
        !          1073:              rtx target;
        !          1074: 
        !          1075:              /* If necessary, reverse the condition.  */
        !          1076:              if (reversep)
        !          1077:                code = reverse_condition (code), uval = temp2, cval = temp3;
        !          1078:              else
        !          1079:                uval = temp3, cval = temp2;
        !          1080: 
        !          1081:              /* See if we can do this with a store-flag insn. */
        !          1082:              start_sequence ();
        !          1083: 
        !          1084:              /* If CVAL is non-zero, normalize to -1.  Otherwise,
        !          1085:                 if UVAL is the constant 1, it is best to just compute
        !          1086:                 the result directly.  If UVAL is constant and STORE_FLAG_VALUE
        !          1087:                 includes all of its bits, it is best to compute the flag
        !          1088:                 value unnormalized and `and' it with UVAL.  Otherwise,
        !          1089:                 normalize to -1 and `and' with UVAL.  */
        !          1090:              normalizep = (cval != const0_rtx ? -1
        !          1091:                            : (uval == const1_rtx ? 1
        !          1092:                               : (GET_CODE (uval) == CONST_INT
        !          1093:                                  && (INTVAL (uval) & ~STORE_FLAG_VALUE) == 0)
        !          1094:                               ? 0 : -1));
        !          1095: 
        !          1096:              /* We will be putting the store-flag insn immediately in
        !          1097:                 front of the comparison that was originally being done,
        !          1098:                 so we know all the variables in TEMP4 will be valid.
        !          1099:                 However, this might be in front of the assignment of
        !          1100:                 A to VAR.  If it is, it would clobber the store-flag
        !          1101:                 we will be emitting.
        !          1102: 
        !          1103:                 Therefore, emit into a temporary which will be copied to
        !          1104:                 VAR immediately after TEMP.  */
        !          1105: 
        !          1106:              target = emit_store_flag (gen_reg_rtx (GET_MODE (var)), code,
        !          1107:                                        XEXP (temp4, 0), XEXP (temp4, 1),
        !          1108:                                        VOIDmode,
        !          1109:                                        (code == LTU || code == LEU 
        !          1110:                                         || code == GEU || code == GTU),
        !          1111:                                        normalizep);
        !          1112:              if (target)
        !          1113:                {
        !          1114:                  rtx before = insn;
        !          1115:                  rtx seq;
        !          1116: 
        !          1117:                  /* Put the store-flag insns in front of the first insn
        !          1118:                     used to compute the condition to ensure that we
        !          1119:                     use the same values of them as the current 
        !          1120:                     comparison.  However, the remainder of the insns we
        !          1121:                     generate will be placed directly in front of the
        !          1122:                     jump insn, in case any of the pseudos we use
        !          1123:                     are modified earlier.  */
        !          1124: 
        !          1125:                  seq = get_insns ();
        !          1126:                  end_sequence ();
        !          1127: 
        !          1128:                  emit_insns_before (seq, temp5);
        !          1129: 
        !          1130:                  start_sequence ();
        !          1131: 
        !          1132:                  /* Both CVAL and UVAL are non-zero.  */
        !          1133:                  if (cval != const0_rtx && uval != const0_rtx)
        !          1134:                    {
        !          1135:                      rtx tem1, tem2;
        !          1136: 
        !          1137:                      tem1 = expand_and (uval, target, NULL_RTX);
        !          1138:                      if (GET_CODE (cval) == CONST_INT
        !          1139:                          && GET_CODE (uval) == CONST_INT
        !          1140:                          && (INTVAL (cval) & INTVAL (uval)) == INTVAL (cval))
        !          1141:                        tem2 = cval;
        !          1142:                      else
        !          1143:                        {
        !          1144:                          tem2 = expand_unop (GET_MODE (var), one_cmpl_optab,
        !          1145:                                              target, NULL_RTX, 0);
        !          1146:                          tem2 = expand_and (cval, tem2,
        !          1147:                                             (GET_CODE (tem2) == REG
        !          1148:                                              ? tem2 : 0));
        !          1149:                        }
        !          1150: 
        !          1151:                      /* If we usually make new pseudos, do so here.  This
        !          1152:                         turns out to help machines that have conditional
        !          1153:                         move insns.  */
        !          1154: 
        !          1155:                      if (flag_expensive_optimizations)
        !          1156:                        target = 0;
        !          1157: 
        !          1158:                      target = expand_binop (GET_MODE (var), ior_optab,
        !          1159:                                             tem1, tem2, target,
        !          1160:                                             1, OPTAB_WIDEN);
        !          1161:                    }
        !          1162:                  else if (normalizep != 1)
        !          1163:                    {
        !          1164:                      /* We know that either CVAL or UVAL is zero.  If
        !          1165:                         UVAL is zero, negate TARGET and `and' with CVAL.
        !          1166:                         Otherwise, `and' with UVAL.  */
        !          1167:                      if (uval == const0_rtx)
        !          1168:                        {
        !          1169:                          target = expand_unop (GET_MODE (var), one_cmpl_optab,
        !          1170:                                                target, NULL_RTX, 0);
        !          1171:                          uval = cval;
        !          1172:                        }
        !          1173: 
        !          1174:                      target = expand_and (uval, target,
        !          1175:                                           (GET_CODE (target) == REG
        !          1176:                                            && ! preserve_subexpressions_p ()
        !          1177:                                            ? target : NULL_RTX));
        !          1178:                    }
        !          1179:                  
        !          1180:                  emit_move_insn (var, target);
        !          1181:                  seq = get_insns ();
        !          1182:                  end_sequence ();
        !          1183: 
        !          1184: #ifdef HAVE_cc0
        !          1185:                  /* If INSN uses CC0, we must not separate it from the
        !          1186:                     insn that sets cc0.  */
        !          1187: 
        !          1188:                  if (reg_mentioned_p (cc0_rtx, PATTERN (before)))
        !          1189:                    before = prev_nonnote_insn (before);
        !          1190: #endif
        !          1191: 
        !          1192:                  emit_insns_before (seq, before);
        !          1193: 
        !          1194:                  delete_insn (temp);
        !          1195:                  next = NEXT_INSN (insn);
        !          1196: 
        !          1197:                  delete_jump (insn);
        !          1198:                  changed = 1;
        !          1199:                  continue;
        !          1200:                }
        !          1201:              else
        !          1202:                end_sequence ();
        !          1203:            }
        !          1204: 
        !          1205:          /* If branches are expensive, convert
        !          1206:                if (foo) bar++;    to    bar += (foo != 0);
        !          1207:             and similarly for "bar--;" 
        !          1208: 
        !          1209:             INSN is the conditional branch around the arithmetic.  We set:
        !          1210: 
        !          1211:             TEMP is the arithmetic insn.
        !          1212:             TEMP1 is the SET doing the arithmetic.
        !          1213:             TEMP2 is the operand being incremented or decremented.
        !          1214:             TEMP3 to the condition being tested.
        !          1215:             TEMP4 to the earliest insn used to find the condition.  */
        !          1216: 
        !          1217:          if ((BRANCH_COST >= 2
        !          1218: #ifdef HAVE_incscc
        !          1219:               || HAVE_incscc
        !          1220: #endif
        !          1221: #ifdef HAVE_decscc
        !          1222:               || HAVE_decscc
        !          1223: #endif
        !          1224:              )
        !          1225:              && ! reload_completed
        !          1226:              && this_is_condjump && ! this_is_simplejump
        !          1227:              && (temp = next_nonnote_insn (insn)) != 0
        !          1228:              && (temp1 = single_set (temp)) != 0
        !          1229:              && (temp2 = SET_DEST (temp1),
        !          1230:                  GET_MODE_CLASS (GET_MODE (temp2)) == MODE_INT)
        !          1231:              && GET_CODE (SET_SRC (temp1)) == PLUS
        !          1232:              && (XEXP (SET_SRC (temp1), 1) == const1_rtx
        !          1233:                  || XEXP (SET_SRC (temp1), 1) == constm1_rtx)
        !          1234:              && rtx_equal_p (temp2, XEXP (SET_SRC (temp1), 0))
        !          1235:              /* INSN must either branch to the insn after TEMP or the insn
        !          1236:                 after TEMP must branch to the same place as INSN.  */
        !          1237:              && (reallabelprev == temp
        !          1238:                  || ((temp3 = next_active_insn (temp)) != 0
        !          1239:                      && simplejump_p (temp3)
        !          1240:                      && JUMP_LABEL (temp3) == JUMP_LABEL (insn)))
        !          1241:              && (temp3 = get_condition (insn, &temp4)) != 0
        !          1242:              /* We must be comparing objects whose modes imply the size.
        !          1243:                 We could handle BLKmode if (1) emit_store_flag could
        !          1244:                 and (2) we could find the size reliably.  */
        !          1245:              && GET_MODE (XEXP (temp3, 0)) != BLKmode
        !          1246:              && can_reverse_comparison_p (temp3, insn))
        !          1247:            {
        !          1248:              rtx temp6, target = 0, seq, init_insn = 0, init = temp2;
        !          1249:              enum rtx_code code = reverse_condition (GET_CODE (temp3));
        !          1250: 
        !          1251:              start_sequence ();
        !          1252: 
        !          1253:              /* It must be the case that TEMP2 is not modified in the range
        !          1254:                 [TEMP4, INSN).  The one exception we make is if the insn
        !          1255:                 before INSN sets TEMP2 to something which is also unchanged
        !          1256:                 in that range.  In that case, we can move the initialization
        !          1257:                 into our sequence.  */
        !          1258: 
        !          1259:              if ((temp5 = prev_active_insn (insn)) != 0
        !          1260:                  && GET_CODE (temp5) == INSN
        !          1261:                  && (temp6 = single_set (temp5)) != 0
        !          1262:                  && rtx_equal_p (temp2, SET_DEST (temp6))
        !          1263:                  && (CONSTANT_P (SET_SRC (temp6))
        !          1264:                      || GET_CODE (SET_SRC (temp6)) == REG
        !          1265:                      || GET_CODE (SET_SRC (temp6)) == SUBREG))
        !          1266:                {
        !          1267:                  emit_insn (PATTERN (temp5));
        !          1268:                  init_insn = temp5;
        !          1269:                  init = SET_SRC (temp6);
        !          1270:                }
        !          1271: 
        !          1272:              if (CONSTANT_P (init)
        !          1273:                  || ! reg_set_between_p (init, PREV_INSN (temp4), insn))
        !          1274:                target = emit_store_flag (gen_reg_rtx (GET_MODE (temp2)), code,
        !          1275:                                          XEXP (temp3, 0), XEXP (temp3, 1),
        !          1276:                                          VOIDmode,
        !          1277:                                          (code == LTU || code == LEU
        !          1278:                                           || code == GTU || code == GEU), 1);
        !          1279: 
        !          1280:              /* If we can do the store-flag, do the addition or
        !          1281:                 subtraction.  */
        !          1282: 
        !          1283:              if (target)
        !          1284:                target = expand_binop (GET_MODE (temp2),
        !          1285:                                       (XEXP (SET_SRC (temp1), 1) == const1_rtx
        !          1286:                                        ? add_optab : sub_optab),
        !          1287:                                       temp2, target, temp2, 0, OPTAB_WIDEN);
        !          1288: 
        !          1289:              if (target != 0)
        !          1290:                {
        !          1291:                  /* Put the result back in temp2 in case it isn't already.
        !          1292:                     Then replace the jump, possible a CC0-setting insn in
        !          1293:                     front of the jump, and TEMP, with the sequence we have
        !          1294:                     made.  */
        !          1295: 
        !          1296:                  if (target != temp2)
        !          1297:                    emit_move_insn (temp2, target);
        !          1298: 
        !          1299:                  seq = get_insns ();
        !          1300:                  end_sequence ();
        !          1301: 
        !          1302:                  emit_insns_before (seq, temp4);
        !          1303:                  delete_insn (temp);
        !          1304: 
        !          1305:                  if (init_insn)
        !          1306:                    delete_insn (init_insn);
        !          1307: 
        !          1308:                  next = NEXT_INSN (insn);
        !          1309: #ifdef HAVE_cc0
        !          1310:                  delete_insn (prev_nonnote_insn (insn));
        !          1311: #endif
        !          1312:                  delete_insn (insn);
        !          1313:                  changed = 1;
        !          1314:                  continue;
        !          1315:                }
        !          1316:              else
        !          1317:                end_sequence ();
        !          1318:            }
        !          1319: 
        !          1320:          /* Simplify   if (...) x = 1; else {...}  if (x) ...
        !          1321:             We recognize this case scanning backwards as well.
        !          1322: 
        !          1323:             TEMP is the assignment to x;
        !          1324:             TEMP1 is the label at the head of the second if.  */
        !          1325:          /* ?? This should call get_condition to find the values being
        !          1326:             compared, instead of looking for a COMPARE insn when HAVE_cc0
        !          1327:             is not defined.  This would allow it to work on the m88k.  */
        !          1328:          /* ?? This optimization is only safe before cse is run if HAVE_cc0
        !          1329:             is not defined and the condition is tested by a separate compare
        !          1330:             insn.  This is because the code below assumes that the result
        !          1331:             of the compare dies in the following branch.
        !          1332: 
        !          1333:             Not only that, but there might be other insns between the
        !          1334:             compare and branch whose results are live.  Those insns need
        !          1335:             to be executed.
        !          1336: 
        !          1337:             A way to fix this is to move the insns at JUMP_LABEL (insn)
        !          1338:             to before INSN.  If we are running before flow, they will
        !          1339:             be deleted if they aren't needed.   But this doesn't work
        !          1340:             well after flow.
        !          1341: 
        !          1342:             This is really a special-case of jump threading, anyway.  The
        !          1343:             right thing to do is to replace this and jump threading with
        !          1344:             much simpler code in cse.
        !          1345: 
        !          1346:             This code has been turned off in the non-cc0 case in the
        !          1347:             meantime.  */
        !          1348: 
        !          1349: #ifdef HAVE_cc0
        !          1350:          else if (this_is_simplejump
        !          1351:                   /* Safe to skip USE and CLOBBER insns here
        !          1352:                      since they will not be deleted.  */
        !          1353:                   && (temp = prev_active_insn (insn))
        !          1354:                   && no_labels_between_p (temp, insn)
        !          1355:                   && GET_CODE (temp) == INSN
        !          1356:                   && GET_CODE (PATTERN (temp)) == SET
        !          1357:                   && GET_CODE (SET_DEST (PATTERN (temp))) == REG
        !          1358:                   && CONSTANT_P (SET_SRC (PATTERN (temp)))
        !          1359:                   && (temp1 = next_active_insn (JUMP_LABEL (insn)))
        !          1360:                   /* If we find that the next value tested is `x'
        !          1361:                      (TEMP1 is the insn where this happens), win.  */
        !          1362:                   && GET_CODE (temp1) == INSN
        !          1363:                   && GET_CODE (PATTERN (temp1)) == SET
        !          1364: #ifdef HAVE_cc0
        !          1365:                   /* Does temp1 `tst' the value of x?  */
        !          1366:                   && SET_SRC (PATTERN (temp1)) == SET_DEST (PATTERN (temp))
        !          1367:                   && SET_DEST (PATTERN (temp1)) == cc0_rtx
        !          1368:                   && (temp1 = next_nonnote_insn (temp1))
        !          1369: #else
        !          1370:                   /* Does temp1 compare the value of x against zero?  */
        !          1371:                   && GET_CODE (SET_SRC (PATTERN (temp1))) == COMPARE
        !          1372:                   && XEXP (SET_SRC (PATTERN (temp1)), 1) == const0_rtx
        !          1373:                   && (XEXP (SET_SRC (PATTERN (temp1)), 0)
        !          1374:                       == SET_DEST (PATTERN (temp)))
        !          1375:                   && GET_CODE (SET_DEST (PATTERN (temp1))) == REG
        !          1376:                   && (temp1 = find_next_ref (SET_DEST (PATTERN (temp1)), temp1))
        !          1377: #endif
        !          1378:                   && condjump_p (temp1))
        !          1379:            {
        !          1380:              /* Get the if_then_else from the condjump.  */
        !          1381:              rtx choice = SET_SRC (PATTERN (temp1));
        !          1382:              if (GET_CODE (choice) == IF_THEN_ELSE)
        !          1383:                {
        !          1384:                  enum rtx_code code = GET_CODE (XEXP (choice, 0));
        !          1385:                  rtx val = SET_SRC (PATTERN (temp));
        !          1386:                  rtx cond
        !          1387:                    = simplify_relational_operation (code, GET_MODE (SET_DEST (PATTERN (temp))),
        !          1388:                                                     val, const0_rtx);
        !          1389:                  rtx ultimate;
        !          1390: 
        !          1391:                  if (cond == const_true_rtx)
        !          1392:                    ultimate = XEXP (choice, 1);
        !          1393:                  else if (cond == const0_rtx)
        !          1394:                    ultimate = XEXP (choice, 2);
        !          1395:                  else
        !          1396:                    ultimate = 0;
        !          1397: 
        !          1398:                  if (ultimate == pc_rtx)
        !          1399:                    ultimate = get_label_after (temp1);
        !          1400:                  else if (ultimate && GET_CODE (ultimate) != RETURN)
        !          1401:                    ultimate = XEXP (ultimate, 0);
        !          1402: 
        !          1403:                  if (ultimate)
        !          1404:                    changed |= redirect_jump (insn, ultimate);
        !          1405:                }
        !          1406:            }
        !          1407: #endif
        !          1408: 
        !          1409: #if 0
        !          1410:          /* @@ This needs a bit of work before it will be right.
        !          1411: 
        !          1412:             Any type of comparison can be accepted for the first and
        !          1413:             second compare.  When rewriting the first jump, we must
        !          1414:             compute the what conditions can reach label3, and use the
        !          1415:             appropriate code.  We can not simply reverse/swap the code
        !          1416:             of the first jump.  In some cases, the second jump must be
        !          1417:             rewritten also.
        !          1418: 
        !          1419:             For example, 
        !          1420:             <  == converts to >  ==
        !          1421:             <  != converts to ==  >
        !          1422:             etc.
        !          1423: 
        !          1424:             If the code is written to only accept an '==' test for the second
        !          1425:             compare, then all that needs to be done is to swap the condition
        !          1426:             of the first branch.
        !          1427: 
        !          1428:             It is questionable whether we want this optimization anyways,
        !          1429:             since if the user wrote code like this because he/she knew that
        !          1430:             the jump to label1 is taken most of the time, then rewriting
        !          1431:             this gives slower code.  */
        !          1432:          /* @@ This should call get_condition to find the values being
        !          1433:             compared, instead of looking for a COMPARE insn when HAVE_cc0
        !          1434:             is not defined.  This would allow it to work on the m88k.  */
        !          1435:          /* @@ This optimization is only safe before cse is run if HAVE_cc0
        !          1436:             is not defined and the condition is tested by a separate compare
        !          1437:             insn.  This is because the code below assumes that the result
        !          1438:             of the compare dies in the following branch.  */
        !          1439: 
        !          1440:          /* Simplify  test a ~= b
        !          1441:                       condjump label1;
        !          1442:                       test a == b
        !          1443:                       condjump label2;
        !          1444:                       jump label3;
        !          1445:                       label1:
        !          1446: 
        !          1447:             rewriting as
        !          1448:                       test a ~~= b
        !          1449:                       condjump label3
        !          1450:                       test a == b
        !          1451:                       condjump label2
        !          1452:                       label1:
        !          1453: 
        !          1454:             where ~= is an inequality, e.g. >, and ~~= is the swapped
        !          1455:             inequality, e.g. <.
        !          1456: 
        !          1457:             We recognize this case scanning backwards.
        !          1458: 
        !          1459:             TEMP is the conditional jump to `label2';
        !          1460:             TEMP1 is the test for `a == b';
        !          1461:             TEMP2 is the conditional jump to `label1';
        !          1462:             TEMP3 is the test for `a ~= b'.  */
        !          1463:          else if (this_is_simplejump
        !          1464:                   && (temp = prev_active_insn (insn))
        !          1465:                   && no_labels_between_p (temp, insn)
        !          1466:                   && condjump_p (temp)
        !          1467:                   && (temp1 = prev_active_insn (temp))
        !          1468:                   && no_labels_between_p (temp1, temp)
        !          1469:                   && GET_CODE (temp1) == INSN
        !          1470:                   && GET_CODE (PATTERN (temp1)) == SET
        !          1471: #ifdef HAVE_cc0
        !          1472:                   && sets_cc0_p (PATTERN (temp1)) == 1
        !          1473: #else
        !          1474:                   && GET_CODE (SET_SRC (PATTERN (temp1))) == COMPARE
        !          1475:                   && GET_CODE (SET_DEST (PATTERN (temp1))) == REG
        !          1476:                   && (temp == find_next_ref (SET_DEST (PATTERN (temp1)), temp1))
        !          1477: #endif
        !          1478:                   && (temp2 = prev_active_insn (temp1))
        !          1479:                   && no_labels_between_p (temp2, temp1)
        !          1480:                   && condjump_p (temp2)
        !          1481:                   && JUMP_LABEL (temp2) == next_nonnote_insn (NEXT_INSN (insn))
        !          1482:                   && (temp3 = prev_active_insn (temp2))
        !          1483:                   && no_labels_between_p (temp3, temp2)
        !          1484:                   && GET_CODE (PATTERN (temp3)) == SET
        !          1485:                   && rtx_equal_p (SET_DEST (PATTERN (temp3)),
        !          1486:                                   SET_DEST (PATTERN (temp1)))
        !          1487:                   && rtx_equal_p (SET_SRC (PATTERN (temp1)),
        !          1488:                                   SET_SRC (PATTERN (temp3)))
        !          1489:                   && ! inequality_comparisons_p (PATTERN (temp))
        !          1490:                   && inequality_comparisons_p (PATTERN (temp2)))
        !          1491:            {
        !          1492:              rtx fallthrough_label = JUMP_LABEL (temp2);
        !          1493: 
        !          1494:              ++LABEL_NUSES (fallthrough_label);
        !          1495:              if (swap_jump (temp2, JUMP_LABEL (insn)))
        !          1496:                {
        !          1497:                  delete_insn (insn);
        !          1498:                  changed = 1;
        !          1499:                }
        !          1500: 
        !          1501:              if (--LABEL_NUSES (fallthrough_label) == 0)
        !          1502:                delete_insn (fallthrough_label);
        !          1503:            }
        !          1504: #endif
        !          1505:          /* Simplify  if (...) {... x = 1;} if (x) ...
        !          1506: 
        !          1507:             We recognize this case backwards.
        !          1508: 
        !          1509:             TEMP is the test of `x';
        !          1510:             TEMP1 is the assignment to `x' at the end of the
        !          1511:             previous statement.  */
        !          1512:          /* @@ This should call get_condition to find the values being
        !          1513:             compared, instead of looking for a COMPARE insn when HAVE_cc0
        !          1514:             is not defined.  This would allow it to work on the m88k.  */
        !          1515:          /* @@ This optimization is only safe before cse is run if HAVE_cc0
        !          1516:             is not defined and the condition is tested by a separate compare
        !          1517:             insn.  This is because the code below assumes that the result
        !          1518:             of the compare dies in the following branch.  */
        !          1519: 
        !          1520:          /* ??? This has to be turned off.  The problem is that the
        !          1521:             unconditional jump might indirectly end up branching to the
        !          1522:             label between TEMP1 and TEMP.  We can't detect this, in general,
        !          1523:             since it may become a jump to there after further optimizations.
        !          1524:             If that jump is done, it will be deleted, so we will retry
        !          1525:             this optimization in the next pass, thus an infinite loop.
        !          1526: 
        !          1527:             The present code prevents this by putting the jump after the
        !          1528:             label, but this is not logically correct.  */
        !          1529: #if 0
        !          1530:          else if (this_is_condjump
        !          1531:                   /* Safe to skip USE and CLOBBER insns here
        !          1532:                      since they will not be deleted.  */
        !          1533:                   && (temp = prev_active_insn (insn))
        !          1534:                   && no_labels_between_p (temp, insn)
        !          1535:                   && GET_CODE (temp) == INSN
        !          1536:                   && GET_CODE (PATTERN (temp)) == SET
        !          1537: #ifdef HAVE_cc0
        !          1538:                   && sets_cc0_p (PATTERN (temp)) == 1
        !          1539:                   && GET_CODE (SET_SRC (PATTERN (temp))) == REG
        !          1540: #else
        !          1541:                   /* Temp must be a compare insn, we can not accept a register
        !          1542:                      to register move here, since it may not be simply a
        !          1543:                      tst insn.  */
        !          1544:                   && GET_CODE (SET_SRC (PATTERN (temp))) == COMPARE
        !          1545:                   && XEXP (SET_SRC (PATTERN (temp)), 1) == const0_rtx
        !          1546:                   && GET_CODE (XEXP (SET_SRC (PATTERN (temp)), 0)) == REG
        !          1547:                   && GET_CODE (SET_DEST (PATTERN (temp))) == REG
        !          1548:                   && insn == find_next_ref (SET_DEST (PATTERN (temp)), temp)
        !          1549: #endif
        !          1550:                   /* May skip USE or CLOBBER insns here
        !          1551:                      for checking for opportunity, since we
        !          1552:                      take care of them later.  */
        !          1553:                   && (temp1 = prev_active_insn (temp))
        !          1554:                   && GET_CODE (temp1) == INSN
        !          1555:                   && GET_CODE (PATTERN (temp1)) == SET
        !          1556: #ifdef HAVE_cc0
        !          1557:                   && SET_SRC (PATTERN (temp)) == SET_DEST (PATTERN (temp1))
        !          1558: #else
        !          1559:                   && (XEXP (SET_SRC (PATTERN (temp)), 0)
        !          1560:                       == SET_DEST (PATTERN (temp1)))
        !          1561: #endif
        !          1562:                   && CONSTANT_P (SET_SRC (PATTERN (temp1)))
        !          1563:                   /* If this isn't true, cse will do the job.  */
        !          1564:                   && ! no_labels_between_p (temp1, temp))
        !          1565:            {
        !          1566:              /* Get the if_then_else from the condjump.  */
        !          1567:              rtx choice = SET_SRC (PATTERN (insn));
        !          1568:              if (GET_CODE (choice) == IF_THEN_ELSE
        !          1569:                  && (GET_CODE (XEXP (choice, 0)) == EQ
        !          1570:                      || GET_CODE (XEXP (choice, 0)) == NE))
        !          1571:                {
        !          1572:                  int want_nonzero = (GET_CODE (XEXP (choice, 0)) == NE);
        !          1573:                  rtx last_insn;
        !          1574:                  rtx ultimate;
        !          1575:                  rtx p;
        !          1576: 
        !          1577:                  /* Get the place that condjump will jump to
        !          1578:                     if it is reached from here.  */
        !          1579:                  if ((SET_SRC (PATTERN (temp1)) != const0_rtx)
        !          1580:                      == want_nonzero)
        !          1581:                    ultimate = XEXP (choice, 1);
        !          1582:                  else
        !          1583:                    ultimate = XEXP (choice, 2);
        !          1584:                  /* Get it as a CODE_LABEL.  */
        !          1585:                  if (ultimate == pc_rtx)
        !          1586:                    ultimate = get_label_after (insn);
        !          1587:                  else
        !          1588:                    /* Get the label out of the LABEL_REF.  */
        !          1589:                    ultimate = XEXP (ultimate, 0);
        !          1590: 
        !          1591:                  /* Insert the jump immediately before TEMP, specifically
        !          1592:                     after the label that is between TEMP1 and TEMP.  */
        !          1593:                  last_insn = PREV_INSN (temp);
        !          1594: 
        !          1595:                  /* If we would be branching to the next insn, the jump
        !          1596:                     would immediately be deleted and the re-inserted in
        !          1597:                     a subsequent pass over the code.  So don't do anything
        !          1598:                     in that case.  */
        !          1599:                  if (next_active_insn (last_insn)
        !          1600:                      != next_active_insn (ultimate))
        !          1601:                    {
        !          1602:                      emit_barrier_after (last_insn);
        !          1603:                      p = emit_jump_insn_after (gen_jump (ultimate),
        !          1604:                                                last_insn);
        !          1605:                      JUMP_LABEL (p) = ultimate;
        !          1606:                      ++LABEL_NUSES (ultimate);
        !          1607:                      if (INSN_UID (ultimate) < max_jump_chain
        !          1608:                          && INSN_CODE (p) < max_jump_chain)
        !          1609:                        {
        !          1610:                          jump_chain[INSN_UID (p)]
        !          1611:                            = jump_chain[INSN_UID (ultimate)];
        !          1612:                          jump_chain[INSN_UID (ultimate)] = p;
        !          1613:                        }
        !          1614:                      changed = 1;
        !          1615:                      continue;
        !          1616:                    }
        !          1617:                }
        !          1618:            }
        !          1619: #endif
        !          1620:          /* Detect a conditional jump going to the same place
        !          1621:             as an immediately following unconditional jump.  */
        !          1622:          else if (this_is_condjump
        !          1623:                   && (temp = next_active_insn (insn)) != 0
        !          1624:                   && simplejump_p (temp)
        !          1625:                   && (next_active_insn (JUMP_LABEL (insn))
        !          1626:                       == next_active_insn (JUMP_LABEL (temp))))
        !          1627:            {
        !          1628:              delete_jump (insn);
        !          1629:              changed = 1;
        !          1630:              continue;
        !          1631:            }
        !          1632:          /* Detect a conditional jump jumping over an unconditional jump.  */
        !          1633: 
        !          1634:          else if (this_is_condjump && ! this_is_simplejump
        !          1635:                   && reallabelprev != 0
        !          1636:                   && GET_CODE (reallabelprev) == JUMP_INSN
        !          1637:                   && prev_active_insn (reallabelprev) == insn
        !          1638:                   && no_labels_between_p (insn, reallabelprev)
        !          1639:                   && simplejump_p (reallabelprev))
        !          1640:            {
        !          1641:              /* When we invert the unconditional jump, we will be
        !          1642:                 decrementing the usage count of its old label.
        !          1643:                 Make sure that we don't delete it now because that
        !          1644:                 might cause the following code to be deleted.  */
        !          1645:              rtx prev_uses = prev_nonnote_insn (reallabelprev);
        !          1646:              rtx prev_label = JUMP_LABEL (insn);
        !          1647: 
        !          1648:              if (prev_label)
        !          1649:                ++LABEL_NUSES (prev_label);
        !          1650: 
        !          1651:              if (invert_jump (insn, JUMP_LABEL (reallabelprev)))
        !          1652:                {
        !          1653:                  /* It is very likely that if there are USE insns before
        !          1654:                     this jump, they hold REG_DEAD notes.  These REG_DEAD
        !          1655:                     notes are no longer valid due to this optimization,
        !          1656:                     and will cause the life-analysis that following passes
        !          1657:                     (notably delayed-branch scheduling) to think that
        !          1658:                     these registers are dead when they are not.
        !          1659: 
        !          1660:                     To prevent this trouble, we just remove the USE insns
        !          1661:                     from the insn chain.  */
        !          1662: 
        !          1663:                  while (prev_uses && GET_CODE (prev_uses) == INSN
        !          1664:                         && GET_CODE (PATTERN (prev_uses)) == USE)
        !          1665:                    {
        !          1666:                      rtx useless = prev_uses;
        !          1667:                      prev_uses = prev_nonnote_insn (prev_uses);
        !          1668:                      delete_insn (useless);
        !          1669:                    }
        !          1670: 
        !          1671:                  delete_insn (reallabelprev);
        !          1672:                  next = insn;
        !          1673:                  changed = 1;
        !          1674:                }
        !          1675: 
        !          1676:              /* We can now safely delete the label if it is unreferenced
        !          1677:                 since the delete_insn above has deleted the BARRIER.  */
        !          1678:              if (prev_label && --LABEL_NUSES (prev_label) == 0)
        !          1679:                delete_insn (prev_label);
        !          1680:              continue;
        !          1681:            }
        !          1682:          else
        !          1683:            {
        !          1684:              /* Detect a jump to a jump.  */
        !          1685: 
        !          1686:              nlabel = follow_jumps (JUMP_LABEL (insn));
        !          1687:              if (nlabel != JUMP_LABEL (insn)
        !          1688:                  && redirect_jump (insn, nlabel))
        !          1689:                {
        !          1690:                  changed = 1;
        !          1691:                  next = insn;
        !          1692:                }
        !          1693: 
        !          1694:              /* Look for   if (foo) bar; else break;  */
        !          1695:              /* The insns look like this:
        !          1696:                 insn = condjump label1;
        !          1697:                 ...range1 (some insns)...
        !          1698:                 jump label2;
        !          1699:                 label1:
        !          1700:                 ...range2 (some insns)...
        !          1701:                 jump somewhere unconditionally
        !          1702:                 label2:  */
        !          1703:              {
        !          1704:                rtx label1 = next_label (insn);
        !          1705:                rtx range1end = label1 ? prev_active_insn (label1) : 0;
        !          1706:                /* Don't do this optimization on the first round, so that
        !          1707:                   jump-around-a-jump gets simplified before we ask here
        !          1708:                   whether a jump is unconditional.
        !          1709: 
        !          1710:                   Also don't do it when we are called after reload since
        !          1711:                   it will confuse reorg.  */
        !          1712:                if (! first
        !          1713:                    && (reload_completed ? ! flag_delayed_branch : 1)
        !          1714:                    /* Make sure INSN is something we can invert.  */
        !          1715:                    && condjump_p (insn)
        !          1716:                    && label1 != 0
        !          1717:                    && JUMP_LABEL (insn) == label1
        !          1718:                    && LABEL_NUSES (label1) == 1
        !          1719:                    && GET_CODE (range1end) == JUMP_INSN
        !          1720:                    && simplejump_p (range1end))
        !          1721:                  {
        !          1722:                    rtx label2 = next_label (label1);
        !          1723:                    rtx range2end = label2 ? prev_active_insn (label2) : 0;
        !          1724:                    if (range1end != range2end
        !          1725:                        && JUMP_LABEL (range1end) == label2
        !          1726:                        && GET_CODE (range2end) == JUMP_INSN
        !          1727:                        && GET_CODE (NEXT_INSN (range2end)) == BARRIER
        !          1728:                        /* Invert the jump condition, so we
        !          1729:                           still execute the same insns in each case.  */
        !          1730:                        && invert_jump (insn, label1))
        !          1731:                      {
        !          1732:                        rtx range1beg = next_active_insn (insn);
        !          1733:                        rtx range2beg = next_active_insn (label1);
        !          1734:                        rtx range1after, range2after;
        !          1735:                        rtx range1before, range2before;
        !          1736: 
        !          1737:                        /* Include in each range any notes before it, to be
        !          1738:                           sure that we get the line number note if any, even
        !          1739:                           if there are other notes here.  */
        !          1740:                        while (PREV_INSN (range1beg)
        !          1741:                               && GET_CODE (PREV_INSN (range1beg)) == NOTE)
        !          1742:                          range1beg = PREV_INSN (range1beg);
        !          1743: 
        !          1744:                        while (PREV_INSN (range2beg)
        !          1745:                               && GET_CODE (PREV_INSN (range2beg)) == NOTE)
        !          1746:                          range2beg = PREV_INSN (range2beg);
        !          1747: 
        !          1748:                        /* Don't move NOTEs for blocks or loops; shift them
        !          1749:                           outside the ranges, where they'll stay put.  */
        !          1750:                        range1beg = squeeze_notes (range1beg, range1end);
        !          1751:                        range2beg = squeeze_notes (range2beg, range2end);
        !          1752: 
        !          1753:                        /* Get current surrounds of the 2 ranges.  */
        !          1754:                        range1before = PREV_INSN (range1beg);
        !          1755:                        range2before = PREV_INSN (range2beg);
        !          1756:                        range1after = NEXT_INSN (range1end);
        !          1757:                        range2after = NEXT_INSN (range2end);
        !          1758: 
        !          1759:                        /* Splice range2 where range1 was.  */
        !          1760:                        NEXT_INSN (range1before) = range2beg;
        !          1761:                        PREV_INSN (range2beg) = range1before;
        !          1762:                        NEXT_INSN (range2end) = range1after;
        !          1763:                        PREV_INSN (range1after) = range2end;
        !          1764:                        /* Splice range1 where range2 was.  */
        !          1765:                        NEXT_INSN (range2before) = range1beg;
        !          1766:                        PREV_INSN (range1beg) = range2before;
        !          1767:                        NEXT_INSN (range1end) = range2after;
        !          1768:                        PREV_INSN (range2after) = range1end;
        !          1769:                        changed = 1;
        !          1770:                        continue;
        !          1771:                      }
        !          1772:                  }
        !          1773:              }
        !          1774: 
        !          1775:              /* Now that the jump has been tensioned,
        !          1776:                 try cross jumping: check for identical code
        !          1777:                 before the jump and before its target label. */
        !          1778: 
        !          1779:              /* First, cross jumping of conditional jumps:  */
        !          1780: 
        !          1781:              if (cross_jump && condjump_p (insn))
        !          1782:                {
        !          1783:                  rtx newjpos, newlpos;
        !          1784:                  rtx x = prev_real_insn (JUMP_LABEL (insn));
        !          1785: 
        !          1786:                  /* A conditional jump may be crossjumped
        !          1787:                     only if the place it jumps to follows
        !          1788:                     an opposing jump that comes back here.  */
        !          1789: 
        !          1790:                  if (x != 0 && ! jump_back_p (x, insn))
        !          1791:                    /* We have no opposing jump;
        !          1792:                       cannot cross jump this insn.  */
        !          1793:                    x = 0;
        !          1794: 
        !          1795:                  newjpos = 0;
        !          1796:                  /* TARGET is nonzero if it is ok to cross jump
        !          1797:                     to code before TARGET.  If so, see if matches.  */
        !          1798:                  if (x != 0)
        !          1799:                    find_cross_jump (insn, x, 2,
        !          1800:                                     &newjpos, &newlpos);
        !          1801: 
        !          1802:                  if (newjpos != 0)
        !          1803:                    {
        !          1804:                      do_cross_jump (insn, newjpos, newlpos);
        !          1805:                      /* Make the old conditional jump
        !          1806:                         into an unconditional one.  */
        !          1807:                      SET_SRC (PATTERN (insn))
        !          1808:                        = gen_rtx (LABEL_REF, VOIDmode, JUMP_LABEL (insn));
        !          1809:                      INSN_CODE (insn) = -1;
        !          1810:                      emit_barrier_after (insn);
        !          1811:                      /* Add to jump_chain unless this is a new label
        !          1812:                         whose UID is too large. */
        !          1813:                      if (INSN_UID (JUMP_LABEL (insn)) < max_jump_chain)
        !          1814:                        {
        !          1815:                          jump_chain[INSN_UID (insn)]
        !          1816:                            = jump_chain[INSN_UID (JUMP_LABEL (insn))];
        !          1817:                          jump_chain[INSN_UID (JUMP_LABEL (insn))] = insn;
        !          1818:                        }
        !          1819:                      changed = 1;
        !          1820:                      next = insn;
        !          1821:                    }
        !          1822:                }
        !          1823: 
        !          1824:              /* Cross jumping of unconditional jumps:
        !          1825:                 a few differences.  */
        !          1826: 
        !          1827:              if (cross_jump && simplejump_p (insn))
        !          1828:                {
        !          1829:                  rtx newjpos, newlpos;
        !          1830:                  rtx target;
        !          1831: 
        !          1832:                  newjpos = 0;
        !          1833: 
        !          1834:                  /* TARGET is nonzero if it is ok to cross jump
        !          1835:                     to code before TARGET.  If so, see if matches.  */
        !          1836:                  find_cross_jump (insn, JUMP_LABEL (insn), 1,
        !          1837:                                   &newjpos, &newlpos);
        !          1838: 
        !          1839:                  /* If cannot cross jump to code before the label,
        !          1840:                     see if we can cross jump to another jump to
        !          1841:                     the same label.  */
        !          1842:                  /* Try each other jump to this label.  */
        !          1843:                  if (INSN_UID (JUMP_LABEL (insn)) < max_uid)
        !          1844:                    for (target = jump_chain[INSN_UID (JUMP_LABEL (insn))];
        !          1845:                         target != 0 && newjpos == 0;
        !          1846:                         target = jump_chain[INSN_UID (target)])
        !          1847:                      if (target != insn
        !          1848:                          && JUMP_LABEL (target) == JUMP_LABEL (insn)
        !          1849:                          /* Ignore TARGET if it's deleted.  */
        !          1850:                          && ! INSN_DELETED_P (target))
        !          1851:                        find_cross_jump (insn, target, 2,
        !          1852:                                         &newjpos, &newlpos);
        !          1853: 
        !          1854:                  if (newjpos != 0)
        !          1855:                    {
        !          1856:                      do_cross_jump (insn, newjpos, newlpos);
        !          1857:                      changed = 1;
        !          1858:                      next = insn;
        !          1859:                    }
        !          1860:                }
        !          1861: 
        !          1862:              /* This code was dead in the previous jump.c!  */
        !          1863:              if (cross_jump && GET_CODE (PATTERN (insn)) == RETURN)
        !          1864:                {
        !          1865:                  /* Return insns all "jump to the same place"
        !          1866:                     so we can cross-jump between any two of them.  */
        !          1867: 
        !          1868:                  rtx newjpos, newlpos, target;
        !          1869: 
        !          1870:                  newjpos = 0;
        !          1871: 
        !          1872:                  /* If cannot cross jump to code before the label,
        !          1873:                     see if we can cross jump to another jump to
        !          1874:                     the same label.  */
        !          1875:                  /* Try each other jump to this label.  */
        !          1876:                  for (target = jump_chain[0];
        !          1877:                       target != 0 && newjpos == 0;
        !          1878:                       target = jump_chain[INSN_UID (target)])
        !          1879:                    if (target != insn
        !          1880:                        && ! INSN_DELETED_P (target)
        !          1881:                        && GET_CODE (PATTERN (target)) == RETURN)
        !          1882:                      find_cross_jump (insn, target, 2,
        !          1883:                                       &newjpos, &newlpos);
        !          1884: 
        !          1885:                  if (newjpos != 0)
        !          1886:                    {
        !          1887:                      do_cross_jump (insn, newjpos, newlpos);
        !          1888:                      changed = 1;
        !          1889:                      next = insn;
        !          1890:                    }
        !          1891:                }
        !          1892:            }
        !          1893:        }
        !          1894: 
        !          1895:       first = 0;
        !          1896:     }
        !          1897: 
        !          1898:   /* Delete extraneous line number notes.
        !          1899:      Note that two consecutive notes for different lines are not really
        !          1900:      extraneous.  There should be some indication where that line belonged,
        !          1901:      even if it became empty.  */
        !          1902: 
        !          1903:   {
        !          1904:     rtx last_note = 0;
        !          1905: 
        !          1906:     for (insn = f; insn; insn = NEXT_INSN (insn))
        !          1907:       if (GET_CODE (insn) == NOTE && NOTE_LINE_NUMBER (insn) >= 0)
        !          1908:        {
        !          1909:          /* Delete this note if it is identical to previous note.  */
        !          1910:          if (last_note
        !          1911:              && NOTE_SOURCE_FILE (insn) == NOTE_SOURCE_FILE (last_note)
        !          1912:              && NOTE_LINE_NUMBER (insn) == NOTE_LINE_NUMBER (last_note))
        !          1913:            {
        !          1914:              delete_insn (insn);
        !          1915:              continue;
        !          1916:            }
        !          1917: 
        !          1918:          last_note = insn;
        !          1919:        }
        !          1920:   }
        !          1921: 
        !          1922: #ifdef HAVE_return
        !          1923:   if (HAVE_return)
        !          1924:     {
        !          1925:       /* If we fall through to the epilogue, see if we can insert a RETURN insn
        !          1926:         in front of it.  If the machine allows it at this point (we might be
        !          1927:         after reload for a leaf routine), it will improve optimization for it
        !          1928:         to be there.  We do this both here and at the start of this pass since
        !          1929:         the RETURN might have been deleted by some of our optimizations.  */
        !          1930:       insn = get_last_insn ();
        !          1931:       while (insn && GET_CODE (insn) == NOTE)
        !          1932:        insn = PREV_INSN (insn);
        !          1933: 
        !          1934:       if (insn && GET_CODE (insn) != BARRIER)
        !          1935:        {
        !          1936:          emit_jump_insn (gen_return ());
        !          1937:          emit_barrier ();
        !          1938:        }
        !          1939:     }
        !          1940: #endif
        !          1941: 
        !          1942:   /* See if there is still a NOTE_INSN_FUNCTION_END in this function.
        !          1943:      If so, delete it, and record that this function can drop off the end.  */
        !          1944: 
        !          1945:   insn = last_insn;
        !          1946:   {
        !          1947:     int n_labels = 1;
        !          1948:     while (insn
        !          1949:           /* One label can follow the end-note: the return label.  */
        !          1950:           && ((GET_CODE (insn) == CODE_LABEL && n_labels-- > 0)
        !          1951:               /* Ordinary insns can follow it if returning a structure.  */
        !          1952:               || GET_CODE (insn) == INSN
        !          1953:               /* If machine uses explicit RETURN insns, no epilogue,
        !          1954:                  then one of them follows the note.  */
        !          1955:               || (GET_CODE (insn) == JUMP_INSN
        !          1956:                   && GET_CODE (PATTERN (insn)) == RETURN)
        !          1957:               /* Other kinds of notes can follow also.  */
        !          1958:               || (GET_CODE (insn) == NOTE
        !          1959:                   && NOTE_LINE_NUMBER (insn) != NOTE_INSN_FUNCTION_END)))
        !          1960:       insn = PREV_INSN (insn);
        !          1961:   }
        !          1962: 
        !          1963:   /* Report if control can fall through at the end of the function.  */
        !          1964:   if (insn && GET_CODE (insn) == NOTE
        !          1965:       && NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_END)
        !          1966:     {
        !          1967:       can_reach_end = 1;
        !          1968:       delete_insn (insn);
        !          1969:     }
        !          1970: 
        !          1971:   /* Show JUMP_CHAIN no longer valid.  */
        !          1972:   jump_chain = 0;
        !          1973: }
        !          1974: 
        !          1975: /* LOOP_START is a NOTE_INSN_LOOP_BEG note that is followed by an unconditional
        !          1976:    jump.  Assume that this unconditional jump is to the exit test code.  If
        !          1977:    the code is sufficiently simple, make a copy of it before INSN,
        !          1978:    followed by a jump to the exit of the loop.  Then delete the unconditional
        !          1979:    jump after INSN.
        !          1980: 
        !          1981:    Note that it is possible we can get confused here if the jump immediately
        !          1982:    after the loop start branches outside the loop but within an outer loop.
        !          1983:    If we are near the exit of that loop, we will copy its exit test.  This
        !          1984:    will not generate incorrect code, but could suppress some optimizations.
        !          1985:    However, such cases are degenerate loops anyway.
        !          1986: 
        !          1987:    Return 1 if we made the change, else 0.
        !          1988: 
        !          1989:    This is only safe immediately after a regscan pass because it uses the
        !          1990:    values of regno_first_uid and regno_last_uid.  */
        !          1991: 
        !          1992: static int
        !          1993: duplicate_loop_exit_test (loop_start)
        !          1994:      rtx loop_start;
        !          1995: {
        !          1996:   rtx insn, set, p;
        !          1997:   rtx copy, link;
        !          1998:   int num_insns = 0;
        !          1999:   rtx exitcode = NEXT_INSN (JUMP_LABEL (next_nonnote_insn (loop_start)));
        !          2000:   rtx lastexit;
        !          2001:   int max_reg = max_reg_num ();
        !          2002:   rtx *reg_map = 0;
        !          2003: 
        !          2004:   /* Scan the exit code.  We do not perform this optimization if any insn:
        !          2005: 
        !          2006:          is a CALL_INSN
        !          2007:         is a CODE_LABEL
        !          2008:         has a REG_RETVAL or REG_LIBCALL note (hard to adjust)
        !          2009:         is a NOTE_INSN_LOOP_BEG because this means we have a nested loop
        !          2010:         is a NOTE_INSN_BLOCK_{BEG,END} because duplicating these notes
        !          2011:              are not valid
        !          2012: 
        !          2013:      Also, don't do this if the exit code is more than 20 insns.  */
        !          2014: 
        !          2015:   for (insn = exitcode;
        !          2016:        insn
        !          2017:        && ! (GET_CODE (insn) == NOTE
        !          2018:             && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END);
        !          2019:        insn = NEXT_INSN (insn))
        !          2020:     {
        !          2021:       switch (GET_CODE (insn))
        !          2022:        {
        !          2023:        case CODE_LABEL:
        !          2024:        case CALL_INSN:
        !          2025:          return 0;
        !          2026:        case NOTE:
        !          2027:          if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG
        !          2028:              || NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG
        !          2029:              || NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END)
        !          2030:            return 0;
        !          2031:          break;
        !          2032:        case JUMP_INSN:
        !          2033:        case INSN:
        !          2034:          if (++num_insns > 20
        !          2035:              || find_reg_note (insn, REG_RETVAL, NULL_RTX)
        !          2036:              || find_reg_note (insn, REG_LIBCALL, NULL_RTX))
        !          2037:            return 0;
        !          2038:          break;
        !          2039:        }
        !          2040:     }
        !          2041: 
        !          2042:   /* Unless INSN is zero, we can do the optimization.  */
        !          2043:   if (insn == 0)
        !          2044:     return 0;
        !          2045: 
        !          2046:   lastexit = insn;
        !          2047: 
        !          2048:   /* See if any insn sets a register only used in the loop exit code and
        !          2049:      not a user variable.  If so, replace it with a new register.  */
        !          2050:   for (insn = exitcode; insn != lastexit; insn = NEXT_INSN (insn))
        !          2051:     if (GET_CODE (insn) == INSN
        !          2052:        && (set = single_set (insn)) != 0
        !          2053:        && GET_CODE (SET_DEST (set)) == REG
        !          2054:        && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER
        !          2055:        && regno_first_uid[REGNO (SET_DEST (set))] == INSN_UID (insn))
        !          2056:       {
        !          2057:        for (p = NEXT_INSN (insn); p != lastexit; p = NEXT_INSN (p))
        !          2058:          if (regno_last_uid[REGNO (SET_DEST (set))] == INSN_UID (p))
        !          2059:            break;
        !          2060: 
        !          2061:        if (p != lastexit)
        !          2062:          {
        !          2063:            /* We can do the replacement.  Allocate reg_map if this is the
        !          2064:               first replacement we found.  */
        !          2065:            if (reg_map == 0)
        !          2066:              {
        !          2067:                reg_map = (rtx *) alloca (max_reg * sizeof (rtx));
        !          2068:                bzero (reg_map, max_reg * sizeof (rtx));
        !          2069:              }
        !          2070: 
        !          2071:            REG_LOOP_TEST_P (SET_DEST (set)) = 1;
        !          2072: 
        !          2073:            reg_map[REGNO (SET_DEST (set))]
        !          2074:              = gen_reg_rtx (GET_MODE (SET_DEST (set)));
        !          2075:          }
        !          2076:       }
        !          2077: 
        !          2078:   /* Now copy each insn.  */
        !          2079:   for (insn = exitcode; insn != lastexit; insn = NEXT_INSN (insn))
        !          2080:     switch (GET_CODE (insn))
        !          2081:       {
        !          2082:       case BARRIER:
        !          2083:        copy = emit_barrier_before (loop_start);
        !          2084:        break;
        !          2085:       case NOTE:
        !          2086:        /* Only copy line-number notes.  */
        !          2087:        if (NOTE_LINE_NUMBER (insn) >= 0)
        !          2088:          {
        !          2089:            copy = emit_note_before (NOTE_LINE_NUMBER (insn), loop_start);
        !          2090:            NOTE_SOURCE_FILE (copy) = NOTE_SOURCE_FILE (insn);
        !          2091:          }
        !          2092:        break;
        !          2093: 
        !          2094:       case INSN:
        !          2095:        copy = emit_insn_before (copy_rtx (PATTERN (insn)), loop_start);
        !          2096:        if (reg_map)
        !          2097:          replace_regs (PATTERN (copy), reg_map, max_reg, 1);
        !          2098: 
        !          2099:        mark_jump_label (PATTERN (copy), copy, 0);
        !          2100: 
        !          2101:        /* Copy all REG_NOTES except REG_LABEL since mark_jump_label will
        !          2102:           make them.  */
        !          2103:        for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
        !          2104:          if (REG_NOTE_KIND (link) != REG_LABEL)
        !          2105:            REG_NOTES (copy)
        !          2106:              = copy_rtx (gen_rtx (EXPR_LIST, REG_NOTE_KIND (link),
        !          2107:                                   XEXP (link, 0), REG_NOTES (copy)));
        !          2108:        if (reg_map && REG_NOTES (copy))
        !          2109:          replace_regs (REG_NOTES (copy), reg_map, max_reg, 1);
        !          2110:        break;
        !          2111: 
        !          2112:       case JUMP_INSN:
        !          2113:        copy = emit_jump_insn_before (copy_rtx (PATTERN (insn)), loop_start);
        !          2114:        if (reg_map)
        !          2115:          replace_regs (PATTERN (copy), reg_map, max_reg, 1);
        !          2116:        mark_jump_label (PATTERN (copy), copy, 0);
        !          2117:        if (REG_NOTES (insn))
        !          2118:          {
        !          2119:            REG_NOTES (copy) = copy_rtx (REG_NOTES (insn));
        !          2120:            if (reg_map)
        !          2121:              replace_regs (REG_NOTES (copy), reg_map, max_reg, 1);
        !          2122:          }
        !          2123:        
        !          2124:        /* If this is a simple jump, add it to the jump chain.  */
        !          2125: 
        !          2126:        if (INSN_UID (copy) < max_jump_chain && JUMP_LABEL (copy)
        !          2127:            && simplejump_p (copy))
        !          2128:          {
        !          2129:            jump_chain[INSN_UID (copy)]
        !          2130:              = jump_chain[INSN_UID (JUMP_LABEL (copy))];
        !          2131:            jump_chain[INSN_UID (JUMP_LABEL (copy))] = copy;
        !          2132:          }
        !          2133:        break;
        !          2134: 
        !          2135:       default:
        !          2136:        abort ();
        !          2137:       }
        !          2138: 
        !          2139:   /* Now clean up by emitting a jump to the end label and deleting the jump
        !          2140:      at the start of the loop.  */
        !          2141:   if (GET_CODE (copy) != BARRIER)
        !          2142:     {
        !          2143:       copy = emit_jump_insn_before (gen_jump (get_label_after (insn)),
        !          2144:                                    loop_start);
        !          2145:       mark_jump_label (PATTERN (copy), copy, 0);
        !          2146:       if (INSN_UID (copy) < max_jump_chain
        !          2147:          && INSN_UID (JUMP_LABEL (copy)) < max_jump_chain)
        !          2148:        {
        !          2149:          jump_chain[INSN_UID (copy)]
        !          2150:            = jump_chain[INSN_UID (JUMP_LABEL (copy))];
        !          2151:          jump_chain[INSN_UID (JUMP_LABEL (copy))] = copy;
        !          2152:        }
        !          2153:       emit_barrier_before (loop_start);
        !          2154:     }
        !          2155: 
        !          2156:   delete_insn (next_nonnote_insn (loop_start));
        !          2157: 
        !          2158:   /* Mark the exit code as the virtual top of the converted loop.  */
        !          2159:   emit_note_before (NOTE_INSN_LOOP_VTOP, exitcode);
        !          2160: 
        !          2161:   return 1;
        !          2162: }
        !          2163: 
        !          2164: /* Move all block-beg, block-end, loop-beg, loop-cont, loop-vtop, and
        !          2165:    loop-end notes between START and END out before START.  Assume that
        !          2166:    END is not such a note.  START may be such a note.  Returns the value
        !          2167:    of the new starting insn, which may be different if the original start
        !          2168:    was such a note.  */
        !          2169: 
        !          2170: rtx
        !          2171: squeeze_notes (start, end)
        !          2172:      rtx start, end;
        !          2173: {
        !          2174:   rtx insn;
        !          2175:   rtx next;
        !          2176: 
        !          2177:   for (insn = start; insn != end; insn = next)
        !          2178:     {
        !          2179:       next = NEXT_INSN (insn);
        !          2180:       if (GET_CODE (insn) == NOTE
        !          2181:          && (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END
        !          2182:              || NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG
        !          2183:              || NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG
        !          2184:              || NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END
        !          2185:              || NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_CONT
        !          2186:              || NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_VTOP))
        !          2187:        {
        !          2188:          if (insn == start)
        !          2189:            start = next;
        !          2190:          else
        !          2191:            {
        !          2192:              rtx prev = PREV_INSN (insn);
        !          2193:              PREV_INSN (insn) = PREV_INSN (start);
        !          2194:              NEXT_INSN (insn) = start;
        !          2195:              NEXT_INSN (PREV_INSN (insn)) = insn;
        !          2196:              PREV_INSN (NEXT_INSN (insn)) = insn;
        !          2197:              NEXT_INSN (prev) = next;
        !          2198:              PREV_INSN (next) = prev;
        !          2199:            }
        !          2200:        }
        !          2201:     }
        !          2202: 
        !          2203:   return start;
        !          2204: }
        !          2205: 
        !          2206: /* Compare the instructions before insn E1 with those before E2
        !          2207:    to find an opportunity for cross jumping.
        !          2208:    (This means detecting identical sequences of insns followed by
        !          2209:    jumps to the same place, or followed by a label and a jump
        !          2210:    to that label, and replacing one with a jump to the other.)
        !          2211: 
        !          2212:    Assume E1 is a jump that jumps to label E2
        !          2213:    (that is not always true but it might as well be).
        !          2214:    Find the longest possible equivalent sequences
        !          2215:    and store the first insns of those sequences into *F1 and *F2.
        !          2216:    Store zero there if no equivalent preceding instructions are found.
        !          2217: 
        !          2218:    We give up if we find a label in stream 1.
        !          2219:    Actually we could transfer that label into stream 2.  */
        !          2220: 
        !          2221: static void
        !          2222: find_cross_jump (e1, e2, minimum, f1, f2)
        !          2223:      rtx e1, e2;
        !          2224:      int minimum;
        !          2225:      rtx *f1, *f2;
        !          2226: {
        !          2227:   register rtx i1 = e1, i2 = e2;
        !          2228:   register rtx p1, p2;
        !          2229:   int lose = 0;
        !          2230: 
        !          2231:   rtx last1 = 0, last2 = 0;
        !          2232:   rtx afterlast1 = 0, afterlast2 = 0;
        !          2233:   rtx prev1;
        !          2234: 
        !          2235:   *f1 = 0;
        !          2236:   *f2 = 0;
        !          2237: 
        !          2238:   while (1)
        !          2239:     {
        !          2240:       i1 = prev_nonnote_insn (i1);
        !          2241: 
        !          2242:       i2 = PREV_INSN (i2);
        !          2243:       while (i2 && (GET_CODE (i2) == NOTE || GET_CODE (i2) == CODE_LABEL))
        !          2244:        i2 = PREV_INSN (i2);
        !          2245: 
        !          2246:       if (i1 == 0)
        !          2247:        break;
        !          2248: 
        !          2249:       /* Don't allow the range of insns preceding E1 or E2
        !          2250:         to include the other (E2 or E1).  */
        !          2251:       if (i2 == e1 || i1 == e2)
        !          2252:        break;
        !          2253: 
        !          2254:       /* If we will get to this code by jumping, those jumps will be
        !          2255:         tensioned to go directly to the new label (before I2),
        !          2256:         so this cross-jumping won't cost extra.  So reduce the minimum.  */
        !          2257:       if (GET_CODE (i1) == CODE_LABEL)
        !          2258:        {
        !          2259:          --minimum;
        !          2260:          break;
        !          2261:        }
        !          2262: 
        !          2263:       if (i2 == 0 || GET_CODE (i1) != GET_CODE (i2))
        !          2264:        break;
        !          2265: 
        !          2266:       p1 = PATTERN (i1);
        !          2267:       p2 = PATTERN (i2);
        !          2268:        
        !          2269: #ifdef STACK_REGS
        !          2270:       /* If cross_jump_death_matters is not 0, the insn's mode
        !          2271:         indicates whether or not the insn contains any stack-like
        !          2272:         regs. */
        !          2273: 
        !          2274:       if (cross_jump_death_matters && GET_MODE (i1) == QImode)
        !          2275:        {
        !          2276:          /* If register stack conversion has already been done, then
        !          2277:             death notes must also be compared before it is certain that
        !          2278:             the two instruction streams match. */
        !          2279: 
        !          2280:          rtx note;
        !          2281:          HARD_REG_SET i1_regset, i2_regset;
        !          2282: 
        !          2283:          CLEAR_HARD_REG_SET (i1_regset);
        !          2284:          CLEAR_HARD_REG_SET (i2_regset);
        !          2285: 
        !          2286:          for (note = REG_NOTES (i1); note; note = XEXP (note, 1))
        !          2287:            if (REG_NOTE_KIND (note) == REG_DEAD
        !          2288:                && STACK_REG_P (XEXP (note, 0)))
        !          2289:              SET_HARD_REG_BIT (i1_regset, REGNO (XEXP (note, 0)));
        !          2290: 
        !          2291:          for (note = REG_NOTES (i2); note; note = XEXP (note, 1))
        !          2292:            if (REG_NOTE_KIND (note) == REG_DEAD
        !          2293:                && STACK_REG_P (XEXP (note, 0)))
        !          2294:              SET_HARD_REG_BIT (i2_regset, REGNO (XEXP (note, 0)));
        !          2295: 
        !          2296:          GO_IF_HARD_REG_EQUAL (i1_regset, i2_regset, done);
        !          2297: 
        !          2298:          lose = 1;
        !          2299: 
        !          2300:        done:
        !          2301:          ;
        !          2302:        }
        !          2303: #endif
        !          2304: 
        !          2305:       if (lose  || GET_CODE (p1) != GET_CODE (p2)
        !          2306:          || ! rtx_renumbered_equal_p (p1, p2))
        !          2307:        {
        !          2308:          /* The following code helps take care of G++ cleanups.  */
        !          2309:          rtx equiv1;
        !          2310:          rtx equiv2;
        !          2311: 
        !          2312:          if (!lose && GET_CODE (p1) == GET_CODE (p2)
        !          2313:              && ((equiv1 = find_reg_note (i1, REG_EQUAL, NULL_RTX)) != 0
        !          2314:                  || (equiv1 = find_reg_note (i1, REG_EQUIV, NULL_RTX)) != 0)
        !          2315:              && ((equiv2 = find_reg_note (i2, REG_EQUAL, NULL_RTX)) != 0
        !          2316:                  || (equiv2 = find_reg_note (i2, REG_EQUIV, NULL_RTX)) != 0)
        !          2317:              /* If the equivalences are not to a constant, they may
        !          2318:                 reference pseudos that no longer exist, so we can't
        !          2319:                 use them.  */
        !          2320:              && CONSTANT_P (XEXP (equiv1, 0))
        !          2321:              && rtx_equal_p (XEXP (equiv1, 0), XEXP (equiv2, 0)))
        !          2322:            {
        !          2323:              rtx s1 = single_set (i1);
        !          2324:              rtx s2 = single_set (i2);
        !          2325:              if (s1 != 0 && s2 != 0
        !          2326:                  && rtx_renumbered_equal_p (SET_DEST (s1), SET_DEST (s2)))
        !          2327:                {
        !          2328:                  validate_change (i1, &SET_SRC (s1), XEXP (equiv1, 0), 1);
        !          2329:                  validate_change (i2, &SET_SRC (s2), XEXP (equiv2, 0), 1);
        !          2330:                  if (! rtx_renumbered_equal_p (p1, p2))
        !          2331:                    cancel_changes (0);
        !          2332:                  else if (apply_change_group ())
        !          2333:                    goto win;
        !          2334:                }
        !          2335:            }
        !          2336: 
        !          2337:          /* Insns fail to match; cross jumping is limited to the following
        !          2338:             insns.  */
        !          2339: 
        !          2340: #ifdef HAVE_cc0
        !          2341:          /* Don't allow the insn after a compare to be shared by
        !          2342:             cross-jumping unless the compare is also shared.
        !          2343:             Here, if either of these non-matching insns is a compare,
        !          2344:             exclude the following insn from possible cross-jumping.  */
        !          2345:          if (sets_cc0_p (p1) || sets_cc0_p (p2))
        !          2346:            last1 = afterlast1, last2 = afterlast2, ++minimum;
        !          2347: #endif
        !          2348: 
        !          2349:          /* If cross-jumping here will feed a jump-around-jump
        !          2350:             optimization, this jump won't cost extra, so reduce
        !          2351:             the minimum.  */
        !          2352:          if (GET_CODE (i1) == JUMP_INSN
        !          2353:              && JUMP_LABEL (i1)
        !          2354:              && prev_real_insn (JUMP_LABEL (i1)) == e1)
        !          2355:            --minimum;
        !          2356:          break;
        !          2357:        }
        !          2358: 
        !          2359:     win:
        !          2360:       if (GET_CODE (p1) != USE && GET_CODE (p1) != CLOBBER)
        !          2361:        {
        !          2362:          /* Ok, this insn is potentially includable in a cross-jump here.  */
        !          2363:          afterlast1 = last1, afterlast2 = last2;
        !          2364:          last1 = i1, last2 = i2, --minimum;
        !          2365:        }
        !          2366:     }
        !          2367: 
        !          2368:   /* We have to be careful that we do not cross-jump into the middle of
        !          2369:      USE-CALL_INSN-CLOBBER sequence.  This sequence is used instead of
        !          2370:      putting the USE and CLOBBERs inside the CALL_INSN.  The delay slot
        !          2371:      scheduler needs to know what registers are used and modified by the
        !          2372:      CALL_INSN and needs the adjacent USE and CLOBBERs to do so.
        !          2373: 
        !          2374:      ??? At some point we should probably change this so that these are
        !          2375:      part of the CALL_INSN.  The way we are doing it now is a kludge that
        !          2376:      is now causing trouble.  */
        !          2377: 
        !          2378:   if (last1 != 0 && GET_CODE (last1) == CALL_INSN
        !          2379:       && (prev1 = prev_nonnote_insn (last1))
        !          2380:       && GET_CODE (prev1) == INSN
        !          2381:       && GET_CODE (PATTERN (prev1)) == USE)
        !          2382:     {
        !          2383:       /* Remove this CALL_INSN from the range we can cross-jump.  */
        !          2384:       last1 = next_real_insn (last1);
        !          2385:       last2 = next_real_insn (last2);
        !          2386: 
        !          2387:       minimum++;
        !          2388:     }
        !          2389: 
        !          2390:   /* Skip past CLOBBERS since they may be right after a CALL_INSN.  It
        !          2391:      isn't worth checking for the CALL_INSN.  */
        !          2392:   while (last1 != 0 && GET_CODE (PATTERN (last1)) == CLOBBER)
        !          2393:     last1 = next_real_insn (last1), last2 = next_real_insn (last2);
        !          2394: 
        !          2395:   if (minimum <= 0 && last1 != 0 && last1 != e1)
        !          2396:     *f1 = last1, *f2 = last2;
        !          2397: }
        !          2398: 
        !          2399: static void
        !          2400: do_cross_jump (insn, newjpos, newlpos)
        !          2401:      rtx insn, newjpos, newlpos;
        !          2402: {
        !          2403:   /* Find an existing label at this point
        !          2404:      or make a new one if there is none.  */
        !          2405:   register rtx label = get_label_before (newlpos);
        !          2406: 
        !          2407:   /* Make the same jump insn jump to the new point.  */
        !          2408:   if (GET_CODE (PATTERN (insn)) == RETURN)
        !          2409:     {
        !          2410:       /* Remove from jump chain of returns.  */
        !          2411:       delete_from_jump_chain (insn);
        !          2412:       /* Change the insn.  */
        !          2413:       PATTERN (insn) = gen_jump (label);
        !          2414:       INSN_CODE (insn) = -1;
        !          2415:       JUMP_LABEL (insn) = label;
        !          2416:       LABEL_NUSES (label)++;
        !          2417:       /* Add to new the jump chain.  */
        !          2418:       if (INSN_UID (label) < max_jump_chain
        !          2419:          && INSN_UID (insn) < max_jump_chain)
        !          2420:        {
        !          2421:          jump_chain[INSN_UID (insn)] = jump_chain[INSN_UID (label)];
        !          2422:          jump_chain[INSN_UID (label)] = insn;
        !          2423:        }
        !          2424:     }
        !          2425:   else
        !          2426:     redirect_jump (insn, label);
        !          2427: 
        !          2428:   /* Delete the matching insns before the jump.  Also, remove any REG_EQUAL
        !          2429:      or REG_EQUIV note in the NEWLPOS stream that isn't also present in
        !          2430:      the NEWJPOS stream.  */
        !          2431: 
        !          2432:   while (newjpos != insn)
        !          2433:     {
        !          2434:       rtx lnote;
        !          2435: 
        !          2436:       for (lnote = REG_NOTES (newlpos); lnote; lnote = XEXP (lnote, 1))
        !          2437:        if ((REG_NOTE_KIND (lnote) == REG_EQUAL
        !          2438:             || REG_NOTE_KIND (lnote) == REG_EQUIV)
        !          2439:            && ! find_reg_note (newjpos, REG_EQUAL, XEXP (lnote, 0))
        !          2440:            && ! find_reg_note (newjpos, REG_EQUIV, XEXP (lnote, 0)))
        !          2441:          remove_note (newlpos, lnote);
        !          2442: 
        !          2443:       delete_insn (newjpos);
        !          2444:       newjpos = next_real_insn (newjpos);
        !          2445:       newlpos = next_real_insn (newlpos);
        !          2446:     }
        !          2447: }
        !          2448: 
        !          2449: /* Return the label before INSN, or put a new label there.  */
        !          2450: 
        !          2451: rtx
        !          2452: get_label_before (insn)
        !          2453:      rtx insn;
        !          2454: {
        !          2455:   rtx label;
        !          2456: 
        !          2457:   /* Find an existing label at this point
        !          2458:      or make a new one if there is none.  */
        !          2459:   label = prev_nonnote_insn (insn);
        !          2460: 
        !          2461:   if (label == 0 || GET_CODE (label) != CODE_LABEL)
        !          2462:     {
        !          2463:       rtx prev = PREV_INSN (insn);
        !          2464: 
        !          2465:       /* Don't put a label between a CALL_INSN and USE insns that precede
        !          2466:         it.  */
        !          2467: 
        !          2468:       if (GET_CODE (insn) == CALL_INSN
        !          2469:          || (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE
        !          2470:              && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == CALL_INSN))
        !          2471:        while (GET_CODE (prev) == INSN && GET_CODE (PATTERN (prev)) == USE)
        !          2472:          prev = PREV_INSN (prev);
        !          2473: 
        !          2474:       label = gen_label_rtx ();
        !          2475:       emit_label_after (label, prev);
        !          2476:       LABEL_NUSES (label) = 0;
        !          2477:     }
        !          2478:   return label;
        !          2479: }
        !          2480: 
        !          2481: /* Return the label after INSN, or put a new label there.  */
        !          2482: 
        !          2483: rtx
        !          2484: get_label_after (insn)
        !          2485:      rtx insn;
        !          2486: {
        !          2487:   rtx label;
        !          2488: 
        !          2489:   /* Find an existing label at this point
        !          2490:      or make a new one if there is none.  */
        !          2491:   label = next_nonnote_insn (insn);
        !          2492: 
        !          2493:   if (label == 0 || GET_CODE (label) != CODE_LABEL)
        !          2494:     {
        !          2495:       /* Don't put a label between a CALL_INSN and CLOBBER insns
        !          2496:         following it. */
        !          2497: 
        !          2498:       if (GET_CODE (insn) == CALL_INSN
        !          2499:          || (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE
        !          2500:              && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == CALL_INSN))
        !          2501:        while (GET_CODE (NEXT_INSN (insn)) == INSN
        !          2502:               && GET_CODE (PATTERN (NEXT_INSN (insn))) == CLOBBER)
        !          2503:          insn = NEXT_INSN (insn);
        !          2504: 
        !          2505:       label = gen_label_rtx ();
        !          2506:       emit_label_after (label, insn);
        !          2507:       LABEL_NUSES (label) = 0;
        !          2508:     }
        !          2509:   return label;
        !          2510: }
        !          2511: 
        !          2512: /* Return 1 if INSN is a jump that jumps to right after TARGET
        !          2513:    only on the condition that TARGET itself would drop through.
        !          2514:    Assumes that TARGET is a conditional jump.  */
        !          2515: 
        !          2516: static int
        !          2517: jump_back_p (insn, target)
        !          2518:      rtx insn, target;
        !          2519: {
        !          2520:   rtx cinsn, ctarget;
        !          2521:   enum rtx_code codei, codet;
        !          2522: 
        !          2523:   if (simplejump_p (insn) || ! condjump_p (insn)
        !          2524:       || simplejump_p (target)
        !          2525:       || target != prev_real_insn (JUMP_LABEL (insn)))
        !          2526:     return 0;
        !          2527: 
        !          2528:   cinsn = XEXP (SET_SRC (PATTERN (insn)), 0);
        !          2529:   ctarget = XEXP (SET_SRC (PATTERN (target)), 0);
        !          2530: 
        !          2531:   codei = GET_CODE (cinsn);
        !          2532:   codet = GET_CODE (ctarget);
        !          2533: 
        !          2534:   if (XEXP (SET_SRC (PATTERN (insn)), 1) == pc_rtx)
        !          2535:     {
        !          2536:       if (! can_reverse_comparison_p (cinsn, insn))
        !          2537:        return 0;
        !          2538:       codei = reverse_condition (codei);
        !          2539:     }
        !          2540: 
        !          2541:   if (XEXP (SET_SRC (PATTERN (target)), 2) == pc_rtx)
        !          2542:     {
        !          2543:       if (! can_reverse_comparison_p (ctarget, target))
        !          2544:        return 0;
        !          2545:       codet = reverse_condition (codet);
        !          2546:     }
        !          2547: 
        !          2548:   return (codei == codet
        !          2549:          && rtx_renumbered_equal_p (XEXP (cinsn, 0), XEXP (ctarget, 0))
        !          2550:          && rtx_renumbered_equal_p (XEXP (cinsn, 1), XEXP (ctarget, 1)));
        !          2551: }
        !          2552: 
        !          2553: /* Given a comparison, COMPARISON, inside a conditional jump insn, INSN,
        !          2554:    return non-zero if it is safe to reverse this comparison.  It is if our
        !          2555:    floating-point is not IEEE, if this is an NE or EQ comparison, or if
        !          2556:    this is known to be an integer comparison.  */
        !          2557: 
        !          2558: int
        !          2559: can_reverse_comparison_p (comparison, insn)
        !          2560:      rtx comparison;
        !          2561:      rtx insn;
        !          2562: {
        !          2563:   rtx arg0;
        !          2564: 
        !          2565:   /* If this is not actually a comparison, we can't reverse it.  */
        !          2566:   if (GET_RTX_CLASS (GET_CODE (comparison)) != '<')
        !          2567:     return 0;
        !          2568: 
        !          2569:   if (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
        !          2570:       /* If this is an NE comparison, it is safe to reverse it to an EQ
        !          2571:         comparison and vice versa, even for floating point.  If no operands
        !          2572:         are NaNs, the reversal is valid.  If some operand is a NaN, EQ is
        !          2573:         always false and NE is always true, so the reversal is also valid.  */
        !          2574:       || GET_CODE (comparison) == NE
        !          2575:       || GET_CODE (comparison) == EQ)
        !          2576:     return 1;
        !          2577: 
        !          2578:   arg0 = XEXP (comparison, 0);
        !          2579: 
        !          2580:   /* Make sure ARG0 is one of the actual objects being compared.  If we
        !          2581:      can't do this, we can't be sure the comparison can be reversed. 
        !          2582: 
        !          2583:      Handle cc0 and a MODE_CC register.  */
        !          2584:   if ((GET_CODE (arg0) == REG && GET_MODE_CLASS (GET_MODE (arg0)) == MODE_CC)
        !          2585: #ifdef HAVE_cc0
        !          2586:       || arg0 == cc0_rtx
        !          2587: #endif
        !          2588:       )
        !          2589:     {
        !          2590:       rtx prev = prev_nonnote_insn (insn);
        !          2591:       rtx set = single_set (prev);
        !          2592: 
        !          2593:       if (set == 0 || SET_DEST (set) != arg0)
        !          2594:        return 0;
        !          2595: 
        !          2596:       arg0 = SET_SRC (set);
        !          2597: 
        !          2598:       if (GET_CODE (arg0) == COMPARE)
        !          2599:        arg0 = XEXP (arg0, 0);
        !          2600:     }
        !          2601: 
        !          2602:   /* We can reverse this if ARG0 is a CONST_INT or if its mode is
        !          2603:      not VOIDmode and neither a MODE_CC nor MODE_FLOAT type.  */
        !          2604:   return (GET_CODE (arg0) == CONST_INT
        !          2605:          || (GET_MODE (arg0) != VOIDmode
        !          2606:              && GET_MODE_CLASS (GET_MODE (arg0)) != MODE_CC
        !          2607:              && GET_MODE_CLASS (GET_MODE (arg0)) != MODE_FLOAT));
        !          2608: }
        !          2609: 
        !          2610: /* Given an rtx-code for a comparison, return the code
        !          2611:    for the negated comparison.
        !          2612:    WATCH OUT!  reverse_condition is not safe to use on a jump
        !          2613:    that might be acting on the results of an IEEE floating point comparison,
        !          2614:    because of the special treatment of non-signaling nans in comparisons.  
        !          2615:    Use can_reverse_comparison_p to be sure.  */
        !          2616: 
        !          2617: enum rtx_code
        !          2618: reverse_condition (code)
        !          2619:      enum rtx_code code;
        !          2620: {
        !          2621:   switch (code)
        !          2622:     {
        !          2623:     case EQ:
        !          2624:       return NE;
        !          2625: 
        !          2626:     case NE:
        !          2627:       return EQ;
        !          2628: 
        !          2629:     case GT:
        !          2630:       return LE;
        !          2631: 
        !          2632:     case GE:
        !          2633:       return LT;
        !          2634: 
        !          2635:     case LT:
        !          2636:       return GE;
        !          2637: 
        !          2638:     case LE:
        !          2639:       return GT;
        !          2640: 
        !          2641:     case GTU:
        !          2642:       return LEU;
        !          2643: 
        !          2644:     case GEU:
        !          2645:       return LTU;
        !          2646: 
        !          2647:     case LTU:
        !          2648:       return GEU;
        !          2649: 
        !          2650:     case LEU:
        !          2651:       return GTU;
        !          2652: 
        !          2653:     default:
        !          2654:       abort ();
        !          2655:       return UNKNOWN;
        !          2656:     }
        !          2657: }
        !          2658: 
        !          2659: /* Similar, but return the code when two operands of a comparison are swapped.
        !          2660:    This IS safe for IEEE floating-point.  */
        !          2661: 
        !          2662: enum rtx_code
        !          2663: swap_condition (code)
        !          2664:      enum rtx_code code;
        !          2665: {
        !          2666:   switch (code)
        !          2667:     {
        !          2668:     case EQ:
        !          2669:     case NE:
        !          2670:       return code;
        !          2671: 
        !          2672:     case GT:
        !          2673:       return LT;
        !          2674: 
        !          2675:     case GE:
        !          2676:       return LE;
        !          2677: 
        !          2678:     case LT:
        !          2679:       return GT;
        !          2680: 
        !          2681:     case LE:
        !          2682:       return GE;
        !          2683: 
        !          2684:     case GTU:
        !          2685:       return LTU;
        !          2686: 
        !          2687:     case GEU:
        !          2688:       return LEU;
        !          2689: 
        !          2690:     case LTU:
        !          2691:       return GTU;
        !          2692: 
        !          2693:     case LEU:
        !          2694:       return GEU;
        !          2695: 
        !          2696:     default:
        !          2697:       abort ();
        !          2698:       return UNKNOWN;
        !          2699:     }
        !          2700: }
        !          2701: 
        !          2702: /* Given a comparison CODE, return the corresponding unsigned comparison.
        !          2703:    If CODE is an equality comparison or already an unsigned comparison,
        !          2704:    CODE is returned.  */
        !          2705: 
        !          2706: enum rtx_code
        !          2707: unsigned_condition (code)
        !          2708:      enum rtx_code code;
        !          2709: {
        !          2710:   switch (code)
        !          2711:     {
        !          2712:     case EQ:
        !          2713:     case NE:
        !          2714:     case GTU:
        !          2715:     case GEU:
        !          2716:     case LTU:
        !          2717:     case LEU:
        !          2718:       return code;
        !          2719: 
        !          2720:     case GT:
        !          2721:       return GTU;
        !          2722: 
        !          2723:     case GE:
        !          2724:       return GEU;
        !          2725: 
        !          2726:     case LT:
        !          2727:       return LTU;
        !          2728: 
        !          2729:     case LE:
        !          2730:       return LEU;
        !          2731: 
        !          2732:     default:
        !          2733:       abort ();
        !          2734:     }
        !          2735: }
        !          2736: 
        !          2737: /* Similarly, return the signed version of a comparison.  */
        !          2738: 
        !          2739: enum rtx_code
        !          2740: signed_condition (code)
        !          2741:      enum rtx_code code;
        !          2742: {
        !          2743:   switch (code)
        !          2744:     {
        !          2745:     case EQ:
        !          2746:     case NE:
        !          2747:     case GT:
        !          2748:     case GE:
        !          2749:     case LT:
        !          2750:     case LE:
        !          2751:       return code;
        !          2752: 
        !          2753:     case GTU:
        !          2754:       return GT;
        !          2755: 
        !          2756:     case GEU:
        !          2757:       return GE;
        !          2758: 
        !          2759:     case LTU:
        !          2760:       return LT;
        !          2761: 
        !          2762:     case LEU:
        !          2763:       return LE;
        !          2764: 
        !          2765:     default:
        !          2766:       abort ();
        !          2767:     }
        !          2768: }
        !          2769: 
        !          2770: /* Return non-zero if CODE1 is more strict than CODE2, i.e., if the
        !          2771:    truth of CODE1 implies the truth of CODE2.  */
        !          2772: 
        !          2773: int
        !          2774: comparison_dominates_p (code1, code2)
        !          2775:      enum rtx_code code1, code2;
        !          2776: {
        !          2777:   if (code1 == code2)
        !          2778:     return 1;
        !          2779: 
        !          2780:   switch (code1)
        !          2781:     {
        !          2782:     case EQ:
        !          2783:       if (code2 == LE || code2 == LEU || code2 == GE || code2 == GEU)
        !          2784:        return 1;
        !          2785:       break;
        !          2786: 
        !          2787:     case LT:
        !          2788:       if (code2 == LE)
        !          2789:        return 1;
        !          2790:       break;
        !          2791: 
        !          2792:     case GT:
        !          2793:       if (code2 == GE)
        !          2794:        return 1;
        !          2795:       break;
        !          2796: 
        !          2797:     case LTU:
        !          2798:       if (code2 == LEU)
        !          2799:        return 1;
        !          2800:       break;
        !          2801: 
        !          2802:     case GTU:
        !          2803:       if (code2 == GEU)
        !          2804:        return 1;
        !          2805:       break;
        !          2806:     }
        !          2807: 
        !          2808:   return 0;
        !          2809: }
        !          2810: 
        !          2811: /* Return 1 if INSN is an unconditional jump and nothing else.  */
        !          2812: 
        !          2813: int
        !          2814: simplejump_p (insn)
        !          2815:      rtx insn;
        !          2816: {
        !          2817:   return (GET_CODE (insn) == JUMP_INSN
        !          2818:          && GET_CODE (PATTERN (insn)) == SET
        !          2819:          && GET_CODE (SET_DEST (PATTERN (insn))) == PC
        !          2820:          && GET_CODE (SET_SRC (PATTERN (insn))) == LABEL_REF);
        !          2821: }
        !          2822: 
        !          2823: /* Return nonzero if INSN is a (possibly) conditional jump
        !          2824:    and nothing more.  */
        !          2825: 
        !          2826: int
        !          2827: condjump_p (insn)
        !          2828:      rtx insn;
        !          2829: {
        !          2830:   register rtx x = PATTERN (insn);
        !          2831:   if (GET_CODE (x) != SET)
        !          2832:     return 0;
        !          2833:   if (GET_CODE (SET_DEST (x)) != PC)
        !          2834:     return 0;
        !          2835:   if (GET_CODE (SET_SRC (x)) == LABEL_REF)
        !          2836:     return 1;
        !          2837:   if (GET_CODE (SET_SRC (x)) != IF_THEN_ELSE)
        !          2838:     return 0;
        !          2839:   if (XEXP (SET_SRC (x), 2) == pc_rtx
        !          2840:       && (GET_CODE (XEXP (SET_SRC (x), 1)) == LABEL_REF
        !          2841:          || GET_CODE (XEXP (SET_SRC (x), 1)) == RETURN))
        !          2842:     return 1;
        !          2843:   if (XEXP (SET_SRC (x), 1) == pc_rtx
        !          2844:       && (GET_CODE (XEXP (SET_SRC (x), 2)) == LABEL_REF
        !          2845:          || GET_CODE (XEXP (SET_SRC (x), 2)) == RETURN))
        !          2846:     return 1;
        !          2847:   return 0;
        !          2848: }
        !          2849: 
        !          2850: /* Return 1 if X is an RTX that does nothing but set the condition codes
        !          2851:    and CLOBBER or USE registers.
        !          2852:    Return -1 if X does explicitly set the condition codes,
        !          2853:    but also does other things.  */
        !          2854: 
        !          2855: int
        !          2856: sets_cc0_p (x)
        !          2857:      rtx x;
        !          2858: {
        !          2859: #ifdef HAVE_cc0
        !          2860:   if (GET_CODE (x) == SET && SET_DEST (x) == cc0_rtx)
        !          2861:     return 1;
        !          2862:   if (GET_CODE (x) == PARALLEL)
        !          2863:     {
        !          2864:       int i;
        !          2865:       int sets_cc0 = 0;
        !          2866:       int other_things = 0;
        !          2867:       for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
        !          2868:        {
        !          2869:          if (GET_CODE (XVECEXP (x, 0, i)) == SET
        !          2870:              && SET_DEST (XVECEXP (x, 0, i)) == cc0_rtx)
        !          2871:            sets_cc0 = 1;
        !          2872:          else if (GET_CODE (XVECEXP (x, 0, i)) == SET)
        !          2873:            other_things = 1;
        !          2874:        }
        !          2875:       return ! sets_cc0 ? 0 : other_things ? -1 : 1;
        !          2876:     }
        !          2877:   return 0;
        !          2878: #else
        !          2879:   abort ();
        !          2880: #endif
        !          2881: }
        !          2882: 
        !          2883: /* Follow any unconditional jump at LABEL;
        !          2884:    return the ultimate label reached by any such chain of jumps.
        !          2885:    If LABEL is not followed by a jump, return LABEL.
        !          2886:    If the chain loops or we can't find end, return LABEL,
        !          2887:    since that tells caller to avoid changing the insn.
        !          2888: 
        !          2889:    If RELOAD_COMPLETED is 0, we do not chain across a NOTE_INSN_LOOP_BEG or
        !          2890:    a USE or CLOBBER.  */
        !          2891: 
        !          2892: rtx
        !          2893: follow_jumps (label)
        !          2894:      rtx label;
        !          2895: {
        !          2896:   register rtx insn;
        !          2897:   register rtx next;
        !          2898:   register rtx value = label;
        !          2899:   register int depth;
        !          2900: 
        !          2901:   for (depth = 0;
        !          2902:        (depth < 10
        !          2903:        && (insn = next_active_insn (value)) != 0
        !          2904:        && GET_CODE (insn) == JUMP_INSN
        !          2905:        && (JUMP_LABEL (insn) != 0 || GET_CODE (PATTERN (insn)) == RETURN)
        !          2906:        && (next = NEXT_INSN (insn))
        !          2907:        && GET_CODE (next) == BARRIER);
        !          2908:        depth++)
        !          2909:     {
        !          2910:       /* Don't chain through the insn that jumps into a loop
        !          2911:         from outside the loop,
        !          2912:         since that would create multiple loop entry jumps
        !          2913:         and prevent loop optimization.  */
        !          2914:       rtx tem;
        !          2915:       if (!reload_completed)
        !          2916:        for (tem = value; tem != insn; tem = NEXT_INSN (tem))
        !          2917:          if (GET_CODE (tem) == NOTE
        !          2918:              && NOTE_LINE_NUMBER (tem) == NOTE_INSN_LOOP_BEG)
        !          2919:            return value;
        !          2920: 
        !          2921:       /* If we have found a cycle, make the insn jump to itself.  */
        !          2922:       if (JUMP_LABEL (insn) == label)
        !          2923:        return label;
        !          2924:       value = JUMP_LABEL (insn);
        !          2925:     }
        !          2926:   if (depth == 10)
        !          2927:     return label;
        !          2928:   return value;
        !          2929: }
        !          2930: 
        !          2931: /* Assuming that field IDX of X is a vector of label_refs,
        !          2932:    replace each of them by the ultimate label reached by it.
        !          2933:    Return nonzero if a change is made.
        !          2934:    If IGNORE_LOOPS is 0, we do not chain across a NOTE_INSN_LOOP_BEG.  */
        !          2935: 
        !          2936: static int
        !          2937: tension_vector_labels (x, idx)
        !          2938:      register rtx x;
        !          2939:      register int idx;
        !          2940: {
        !          2941:   int changed = 0;
        !          2942:   register int i;
        !          2943:   for (i = XVECLEN (x, idx) - 1; i >= 0; i--)
        !          2944:     {
        !          2945:       register rtx olabel = XEXP (XVECEXP (x, idx, i), 0);
        !          2946:       register rtx nlabel = follow_jumps (olabel);
        !          2947:       if (nlabel && nlabel != olabel)
        !          2948:        {
        !          2949:          XEXP (XVECEXP (x, idx, i), 0) = nlabel;
        !          2950:          ++LABEL_NUSES (nlabel);
        !          2951:          if (--LABEL_NUSES (olabel) == 0)
        !          2952:            delete_insn (olabel);
        !          2953:          changed = 1;
        !          2954:        }
        !          2955:     }
        !          2956:   return changed;
        !          2957: }
        !          2958: 
        !          2959: /* Find all CODE_LABELs referred to in X, and increment their use counts.
        !          2960:    If INSN is a JUMP_INSN and there is at least one CODE_LABEL referenced
        !          2961:    in INSN, then store one of them in JUMP_LABEL (INSN).
        !          2962:    If INSN is an INSN or a CALL_INSN and there is at least one CODE_LABEL
        !          2963:    referenced in INSN, add a REG_LABEL note containing that label to INSN.
        !          2964:    Also, when there are consecutive labels, canonicalize on the last of them.
        !          2965: 
        !          2966:    Note that two labels separated by a loop-beginning note
        !          2967:    must be kept distinct if we have not yet done loop-optimization,
        !          2968:    because the gap between them is where loop-optimize
        !          2969:    will want to move invariant code to.  CROSS_JUMP tells us
        !          2970:    that loop-optimization is done with.
        !          2971: 
        !          2972:    Once reload has completed (CROSS_JUMP non-zero), we need not consider
        !          2973:    two labels distinct if they are separated by only USE or CLOBBER insns.  */
        !          2974: 
        !          2975: static void
        !          2976: mark_jump_label (x, insn, cross_jump)
        !          2977:      register rtx x;
        !          2978:      rtx insn;
        !          2979:      int cross_jump;
        !          2980: {
        !          2981:   register RTX_CODE code = GET_CODE (x);
        !          2982:   register int i;
        !          2983:   register char *fmt;
        !          2984: 
        !          2985:   switch (code)
        !          2986:     {
        !          2987:     case PC:
        !          2988:     case CC0:
        !          2989:     case REG:
        !          2990:     case SUBREG:
        !          2991:     case CONST_INT:
        !          2992:     case SYMBOL_REF:
        !          2993:     case CONST_DOUBLE:
        !          2994:     case CLOBBER:
        !          2995:     case CALL:
        !          2996:       return;
        !          2997: 
        !          2998:     case MEM:
        !          2999:       /* If this is a constant-pool reference, see if it is a label.  */
        !          3000:       if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF
        !          3001:          && CONSTANT_POOL_ADDRESS_P (XEXP (x, 0)))
        !          3002:        mark_jump_label (get_pool_constant (XEXP (x, 0)), insn, cross_jump);
        !          3003:       break;
        !          3004: 
        !          3005:     case LABEL_REF:
        !          3006:       {
        !          3007:        register rtx label = XEXP (x, 0);
        !          3008:        register rtx next;
        !          3009:        if (GET_CODE (label) != CODE_LABEL)
        !          3010:          abort ();
        !          3011:        /* Ignore references to labels of containing functions.  */
        !          3012:        if (LABEL_REF_NONLOCAL_P (x))
        !          3013:          break;
        !          3014:        /* If there are other labels following this one,
        !          3015:           replace it with the last of the consecutive labels.  */
        !          3016:        for (next = NEXT_INSN (label); next; next = NEXT_INSN (next))
        !          3017:          {
        !          3018:            if (GET_CODE (next) == CODE_LABEL)
        !          3019:              label = next;
        !          3020:            else if (cross_jump && GET_CODE (next) == INSN
        !          3021:                     && (GET_CODE (PATTERN (next)) == USE
        !          3022:                         || GET_CODE (PATTERN (next)) == CLOBBER))
        !          3023:              continue;
        !          3024:            else if (GET_CODE (next) != NOTE)
        !          3025:              break;
        !          3026:            else if (! cross_jump
        !          3027:                     && (NOTE_LINE_NUMBER (next) == NOTE_INSN_LOOP_BEG
        !          3028:                         || NOTE_LINE_NUMBER (next) == NOTE_INSN_FUNCTION_END))
        !          3029:              break;
        !          3030:          }
        !          3031:        XEXP (x, 0) = label;
        !          3032:        ++LABEL_NUSES (label);
        !          3033:        if (insn)
        !          3034:          {
        !          3035:            if (GET_CODE (insn) == JUMP_INSN)
        !          3036:              JUMP_LABEL (insn) = label;
        !          3037:            else if (! find_reg_note (insn, REG_LABEL, label))
        !          3038:              {
        !          3039:                rtx next = next_real_insn (label);
        !          3040:                /* Don't record labels that refer to dispatch tables.
        !          3041:                   This is not necessary, since the tablejump
        !          3042:                   references the same label.
        !          3043:                   And if we did record them, flow.c would make worse code.  */
        !          3044:                if (next == 0
        !          3045:                    || ! (GET_CODE (next) == JUMP_INSN
        !          3046:                          && (GET_CODE (PATTERN (next)) == ADDR_VEC
        !          3047:                              || GET_CODE (PATTERN (next)) == ADDR_DIFF_VEC)))
        !          3048:                  {
        !          3049:                    REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_LABEL, label,
        !          3050:                                                REG_NOTES (insn));
        !          3051:                    /* Record in the note whether label is nonlocal.  */
        !          3052:                    LABEL_REF_NONLOCAL_P (REG_NOTES (insn))
        !          3053:                      = LABEL_REF_NONLOCAL_P (x);
        !          3054:                  }
        !          3055:              }
        !          3056:          }
        !          3057:        return;
        !          3058:       }
        !          3059: 
        !          3060:   /* Do walk the labels in a vector, but not the first operand of an
        !          3061:      ADDR_DIFF_VEC.  Don't set the JUMP_LABEL of a vector.  */
        !          3062:     case ADDR_VEC:
        !          3063:     case ADDR_DIFF_VEC:
        !          3064:       {
        !          3065:        int eltnum = code == ADDR_DIFF_VEC ? 1 : 0;
        !          3066: 
        !          3067:        for (i = 0; i < XVECLEN (x, eltnum); i++)
        !          3068:          mark_jump_label (XVECEXP (x, eltnum, i), NULL_RTX, cross_jump);
        !          3069:        return;
        !          3070:       }
        !          3071:     }
        !          3072: 
        !          3073:   fmt = GET_RTX_FORMAT (code);
        !          3074:   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
        !          3075:     {
        !          3076:       if (fmt[i] == 'e')
        !          3077:        mark_jump_label (XEXP (x, i), insn, cross_jump);
        !          3078:       else if (fmt[i] == 'E')
        !          3079:        {
        !          3080:          register int j;
        !          3081:          for (j = 0; j < XVECLEN (x, i); j++)
        !          3082:            mark_jump_label (XVECEXP (x, i, j), insn, cross_jump);
        !          3083:        }
        !          3084:     }
        !          3085: }
        !          3086: 
        !          3087: /* If all INSN does is set the pc, delete it,
        !          3088:    and delete the insn that set the condition codes for it
        !          3089:    if that's what the previous thing was.  */
        !          3090: 
        !          3091: void
        !          3092: delete_jump (insn)
        !          3093:      rtx insn;
        !          3094: {
        !          3095:   register rtx set = single_set (insn);
        !          3096: 
        !          3097:   if (set && GET_CODE (SET_DEST (set)) == PC)
        !          3098:     delete_computation (insn);
        !          3099: }
        !          3100: 
        !          3101: /* Delete INSN and recursively delete insns that compute values used only
        !          3102:    by INSN.  This uses the REG_DEAD notes computed during flow analysis.
        !          3103:    If we are running before flow.c, we need do nothing since flow.c will
        !          3104:    delete dead code.  We also can't know if the registers being used are
        !          3105:    dead or not at this point.
        !          3106: 
        !          3107:    Otherwise, look at all our REG_DEAD notes.  If a previous insn does
        !          3108:    nothing other than set a register that dies in this insn, we can delete
        !          3109:    that insn as well.
        !          3110: 
        !          3111:    On machines with CC0, if CC0 is used in this insn, we may be able to
        !          3112:    delete the insn that set it.  */
        !          3113: 
        !          3114: void
        !          3115: delete_computation (insn)
        !          3116:      rtx insn;
        !          3117: {
        !          3118:   rtx note, next;
        !          3119: 
        !          3120: #ifdef HAVE_cc0
        !          3121:   if (reg_referenced_p (cc0_rtx, PATTERN (insn)))
        !          3122:     {
        !          3123:       rtx prev = prev_nonnote_insn (insn);
        !          3124:       /* We assume that at this stage
        !          3125:         CC's are always set explicitly
        !          3126:         and always immediately before the jump that
        !          3127:         will use them.  So if the previous insn
        !          3128:         exists to set the CC's, delete it
        !          3129:         (unless it performs auto-increments, etc.).  */
        !          3130:       if (prev && GET_CODE (prev) == INSN
        !          3131:          && sets_cc0_p (PATTERN (prev)))
        !          3132:        {
        !          3133:          if (sets_cc0_p (PATTERN (prev)) > 0
        !          3134:              && !FIND_REG_INC_NOTE (prev, NULL_RTX))
        !          3135:            delete_computation (prev);
        !          3136:          else
        !          3137:            /* Otherwise, show that cc0 won't be used.  */
        !          3138:            REG_NOTES (prev) = gen_rtx (EXPR_LIST, REG_UNUSED,
        !          3139:                                        cc0_rtx, REG_NOTES (prev));
        !          3140:        }
        !          3141:     }
        !          3142: #endif
        !          3143: 
        !          3144:   for (note = REG_NOTES (insn); note; note = next)
        !          3145:     {
        !          3146:       rtx our_prev;
        !          3147: 
        !          3148:       next = XEXP (note, 1);
        !          3149: 
        !          3150:       if (REG_NOTE_KIND (note) != REG_DEAD
        !          3151:          /* Verify that the REG_NOTE is legitimate.  */
        !          3152:          || GET_CODE (XEXP (note, 0)) != REG)
        !          3153:        continue;
        !          3154: 
        !          3155:       for (our_prev = prev_nonnote_insn (insn);
        !          3156:           our_prev && GET_CODE (our_prev) == INSN;
        !          3157:           our_prev = prev_nonnote_insn (our_prev))
        !          3158:        {
        !          3159:          /* If we reach a SEQUENCE, it is too complex to try to
        !          3160:             do anything with it, so give up.  */
        !          3161:          if (GET_CODE (PATTERN (our_prev)) == SEQUENCE)
        !          3162:            break;
        !          3163: 
        !          3164:          if (GET_CODE (PATTERN (our_prev)) == USE
        !          3165:              && GET_CODE (XEXP (PATTERN (our_prev), 0)) == INSN)
        !          3166:            /* reorg creates USEs that look like this.  We leave them
        !          3167:               alone because reorg needs them for its own purposes.  */
        !          3168:            break;
        !          3169: 
        !          3170:          if (reg_set_p (XEXP (note, 0), PATTERN (our_prev)))
        !          3171:            {
        !          3172:              if (FIND_REG_INC_NOTE (our_prev, NULL_RTX))
        !          3173:                break;
        !          3174: 
        !          3175:              if (GET_CODE (PATTERN (our_prev)) == PARALLEL)
        !          3176:                {
        !          3177:                  /* If we find a SET of something else, we can't
        !          3178:                     delete the insn.  */
        !          3179: 
        !          3180:                  int i;
        !          3181: 
        !          3182:                  for (i = 0; i < XVECLEN (PATTERN (our_prev), 0); i++)
        !          3183:                    {
        !          3184:                      rtx part = XVECEXP (PATTERN (our_prev), 0, i);
        !          3185: 
        !          3186:                      if (GET_CODE (part) == SET
        !          3187:                          && SET_DEST (part) != XEXP (note, 0))
        !          3188:                        break;
        !          3189:                    }
        !          3190: 
        !          3191:                  if (i == XVECLEN (PATTERN (our_prev), 0))
        !          3192:                    delete_computation (our_prev);
        !          3193:                }
        !          3194:              else if (GET_CODE (PATTERN (our_prev)) == SET
        !          3195:                       && SET_DEST (PATTERN (our_prev)) == XEXP (note, 0))
        !          3196:                delete_computation (our_prev);
        !          3197: 
        !          3198:              break;
        !          3199:            }
        !          3200: 
        !          3201:          /* If OUR_PREV references the register that dies here, it is an
        !          3202:             additional use.  Hence any prior SET isn't dead.  However, this
        !          3203:             insn becomes the new place for the REG_DEAD note.  */
        !          3204:          if (reg_overlap_mentioned_p (XEXP (note, 0),
        !          3205:                                       PATTERN (our_prev)))
        !          3206:            {
        !          3207:              XEXP (note, 1) = REG_NOTES (our_prev);
        !          3208:              REG_NOTES (our_prev) = note;
        !          3209:              break;
        !          3210:            }
        !          3211:        }
        !          3212:     }
        !          3213: 
        !          3214:   delete_insn (insn);
        !          3215: }
        !          3216: 
        !          3217: /* Delete insn INSN from the chain of insns and update label ref counts.
        !          3218:    May delete some following insns as a consequence; may even delete
        !          3219:    a label elsewhere and insns that follow it.
        !          3220: 
        !          3221:    Returns the first insn after INSN that was not deleted.  */
        !          3222: 
        !          3223: rtx
        !          3224: delete_insn (insn)
        !          3225:      register rtx insn;
        !          3226: {
        !          3227:   register rtx next = NEXT_INSN (insn);
        !          3228:   register rtx prev = PREV_INSN (insn);
        !          3229:   register int was_code_label = (GET_CODE (insn) == CODE_LABEL);
        !          3230:   register int dont_really_delete = 0;
        !          3231: 
        !          3232:   while (next && INSN_DELETED_P (next))
        !          3233:     next = NEXT_INSN (next);
        !          3234: 
        !          3235:   /* This insn is already deleted => return first following nondeleted.  */
        !          3236:   if (INSN_DELETED_P (insn))
        !          3237:     return next;
        !          3238: 
        !          3239:   /* Don't delete user-declared labels.  Convert them to special NOTEs
        !          3240:      instead.  */
        !          3241:   if (was_code_label && LABEL_NAME (insn) != 0
        !          3242:       && optimize && ! dont_really_delete)
        !          3243:     {
        !          3244:       PUT_CODE (insn, NOTE);
        !          3245:       NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED_LABEL;
        !          3246:       NOTE_SOURCE_FILE (insn) = 0;
        !          3247:       dont_really_delete = 1;
        !          3248:     }
        !          3249:   else
        !          3250:     /* Mark this insn as deleted.  */
        !          3251:     INSN_DELETED_P (insn) = 1;
        !          3252: 
        !          3253:   /* If this is an unconditional jump, delete it from the jump chain.  */
        !          3254:   if (simplejump_p (insn))
        !          3255:     delete_from_jump_chain (insn);
        !          3256: 
        !          3257:   /* If instruction is followed by a barrier,
        !          3258:      delete the barrier too.  */
        !          3259: 
        !          3260:   if (next != 0 && GET_CODE (next) == BARRIER)
        !          3261:     {
        !          3262:       INSN_DELETED_P (next) = 1;
        !          3263:       next = NEXT_INSN (next);
        !          3264:     }
        !          3265: 
        !          3266:   /* Patch out INSN (and the barrier if any) */
        !          3267: 
        !          3268:   if (optimize && ! dont_really_delete)
        !          3269:     {
        !          3270:       if (prev)
        !          3271:        {
        !          3272:          NEXT_INSN (prev) = next;
        !          3273:          if (GET_CODE (prev) == INSN && GET_CODE (PATTERN (prev)) == SEQUENCE)
        !          3274:            NEXT_INSN (XVECEXP (PATTERN (prev), 0,
        !          3275:                                XVECLEN (PATTERN (prev), 0) - 1)) = next;
        !          3276:        }
        !          3277: 
        !          3278:       if (next)
        !          3279:        {
        !          3280:          PREV_INSN (next) = prev;
        !          3281:          if (GET_CODE (next) == INSN && GET_CODE (PATTERN (next)) == SEQUENCE)
        !          3282:            PREV_INSN (XVECEXP (PATTERN (next), 0, 0)) = prev;
        !          3283:        }
        !          3284: 
        !          3285:       if (prev && NEXT_INSN (prev) == 0)
        !          3286:        set_last_insn (prev);
        !          3287:     }
        !          3288: 
        !          3289:   /* If deleting a jump, decrement the count of the label,
        !          3290:      and delete the label if it is now unused.  */
        !          3291: 
        !          3292:   if (GET_CODE (insn) == JUMP_INSN && JUMP_LABEL (insn))
        !          3293:     if (--LABEL_NUSES (JUMP_LABEL (insn)) == 0)
        !          3294:       {
        !          3295:        /* This can delete NEXT or PREV,
        !          3296:           either directly if NEXT is JUMP_LABEL (INSN),
        !          3297:           or indirectly through more levels of jumps.  */
        !          3298:        delete_insn (JUMP_LABEL (insn));
        !          3299:        /* I feel a little doubtful about this loop,
        !          3300:           but I see no clean and sure alternative way
        !          3301:           to find the first insn after INSN that is not now deleted.
        !          3302:           I hope this works.  */
        !          3303:        while (next && INSN_DELETED_P (next))
        !          3304:          next = NEXT_INSN (next);
        !          3305:        return next;
        !          3306:       }
        !          3307: 
        !          3308:   while (prev && (INSN_DELETED_P (prev) || GET_CODE (prev) == NOTE))
        !          3309:     prev = PREV_INSN (prev);
        !          3310: 
        !          3311:   /* If INSN was a label and a dispatch table follows it,
        !          3312:      delete the dispatch table.  The tablejump must have gone already.
        !          3313:      It isn't useful to fall through into a table.  */
        !          3314: 
        !          3315:   if (was_code_label
        !          3316:       && NEXT_INSN (insn) != 0
        !          3317:       && GET_CODE (NEXT_INSN (insn)) == JUMP_INSN
        !          3318:       && (GET_CODE (PATTERN (NEXT_INSN (insn))) == ADDR_VEC
        !          3319:          || GET_CODE (PATTERN (NEXT_INSN (insn))) == ADDR_DIFF_VEC))
        !          3320:     next = delete_insn (NEXT_INSN (insn));
        !          3321: 
        !          3322:   /* If INSN was a label, delete insns following it if now unreachable.  */
        !          3323: 
        !          3324:   if (was_code_label && prev && GET_CODE (prev) == BARRIER)
        !          3325:     {
        !          3326:       register RTX_CODE code;
        !          3327:       while (next != 0
        !          3328:             && ((code = GET_CODE (next)) == INSN
        !          3329:                 || code == JUMP_INSN || code == CALL_INSN
        !          3330:                 || code == NOTE
        !          3331:                 || (code == CODE_LABEL && INSN_DELETED_P (next))))
        !          3332:        {
        !          3333:          if (code == NOTE
        !          3334:              && NOTE_LINE_NUMBER (next) != NOTE_INSN_FUNCTION_END)
        !          3335:            next = NEXT_INSN (next);
        !          3336:          /* Keep going past other deleted labels to delete what follows.  */
        !          3337:          else if (code == CODE_LABEL && INSN_DELETED_P (next))
        !          3338:            next = NEXT_INSN (next);
        !          3339:          else
        !          3340:            /* Note: if this deletes a jump, it can cause more
        !          3341:               deletion of unreachable code, after a different label.
        !          3342:               As long as the value from this recursive call is correct,
        !          3343:               this invocation functions correctly.  */
        !          3344:            next = delete_insn (next);
        !          3345:        }
        !          3346:     }
        !          3347: 
        !          3348:   return next;
        !          3349: }
        !          3350: 
        !          3351: /* Advance from INSN till reaching something not deleted
        !          3352:    then return that.  May return INSN itself.  */
        !          3353: 
        !          3354: rtx
        !          3355: next_nondeleted_insn (insn)
        !          3356:      rtx insn;
        !          3357: {
        !          3358:   while (INSN_DELETED_P (insn))
        !          3359:     insn = NEXT_INSN (insn);
        !          3360:   return insn;
        !          3361: }
        !          3362: 
        !          3363: /* Delete a range of insns from FROM to TO, inclusive.
        !          3364:    This is for the sake of peephole optimization, so assume
        !          3365:    that whatever these insns do will still be done by a new
        !          3366:    peephole insn that will replace them.  */
        !          3367: 
        !          3368: void
        !          3369: delete_for_peephole (from, to)
        !          3370:      register rtx from, to;
        !          3371: {
        !          3372:   register rtx insn = from;
        !          3373: 
        !          3374:   while (1)
        !          3375:     {
        !          3376:       register rtx next = NEXT_INSN (insn);
        !          3377:       register rtx prev = PREV_INSN (insn);
        !          3378: 
        !          3379:       if (GET_CODE (insn) != NOTE)
        !          3380:        {
        !          3381:          INSN_DELETED_P (insn) = 1;
        !          3382: 
        !          3383:          /* Patch this insn out of the chain.  */
        !          3384:          /* We don't do this all at once, because we
        !          3385:             must preserve all NOTEs.  */
        !          3386:          if (prev)
        !          3387:            NEXT_INSN (prev) = next;
        !          3388: 
        !          3389:          if (next)
        !          3390:            PREV_INSN (next) = prev;
        !          3391:        }
        !          3392: 
        !          3393:       if (insn == to)
        !          3394:        break;
        !          3395:       insn = next;
        !          3396:     }
        !          3397: 
        !          3398:   /* Note that if TO is an unconditional jump
        !          3399:      we *do not* delete the BARRIER that follows,
        !          3400:      since the peephole that replaces this sequence
        !          3401:      is also an unconditional jump in that case.  */
        !          3402: }
        !          3403: 
        !          3404: /* Invert the condition of the jump JUMP, and make it jump
        !          3405:    to label NLABEL instead of where it jumps now.  */
        !          3406: 
        !          3407: int
        !          3408: invert_jump (jump, nlabel)
        !          3409:      rtx jump, nlabel;
        !          3410: {
        !          3411:   register rtx olabel = JUMP_LABEL (jump);
        !          3412: 
        !          3413:   /* We have to either invert the condition and change the label or
        !          3414:      do neither.  Either operation could fail.  We first try to invert
        !          3415:      the jump. If that succeeds, we try changing the label.  If that fails,
        !          3416:      we invert the jump back to what it was.  */
        !          3417: 
        !          3418:   if (! invert_exp (PATTERN (jump), jump))
        !          3419:     return 0;
        !          3420: 
        !          3421:   if (redirect_jump (jump, nlabel))
        !          3422:     return 1;
        !          3423: 
        !          3424:   if (! invert_exp (PATTERN (jump), jump))
        !          3425:     /* This should just be putting it back the way it was.  */
        !          3426:     abort ();
        !          3427: 
        !          3428:   return  0;
        !          3429: }
        !          3430: 
        !          3431: /* Invert the jump condition of rtx X contained in jump insn, INSN. 
        !          3432: 
        !          3433:    Return 1 if we can do so, 0 if we cannot find a way to do so that
        !          3434:    matches a pattern.  */
        !          3435: 
        !          3436: int
        !          3437: invert_exp (x, insn)
        !          3438:      rtx x;
        !          3439:      rtx insn;
        !          3440: {
        !          3441:   register RTX_CODE code;
        !          3442:   register int i;
        !          3443:   register char *fmt;
        !          3444: 
        !          3445:   code = GET_CODE (x);
        !          3446: 
        !          3447:   if (code == IF_THEN_ELSE)
        !          3448:     {
        !          3449:       register rtx comp = XEXP (x, 0);
        !          3450:       register rtx tem;
        !          3451: 
        !          3452:       /* We can do this in two ways:  The preferable way, which can only
        !          3453:         be done if this is not an integer comparison, is to reverse
        !          3454:         the comparison code.  Otherwise, swap the THEN-part and ELSE-part
        !          3455:         of the IF_THEN_ELSE.  If we can't do either, fail.  */
        !          3456: 
        !          3457:       if (can_reverse_comparison_p (comp, insn)
        !          3458:          && validate_change (insn, &XEXP (x, 0),
        !          3459:                              gen_rtx (reverse_condition (GET_CODE (comp)),
        !          3460:                                       GET_MODE (comp), XEXP (comp, 0),
        !          3461:                                       XEXP (comp, 1)), 0))
        !          3462:        return 1;
        !          3463:                                       
        !          3464:       tem = XEXP (x, 1);
        !          3465:       validate_change (insn, &XEXP (x, 1), XEXP (x, 2), 1);
        !          3466:       validate_change (insn, &XEXP (x, 2), tem, 1);
        !          3467:       return apply_change_group ();
        !          3468:     }
        !          3469: 
        !          3470:   fmt = GET_RTX_FORMAT (code);
        !          3471:   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
        !          3472:     {
        !          3473:       if (fmt[i] == 'e')
        !          3474:        if (! invert_exp (XEXP (x, i), insn))
        !          3475:          return 0;
        !          3476:       if (fmt[i] == 'E')
        !          3477:        {
        !          3478:          register int j;
        !          3479:          for (j = 0; j < XVECLEN (x, i); j++)
        !          3480:            if (!invert_exp (XVECEXP (x, i, j), insn))
        !          3481:              return 0;
        !          3482:        }
        !          3483:     }
        !          3484: 
        !          3485:   return 1;
        !          3486: }
        !          3487: 
        !          3488: /* Make jump JUMP jump to label NLABEL instead of where it jumps now.
        !          3489:    If the old jump target label is unused as a result,
        !          3490:    it and the code following it may be deleted.
        !          3491: 
        !          3492:    If NLABEL is zero, we are to turn the jump into a (possibly conditional)
        !          3493:    RETURN insn.
        !          3494: 
        !          3495:    The return value will be 1 if the change was made, 0 if it wasn't (this
        !          3496:    can only occur for NLABEL == 0).  */
        !          3497: 
        !          3498: int
        !          3499: redirect_jump (jump, nlabel)
        !          3500:      rtx jump, nlabel;
        !          3501: {
        !          3502:   register rtx olabel = JUMP_LABEL (jump);
        !          3503: 
        !          3504:   if (nlabel == olabel)
        !          3505:     return 1;
        !          3506: 
        !          3507:   if (! redirect_exp (&PATTERN (jump), olabel, nlabel, jump))
        !          3508:     return 0;
        !          3509: 
        !          3510:   /* If this is an unconditional branch, delete it from the jump_chain of
        !          3511:      OLABEL and add it to the jump_chain of NLABEL (assuming both labels
        !          3512:      have UID's in range and JUMP_CHAIN is valid).  */
        !          3513:   if (jump_chain && (simplejump_p (jump)
        !          3514:                     || GET_CODE (PATTERN (jump)) == RETURN))
        !          3515:     {
        !          3516:       int label_index = nlabel ? INSN_UID (nlabel) : 0;
        !          3517: 
        !          3518:       delete_from_jump_chain (jump);
        !          3519:       if (label_index < max_jump_chain
        !          3520:          && INSN_UID (jump) < max_jump_chain)
        !          3521:        {
        !          3522:          jump_chain[INSN_UID (jump)] = jump_chain[label_index];
        !          3523:          jump_chain[label_index] = jump;
        !          3524:        }
        !          3525:     }
        !          3526: 
        !          3527:   JUMP_LABEL (jump) = nlabel;
        !          3528:   if (nlabel)
        !          3529:     ++LABEL_NUSES (nlabel);
        !          3530: 
        !          3531:   if (olabel && --LABEL_NUSES (olabel) == 0)
        !          3532:     delete_insn (olabel);
        !          3533: 
        !          3534:   return 1;
        !          3535: }
        !          3536: 
        !          3537: /* Delete the instruction JUMP from any jump chain it might be on.  */
        !          3538: 
        !          3539: static void
        !          3540: delete_from_jump_chain (jump)
        !          3541:      rtx jump;
        !          3542: {
        !          3543:   int index;
        !          3544:   rtx olabel = JUMP_LABEL (jump);
        !          3545: 
        !          3546:   /* Handle unconditional jumps.  */
        !          3547:   if (jump_chain && olabel != 0
        !          3548:       && INSN_UID (olabel) < max_jump_chain
        !          3549:       && simplejump_p (jump))
        !          3550:     index = INSN_UID (olabel);
        !          3551:   /* Handle return insns.  */
        !          3552:   else if (jump_chain && GET_CODE (PATTERN (jump)) == RETURN)
        !          3553:     index = 0;
        !          3554:   else return;
        !          3555: 
        !          3556:   if (jump_chain[index] == jump)
        !          3557:     jump_chain[index] = jump_chain[INSN_UID (jump)];
        !          3558:   else
        !          3559:     {
        !          3560:       rtx insn;
        !          3561: 
        !          3562:       for (insn = jump_chain[index];
        !          3563:           insn != 0;
        !          3564:           insn = jump_chain[INSN_UID (insn)])
        !          3565:        if (jump_chain[INSN_UID (insn)] == jump)
        !          3566:          {
        !          3567:            jump_chain[INSN_UID (insn)] = jump_chain[INSN_UID (jump)];
        !          3568:            break;
        !          3569:          }
        !          3570:     }
        !          3571: }
        !          3572: 
        !          3573: /* If NLABEL is nonzero, throughout the rtx at LOC,
        !          3574:    alter (LABEL_REF OLABEL) to (LABEL_REF NLABEL).  If OLABEL is
        !          3575:    zero, alter (RETURN) to (LABEL_REF NLABEL).
        !          3576: 
        !          3577:    If NLABEL is zero, alter (LABEL_REF OLABEL) to (RETURN) and check
        !          3578:    validity with validate_change.  Convert (set (pc) (label_ref olabel))
        !          3579:    to (return).
        !          3580: 
        !          3581:    Return 0 if we found a change we would like to make but it is invalid.
        !          3582:    Otherwise, return 1.  */
        !          3583: 
        !          3584: int
        !          3585: redirect_exp (loc, olabel, nlabel, insn)
        !          3586:      rtx *loc;
        !          3587:      rtx olabel, nlabel;
        !          3588:      rtx insn;
        !          3589: {
        !          3590:   register rtx x = *loc;
        !          3591:   register RTX_CODE code = GET_CODE (x);
        !          3592:   register int i;
        !          3593:   register char *fmt;
        !          3594: 
        !          3595:   if (code == LABEL_REF)
        !          3596:     {
        !          3597:       if (XEXP (x, 0) == olabel)
        !          3598:        {
        !          3599:          if (nlabel)
        !          3600:            XEXP (x, 0) = nlabel;
        !          3601:          else
        !          3602:            return validate_change (insn, loc, gen_rtx (RETURN, VOIDmode), 0);
        !          3603:          return 1;
        !          3604:        }
        !          3605:     }
        !          3606:   else if (code == RETURN && olabel == 0)
        !          3607:     {
        !          3608:       x = gen_rtx (LABEL_REF, VOIDmode, nlabel);
        !          3609:       if (loc == &PATTERN (insn))
        !          3610:        x = gen_rtx (SET, VOIDmode, pc_rtx, x);
        !          3611:       return validate_change (insn, loc, x, 0);
        !          3612:     }
        !          3613: 
        !          3614:   if (code == SET && nlabel == 0 && SET_DEST (x) == pc_rtx
        !          3615:       && GET_CODE (SET_SRC (x)) == LABEL_REF
        !          3616:       && XEXP (SET_SRC (x), 0) == olabel)
        !          3617:     return validate_change (insn, loc, gen_rtx (RETURN, VOIDmode), 0);
        !          3618: 
        !          3619:   fmt = GET_RTX_FORMAT (code);
        !          3620:   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
        !          3621:     {
        !          3622:       if (fmt[i] == 'e')
        !          3623:        if (! redirect_exp (&XEXP (x, i), olabel, nlabel, insn))
        !          3624:          return 0;
        !          3625:       if (fmt[i] == 'E')
        !          3626:        {
        !          3627:          register int j;
        !          3628:          for (j = 0; j < XVECLEN (x, i); j++)
        !          3629:            if (! redirect_exp (&XVECEXP (x, i, j), olabel, nlabel, insn))
        !          3630:              return 0;
        !          3631:        }
        !          3632:     }
        !          3633: 
        !          3634:   return 1;
        !          3635: }
        !          3636: 
        !          3637: /* Make jump JUMP jump to label NLABEL, assuming it used to be a tablejump.
        !          3638: 
        !          3639:    If the old jump target label (before the dispatch table) becomes unused,
        !          3640:    it and the dispatch table may be deleted.  In that case, find the insn
        !          3641:    before the jump references that label and delete it and logical successors
        !          3642:    too.  */
        !          3643: 
        !          3644: void
        !          3645: redirect_tablejump (jump, nlabel)
        !          3646:      rtx jump, nlabel;
        !          3647: {
        !          3648:   register rtx olabel = JUMP_LABEL (jump);
        !          3649: 
        !          3650:   /* Add this jump to the jump_chain of NLABEL.  */
        !          3651:   if (jump_chain && INSN_UID (nlabel) < max_jump_chain
        !          3652:       && INSN_UID (jump) < max_jump_chain)
        !          3653:     {
        !          3654:       jump_chain[INSN_UID (jump)] = jump_chain[INSN_UID (nlabel)];
        !          3655:       jump_chain[INSN_UID (nlabel)] = jump;
        !          3656:     }
        !          3657: 
        !          3658:   PATTERN (jump) = gen_jump (nlabel);
        !          3659:   JUMP_LABEL (jump) = nlabel;
        !          3660:   ++LABEL_NUSES (nlabel);
        !          3661:   INSN_CODE (jump) = -1;
        !          3662: 
        !          3663:   if (--LABEL_NUSES (olabel) == 0)
        !          3664:     {
        !          3665:       delete_labelref_insn (jump, olabel, 0);
        !          3666:       delete_insn (olabel);
        !          3667:     }
        !          3668: }
        !          3669: 
        !          3670: /* Find the insn referencing LABEL that is a logical predecessor of INSN.
        !          3671:    If we found one, delete it and then delete this insn if DELETE_THIS is
        !          3672:    non-zero.  Return non-zero if INSN or a predecessor references LABEL.  */
        !          3673: 
        !          3674: static int
        !          3675: delete_labelref_insn (insn, label, delete_this)
        !          3676:      rtx insn, label;
        !          3677:      int delete_this;
        !          3678: {
        !          3679:   int deleted = 0;
        !          3680:   rtx link;
        !          3681: 
        !          3682:   if (GET_CODE (insn) != NOTE
        !          3683:       && reg_mentioned_p (label, PATTERN (insn)))
        !          3684:     {
        !          3685:       if (delete_this)
        !          3686:        {
        !          3687:          delete_insn (insn);
        !          3688:          deleted = 1;
        !          3689:        }
        !          3690:       else
        !          3691:        return 1;
        !          3692:     }
        !          3693: 
        !          3694:   for (link = LOG_LINKS (insn); link; link = XEXP (link, 1))
        !          3695:     if (delete_labelref_insn (XEXP (link, 0), label, 1))
        !          3696:       {
        !          3697:        if (delete_this)
        !          3698:          {
        !          3699:            delete_insn (insn);
        !          3700:            deleted = 1;
        !          3701:          }
        !          3702:        else
        !          3703:          return 1;
        !          3704:       }
        !          3705: 
        !          3706:   return deleted;
        !          3707: }
        !          3708: 
        !          3709: /* Like rtx_equal_p except that it considers two REGs as equal
        !          3710:    if they renumber to the same value.  */
        !          3711: 
        !          3712: int
        !          3713: rtx_renumbered_equal_p (x, y)
        !          3714:      rtx x, y;
        !          3715: {
        !          3716:   register int i;
        !          3717:   register RTX_CODE code = GET_CODE (x);
        !          3718:   register char *fmt;
        !          3719:       
        !          3720:   if (x == y)
        !          3721:     return 1;
        !          3722:   if ((code == REG || (code == SUBREG && GET_CODE (SUBREG_REG (x)) == REG))
        !          3723:       && (GET_CODE (y) == REG || (GET_CODE (y) == SUBREG
        !          3724:                                  && GET_CODE (SUBREG_REG (y)) == REG)))
        !          3725:     {
        !          3726:       register int j;
        !          3727: 
        !          3728:       if (GET_MODE (x) != GET_MODE (y))
        !          3729:        return 0;
        !          3730: 
        !          3731:       /* If we haven't done any renumbering, don't
        !          3732:         make any assumptions.  */
        !          3733:       if (reg_renumber == 0)
        !          3734:        return rtx_equal_p (x, y);
        !          3735: 
        !          3736:       if (code == SUBREG)
        !          3737:        {
        !          3738:          i = REGNO (SUBREG_REG (x));
        !          3739:          if (reg_renumber[i] >= 0)
        !          3740:            i = reg_renumber[i];
        !          3741:          i += SUBREG_WORD (x);
        !          3742:        }
        !          3743:       else
        !          3744:        {
        !          3745:          i = REGNO (x);
        !          3746:          if (reg_renumber[i] >= 0)
        !          3747:            i = reg_renumber[i];
        !          3748:        }
        !          3749:       if (GET_CODE (y) == SUBREG)
        !          3750:        {
        !          3751:          j = REGNO (SUBREG_REG (y));
        !          3752:          if (reg_renumber[j] >= 0)
        !          3753:            j = reg_renumber[j];
        !          3754:          j += SUBREG_WORD (y);
        !          3755:        }
        !          3756:       else
        !          3757:        {
        !          3758:          j = REGNO (y);
        !          3759:          if (reg_renumber[j] >= 0)
        !          3760:            j = reg_renumber[j];
        !          3761:        }
        !          3762:       return i == j;
        !          3763:     }
        !          3764:   /* Now we have disposed of all the cases 
        !          3765:      in which different rtx codes can match.  */
        !          3766:   if (code != GET_CODE (y))
        !          3767:     return 0;
        !          3768:   switch (code)
        !          3769:     {
        !          3770:     case PC:
        !          3771:     case CC0:
        !          3772:     case ADDR_VEC:
        !          3773:     case ADDR_DIFF_VEC:
        !          3774:       return 0;
        !          3775: 
        !          3776:     case CONST_INT:
        !          3777:       return INTVAL (x) == INTVAL (y);
        !          3778: 
        !          3779:     case LABEL_REF:
        !          3780:       /* We can't assume nonlocal labels have their following insns yet.  */
        !          3781:       if (LABEL_REF_NONLOCAL_P (x) || LABEL_REF_NONLOCAL_P (y))
        !          3782:        return XEXP (x, 0) == XEXP (y, 0);
        !          3783:       /* Two label-refs are equivalent if they point at labels
        !          3784:         in the same position in the instruction stream.  */
        !          3785:       return (next_real_insn (XEXP (x, 0))
        !          3786:              == next_real_insn (XEXP (y, 0)));
        !          3787: 
        !          3788:     case SYMBOL_REF:
        !          3789:       return XSTR (x, 0) == XSTR (y, 0);
        !          3790:     }
        !          3791: 
        !          3792:   /* (MULT:SI x y) and (MULT:HI x y) are NOT equivalent.  */
        !          3793: 
        !          3794:   if (GET_MODE (x) != GET_MODE (y))
        !          3795:     return 0;
        !          3796: 
        !          3797:   /* Compare the elements.  If any pair of corresponding elements
        !          3798:      fail to match, return 0 for the whole things.  */
        !          3799: 
        !          3800:   fmt = GET_RTX_FORMAT (code);
        !          3801:   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
        !          3802:     {
        !          3803:       register int j;
        !          3804:       switch (fmt[i])
        !          3805:        {
        !          3806:        case 'w':
        !          3807:          if (XWINT (x, i) != XWINT (y, i))
        !          3808:            return 0;
        !          3809:          break;
        !          3810: 
        !          3811:        case 'i':
        !          3812:          if (XINT (x, i) != XINT (y, i))
        !          3813:            return 0;
        !          3814:          break;
        !          3815: 
        !          3816:        case 's':
        !          3817:          if (strcmp (XSTR (x, i), XSTR (y, i)))
        !          3818:            return 0;
        !          3819:          break;
        !          3820: 
        !          3821:        case 'e':
        !          3822:          if (! rtx_renumbered_equal_p (XEXP (x, i), XEXP (y, i)))
        !          3823:            return 0;
        !          3824:          break;
        !          3825: 
        !          3826:        case 'u':
        !          3827:          if (XEXP (x, i) != XEXP (y, i))
        !          3828:            return 0;
        !          3829:          /* fall through.  */
        !          3830:        case '0':
        !          3831:          break;
        !          3832: 
        !          3833:        case 'E':
        !          3834:          if (XVECLEN (x, i) != XVECLEN (y, i))
        !          3835:            return 0;
        !          3836:          for (j = XVECLEN (x, i) - 1; j >= 0; j--)
        !          3837:            if (!rtx_renumbered_equal_p (XVECEXP (x, i, j), XVECEXP (y, i, j)))
        !          3838:              return 0;
        !          3839:          break;
        !          3840: 
        !          3841:        default:
        !          3842:          abort ();
        !          3843:        }
        !          3844:     }
        !          3845:   return 1;
        !          3846: }
        !          3847: 
        !          3848: /* If X is a hard register or equivalent to one or a subregister of one,
        !          3849:    return the hard register number.  If X is a pseudo register that was not
        !          3850:    assigned a hard register, return the pseudo register number.  Otherwise,
        !          3851:    return -1.  Any rtx is valid for X.  */
        !          3852: 
        !          3853: int
        !          3854: true_regnum (x)
        !          3855:      rtx x;
        !          3856: {
        !          3857:   if (GET_CODE (x) == REG)
        !          3858:     {
        !          3859:       if (REGNO (x) >= FIRST_PSEUDO_REGISTER && reg_renumber[REGNO (x)] >= 0)
        !          3860:        return reg_renumber[REGNO (x)];
        !          3861:       return REGNO (x);
        !          3862:     }
        !          3863:   if (GET_CODE (x) == SUBREG)
        !          3864:     {
        !          3865:       int base = true_regnum (SUBREG_REG (x));
        !          3866:       if (base >= 0 && base < FIRST_PSEUDO_REGISTER)
        !          3867:        return SUBREG_WORD (x) + base;
        !          3868:     }
        !          3869:   return -1;
        !          3870: }
        !          3871: 
        !          3872: /* Optimize code of the form:
        !          3873: 
        !          3874:        for (x = a[i]; x; ...)
        !          3875:          ...
        !          3876:        for (x = a[i]; x; ...)
        !          3877:          ...
        !          3878:       foo:
        !          3879: 
        !          3880:    Loop optimize will change the above code into
        !          3881: 
        !          3882:        if (x = a[i])
        !          3883:          for (;;)
        !          3884:             { ...; if (! (x = ...)) break; }
        !          3885:        if (x = a[i])
        !          3886:          for (;;)
        !          3887:             { ...; if (! (x = ...)) break; }
        !          3888:       foo:
        !          3889: 
        !          3890:    In general, if the first test fails, the program can branch
        !          3891:    directly to `foo' and skip the second try which is doomed to fail.
        !          3892:    We run this after loop optimization and before flow analysis.  */
        !          3893:    
        !          3894: /* When comparing the insn patterns, we track the fact that different
        !          3895:    pseudo-register numbers may have been used in each computation.
        !          3896:    The following array stores an equivalence -- same_regs[I] == J means
        !          3897:    that pseudo register I was used in the first set of tests in a context
        !          3898:    where J was used in the second set.  We also count the number of such
        !          3899:    pending equivalences.  If nonzero, the expressions really aren't the
        !          3900:    same.  */
        !          3901: 
        !          3902: static int *same_regs;
        !          3903: 
        !          3904: static int num_same_regs;
        !          3905: 
        !          3906: /* Track any registers modified between the target of the first jump and
        !          3907:    the second jump.  They never compare equal.  */
        !          3908: 
        !          3909: static char *modified_regs;
        !          3910: 
        !          3911: /* Record if memory was modified.  */
        !          3912: 
        !          3913: static int modified_mem;
        !          3914: 
        !          3915: /* Called via note_stores on each insn between the target of the first 
        !          3916:    branch and the second branch.  It marks any changed registers.  */
        !          3917: 
        !          3918: static void
        !          3919: mark_modified_reg (dest, x)
        !          3920:      rtx dest;
        !          3921:      rtx x;
        !          3922: {
        !          3923:   int regno, i;
        !          3924: 
        !          3925:   if (GET_CODE (dest) == SUBREG)
        !          3926:     dest = SUBREG_REG (dest);
        !          3927: 
        !          3928:   if (GET_CODE (dest) == MEM)
        !          3929:     modified_mem = 1;
        !          3930: 
        !          3931:   if (GET_CODE (dest) != REG)
        !          3932:     return;
        !          3933: 
        !          3934:   regno = REGNO (dest);
        !          3935:   if (regno >= FIRST_PSEUDO_REGISTER)
        !          3936:     modified_regs[regno] = 1;
        !          3937:   else
        !          3938:     for (i = 0; i < HARD_REGNO_NREGS (regno, GET_MODE (dest)); i++)
        !          3939:       modified_regs[regno + i] = 1;
        !          3940: }
        !          3941: 
        !          3942: /* F is the first insn in the chain of insns.  */
        !          3943:    
        !          3944: void
        !          3945: thread_jumps (f, max_reg, verbose)
        !          3946:      rtx f;
        !          3947:      int max_reg;
        !          3948:      int verbose;
        !          3949: {
        !          3950:   /* Basic algorithm is to find a conditional branch,
        !          3951:      the label it may branch to, and the branch after
        !          3952:      that label.  If the two branches test the same condition,
        !          3953:      walk back from both branch paths until the insn patterns
        !          3954:      differ, or code labels are hit.  If we make it back to
        !          3955:      the target of the first branch, then we know that the first branch
        !          3956:      will either always succeed or always fail depending on the relative
        !          3957:      senses of the two branches.  So adjust the first branch accordingly
        !          3958:      in this case.  */
        !          3959:      
        !          3960:   rtx label, b1, b2, t1, t2;
        !          3961:   enum rtx_code code1, code2;
        !          3962:   rtx b1op0, b1op1, b2op0, b2op1;
        !          3963:   int changed = 1;
        !          3964:   int i;
        !          3965:   int *all_reset;
        !          3966: 
        !          3967:   /* Allocate register tables and quick-reset table.  */
        !          3968:   modified_regs = (char *) alloca (max_reg * sizeof (char));
        !          3969:   same_regs = (int *) alloca (max_reg * sizeof (int));
        !          3970:   all_reset = (int *) alloca (max_reg * sizeof (int));
        !          3971:   for (i = 0; i < max_reg; i++)
        !          3972:     all_reset[i] = -1;
        !          3973:     
        !          3974:   while (changed)
        !          3975:     {
        !          3976:       changed = 0;
        !          3977: 
        !          3978:       for (b1 = f; b1; b1 = NEXT_INSN (b1))
        !          3979:        {
        !          3980:          /* Get to a candidate branch insn.  */
        !          3981:          if (GET_CODE (b1) != JUMP_INSN
        !          3982:              || ! condjump_p (b1) || simplejump_p (b1)
        !          3983:              || JUMP_LABEL (b1) == 0)
        !          3984:            continue;
        !          3985: 
        !          3986:          bzero (modified_regs, max_reg * sizeof (char));
        !          3987:          modified_mem = 0;
        !          3988: 
        !          3989:          bcopy (all_reset, same_regs, max_reg * sizeof (int));
        !          3990:          num_same_regs = 0;
        !          3991: 
        !          3992:          label = JUMP_LABEL (b1);
        !          3993: 
        !          3994:          /* Look for a branch after the target.  Record any registers and
        !          3995:             memory modified between the target and the branch.  Stop when we
        !          3996:             get to a label since we can't know what was changed there.  */
        !          3997:          for (b2 = NEXT_INSN (label); b2; b2 = NEXT_INSN (b2))
        !          3998:            {
        !          3999:              if (GET_CODE (b2) == CODE_LABEL)
        !          4000:                break;
        !          4001: 
        !          4002:              else if (GET_CODE (b2) == JUMP_INSN)
        !          4003:                {
        !          4004:                  /* If this is an unconditional jump and is the only use of
        !          4005:                     its target label, we can follow it.  */
        !          4006:                  if (simplejump_p (b2)
        !          4007:                      && JUMP_LABEL (b2) != 0
        !          4008:                      && LABEL_NUSES (JUMP_LABEL (b2)) == 1)
        !          4009:                    {
        !          4010:                      b2 = JUMP_LABEL (b2);
        !          4011:                      continue;
        !          4012:                    }
        !          4013:                  else
        !          4014:                    break;
        !          4015:                }
        !          4016: 
        !          4017:              if (GET_CODE (b2) != CALL_INSN && GET_CODE (b2) != INSN)
        !          4018:                continue;
        !          4019: 
        !          4020:              if (GET_CODE (b2) == CALL_INSN)
        !          4021:                {
        !          4022:                  modified_mem = 1;
        !          4023:                  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
        !          4024:                    if (call_used_regs[i] && ! fixed_regs[i]
        !          4025:                        && i != STACK_POINTER_REGNUM
        !          4026:                        && i != FRAME_POINTER_REGNUM
        !          4027:                        && i != HARD_FRAME_POINTER_REGNUM
        !          4028:                        && i != ARG_POINTER_REGNUM)
        !          4029:                      modified_regs[i] = 1;
        !          4030:                }
        !          4031: 
        !          4032:              note_stores (PATTERN (b2), mark_modified_reg);
        !          4033:            }
        !          4034: 
        !          4035:          /* Check the next candidate branch insn from the label
        !          4036:             of the first.  */
        !          4037:          if (b2 == 0
        !          4038:              || GET_CODE (b2) != JUMP_INSN
        !          4039:              || b2 == b1
        !          4040:              || ! condjump_p (b2)
        !          4041:              || simplejump_p (b2))
        !          4042:            continue;
        !          4043: 
        !          4044:          /* Get the comparison codes and operands, reversing the
        !          4045:             codes if appropriate.  If we don't have comparison codes,
        !          4046:             we can't do anything.  */
        !          4047:          b1op0 = XEXP (XEXP (SET_SRC (PATTERN (b1)), 0), 0);
        !          4048:          b1op1 = XEXP (XEXP (SET_SRC (PATTERN (b1)), 0), 1);
        !          4049:          code1 = GET_CODE (XEXP (SET_SRC (PATTERN (b1)), 0));
        !          4050:          if (XEXP (SET_SRC (PATTERN (b1)), 1) == pc_rtx)
        !          4051:            code1 = reverse_condition (code1);
        !          4052: 
        !          4053:          b2op0 = XEXP (XEXP (SET_SRC (PATTERN (b2)), 0), 0);
        !          4054:          b2op1 = XEXP (XEXP (SET_SRC (PATTERN (b2)), 0), 1);
        !          4055:          code2 = GET_CODE (XEXP (SET_SRC (PATTERN (b2)), 0));
        !          4056:          if (XEXP (SET_SRC (PATTERN (b2)), 1) == pc_rtx)
        !          4057:            code2 = reverse_condition (code2);
        !          4058: 
        !          4059:          /* If they test the same things and knowing that B1 branches
        !          4060:             tells us whether or not B2 branches, check if we
        !          4061:             can thread the branch.  */
        !          4062:          if (rtx_equal_for_thread_p (b1op0, b2op0, b2)
        !          4063:              && rtx_equal_for_thread_p (b1op1, b2op1, b2)
        !          4064:              && (comparison_dominates_p (code1, code2)
        !          4065:                  || comparison_dominates_p (code1, reverse_condition (code2))))
        !          4066:            {
        !          4067:              t1 = prev_nonnote_insn (b1);
        !          4068:              t2 = prev_nonnote_insn (b2);
        !          4069:              
        !          4070:              while (t1 != 0 && t2 != 0)
        !          4071:                {
        !          4072:                  if (t1 == 0 || t2 == 0)
        !          4073:                    break;
        !          4074: 
        !          4075:                  if (t2 == label)
        !          4076:                    {
        !          4077:                      /* We have reached the target of the first branch.
        !          4078:                         If there are no pending register equivalents,
        !          4079:                         we know that this branch will either always
        !          4080:                         succeed (if the senses of the two branches are
        !          4081:                         the same) or always fail (if not).  */
        !          4082:                      rtx new_label;
        !          4083: 
        !          4084:                      if (num_same_regs != 0)
        !          4085:                        break;
        !          4086: 
        !          4087:                      if (comparison_dominates_p (code1, code2))
        !          4088:                        new_label = JUMP_LABEL (b2);
        !          4089:                      else
        !          4090:                        new_label = get_label_after (b2);
        !          4091: 
        !          4092:                      if (JUMP_LABEL (b1) != new_label)
        !          4093:                        {
        !          4094:                          rtx prev = PREV_INSN (new_label);
        !          4095: 
        !          4096:                          if (NOTE_LINE_NUMBER (prev) == NOTE_INSN_LOOP_BEG)
        !          4097:                            {
        !          4098:                              /* Don't branch into the beginning of a loop.
        !          4099:                                 Loop optmization will move loop-invariant
        !          4100:                                 insns out of the loop, and we want to execute
        !          4101:                                 them in this execution thread... */
        !          4102:                              new_label = gen_label_rtx ();
        !          4103:                              emit_label_after (new_label, PREV_INSN (prev));
        !          4104:                            }
        !          4105:                          changed = redirect_jump (b1, new_label);
        !          4106:                        }
        !          4107:                      break;
        !          4108:                    }
        !          4109:                    
        !          4110:                  /* If either of these is not a normal insn (it might be
        !          4111:                     a JUMP_INSN, CALL_INSN, or CODE_LABEL) we fail.  (NOTEs
        !          4112:                     have already been skipped above.)  Similarly, fail
        !          4113:                     if the insns are different.  */
        !          4114:                  if (GET_CODE (t1) != INSN || GET_CODE (t2) != INSN
        !          4115:                      || recog_memoized (t1) != recog_memoized (t2)
        !          4116:                      || ! rtx_equal_for_thread_p (PATTERN (t1),
        !          4117:                                                   PATTERN (t2), t2))
        !          4118:                    break;
        !          4119:                    
        !          4120:                  t1 = prev_nonnote_insn (t1);
        !          4121:                  t2 = prev_nonnote_insn (t2);
        !          4122:                }
        !          4123:            }
        !          4124:        }
        !          4125:     }
        !          4126: }
        !          4127: 
        !          4128: /* This is like RTX_EQUAL_P except that it knows about our handling of
        !          4129:    possibly equivalent registers and knows to consider volatile and
        !          4130:    modified objects as not equal.
        !          4131:    
        !          4132:    YINSN is the insn containing Y.  */
        !          4133: 
        !          4134: int
        !          4135: rtx_equal_for_thread_p (x, y, yinsn)
        !          4136:      rtx x, y;
        !          4137:      rtx yinsn;
        !          4138: {
        !          4139:   register int i;
        !          4140:   register int j;
        !          4141:   register enum rtx_code code;
        !          4142:   register char *fmt;
        !          4143: 
        !          4144:   code = GET_CODE (x);
        !          4145:   /* Rtx's of different codes cannot be equal.  */
        !          4146:   if (code != GET_CODE (y))
        !          4147:     return 0;
        !          4148: 
        !          4149:   /* (MULT:SI x y) and (MULT:HI x y) are NOT equivalent.
        !          4150:      (REG:SI x) and (REG:HI x) are NOT equivalent.  */
        !          4151: 
        !          4152:   if (GET_MODE (x) != GET_MODE (y))
        !          4153:     return 0;
        !          4154: 
        !          4155:   /* Handle special-cases first.  */
        !          4156:   switch (code)
        !          4157:     {
        !          4158:     case REG:
        !          4159:       if (REGNO (x) == REGNO (y) && ! modified_regs[REGNO (x)])
        !          4160:         return 1;
        !          4161: 
        !          4162:       /* If neither is user variable or hard register, check for possible
        !          4163:         equivalence.  */
        !          4164:       if (REG_USERVAR_P (x) || REG_USERVAR_P (y)
        !          4165:          || REGNO (x) < FIRST_PSEUDO_REGISTER
        !          4166:          || REGNO (y) < FIRST_PSEUDO_REGISTER)
        !          4167:        return 0;
        !          4168: 
        !          4169:       if (same_regs[REGNO (x)] == -1)
        !          4170:        {
        !          4171:          same_regs[REGNO (x)] = REGNO (y);
        !          4172:          num_same_regs++;
        !          4173: 
        !          4174:          /* If this is the first time we are seeing a register on the `Y'
        !          4175:             side, see if it is the last use.  If not, we can't thread the 
        !          4176:             jump, so mark it as not equivalent.  */
        !          4177:          if (regno_last_uid[REGNO (y)] != INSN_UID (yinsn))
        !          4178:            return 0;
        !          4179: 
        !          4180:          return 1;
        !          4181:        }
        !          4182:       else
        !          4183:        return (same_regs[REGNO (x)] == REGNO (y));
        !          4184: 
        !          4185:       break;
        !          4186: 
        !          4187:     case MEM:
        !          4188:       /* If memory modified or either volatile, not equivalent.
        !          4189:         Else, check address. */
        !          4190:       if (modified_mem || MEM_VOLATILE_P (x) || MEM_VOLATILE_P (y))
        !          4191:        return 0;
        !          4192: 
        !          4193:       return rtx_equal_for_thread_p (XEXP (x, 0), XEXP (y, 0), yinsn);
        !          4194: 
        !          4195:     case ASM_INPUT:
        !          4196:       if (MEM_VOLATILE_P (x) || MEM_VOLATILE_P (y))
        !          4197:        return 0;
        !          4198: 
        !          4199:       break;
        !          4200: 
        !          4201:     case SET:
        !          4202:       /* Cancel a pending `same_regs' if setting equivalenced registers.
        !          4203:         Then process source.  */
        !          4204:       if (GET_CODE (SET_DEST (x)) == REG
        !          4205:           && GET_CODE (SET_DEST (y)) == REG)
        !          4206:        {
        !          4207:           if (same_regs[REGNO (SET_DEST (x))] == REGNO (SET_DEST (y)))
        !          4208:            {
        !          4209:              same_regs[REGNO (SET_DEST (x))] = -1;
        !          4210:              num_same_regs--;
        !          4211:            }
        !          4212:          else if (REGNO (SET_DEST (x)) != REGNO (SET_DEST (y)))
        !          4213:            return 0;
        !          4214:        }
        !          4215:       else
        !          4216:        if (rtx_equal_for_thread_p (SET_DEST (x), SET_DEST (y), yinsn) == 0)
        !          4217:          return 0;
        !          4218: 
        !          4219:       return rtx_equal_for_thread_p (SET_SRC (x), SET_SRC (y), yinsn);
        !          4220: 
        !          4221:     case LABEL_REF:
        !          4222:       return XEXP (x, 0) == XEXP (y, 0);
        !          4223: 
        !          4224:     case SYMBOL_REF:
        !          4225:       return XSTR (x, 0) == XSTR (y, 0);
        !          4226:     }
        !          4227: 
        !          4228:   if (x == y)
        !          4229:     return 1;
        !          4230: 
        !          4231:   fmt = GET_RTX_FORMAT (code);
        !          4232:   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
        !          4233:     {
        !          4234:       switch (fmt[i])
        !          4235:        {
        !          4236:        case 'w':
        !          4237:          if (XWINT (x, i) != XWINT (y, i))
        !          4238:            return 0;
        !          4239:          break;
        !          4240: 
        !          4241:        case 'n':
        !          4242:        case 'i':
        !          4243:          if (XINT (x, i) != XINT (y, i))
        !          4244:            return 0;
        !          4245:          break;
        !          4246: 
        !          4247:        case 'V':
        !          4248:        case 'E':
        !          4249:          /* Two vectors must have the same length.  */
        !          4250:          if (XVECLEN (x, i) != XVECLEN (y, i))
        !          4251:            return 0;
        !          4252: 
        !          4253:          /* And the corresponding elements must match.  */
        !          4254:          for (j = 0; j < XVECLEN (x, i); j++)
        !          4255:            if (rtx_equal_for_thread_p (XVECEXP (x, i, j),
        !          4256:                                        XVECEXP (y, i, j), yinsn) == 0)
        !          4257:              return 0;
        !          4258:          break;
        !          4259: 
        !          4260:        case 'e':
        !          4261:          if (rtx_equal_for_thread_p (XEXP (x, i), XEXP (y, i), yinsn) == 0)
        !          4262:            return 0;
        !          4263:          break;
        !          4264: 
        !          4265:        case 'S':
        !          4266:        case 's':
        !          4267:          if (strcmp (XSTR (x, i), XSTR (y, i)))
        !          4268:            return 0;
        !          4269:          break;
        !          4270: 
        !          4271:        case 'u':
        !          4272:          /* These are just backpointers, so they don't matter.  */
        !          4273:          break;
        !          4274: 
        !          4275:        case '0':
        !          4276:          break;
        !          4277: 
        !          4278:          /* It is believed that rtx's at this level will never
        !          4279:             contain anything but integers and other rtx's,
        !          4280:             except for within LABEL_REFs and SYMBOL_REFs.  */
        !          4281:        default:
        !          4282:          abort ();
        !          4283:        }
        !          4284:     }
        !          4285:   return 1;
        !          4286: }

unix.superglobalmegacorp.com

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