Annotation of researchv10dc/cmd/gcc/jump.c, revision 1.1

1.1     ! root        1: /* Optimize jump instructions, for GNU compiler.
        !             2:    Copyright (C) 1988 Free Software Foundation, Inc.
        !             3: 
        !             4: This file is part of GNU CC.
        !             5: 
        !             6: GNU CC is distributed in the hope that it will be useful,
        !             7: but WITHOUT ANY WARRANTY.  No author or distributor
        !             8: accepts responsibility to anyone for the consequences of using it
        !             9: or for whether it serves any particular purpose or works at all,
        !            10: unless he says so in writing.  Refer to the GNU CC General Public
        !            11: License for full details.
        !            12: 
        !            13: Everyone is granted permission to copy, modify and redistribute
        !            14: GNU CC, but only under the conditions described in the
        !            15: GNU CC General Public License.   A copy of this license is
        !            16: supposed to have been given to you along with GNU CC so you
        !            17: can know your rights and responsibilities.  It should be in a
        !            18: file named COPYING.  Among other things, the copyright notice
        !            19: and this notice must be preserved on all copies.  */
        !            20: 
        !            21: 
        !            22: /* This is the jump-optimization pass of the compiler.
        !            23:    It is run two or three times: once before cse, sometimes once after cse,
        !            24:    and once after reload (before final).
        !            25: 
        !            26:    jump_optimize deletes unreachable code and labels that are not used.
        !            27:    It also deletes jumps that jump to the following insn,
        !            28:    and simplifies jumps around unconditional jumps and jumps
        !            29:    to unconditional jumps.
        !            30: 
        !            31:    Each CODE_LABEL has a count of the times it is used
        !            32:    stored in the LABEL_NUSES internal field, and each JUMP_INSN
        !            33:    has one label that it refers to stored in the
        !            34:    JUMP_LABEL internal field.  With this we can detect labels that
        !            35:    become unused because of the deletion of all the jumps that
        !            36:    formerly used them.  The JUMP_LABEL info is sometimes looked
        !            37:    at by later passes.
        !            38: 
        !            39:    Optionally, cross-jumping can be done.  Currently it is done
        !            40:    only the last time (when after reload and before final).
        !            41:    In fact, the code for cross-jumping now assumes that register
        !            42:    allocation has been done, since it uses `rtx_renumbered_equal_p'.
        !            43: 
        !            44:    Jump optimization is done after cse when cse's constant-propagation
        !            45:    causes jumps to become unconditional or to be deleted.
        !            46: 
        !            47:    Unreachable loops are not detected here, because the labels
        !            48:    have references and the insns appear reachable from the labels.
        !            49:    find_basic_blocks in flow.c finds and deletes such loops.
        !            50: 
        !            51:    The subroutines delete_insn, redirect_jump, invert_jump, next_real_insn
        !            52:    and prev_real_insn are used from other passes as well.  */
        !            53: 
        !            54: #include "config.h"
        !            55: #include "rtl.h"
        !            56: #include "flags.h"
        !            57: #include "regs.h"
        !            58: 
        !            59: /* ??? Eventually must record somehow the labels used by jumps
        !            60:    from nested functions.  */
        !            61: /* Pre-record the next or previous real insn for each label?
        !            62:    No, this pass is very fast anyway.  */
        !            63: /* Condense consecutive labels?
        !            64:    This would make life analysis faster, maybe.  */
        !            65: /* Optimize jump y; x: ... y: jumpif... x?
        !            66:    Don't know if it is worth bothering with.  */
        !            67: /* Optimize two cases of conditional jump to conditional jump?
        !            68:    This can never delete any instruction or make anything dead,
        !            69:    or even change what is live at any point.
        !            70:    So perhaps let combiner do it.  */
        !            71: 
        !            72: /* Vector indexed by uid.
        !            73:    For each CODE_LABEL, index by its uid to get first unconditional jump
        !            74:    that jumps to the label.
        !            75:    For each JUMP_INSN, index by its uid to get the next unconditional jump
        !            76:    that jumps to the same label.
        !            77:    Element 0 is the start of a chain of all return insns.
        !            78:    (It is safe to use element 0 because insn uid 0 is not used.  */
        !            79: 
        !            80: rtx *jump_chain;
        !            81: 
        !            82: rtx delete_insn ();
        !            83: void redirect_jump ();
        !            84: void invert_jump ();
        !            85: rtx next_real_insn ();
        !            86: rtx prev_real_insn ();
        !            87: rtx next_label ();
        !            88: 
        !            89: static void mark_jump_label ();
        !            90: static void delete_jump ();
        !            91: static void invert_exp ();
        !            92: static void redirect_exp ();
        !            93: static rtx follow_jumps ();
        !            94: static int tension_vector_labels ();
        !            95: static void find_cross_jump ();
        !            96: static void do_cross_jump ();
        !            97: static enum rtx_code reverse_condition ();
        !            98: static int jump_back_p ();
        !            99: 
        !           100: /* Delete no-op jumps and optimize jumps to jumps
        !           101:    and jumps around jumps.
        !           102:    Delete unused labels and unreachable code.
        !           103:    If CROSS_JUMP is nonzero, detect matching code
        !           104:    before a jump and its destination and unify them.
        !           105:    If NOOP_MOVES is nonzero, also delete no-op move insns
        !           106:    and perform machine-specific peephole optimizations
        !           107:    (but flag_no_peephole inhibits the latter).
        !           108: 
        !           109:    If `optimize' is zero, don't change any code,
        !           110:    just determine whether control drops off the end of the function.
        !           111:    This case occurs when we have -W and not -O.
        !           112:    It works because `delete_insn' checks the value of `optimize'
        !           113:    and refrains from actually deleting when that is 0.  */
        !           114: 
        !           115: void
        !           116: jump_optimize (f, cross_jump, noop_moves)
        !           117:      rtx f;
        !           118: {
        !           119:   register rtx insn;
        !           120:   int changed;
        !           121:   int first = 1;
        !           122:   int max_uid = 0;
        !           123:   rtx last_insn;
        !           124: 
        !           125:   /* Initialize LABEL_NUSES and JUMP_LABEL fields.  */
        !           126: 
        !           127:   for (insn = f; insn; insn = NEXT_INSN (insn))
        !           128:     {
        !           129:       if (GET_CODE (insn) == CODE_LABEL)
        !           130:        LABEL_NUSES (insn) = 0;
        !           131:       if (GET_CODE (insn) == JUMP_INSN)
        !           132:        JUMP_LABEL (insn) = 0;
        !           133:       if (INSN_UID (insn) > max_uid)
        !           134:        max_uid = INSN_UID (insn);
        !           135:     }
        !           136: 
        !           137:   max_uid++;
        !           138: 
        !           139:   jump_chain = (rtx *) alloca (max_uid * sizeof (rtx));
        !           140:   bzero (jump_chain, max_uid * sizeof (rtx));
        !           141: 
        !           142:   /* Delete insns following barriers, up to next label.  */
        !           143: 
        !           144:   for (insn = f; insn;)
        !           145:     {
        !           146:       if (GET_CODE (insn) == BARRIER)
        !           147:        {
        !           148:          insn = NEXT_INSN (insn);
        !           149:          while (insn != 0 && GET_CODE (insn) != CODE_LABEL)
        !           150:            {
        !           151:              if (GET_CODE (insn) == NOTE
        !           152:                  && NOTE_LINE_NUMBER (insn) != NOTE_INSN_FUNCTION_END)
        !           153:                insn = NEXT_INSN (insn);
        !           154:              else
        !           155:                insn = delete_insn (insn);
        !           156:            }
        !           157:          /* INSN is now the code_label.  */
        !           158:        }
        !           159:       else
        !           160:        insn = NEXT_INSN (insn);
        !           161:     }
        !           162: 
        !           163:   /* Mark the label each jump jumps to.
        !           164:      Combine consecutive labels, and count uses of labels.
        !           165: 
        !           166:      For each label, make a chain (using `jump_chain')
        !           167:      of all the *unconditional* jumps that jump to it;
        !           168:      also make a chain of all returns.  */
        !           169: 
        !           170:   for (insn = f; insn; insn = NEXT_INSN (insn))
        !           171:     if (GET_CODE (insn) == JUMP_INSN && !insn->volatil)
        !           172:       {
        !           173:        mark_jump_label (PATTERN (insn), insn, cross_jump);
        !           174:        if (JUMP_LABEL (insn) != 0 && simplejump_p (insn))
        !           175:          {
        !           176:            jump_chain[INSN_UID (insn)]
        !           177:              = jump_chain[INSN_UID (JUMP_LABEL (insn))];
        !           178:            jump_chain[INSN_UID (JUMP_LABEL (insn))] = insn;
        !           179:          }
        !           180:        if (GET_CODE (PATTERN (insn)) == RETURN)
        !           181:          {
        !           182:            jump_chain[INSN_UID (insn)] = jump_chain[0];
        !           183:            jump_chain[0] = insn;
        !           184:          }
        !           185:       }
        !           186: 
        !           187:   /* Delete all labels already not referenced.
        !           188:      Also find the last insn.  */
        !           189: 
        !           190:   last_insn = 0;
        !           191:   for (insn = f; insn; )
        !           192:     {
        !           193:       if (GET_CODE (insn) == CODE_LABEL && LABEL_NUSES (insn) == 0)
        !           194:        insn = delete_insn (insn);
        !           195:       else
        !           196:        {
        !           197:          last_insn = insn;
        !           198:          insn = NEXT_INSN (insn);
        !           199:        }
        !           200:     }
        !           201: 
        !           202:   if (!optimize)
        !           203:     {
        !           204:       /* See if there is still a NOTE_INSN_FUNCTION_END in this function.
        !           205:         If so record that this function can drop off the end.  */
        !           206: 
        !           207:       insn = last_insn;
        !           208:       while (insn && (GET_CODE (insn) == CODE_LABEL
        !           209:                      /* If machine uses explicit RETURN insns, no epilogue,
        !           210:                         then this note precedes the drop-through RETURN.  */
        !           211:                      || (GET_CODE (insn) == JUMP_INSN
        !           212:                          && GET_CODE (PATTERN (insn)) == RETURN)))
        !           213:        insn = PREV_INSN (insn);
        !           214: 
        !           215:       if (GET_CODE (insn) == NOTE
        !           216:          && NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_END
        !           217:          && ! insn->volatil)
        !           218:        {
        !           219:          extern int current_function_returns_null;
        !           220:          current_function_returns_null = 1;
        !           221:        }
        !           222:       /* Zero the "deleted" flag of all the "deleted" insns.  */
        !           223:       for (insn = f; insn; insn = NEXT_INSN (insn))
        !           224:        insn->volatil = 0;
        !           225:       return;
        !           226:     }
        !           227: 
        !           228: #if 0
        !           229: #ifdef EXIT_IGNORE_STACK
        !           230:   /* If the last insn just adjusts the stack,
        !           231:      we can delete it on certain machines,
        !           232:      provided we have a frame pointer.  */
        !           233: 
        !           234:   if (frame_pointer_needed && EXIT_IGNORE_STACK)
        !           235:     {
        !           236:       insn = last_insn;
        !           237:       while (insn)
        !           238:        {
        !           239:          rtx prev;
        !           240:          /* Back up to a real insn.  */
        !           241:          if (GET_CODE (insn) != INSN && GET_CODE (insn) != JUMP_INSN
        !           242:              && GET_CODE (insn) != CALL_INSN)
        !           243:            insn = prev_real_insn (insn);
        !           244:          if (insn == 0)
        !           245:            break;
        !           246:          prev = PREV_INSN (insn);
        !           247:          /* If this insn is a stack adjust, delete it.  */
        !           248:          if (GET_CODE (insn) == INSN
        !           249:              && GET_CODE (PATTERN (insn)) == SET
        !           250:              && GET_CODE (SET_DEST (PATTERN (insn))) == REG
        !           251:              && REGNO (SET_DEST (PATTERN (insn))) == STACK_POINTER_REGNUM)
        !           252:            {
        !           253:              delete_insn (insn);
        !           254:              if (insn == last_insn)
        !           255:                last_insn = prev;
        !           256:            }
        !           257:          else
        !           258:            /* If we find an insn that isn't a stack adjust, stop deleting.  */
        !           259:            break;
        !           260:          /* Back up to insn before the deleted one and try to delete more.  */
        !           261:          insn = prev;
        !           262:        }
        !           263:     }
        !           264: #endif
        !           265: #endif
        !           266: 
        !           267:   if (noop_moves)
        !           268:     for (insn = f; insn; )
        !           269:       {
        !           270:        register rtx next = NEXT_INSN (insn);
        !           271: 
        !           272:        if (GET_CODE (insn) == INSN)
        !           273:          {
        !           274:            register rtx body = PATTERN (insn);
        !           275: 
        !           276:            /* Delete insns that existed just to advise flow-analysis.  */
        !           277: 
        !           278:            if (GET_CODE (body) == USE
        !           279:                || GET_CODE (body) == CLOBBER)
        !           280:              delete_insn (insn);
        !           281: 
        !           282:            /* Detect and delete no-op move instructions
        !           283:               resulting from not allocating a parameter in a register.  */
        !           284: 
        !           285:            else if (GET_CODE (body) == SET
        !           286:                     && (SET_DEST (body) == SET_SRC (body)
        !           287:                         || (GET_CODE (SET_DEST (body)) == MEM
        !           288:                             && GET_CODE (SET_SRC (body)) == MEM
        !           289:                             && rtx_equal_p (SET_SRC (body), SET_DEST (body))))
        !           290:                     && ! SET_DEST (body)->volatil
        !           291:                     && ! SET_SRC (body)->volatil)
        !           292:              delete_insn (insn);
        !           293: 
        !           294:            /* Detect and ignore no-op move instructions
        !           295:               resulting from smart or fortuitous register allocation.  */
        !           296: 
        !           297:            else if (GET_CODE (body) == SET)
        !           298:              {
        !           299:                int sreg = true_regnum (SET_SRC (body));
        !           300:                int dreg = true_regnum (SET_DEST (body));
        !           301: 
        !           302:                if (sreg == dreg && sreg >= 0)
        !           303:                  delete_insn (insn);
        !           304:                else if (sreg >= 0 && dreg >= 0)
        !           305:                  {
        !           306:                    rtx tem = find_equiv_reg (0, insn, 0,
        !           307:                                              sreg, 0, dreg);
        !           308:                    if (tem != 0
        !           309:                        && GET_MODE (tem) == GET_MODE (SET_DEST (body)))
        !           310:                      delete_insn (insn);
        !           311:                  }
        !           312:              }
        !           313:          }
        !           314:       insn = next;
        !           315:     }
        !           316: 
        !           317:   /* Now iterate optimizing jumps until nothing changes over one pass.  */
        !           318:   changed = 1;
        !           319:   while (changed)
        !           320:     {
        !           321:       register rtx next;
        !           322:       changed = 0;
        !           323: 
        !           324:       for (insn = f; insn; insn = next)
        !           325:        {
        !           326:          next = NEXT_INSN (insn);
        !           327: 
        !           328:          /* On the first iteration, if this is the last jump pass
        !           329:             (just before final), do the special peephole optimizations.  */
        !           330: 
        !           331:          if (noop_moves && first && !flag_no_peephole)
        !           332:            if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN)
        !           333:              peephole (insn);
        !           334: 
        !           335:          /* Tension the labels in dispatch tables.  */
        !           336: 
        !           337:          if (GET_CODE (insn) == JUMP_INSN)
        !           338:            {
        !           339:              if (GET_CODE (PATTERN (insn)) == ADDR_VEC)
        !           340:                changed |= tension_vector_labels (PATTERN (insn), 0);
        !           341:              if (GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
        !           342:                changed |= tension_vector_labels (PATTERN (insn), 1);
        !           343:            }
        !           344: 
        !           345:          if (GET_CODE (insn) == JUMP_INSN && JUMP_LABEL (insn))
        !           346:            {
        !           347:              register rtx reallabelprev = prev_real_insn (JUMP_LABEL (insn));
        !           348: 
        !           349:              /* Delete insns that adjust stack pointer before a return,
        !           350:                 if this is the last jump-optimization before final
        !           351:                 and we need to have a frame pointer.  */
        !           352: #if 0
        !           353: #ifdef EXIT_IGNORE_STACK
        !           354:              if (noop_moves && frame_pointer_needed && EXIT_IGNORE_STACK
        !           355:                  && NEXT_INSN (JUMP_LABEL (insn)) == 0)
        !           356:                {
        !           357:                  rtx prev = prev_real_insn (insn);
        !           358:                  if (prev != 0
        !           359:                      && GET_CODE (prev) == INSN
        !           360:                      && GET_CODE (PATTERN (prev)) == SET
        !           361:                      && GET_CODE (SET_DEST (PATTERN (prev))) == REG
        !           362:                      && REGNO (SET_DEST (PATTERN (prev))) == STACK_POINTER_REGNUM)
        !           363:                    {
        !           364:                      delete_insn (prev);
        !           365:                      changed = 1;
        !           366:                    }
        !           367:                }
        !           368: #endif
        !           369: #endif
        !           370: 
        !           371:              /* Detect jump to following insn.  */
        !           372:              if (reallabelprev == insn && condjump_p (insn))
        !           373:                {
        !           374:                  reallabelprev = PREV_INSN (insn);
        !           375:                  delete_jump (insn);
        !           376:                  changed = 1;
        !           377:                }
        !           378:              /* Detect jumping over an unconditional jump.  */
        !           379:              else if (reallabelprev != 0
        !           380:                       && GET_CODE (reallabelprev) == JUMP_INSN
        !           381:                       && prev_real_insn (reallabelprev) == insn
        !           382:                       && no_labels_between_p (insn, reallabelprev)
        !           383:                       && simplejump_p (reallabelprev)
        !           384:                       /* Ignore this if INSN is a hairy kind of jump,
        !           385:                          since they may not be invertible.
        !           386:                          This is conservative; could instead construct
        !           387:                          the inverted insn and try recognizing it.  */
        !           388:                       && condjump_p (insn))
        !           389:                {
        !           390:                  /* Delete the original unconditional jump (and barrier).  */
        !           391:                  /* But don't lEST (PATTERN (insn))) == STACK_POINTER_REGNUM)
        !           392:            {
        !           393:              delete_insn (insn);
        !           394:              if (insn == last_insn)
        !           395:                last_insn = prev;
        !           396:            }
        !           397:          else
        !           398:            /* If we find an insn that isn't a stack adjust, stop deleting.  */
        !           399:            break;
        !           400:          /* Back up to insn before the deleted one and try to delete more.  */
        !           401:          insn = prev;
        !           402:        }
        !           403:     }
        !           404: #endif
        !           405: #endif
        !           406: 
        !           407:   if (noop_moves)
        !           408:     for (insn = f; insn; )
        !           409:       {
        !           410:        register rtx next = NEXT_INSN (insn);
        !           411: 
        !           412:        if (GET_CODE (insn) == INSN)
        !           413:          {
        !           414:            register rtx body = PATTERN (insn);
        !           415: 
        !           416:            /* Delete insns that existed just to advise flow-analysis.  */
        !           417: 
        !           418:            if (GET_CODE (body) == USE
        !           419:                || GET_CODE (body) == CLOBBER)
        !           420:              delete_insn (insn);
        !           421: 
        !           422:            /* Detect and delete no-op move instructions
        !           423:               resulting from not allocating a parameter in a register.  */
        !           424: 
        !           425:            else if (GET_CODE (body) == SET
        !           426:                     && (SET_DEST (body) == SET_SRC (body)
        !           427:                         || (GET_CODE (SET_DEST (body)) == MEM
        !           428:                             && GET_CODE (SET_SRC (body)) == MEM
        !           429:                             && rtx_equal_p (SET_SRC (body), SET_DEST (body))))
        !           430:                     && ! SET_DEST (body)->volatil
        !           431:                     && ! SET_SRC (body)->volatil)
        !           432:              delete_insn (insn);
        !           433: 
        !           434:            /* Detect and ignore no-op move instructions
        !           435:               resulting from smart or fortuitous register allocation.  */
        !           436: 
        !           437:            else if (GET_CODE (body) == SET)
        !           438:              {
        !           439:                int sreg = true_regnum (SET_SRC (body));
        !           440:                int dreg = true_regnum (SET_DEST (body));
        !           441: 
        !           442:                if (sreg == dreg && sreg >= 0)
        !           443:                  delete_insn (insn);
        !           444:                else if (sreg >= 0 && dreg >= 0)
        !           445:                  {
        !           446:                    rtx tem = find_equiv_reg (0, insn, 0,
        !           447:                                              sreg, 0, dreg);
        !           448:                    if (tem != 0
        !           449:                        && GET_MODE (tem) == GET_MODE (SET_DEST (body)))
        !           450:                      delete_insn (insn);
        !           451:                  }
        !           452:              }
        !           453:          }
        !           454:       insn = next;
        !           455:     }
        !           456: 
        !           457:   /* Now iterate optimizing jumps until nothing changes over one pass.  */
        !           458:   changed = 1;
        !           459:   while (changed)
        !           460:     {
        !           461:       register rtx next;
        !           462:       changed = 0;
        !           463: 
        !           464:       for (insn = f; insn; insn = next)
        !           465:        {
        !           466:          next = NEXT_INSN (insn);
        !           467: 
        !           468:          /* On the first iteration, if this is the last jump pass
        !           469:             (just before final), do the special peephole optimizations.  */
        !           470: 
        !           471:          if (noop_moves && first && !flag_no_peephole)
        !           472:            if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN)
        !           473:              peephole (insn);
        !           474: 
        !           475:          /* Tension the labels in dispatch tables.  */
        !           476: 
        !           477:          if (GET_CODE (insn) == JUMP_INSN)
        !           478:            {
        !           479:              if (GET_CODE (PATTERN (insn)) == ADDR_VEC)
        !           480:                changed |= tension_vector_labels (PATTERN (insn), 0);
        !           481:              if (GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
        !           482:                changed |= tension_vector_labels (PATTERN (insn), 1);
        !           483:            }
        !           484: 
        !           485:          if (GET_CODE (insn) == JUMP_INSN && JUMP_LABEL (insn))
        !           486:            {
        !           487:              register rtx reallabelprev = prev_real_insn (JUMP_LABEL (insn));
        !           488: 
        !           489:              /* Delete insns that adjust stack pointer before a return,
        !           490:                 if this is the last jump-optimization before final
        !           491:                 and we need to have a frame pointer.  */
        !           492: #if 0
        !           493: #ifdef EXIT_IGNORE_STACK
        !           494:              if (noop_moves && frame_pointer_needed && EXIT_IGNORE_STACK
        !           495:                  && NEXT_INSN (JUMP_LABEL (insn)) == 0)
        !           496:                {
        !           497:                  rtx prev = prev_real_insn (insn);
        !           498:                  if (prev != 0
        !           499:                      && GET_CODE (prev) == INSN
        !           500:                      && GET_CODE (PATTERN (prev)) == SET
        !           501:                      && GET_CODE (SET_DEST (PATTERN (prev))) == REG
        !           502:                      && REGNO (SET_DEST (PATTERN (prev))) == STACK_POINTER_REGNUM)
        !           503:                    {
        !           504:                      delete_insn (prev);
        !           505:                      changed = 1;
        !           506:                    }
        !           507:                }
        !           508: #endif
        !           509: #endif
        !           510: 
        !           511:              /* Detect jump to following insn.  */
        !           512:              if (reallabelprev == insn && condjump_p (insn))
        !           513:                {
        !           514:                  reallabelprev = PREV_INSN (insn);
        !           515:                  delete_jump (insn);
        !           516:                  changed = 1;
        !           517:                }
        !           518:              /* Detect jumping over an unconditional jump.  */
        !           519:              else if (reallabelprev != 0
        !           520:                       && GET_CODE (reallabelprev) == JUMP_INSN
        !           521:                       && prev_real_insn (reallabelprev) == insn
        !           522:                       && no_labels_between_p (insn, reallabelprev)
        !           523:                       && simplejump_p (reallabelprev)
        !           524:                       /* Ignore this if INSN is a hairy kind of jump,
        !           525:                          since they may not be invertible.
        !           526:                          This is conservative; could instead construct
        !           527:                          the inverted insn and try recognizing it.  */
        !           528:                       && condjump_p (insn))
        !           529:                {
        !           530:                  /* Delete the original unconditional jump (and barrier).  */
        !           531:                  /* But don't l/* If cannot cross jump to code before the label,
        !           532:                         see if we can cross jump to another jump to
        !           533:                         the same label.  */
        !           534:                      /* Try each other jump to this label.  */
        !           535:                      if (INSN_UID (JUMP_LABEL (insn)) < max_uid)
        !           536:                        for (target = jump_chain[INSN_UID (JUMP_LABEL (insn))];
        !           537:                             target != 0 && newjpos == 0;
        !           538:                             target = jump_chain[INSN_UID (target)])
        !           539:                          if (target != insn
        !           540:                              && JUMP_LABEL (target) == JUMP_LABEL (insn)
        !           541:                              /* Ignore TARGET if it's deleted.  */
        !           542:                              && ! target->volatil)
        !           543:                            find_cross_jump (insn, target, 2,
        !           544:                                             &newjpos, &newlpos);
        !           545: 
        !           546:                      if (newjpos != 0)
        !           547:                        {
        !           548:                          do_cross_jump (insn, newjpos, newlpos);
        !           549:                          changed = 1;
        !           550:                          next = insn;
        !           551:                        }
        !           552:                    }
        !           553:                }
        !           554:            }
        !           555:          else if (GET_CODE (insn) == JUMP_INSN
        !           556:                   && GET_CODE (PATTERN (insn)) == RETURN)
        !           557:            {
        !           558:              /* Return insns all "jump to the same place"
        !           559:                 so we can cross-jump between any two of them.  */
        !           560:              if (cross_jump)
        !           561:                {
        !           562:                  rtx newjpos, newlpos, target;
        !           563: 
        !           564:                  newjpos = 0;
        !           565: 
        !           566:                  /* If cannot cross jump to code before the label,
        !           567:                     see if we can cross jump to another jump to
        !           568:                     the same label.  */
        !           569:                  /* Try each other jump to this label.  */
        !           570:                  for (target = jump_chain[0];
        !           571:                       target != 0 && newjpos == 0;
        !           572:                       target = jump_chain[INSN_UID (target)])
        !           573:                    if (target != insn
        !           574:                        && ! target->volatil
        !           575:                        && GET_CODE (PATTERN (target)) == RETURN)
        !           576:                      find_cross_jump (insn, target, 2,
        !           577:                                       &newjpos, &newlpos);
        !           578: 
        !           579:                  if (newjpos != 0)
        !           580:                    {
        !           581:                      do_cross_jump (insn, newjpos, newlpos);
        !           582:                      changed = 1;
        !           583:                      next = insn;
        !           584:                    }
        !           585:                }
        !           586:            }
        !           587: 
        !           588:        }
        !           589: 
        !           590:       first = 0;
        !           591:     }
        !           592: 
        !           593:   /* See if there is still a NOTE_INSN_FUNCTION_END in this function.
        !           594:      If so, delete it, and record that this function can drop off the end.  */
        !           595: 
        !           596:   insn = last_insn;
        !           597:   while (insn && (GET_CODE (insn) == CODE_LABEL
        !           598:                  /* If machine uses explicit RETURN insns, no epilogue,
        !           599:                     then this note precedes the drop-through RETURN.  */
        !           600:                  || (GET_CODE (insn) == JUMP_INSN
        !           601:                      && GET_CODE (PATTERN (insn)) == RETURN)))
        !           602:     insn = PREV_INSN (insn);
        !           603:   if (GET_CODE (insn) == NOTE && NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_END)
        !           604:     {
        !           605:       extern int current_function_returns_null;
        !           606:       current_function_returns_null = 1;
        !           607:       delete_insn (insn);
        !           608:     }
        !           609: }
        !           610: 
        !           611: /* Compare the instructions before insn E1 with those before E2.
        !           612:    Assume E1 is a jump that jumps to label E2
        !           613:    (that is not always true but it might as well be).
        !           614:    Find the longest possible equivalent sequences
        !           615:    and store the first insns of those sequences into *F1 and *F2.
        !           616:    Store zero there if no equivalent preceding instructions are found.
        !           617: 
        !           618:    We give up if we find a label in stream 1.
        !           619:    Actually we could transfer that label into stream 2.  */
        !           620: 
        !           621: static void
        !           622: find_cross_jump (e1, e2, minimum, f1, f2)
        !           623:      rtx e1, e2;
        !           624:      int minimum;
        !           625:      rtx *f1, *f2;
        !           626: {
        !           627:   register rtx i1 = e1, i2 = e2;
        !           628:   register rtx p1, p2;
        !           629: 
        !           630:   rtx last1 = 0, last2 = 0;
        !           631:   rtx afterlast1 = 0, afterlast2 = 0;
        !           632: 
        !           633:   *f1 = 0;
        !           634:   *f2 = 0;
        !           635: 
        !           636:   while (1)
        !           637:     {
        !           638:       i1 = PREV_INSN (i1);
        !           639:       while (i1 && GET_CODE (i1) == NOTE)
        !           640:        i1 = PREV_INSN (i1);
        !           641: 
        !           642:       i2 = PREV_INSN (i2);
        !           643:       while (i2 && (GET_CODE (i2) == NOTE || GET_CODE (i2) == CODE_LABEL))
        !           644:        i2 = PREV_INSN (i2);
        !           645: 
        !           646:       if (i1 == 0)
        !           647:        break;
        !           648: 
        !           649:       /* If we will get to this code by jumping, those jumps will be
        !           650:         tensioned to go directly to the new label (before I2),
        !           651:         so this cross-jumping won't cost extra.  So reduce the minimum.  */
        !           652:       if (GET_CODE (i1) == CODE_LABEL)
        !           653:        {
        !           654:          --minimum;
        !           655:          break;
        !           656:        }
        !           657: 
        !           658:       if (i2 == 0 || GET_CODE (i1) != GET_CODE (i2))
        !           659:        break;
        !           660: 
        !           661:       p1 = PATTERN (i1);
        !           662:       p2 = PATTERN (i2);
        !           663:        
        !           664:       if (GET_CODE (p1) != GET_CODE (p2)
        !           665:          || !rtx_renumbered_equal_p (p1, p2))
        !           666:        {
        !           667:          /* Insns fail to match; cross jumping is limited to the following
        !           668:             insns.  */
        !           669: 
        !           670:          /* Don't allow the insn after a compare to be shared by cross-jumping
        !           671:             unless the compare is also shared.
        !           672:             Here, if either of these non-matching insns is a compare,
        !           673:             exclude the following insn from possible cross-jumping.  */
        !           674:          if ((GET_CODE (p1) == SET && SET_DEST (p1) == cc0_rtx)
        !           675:              || (GET_CODE (p2) == SET && SET_DEST (p2) == cc0_rtx))
        !           676:            last1 = afterlast1, last2 = afterlast2, ++minimum;
        !           677: 
        !           678:          /* If cross-jumping here will feed a jump-around-jump optimization,
        !           679:             this jump won't cost extra, so reduce the minimum.  */
        !           680:          if (GET_CODE (i1) == JUMP_INSN
        !           681:              && JUMP_LABEL (i1)
        !           682:              && prev_real_insn (JUMP_LABEL (i1)) == e1)
        !           683:            --minimum;
        !           684:          break;
        !           685:        }
        !           686: 
        !           687:       if (GET_CODE (p1) != USE && GET_CODE (p1) != CLOBBER)
        !           688:        {
        !           689:          /* Ok, this insn is potentially includable in a cross-jump here.  */
        !           690:          afterlast1 = last1, afterlast2 = last2;
        !           691:          last1 = i1, last2 = i2, --minimum;
        !           692:        }
        !           693:     }
        !           694: 
        !           695:   if (minimum <= 0 && last1 != 0)
        !           696:     *f1 = last1, *f2 = last2;
        !           697: }
        !           698: 
        !           699: static void
        !           700: do_cross_jump (insn, newjpos, newlpos)
        !           701:      rtx insn, newjpos, newlpos;
        !           702: {
        !           703:   register rtx label;
        !           704:   /* Find an existing label at this point
        !           705:      or make a new one if there is none.  */
        !           706:   label = PREV_INSN (newlpos);
        !           707:   if (GET_CODE (label) != CODE_LABEL)
        !           708:     {
        !           709:       label = gen_label_rtx ();
        !           710:       emit_label_after (label, PREV_INSN (newlpos));
        !           711:       LABEL_NUSES (label) = 0;
        !           712:     }
        !           713:   /* Make the same jump insn jump to the new point.  */
        !           714:   if (GET_CODE (PATTERN (insn)) == RETURN)
        !           715:     {
        !           716:       extern rtx gen_jump ();
        !           717:       PATTERN (insn) = gen_jump (label);
        !           718:       INSN_CODE (insn) = -1;
        !           719:       JUMP_LABEL (insn) = label;
        !           720:       LABEL_NUSES (label)++;
        !           721:     }
        !           722:   else
        !           723:     redirect_jump (insn, label);
        !           724:   /* Delete the matching insns before the jump.  */
        !           725:   newjpos = PREV_INSN (newjpos);
        !           726:   while (NEXT_INSN (newjpos) != insn)
        !           727:     /* Don't delete line numbers.  */
        !           728:     if (GET_CODE (NEXT_INSN (newjpos)) != NOTE)
        !           729:       delete_insn (NEXT_INSN (newjpos));
        !           730:     else
        !           731:       newjpos = NEXT_INSN (newjpos);
        !           732: }
        !           733: 
        !           734: /* Return 1 if INSN is a jump that jumps to right after TARGET
        !           735:    only on the condition that TARGET itself would drop through.
        !           736:    Assumes that TARGET is a conditional jump.  */
        !           737: 
        !           738: static int
        !           739: jump_back_p (insn, target)
        !           740:      rtx insn, target;
        !           741: {
        !           742:   rtx cinsn, ctarget;
        !           743:   enum rtx_code codei, codet;
        !           744: 
        !           745:   if (simplejump_p (insn) || ! condjump_p (insn)
        !           746:       || simplejump_p (target))
        !           747:     return 0;
        !           748:   if (target != prev_real_insn (JUMP_LABEL (insn)))
        !           749:     return 0;
        !           750: 
        !           751:   cinsn = XEXP (SET_SRC (PATTERN (insn)), 0);
        !           752:   ctarget = XEXP (SET_SRC (PATTERN (target)), 0);
        !           753: 
        !           754:   codei = GET_CODE (cinsn);
        !           755:   codet = GET_CODE (ctarget);
        !           756:   if (XEXP (SET_SRC (PATTERN (insn)), 1) == pc_rtx)
        !           757:     codei = reverse_condition (codei);
        !           758:   if (XEXP (SET_SRC (PATTERN (target)), 2) == pc_rtx)
        !           759:     codet = reverse_condition (codet);
        !           760:   return (codei == codet
        !           761:          && rtx_renumbered_equal_p (XEXP (cinsn, 0), XEXP (ctarget, 0))
        !           762:          && rtx_renumbered_equal_p (XEXP (cinsn, 1), XEXP (ctarget, 1)));
        !           763: }
        !           764: 
        !           765: /* Given an rtx-code for a comparison, return the code
        !           766:    for the negated comparison.  */
        !           767: 
        !           768: static enum rtx_code
        !           769: reverse_condition (code)
        !           770:      enum rtx_code code;
        !           771: {
        !           772:   switch (code)
        !           773:     {
        !           774:     case EQ:
        !           775:       return NE;
        !           776: 
        !           777:     case NE:
        !           778:       return EQ;
        !           779: 
        !           780:     case GT:
        !           781:       return LE;
        !           782: 
        !           783:     case GE:
        !           784:       return LT;
        !           785: 
        !           786:     case LT:
        !           787:       return GE;
        !           788: 
        !           789:     case LE:
        !           790:       return GT;
        !           791: 
        !           792:     case GTU:
        !           793:       return LEU;
        !           794: 
        !           795:     case GEU:
        !           796:       return LTU;
        !           797: 
        !           798:     case LTU:
        !           799:       return GEU;
        !           800: 
        !           801:     case LEU:
        !           802:       return GTU;
        !           803: 
        !           804:     default:
        !           805:       abort ();
        !           806:       return UNKNOWN;
        !           807:     }
        !           808: }
        !           809: 
        !           810: /* Return 1 if INSN is an unconditional jump and nothing else.  */
        !           811: 
        !           812: int
        !           813: simplejump_p (insn)
        !           814:      rtx insn;
        !           815: {
        !           816:   register rtx x = PATTERN (insn);
        !           817:   if (GET_CODE (x) != SET)
        !           818:     return 0;
        !           819:   if (GET_CODE (SET_DEST (x)) != PC)
        !           820:     return 0;
        !           821:   if (GET_CODE (SET_SRC (x)) != LABEL_REF)
        !           822:     return 0;
        !           823:   return 1;
        !           824: }
        !           825: 
        !           826: /* Return nonzero if INSN is a (possibly) conditional jump
        !           827:    and nothing more.  */
        !           828: 
        !           829: static int
        !           830: condjump_p (insn)
        !           831:      rtx insn;
        !           832: {
        !           833:   register rtx x = PATTERN (insn);
        !           834:   if (GET_CODE (x) != SET)
        !           835:     return 0;
        !           836:   if (GET_CODE (SET_DEST (x)) != PC)
        !           837:     return 0;
        !           838:   if (GET_CODE (SET_SRC (x)) == LABEL_REF)
        !           839:     return 1;
        !           840:   if (GET_CODE (SET_SRC (x)) != IF_THEN_ELSE)
        !           841:     return 0;
        !           842:   if (XEXP (SET_SRC (x), 2) == pc_rtx
        !           843:       && GET_CODE (XEXP (SET_SRC (x), 1)) == LABEL_REF)
        !           844:     return 1;
        !           845:   if (XEXP (SET_SRC (x), 1) == pc_rtx
        !           846:       && GET_CODE (XEXP (SET_SRC (x), 2)) == LABEL_REF)
        !           847:     return 1;
        !           848:   return 0;
        !           849: }
        !           850: 
        !           851: /* Return 1 if in between BEG and END there is no CODE_LABEL insn.  */
        !           852: 
        !           853: int
        !           854: no_labels_between_p (beg, end)
        !           855:      rtx beg, end;
        !           856: {
        !           857:   register rtx p;
        !           858:   for (p = beg; p != end; p = NEXT_INSN (p))
        !           859:     if (GET_CODE (p) == CODE_LABEL)
        !           860:       return 0;
        !           861:   return 1;
        !           862: }
        !           863: 
        !           864: /* Return the last INSN, CALL_INSN or JUMP_INSN before LABEL;
        !           865:    or 0, if there is none.  */
        !           866: 
        !           867: rtx
        !           868: prev_real_insn (label)
        !           869:      rtx label;
        !           870: {
        !           871:   register rtx insn = PREV_INSN (label);
        !           872:   register RTX_CODE code;
        !           873: 
        !           874:   while (1)
        !           875:     {
        !           876:       if (insn == 0)
        !           877:        return 0;
        !           878:       code = GET_CODE (insn);
        !           879:       if (code == INSN || code == CALL_INSN || code == JUMP_INSN)
        !           880:        break;
        !           881:       insn = PREV_INSN (insn);
        !           882:     }
        !           883: 
        !           884:   return insn;
        !           885: }
        !           886: 
        !           887: /* Return the next INSN, CALL_INSN or JUMP_INSN after LABEL;
        !           888:    or 0, if there is none.  */
        !           889: 
        !           890: rtx
        !           891: next_real_insn (label)
        !           892:      rtx label;
        !           893: {
        !           894:   register rtx insn = NEXT_INSN (label);
        !           895:   register RTX_CODE code;
        !           896: 
        !           897:   while (1)
        !           898:     {
        !           899:       if (insn == 0)
        !           900:        return insn;
        !           901:       code = GET_CODE (insn);
        !           902:       if (code == INSN || code == CALL_INSN || code == JUMP_INSN)
        !           903:        break;
        !           904:       insn = NEXT_INSN (insn);
        !           905:     }
        !           906: 
        !           907:   return insn;
        !           908: }
        !           909: 
        !           910: /* Return the next CODE_LABEL after the insn INSN, or 0 if there is none.  */
        !           911: 
        !           912: rtx
        !           913: next_label (insn)
        !           914:      rtx insn;
        !           915: {
        !           916:   do insn = NEXT_INSN (insn);
        !           917:   while (insn != 0 && GET_CODE (insn) != CODE_LABEL);
        !           918:   return insn;
        !           919: }
        !           920: 
        !           921: /* Follow any unconditional jump at LABEL;
        !           922:    return the ultimate label reached by any such chain of jumps.
        !           923:    If LABEL is not followed by a jump, return LABEL.  */
        !           924: 
        !           925: static rtx
        !           926: follow_jumps (label)
        !           927:      rtx label;
        !           928: {
        !           929:   register rtx insn;
        !           930:   register rtx next;
        !           931:   register rtx value = label;
        !           932:   register int depth;
        !           933: 
        !           934:   for (depth = 0;
        !           935:        (depth < 10
        !           936:        && (insn = next_real_insn (value)) != 0
        !           937:        && GET_CODE (insn) == JUMP_INSN
        !           938:        && JUMP_LABEL (insn) != 0
        !           939:        && (next = NEXT_INSN (insn))
        !           940:        && GET_CODE (next) == BARRIER);
        !           941:        depth++)
        !           942:     {
        !           943:       /* If we have found a cycle, make the insn jump to itself.  */
        !           944:       if (JUMP_LABEL (insn) == label)
        !           945:        break;
        !           946:       value = JUMP_LABEL (insn);
        !           947:     }
        !           948:   return value;
        !           949: }
        !           950: 
        !           951: /* Assuming that field IDX of X is a vector of label_refs,
        !           952:    replace each of them by the ultimate label reached by it.
        !           953:    Return nonzero if a change is made.  */
        !           954: 
        !           955: static int
        !           956: tension_vector_labels (x, idx)
        !           957:      register rtx x;
        !           958:      register int idx;
        !           959: {
        !           960:   int changed = 0;
        !           961:   register int i;
        !           962:   for (i = XVECLEN (x, idx) - 1; i >= 0; i--)
        !           963:     {
        !           964:       register rtx olabel = XEXP (XVECEXP (x, idx, i), 0);
        !           965:       register rtx nlabel = follow_jumps (olabel);
        !           966:       if (nlabel != olabel)
        !           967:        {
        !           968:          XEXP (XVECEXP (x, idx, i), 0) = nlabel;
        !           969:          ++LABEL_NUSES (nlabel);
        !           970:          if (--LABEL_NUSES (olabel) == 0)
        !           971:            delete_insn (olabel);
        !           972:          changed = 1;
        !           973:        }
        !           974:     }
        !           975:   return changed;
        !           976: }
        !           977: 
        !           978: /* Find all CODE_LABELs referred to in X,
        !           979:    and increment their use counts.
        !           980:    Also store one of them in JUMP_LABEL (INSN) if INSN is nonzero.
        !           981:    Also, when there are consecutive labels,
        !           982:    canonicalize on the last of them.
        !           983: 
        !           984:    Note that two labels separated by a loop-beginning note
        !           985:    must be kept distinct if we have not yet done loop-optimization,
        !           986:    because the gap between them is where loop-optimize
        !           987:    will want to move invariant code to.  CROSS_JUMP tells us
        !           988:    that loop-optimization is done with.  */
        !           989: 
        !           990: static void
        !           991: mark_jump_label (x, insn, cross_jump)
        !           992:      register rtx x;
        !           993:      rtx insn;
        !           994:      int cross_jump;
        !           995: {
        !           996:   register RTX_CODE code = GET_CODE (x);
        !           997:   register int i;
        !           998:   register char *fmt;
        !           999: 
        !          1000:   if (code == LABEL_REF)
        !          1001:     {
        !          1002:       register rtx label = XEXP (x, 0);
        !          1003:       register rtx next;
        !          1004:       if (GET_CODE (label) != CODE_LABEL)
        !          1005:        return;
        !          1006:       /* If there are other labels following this one,
        !          1007:         replace it with the last of the consecutive labels.  */
        !          1008:       for (next = NEXT_INSN (label); next; next = NEXT_INSN (next))
        !          1009:        {
        !          1010:          if (GET_CODE (next) == CODE_LABEL)
        !          1011:            label = next;
        !          1012:          else if (GET_CODE (next) != NOTE
        !          1013:                   || NOTE_LINE_NUMBER (next) == NOTE_INSN_LOOP_BEG
        !          1014:                   || NOTE_LINE_NUMBER (next) == NOTE_INSN_FUNCTION_END)
        !          1015:            break;
        !          1016:        }
        !          1017:       XEXP (x, 0) = label;
        !          1018:       ++LABEL_NUSES (label);
        !          1019:       if (insn)
        !          1020:        JUMP_LABEL (insn) = label;
        !          1021:       return;
        !          1022:     }
        !          1023: 
        !          1024:   /* Do walk the labels in a vector,
        !          1025:      but don't set its JUMP_LABEL.  */
        !          1026:   if (code == ADDR_VEC || code == ADDR_DIFF_VEC)
        !          1027:     insn = 0;
        !          1028: 
        !          1029:   fmt = GET_RTX_FORMAT (code);
        !          1030:   for (i = GET_RTX_LENGTH (code); i >= 0; i--)
        !          1031:     {
        !          1032:       if (fmt[i] == 'e')
        !          1033:        mark_jump_label (XEXP (x, i), insn, cross_jump);
        !          1034:       else if (fmt[i] == 'E')
        !          1035:        {
        !          1036:          register int j;
        !          1037:          for (j = 0; j < XVECLEN (x, i); j++)
        !          1038:            mark_jump_label (XVECEXP (x, i, j), insn, cross_jump);
        !          1039:        }
        !          1040:     }
        !          1041: }
        !          1042: 
        !          1043: /* If all INSN does is set the pc, delete it,
        !          1044:    and delete the insn that set the condition codes for it
        !          1045:    if that's what the previous thing was.  */
        !          1046: 
        !          1047: static void
        !          1048: delete_jump (insn)
        !          1049:      rtx insn;
        !          1050: {
        !          1051:   register rtx x = PATTERN (insn);
        !          1052:   register rtx prev;
        !          1053: 
        !          1054:   if (GET_CODE (x) == SET
        !          1055:       && GET_CODE (SET_DEST (x)) == PC)
        !          1056:     {
        !          1057:       prev = PREV_INSN (insn);
        !          1058:       delete_insn (insn);
        !          1059:       /* We assume that at this stage
        !          1060:         CC's are always set explicitly
        !          1061:         and always immediately before the jump that
        !          1062:         will use them.  So if the previous insn
        !          1063:         exists to set the CC's, delete it.  */
        !          1064:       while (prev && GET_CODE (prev) == NOTE)
        !          1065:        prev = PREV_INSN (prev);
        !          1066:       if (prev && GET_CODE (prev) == INSN
        !          1067:          && GET_CODE (PATTERN (prev)) == SET
        !          1068:          && SET_DEST (PATTERN (prev)) == cc0_rtx)
        !          1069:        delete_insn (prev);
        !          1070:     }
        !          1071: }
        !          1072: 
        !          1073: /* Delete insn INSN from the chain of insns and update label ref counts.
        !          1074:    May delete some following insns as a consequence; may even delete
        !          1075:    a label elsewhere and insns that follow it.
        !          1076: 
        !          1077:    Returns the first insn after INSN that was not deleted.  */
        !          1078: 
        !          1079: rtx
        !          1080: delete_insn (insn)
        !          1081:      register rtx insn;
        !          1082: {
        !          1083:   register rtx next = NEXT_INSN (insn);
        !          1084:   register rtx prev = PREV_INSN (insn);
        !          1085: 
        !          1086:   if (insn->volatil)
        !          1087:     {
        !          1088:       /* This insn is already deleted => return first following nondeleted.  */
        !          1089:       while (next && next->volatil)
        !          1090:        next = NEXT_INSN (next);
        !          1091:       return next;
        !          1092:     }
        !          1093: 
        !          1094:   /* Mark this insn as deleted.  */
        !          1095: 
        !          1096:   insn->volatil = 1;
        !          1097: 
        !          1098:   /* If instruction is followed by a barrier,
        !          1099:      delete the barrier too.  */
        !          1100: 
        !          1101:   if (next != 0 && GET_CODE (next) == BARRIER)
        !          1102:     {
        !          1103:       next->volatil = 1;
        !          1104:       next = NEXT_INSN (next);
        !          1105:     }
        !          1106: 
        !          1107:   /* Patch out INSN (and the barrier if any) */
        !          1108: 
        !          1109:   if (optimize)
        !          1110:     {
        !          1111:       if (prev)
        !          1112:        NEXT_INSN (prev) = next;
        !          1113: 
        !          1114:       if (next)
        !          1115:        PREV_INSN (next)= prev;
        !          1116:     }
        !          1117: 
        !          1118:   /* If deleting a jump, decrement the count of the label,
        !          1119:      and delete the label if it is now unused.  */
        !          1120: 
        !          1121:   if (GET_CODE (insn) == JUMP_INSN && JUMP_LABEL (insn))
        !          1122:     if (--LABEL_NUSES (JUMP_LABEL (insn)) == 0)
        !          1123:       {
        !          1124:        /* This can delete NEXT or PREV,
        !          1125:           either directly if NEXT is JUMP_LABEL (INSN),
        !          1126:           or indirectly through more levels of jumps.  */
        !          1127:        delete_insn (JUMP_LABEL (insn));
        !          1128:        /* I feel a little doubtful about this loop,
        !          1129:           but I see no clean and sure alternative way
        !          1130:           to find the first insn after INSN that is not now deleted.
        !          1131:           I hope this works.  */
        !          1132:        while (next && next->volatil)
        !          1133:          next = NEXT_INSN (next);
        !          1134:        return next;
        !          1135:       }
        !          1136: 
        !          1137:   while (prev && GET_CODE (prev) == NOTE)
        !          1138:     prev = PREV_INSN (prev);
        !          1139: 
        !          1140:   /* If INSN was a label, delete insns following it if now unreachable.  */
        !          1141: 
        !          1142:   if (GET_CODE (insn) == CODE_LABEL && prev
        !          1143:       && GET_CODE (prev) == BARRIER)
        !          1144:     {
        !          1145:       register RTX_CODE code;
        !          1146:       while (next != 0
        !          1147:             && ((code = GET_CODE (next)) == INSN
        !          1148:                 || code == JUMP_INSN || code == CALL_INSN
        !          1149:                 || code == NOTE))
        !          1150:        {
        !          1151:          if (code == NOTE
        !          1152:              && NOTE_LINE_NUMBER (next) != NOTE_INSN_FUNCTION_END)
        !          1153:            next = NEXT_INSN (next);
        !          1154:          else
        !          1155:            /* Note: if this deletes a jump, it can cause more
        !          1156:               deletion of unreachable code, after a different label.
        !          1157:               As long as the value from this recursive call is correct,
        !          1158:               this invocation functions correctly.  */
        !          1159:            next = delete_insn (next);
        !          1160:        }
        !          1161:     }
        !          1162: 
        !          1163:   return next;
        !          1164: }
        !          1165: 
        !          1166: /* Advance from INSN till reaching something not deleted
        !          1167:    then return that.  May return INSN itself.  */
        !          1168: 
        !          1169: rtx
        !          1170: next_nondeleted_insn (insn)
        !          1171:      rtx insn;
        !          1172: {
        !          1173:   while (insn->volatil)
        !          1174:     insn = NEXT_INSN (insn);
        !          1175:   return insn;
        !          1176: }
        !          1177: 
        !          1178: /* Invert the condition of the jump JUMP, and make it jump
        !          1179:    to label NLABEL instead of where it jumps now.  */
        !          1180: 
        !          1181: void
        !          1182: invert_jump (jump, nlabel)
        !          1183:      rtx jump, nlabel;
        !          1184: {
        !          1185:   register rtx olabel = JUMP_LABEL (jump);
        !          1186:   invert_exp (PATTERN (jump), olabel, nlabel);
        !          1187:   JUMP_LABEL (jump) = nlabel;
        !          1188:   ++LABEL_NUSES (nlabel);
        !          1189:   INSN_CODE (jump) = -1;
        !          1190: 
        !          1191:   if (--LABEL_NUSES (olabel) == 0)
        !          1192:     delete_insn (olabel);
        !          1193: }
        !          1194: 
        !          1195: /* Invert the jump condition of rtx X,
        !          1196:    and replace OLABEL with NLABEL throughout.  */
        !          1197: 
        !          1198: static void
        !          1199: invert_exp (x, olabel, nlabel)
        !          1200:      rtx x;
        !          1201:      rtx olabel, nlabel;
        !          1202: {
        !          1203:   register RTX_CODE code = GET_CODE (x);
        !          1204:   register int i;
        !          1205:   register char *fmt;
        !          1206: 
        !          1207:   if (code == IF_THEN_ELSE)
        !          1208:     {
        !          1209:       /* Inverting the jump condition of an IF_THEN_ELSE
        !          1210:         means exchanging the THEN-part with the ELSE-part.  */
        !          1211:       register rtx tem = XEXP (x, 1);
        !          1212:       XEXP (x, 1) = XEXP (x, 2);
        !          1213:       XEXP (x, 2) = tem;
        !          1214:     }
        !          1215: 
        !          1216:   if (code == LABEL_REF)
        !          1217:     {
        !          1218:       if (XEXP (x, 0) == olabel)
        !          1219:        XEXP (x, 0) = nlabel;
        !          1220:       return;
        !          1221:     }
        !          1222: 
        !          1223:   fmt = GET_RTX_FORMAT (code);
        !          1224:   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
        !          1225:     {
        !          1226:       if (fmt[i] == 'e')
        !          1227:        invert_exp (XEXP (x, i), olabel, nlabel);
        !          1228:       if (fmt[i] == 'E')
        !          1229:        {
        !          1230:          register int j;
        !          1231:          for (j = 0; j < XVECLEN (x, i); j++)
        !          1232:            invert_exp (XVECEXP (x, i, j), olabel, nlabel);
        !          1233:        }
        !          1234:     }
        !          1235: }
        !          1236: 
        !          1237: /* Make jump JUMP jump to label NLABEL instead of where it jumps now.
        !          1238:    If the old jump target label is unused as a result,
        !          1239:    it and the code following it may be deleted.  */
        !          1240: 
        !          1241: void
        !          1242: redirect_jump (jump, nlabel)
        !          1243:      rtx jump, nlabel;
        !          1244: {
        !          1245:   register rtx olabel = JUMP_LABEL (jump);
        !          1246: 
        !          1247:   if (nlabel == olabel)
        !          1248:     return;
        !          1249: 
        !          1250:   redirect_exp (PATTERN (jump), olabel, nlabel);
        !          1251:   JUMP_LABEL (jump) = nlabel;
        !          1252:   ++LABEL_NUSES (nlabel);
        !          1253:   INSN_CODE (jump) = -1;
        !          1254: 
        !          1255:   if (--LABEL_NUSES (olabel) == 0)
        !          1256:     delete_insn (olabel);
        !          1257: }
        !          1258: 
        !          1259: /* Throughout the rtx X,
        !          1260:    alter (LABEL_REF OLABEL) to (LABEL_REF NLABEL).  */
        !          1261: 
        !          1262: static void
        !          1263: redirect_exp (x, olabel, nlabel)
        !          1264:      rtx x;
        !          1265:      rtx olabel, nlabel;
        !          1266: {
        !          1267:   register RTX_CODE code = GET_CODE (x);
        !          1268:   register int i;
        !          1269:   register char *fmt;
        !          1270: 
        !          1271:   if (code == LABEL_REF)
        !          1272:     {
        !          1273:       if (XEXP (x, 0) == olabel)
        !          1274:        XEXP (x, 0) = nlabel;
        !          1275:       return;
        !          1276:     }
        !          1277: 
        !          1278:   fmt = GET_RTX_FORMAT (code);
        !          1279:   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
        !          1280:     {
        !          1281:       if (fmt[i] == 'e')
        !          1282:        redirect_exp (XEXP (x, i), olabel, nlabel);
        !          1283:       if (fmt[i] == 'E')
        !          1284:        {
        !          1285:          register int j;
        !          1286:          for (j = 0; j < XVECLEN (x, i); j++)
        !          1287:            redirect_exp (XVECEXP (x, i, j), olabel, nlabel);
        !          1288:        }
        !          1289:     }
        !          1290: }
        !          1291: 
        !          1292: /* Like rtx_equal_p except that it considers two REGs as equal
        !          1293:    if they renumber to the same value.  */
        !          1294: 
        !          1295: int
        !          1296: rtx_renumbered_equal_p (x, y)
        !          1297:      rtx x, y;
        !          1298: {
        !          1299:   register int i;
        !          1300:   register RTX_CODE code = GET_CODE (x);
        !          1301:   register char *fmt;
        !          1302:       
        !          1303:   if (x == y)
        !          1304:     return 1;
        !          1305:   if ((code == REG || (code == SUBREG && GET_CODE (SUBREG_REG (x)) == REG))
        !          1306:       && (GET_CODE (y) == REG || (GET_CODE (y) == SUBREG
        !          1307:                                  && GET_CODE (SUBREG_REG (y)) == REG)))
        !          1308:     {
        !          1309:       register int j;
        !          1310: 
        !          1311:       if (GET_MODE (x) != GET_MODE (y))
        !          1312:        return 0;
        !          1313: 
        !          1314:       if (code == SUBREG)
        !          1315:        {
        !          1316:          i = REGNO (SUBREG_REG (x));
        !          1317:          if (reg_renumber[i] >= 0)
        !          1318:            i = reg_renumber[i];
        !          1319:          i += SUBREG_WORD (x);
        !          1320:        }
        !          1321:       else
        !          1322:        {
        !          1323:          i = REGNO (x);
        !          1324:          if (reg_renumber[i] >= 0)
        !          1325:            i = reg_renumber[i];
        !          1326:        }
        !          1327:       if (GET_CODE (y) == SUBREG)
        !          1328:        {
        !          1329:          j = REGNO (SUBREG_REG (y));
        !          1330:          if (reg_renumber[j] >= 0)
        !          1331:            j = reg_renumber[j];
        !          1332:          j += SUBREG_WORD (y);
        !          1333:        }
        !          1334:       else
        !          1335:        {
        !          1336:          j = REGNO (y);
        !          1337:          if (reg_renumber[j] >= 0)
        !          1338:            j = reg_renumber[j];
        !          1339:        }
        !          1340:       return i == j;
        !          1341:     }
        !          1342:   /* Now we have disposed of all the cases 
        !          1343:      in which different rtx codes can match.  */
        !          1344:   if (code != GET_CODE (y))
        !          1345:     return 0;
        !          1346:   /* Two label-refs are equivalent if they point at labels
        !          1347:      in the same position in the instruction stream.  */
        !          1348:   if (code == LABEL_REF)
        !          1349:     return (next_real_insn (XEXP (x, 0))
        !          1350:            == next_real_insn (XEXP (y, 0)));
        !          1351:   if (code == SYMBOL_REF)
        !          1352:     return XSTR (x, 0) == XSTR (y, 0);
        !          1353: 
        !          1354:   /* (MULT:SI x y) and (MULT:HI x y) are NOT equivalent.  */
        !          1355: 
        !          1356:   if (GET_MODE (x) != GET_MODE (y))
        !          1357:     return 0;
        !          1358: 
        !          1359:   /* Compare the elements.  If any pair of corresponding elements
        !          1360:      fail to match, return 0 for the whole things.  */
        !          1361: 
        !          1362:   fmt = GET_RTX_FORMAT (code);
        !          1363:   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
        !          1364:     {
        !          1365:       register int j;
        !          1366:       switch (fmt[i])
        !          1367:        {
        !          1368:        case 'i':
        !          1369:          if (XINT (x, i) != XINT (y, i))
        !          1370:            return 0;
        !          1371:          break;
        !          1372: 
        !          1373:        case 's':
        !          1374:          if (strcmp (XSTR (x, i), XSTR (y, i)))
        !          1375:            return 0;
        !          1376:          break;
        !          1377: 
        !          1378:        case 'e':
        !          1379:          if (! rtx_renumbered_equal_p (XEXP (x, i), XEXP (y, i)))
        !          1380:            return 0;
        !          1381:          break;
        !          1382: 
        !          1383:        case '0':
        !          1384:          break;
        !          1385: 
        !          1386:        case 'E':
        !          1387:          if (XVECLEN (x, i) != XVECLEN (y, i))
        !          1388:            return 0;
        !          1389:          for (j = XVECLEN (x, i) - 1; j >= 0; j--)
        !          1390:            if (!rtx_renumbered_equal_p (XVECEXP (x, i, j), XVECEXP (y, i, j)))
        !          1391:              return 0;
        !          1392:          break;
        !          1393: 
        !          1394:          /* It is believed that rtx's at this level will never
        !          1395:             contain anything but integers and other rtx's,
        !          1396:             except for within LABEL_REFs and SYMBOL_REFs.  */
        !          1397:        default:
        !          1398:          abort ();
        !          1399:        }
        !          1400:     }
        !          1401:   return 1;
        !          1402: }
        !          1403: 
        !          1404: /* If X is a hard register or equivalent to one or a subregister of one,
        !          1405:    return the hard register number.  Otherwise, return -1.
        !          1406:    Any rtx is valid for X.  */
        !          1407: 
        !          1408: int
        !          1409: true_regnum (x)
        !          1410:      rtx x;
        !          1411: {
        !          1412:   if (GET_CODE (x) == REG)
        !          1413:     {
        !          1414:       if (REGNO (x) >= FIRST_PSEUDO_REGISTER)
        !          1415:        return reg_renumber[REGNO (x)];
        !          1416:       return REGNO (x);
        !          1417:     }
        !          1418:   if (GET_CODE (x) == SUBREG)
        !          1419:     {
        !          1420:       int base = true_regnum (SUBREG_REG (x));
        !          1421:       if (base >= 0)
        !          1422:        return SUBREG_WORD (x) + base;
        !          1423:     }
        !          1424:   return -1;
        !          1425: }

unix.superglobalmegacorp.com

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