Annotation of gcc/loop.c, revision 1.1.1.2

1.1       root        1: /* Move constant computations out of loops.
1.1.1.2 ! root        2:    Copyright (C) 1987, 1988 Free Software Foundation, Inc.
1.1       root        3: 
                      4: This file is part of GNU CC.
                      5: 
                      6: GNU CC is distributed in the hope that it will be useful,
                      7: but WITHOUT ANY WARRANTY.  No author or distributor
                      8: accepts responsibility to anyone for the consequences of using it
                      9: or for whether it serves any particular purpose or works at all,
                     10: unless he says so in writing.  Refer to the GNU CC General Public
                     11: License for full details.
                     12: 
                     13: Everyone is granted permission to copy, modify and redistribute
                     14: GNU CC, but only under the conditions described in the
                     15: GNU CC General Public License.   A copy of this license is
                     16: supposed to have been given to you along with GNU CC so you
                     17: can know your rights and responsibilities.  It should be in a
                     18: file named COPYING.  Among other things, the copyright notice
                     19: and this notice must be preserved on all copies.  */
                     20: 
                     21: 
                     22: /* This is the loop optimization pass of the compiler.
                     23:    It finds invariant computations within loops and moves them
                     24:    to the beginning of the loop.
                     25: 
                     26:    It also finds cases where
                     27:    a register is set within the loop by zero-extending a narrower value
                     28:    and changes these to zero the entire register once before the loop
                     29:    and merely copy the low part within the loop.
                     30: 
                     31:    Most of the complexity is in heuristics to decide when it is worth
                     32:    while to do these things.  */
                     33: 
                     34: /* ??? verify_loop would run faster if we made one table
                     35:    of the minimum and maximum luids from which each label is reached.
                     36:    Also, it would be faster if loop_store_addrs were a hash table.  */
                     37: 
                     38: #include "config.h"
                     39: #include "rtl.h"
                     40: #include "insn-config.h"
                     41: #include "regs.h"
                     42: #include "recog.h"
1.1.1.2 ! root       43: #include <stdio.h>
1.1       root       44: 
                     45: /* Vector mapping INSN_UIDs to luids.
                     46:    The luids are like uids but increase monononically always.
                     47:    We use them to see whether a jump comes from outside a given loop.  */
                     48: 
                     49: static short *uid_luid;
                     50: 
                     51: /* Get the luid of an insn.  */
                     52: 
                     53: #define INSN_LUID(INSN) (uid_luid[INSN_UID (INSN)])
                     54: 
                     55: /* 1 + largest uid of any insn.  */
                     56: 
                     57: static int max_uid;
                     58: 
                     59: /* 1 + luid of last insn.  */
                     60: 
                     61: static int max_luid;
                     62: 
                     63: /* Nonzero if somewhere in the current loop
                     64:    there is either a subroutine call,
                     65:    or a store into a memory address that is not fixed,
                     66:    or a store in a BLKmode memory operand,
                     67:    or too many different fixed addresses stored in
                     68:    to record them all in `loop_store_addrs'.
                     69: 
                     70:    In any of these cases, no memory location can be regarded
                     71:    as invariant.  */
                     72: 
                     73: static int unknown_address_altered;
                     74: 
                     75: /* Nonzero if somewhere in the current loop there is a store
                     76:    into a memory address that is not fixed but is known to be
                     77:    part of an aggregate.
                     78: 
                     79:    In this case, no memory reference in an aggregate may be
                     80:    considered invariant.  */
                     81: 
                     82: static int unknown_aggregate_altered;
                     83: 
                     84: /* Nonzero if somewhere in the current loop there is a store
                     85:    into a memory address other than a fixed address not in an aggregate.
                     86: 
                     87:    In this case, no memory reference in an aggregate at a varying address
                     88:    may be considered invariant.  */
                     89: 
                     90: static int fixed_aggregate_altered;
                     91: 
                     92: /* Nonzero if there is a subroutine call in the current loop.
                     93:    (unknown_address_altered is also nonzero in this case.)  */
                     94: 
                     95: static int loop_has_call;
                     96: 
                     97: /* Array of fixed memory addresses that are stored in this loop.
                     98:    If there are too many to fit here,
                     99:    we just turn on unknown_address_altered.  */
                    100: 
                    101: #define NUM_STORES 10
                    102: static rtx loop_store_addrs[NUM_STORES];
                    103: static int loop_store_widths[NUM_STORES];
                    104: 
                    105: /* Index of first available slot in above array.  */
                    106: static int loop_store_addrs_idx;
                    107: 
                    108: /* During the analysis of a loop, a chain of `struct movable's
                    109:    is made to record all the movable insns found.
                    110:    Then the entire chain can be scanned to decide which to move.  */
                    111: 
                    112: struct movable
                    113: {
                    114:   rtx insn;                    /* A movable insn */
1.1.1.2 ! root      115:   int consec;                  /* Number of consecutive following insns 
        !           116:                                   that must be moved with this one.  */
1.1       root      117:   int regno;                   /* The register it sets */
                    118:   short lifetime;              /* lifetime of that register;
                    119:                                   may be adjusted when matching movables
                    120:                                   that load the same value are found.  */
1.1.1.2 ! root      121:   short times_used;            /* Number of times the register is used,
        !           122:                                   plus uses of related insns that could
        !           123:                                   be moved if this one is.  */
1.1       root      124:   unsigned int cond : 1;       /* 1 if only conditionally movable */
                    125:   unsigned int force : 1;      /* 1 means MUST move this insn */
                    126:   unsigned int global : 1;     /* 1 means reg is live outside this loop */
1.1.1.2 ! root      127:   unsigned int done : 1;       /* 1 inhibits further processing of this */
        !           128:   unsigned int partial : 1;    /* Moving this doesn't make it invariant.  */
1.1       root      129:   struct movable *match;       /* First entry for same value */
                    130:   struct movable *forces;      /* An insn that must be moved if this is */
                    131:   struct movable *next;
                    132: };
                    133: 
1.1.1.2 ! root      134: static FILE *loop_dump_stream;
        !           135: 
1.1       root      136: static rtx verify_loop ();
                    137: static int invariant_p ();
                    138: static int can_jump_into_range_p ();
                    139: static void count_loop_regs_set ();
                    140: static void note_addr_stored ();
                    141: static int loop_reg_used_before_p ();
                    142: static void constant_high_bytes ();
                    143: static void scan_loop ();
                    144: static rtx replace_regs ();
1.1.1.2 ! root      145: static void move_movables ();
        !           146: static int may_trap_p ();
1.1       root      147: 
                    148: /* Entry point of this file.  Perform loop optimization
                    149:    on the current function.  F is the first insn of the function
                    150:    and NREGS is the number of register numbers used.  */
                    151: 
1.1.1.2 ! root      152: void
        !           153: loop_optimize (f, nregs, dumpfile)
1.1       root      154:      /* f is the first instruction of a chain of insns for one function */
                    155:      rtx f;
                    156:      /* nregs is the total number of registers used in it */
                    157:      int nregs;
1.1.1.2 ! root      158:      FILE *dumpfile;
1.1       root      159: {
                    160:   register rtx insn;
                    161:   register int i;
                    162:   rtx end;
                    163:   rtx last_insn;
                    164: 
1.1.1.2 ! root      165:   loop_dump_stream = dumpfile;
        !           166: 
1.1       root      167:   init_recog ();
                    168: 
                    169:   /* First find the last real insn, and count the number of insns,
                    170:      and assign insns their suids.  */
                    171: 
                    172:   for (insn = f, i = 0; insn; insn = NEXT_INSN (insn))
                    173:     if (INSN_UID (insn) > i)
                    174:       i = INSN_UID (insn);
                    175: 
                    176:   max_uid = i + 1;
                    177:   uid_luid = (short *) alloca ((i + 1) * sizeof (short));
                    178:   bzero (uid_luid, (i + 1) * sizeof (short));
                    179: 
                    180:   /* Compute the mapping from uids to luids.
                    181:      LUIDs are numbers assigned to insns, like uids,
                    182:      except that luids increase monotonically through the code.  */
                    183: 
                    184:   for (insn = f, i = 0; insn; insn = NEXT_INSN (insn))
                    185:     {
                    186:       last_insn = insn;
                    187:       INSN_LUID (insn) = ++i;
                    188:     }
                    189: 
                    190:   max_luid = i;
                    191: 
                    192:   /* Don't leave gaps in uid_luid for insns that have been
                    193:      deleted.  It is possible that the first or last insn
                    194:      using some register has been deleted by cross-jumping.
                    195:      Make sure that uid_luid for that former insn's uid
                    196:      points to the general area where that insn used to be.  */
                    197:   for (i = 0; i < max_uid; i++)
1.1.1.2 ! root      198:     {
        !           199:       uid_luid[0] = uid_luid[i];
        !           200:       if (uid_luid[0] != 0)
        !           201:        break;
        !           202:     }
        !           203:   for (i = 0; i < max_uid; i++)
1.1       root      204:     if (uid_luid[i] == 0)
                    205:       uid_luid[i] = uid_luid[i - 1];
                    206: 
                    207:   /* Find and process each loop.
                    208:      We scan from the end, and process each loop when its start is seen,
                    209:      so we process innermost loops first.  */
                    210: 
                    211:   for (insn = last_insn; insn; insn = PREV_INSN (insn))
                    212:     if (GET_CODE (insn) == NOTE
                    213:        && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG
                    214:        /* Make sure it really is a loop -- no jumps in from outside.  */
                    215:        && (end = verify_loop (f, insn)))
                    216:       scan_loop (insn, end, nregs);
                    217: }
                    218: 
                    219: /* Optimize one loop whose start is LOOP_START and end is END.
                    220:    LOOP_START is the NOTE_INSN_LOOP_BEG and END is the matching
                    221:    NOTE_INSN_LOOP_END.  */
                    222: 
                    223: static void
                    224: scan_loop (loop_start, end, nregs)
                    225:      rtx loop_start, end;
                    226:      int nregs;
                    227: {
                    228:   register int i;
                    229:   register rtx p = NEXT_INSN (loop_start);
                    230:   /* 1 if we are scanning insns that could be executed zero times.  */
                    231:   int maybe_never = 0;
                    232:   /* For a rotated loop that is entered near the bottom,
                    233:      this is the label at the top.  Otherwise it is zero.  */
                    234:   rtx loop_top = 0;
1.1.1.2 ! root      235:   /* This is the insn (whatever kind) before the NOTE that starts the loop.
        !           236:      Any insns moved out of the loop will follow it.  */
        !           237:   rtx before_start = PREV_INSN (loop_start);
1.1       root      238:   /* Jump insn that enters the loop, or 0 if control drops in.  */
                    239:   rtx loop_entry_jump = 0;
                    240:   /* Place in the loop where control enters.  */
                    241:   rtx scan_start;
                    242:   /* Number of insns in the loop.  */
                    243:   int insn_count;
                    244:   int tem;
                    245:   /* Indexed by register number, contains the number of times the reg
                    246:      is set during the loop being scanned, or -1 if the insns that set it
                    247:      have all been scanned as candidates for being moved out of the loop.
                    248:      0 indicates an invariant register; -1 a conditionally invariant one.  */
                    249:   short *n_times_set;
                    250:   /* Indexed by register number, contains the number of times the reg
                    251:      was set during the loop being scanned, not counting changes due
                    252:      to moving these insns out of the loop.  */
                    253:   short *n_times_used;
                    254:   /* Indexed by register number, contains 1 for a register whose
                    255:      assignments may not be moved out of the loop.  */
                    256:   char *may_not_move;
                    257:   /* Chain describing insns movable in current loop.  */
                    258:   struct movable *movables = 0;
                    259:   /* Last element in `movables' -- so we can add elements at the end.  */
                    260:   struct movable *last_movable = 0;
                    261:   /* Ratio of extra register life span we can justify
                    262:      for saving an instruction.  More if loop doesn't call subroutines
                    263:      since in that case saving an insn makes more difference
                    264:      and more registers are available.  */
1.1.1.2 ! root      265:   int threshold = loop_has_call ? 17 : 34;
1.1       root      266: 
                    267:   n_times_set = (short *) alloca (nregs * sizeof (short));
                    268:   n_times_used = (short *) alloca (nregs * sizeof (short));
                    269:   may_not_move = (char *) alloca (nregs);
                    270: 
                    271:   /* Determine whether this loop starts with a jump down
                    272:      to a test at the end.  */
                    273:   while (p != end
                    274:         && GET_CODE (p) != CODE_LABEL && GET_CODE (p) != JUMP_INSN)
                    275:     p = NEXT_INSN (p);
                    276: 
                    277:   /* "Loop" contains neither jumps nor labels;
                    278:      it must have been a dummy.  Think no more about it.  */
                    279:   if (p == end)
                    280:     return;
                    281: 
1.1.1.2 ! root      282:   scan_start = p;
        !           283: 
1.1       root      284:   /* If loop has a jump before the first label,
                    285:      the true entry is the target of that jump.
                    286:      Start scan from there.
                    287:      But record in LOOP_TOP the place where the end-test jumps
                    288:      back to so we can scan that after the end of the loop.  */
                    289:   if (GET_CODE (p) == JUMP_INSN)
                    290:     {
                    291:       loop_entry_jump = p;
                    292:       loop_top = NEXT_INSN (p);
                    293:       /* Loop entry will never be a conditional jump.
                    294:         If we see one, this must not be a real loop.  */
                    295:       if (GET_CODE (loop_top) != BARRIER)
                    296:        return;
                    297:       p = JUMP_LABEL (p);
                    298:       /* Check to see whether the jump actually
                    299:         jumps out of the loop (meaning it's no loop).
                    300:         This case can happen for things like
                    301:         do {..} while (0).  */
1.1.1.2 ! root      302:       if (p == 0
        !           303:          || INSN_LUID (p) < INSN_LUID (loop_start)
1.1       root      304:          || INSN_LUID (p) >= INSN_LUID (end))
1.1.1.2 ! root      305:        {
        !           306:          if (loop_dump_stream)
        !           307:            fprintf (loop_dump_stream, "\nLoop from %d to %d is phony.\n\n",
        !           308:                     INSN_UID (loop_start), INSN_UID (end));
        !           309:          return;
        !           310:        }
        !           311: 
        !           312:       /* Find the first label after the entry-jump.  */
        !           313:       while (GET_CODE (loop_top) != CODE_LABEL)
        !           314:        {
        !           315:          loop_top = NEXT_INSN (loop_top);
        !           316:          if (loop_top == 0)
        !           317:            abort ();
        !           318:        }
        !           319: 
        !           320:       /* Maybe rearrange the loop to drop straight in
        !           321:         with a new test to jump around it entirely.
        !           322:         (The latter is considered outside the loop.)
        !           323:         If this is done, we no longer enter with a jump.  */
        !           324:       if (loop_skip_over (loop_start, end, loop_entry_jump))
        !           325:        loop_top = 0;
        !           326:       else
        !           327:        /* We really do enter with a jump;
        !           328:           scan the loop from the place where the jump jumps to.  */
        !           329:        scan_start = p;
1.1       root      330:     }
                    331: 
                    332:   /* Count number of times each reg is set during this loop.
                    333:      Set MAY_NOT_MOVE[I] if it is not safe to move out
                    334:      the setting of register I.  */
                    335: 
                    336:   bzero (n_times_set, nregs * sizeof (short));
                    337:   bzero (may_not_move, nregs);
1.1.1.2 ! root      338:   count_loop_regs_set (loop_top ? loop_top : loop_start, end,
        !           339:                       n_times_set, may_not_move, 
1.1       root      340:                       &insn_count, nregs);
                    341:   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
                    342:     may_not_move[i] = 1, n_times_set[i] = 1;
                    343:   bcopy (n_times_set, n_times_used, nregs * sizeof (short));
                    344: 
1.1.1.2 ! root      345:   if (loop_dump_stream)
        !           346:     fprintf (loop_dump_stream, "\nLoop from %d to %d: %d real insns\n\n",
        !           347:             INSN_UID (loop_start), INSN_UID (end), insn_count);
        !           348: 
1.1       root      349:   /* Scan through the loop finding insns that are safe to move.
                    350:      In each such insn, store QImode as the mode, to mark it.
                    351:      Then set n_times_set to -1 for the reg being set, so that
                    352:      this reg will be considered invariant for subsequent insns.
                    353:      We consider whether subsequent insns use the reg
                    354:      in deciding whether it is worth actually moving.
                    355: 
                    356:      MAYBE_NEVER is nonzero if we have passed a conditional jump insn
                    357:      and therefore it is possible that the insns we are scanning
                    358:      would never be executed.  At such times, we must make sure
                    359:      that it is safe to execute the insn once instead of zero times.
                    360:      When MAYBE_NEVER is 0, all insns will be executed at least once
                    361:      so that is not a problem.  */
                    362: 
1.1.1.2 ! root      363:   p = scan_start;
1.1       root      364:   while (1)
                    365:     {
                    366:       p = NEXT_INSN (p);
                    367:       /* At end of a straight-in loop, we are done.
                    368:         At end of a loop entered at the bottom, scan the top.  */
                    369:       if (p == scan_start)
                    370:        break;
                    371:       if (p == end)
                    372:        {
                    373:          if (loop_top != 0)
                    374:            p = NEXT_INSN (loop_top);
                    375:          else
                    376:            break;
                    377:          if (p == scan_start)
                    378:            break;
                    379:        }
                    380:       if (GET_CODE (p) == INSN
                    381:          && GET_CODE (PATTERN (p)) == SET
                    382:          && GET_CODE (SET_DEST (PATTERN (p))) == REG
                    383:          && ! may_not_move[REGNO (SET_DEST (PATTERN (p)))])
                    384:        {
                    385:          /* If this register is used or set outside the loop,
                    386:             then we can move it only if we know this insn is
                    387:             executed exactly once per iteration,
                    388:             and we can check all the insns executed before it
                    389:             to make sure none of them used the value that
                    390:             was lying around at entry to the loop.  */
                    391:          if ((uid_luid[regno_last_uid[REGNO (SET_DEST (PATTERN (p)))]] > INSN_LUID (end)
                    392:               || uid_luid[regno_first_uid[REGNO (SET_DEST (PATTERN (p)))]] < INSN_LUID (loop_start))
                    393:              && (maybe_never
                    394:                  || loop_reg_used_before_p (p, loop_start, scan_start, end)))
                    395:            ;
1.1.1.2 ! root      396:          /* If this can cause a trap (such as divide by zero), can't move it
        !           397:             unless it's guaranteed to be executed once loop is entered.  */
        !           398:          else if (maybe_never && may_trap_p (SET_SRC (PATTERN (p))))
        !           399:            ;
1.1       root      400:          else if ((tem = invariant_p (SET_SRC (PATTERN (p)), n_times_set))
                    401:                   && (n_times_set[REGNO (SET_DEST (PATTERN (p)))] == 1
1.1.1.2 ! root      402:                       || consec_sets_invariant_p (SET_DEST (PATTERN (p)),
        !           403:                                                   p, n_times_set)))
1.1       root      404:            {
                    405:              register struct movable *m;
                    406:              register int regno = REGNO (SET_DEST (PATTERN (p)));
1.1.1.2 ! root      407:              int count;
1.1       root      408:              m = (struct movable *) alloca (sizeof (struct movable));
                    409:              m->next = 0;
                    410:              m->insn = p;
                    411:              m->force = 0;
1.1.1.2 ! root      412:              m->consec = n_times_set[REGNO (SET_DEST (PATTERN (p)))] - 1;
        !           413:              m->done = 0;
1.1       root      414:              m->forces = 0;
1.1.1.2 ! root      415:              m->partial = 0;
1.1       root      416:              m->regno = regno;
                    417:              m->cond = (tem > 1);
                    418:              m->global = (uid_luid[regno_last_uid[regno]] > INSN_LUID (end)
                    419:                           || uid_luid[regno_first_uid[regno]] < INSN_LUID (loop_start));
                    420:              m->match = 0;
                    421:              m->lifetime = (uid_luid[regno_last_uid[regno]]
                    422:                             - uid_luid[regno_first_uid[regno]]);
1.1.1.2 ! root      423:              m->times_used = n_times_used[regno];
1.1       root      424:              n_times_set[regno] = -1;
                    425:              /* Add M to the end of the chain MOVABLES.  */
                    426:              if (movables == 0)
                    427:                movables = m;
                    428:              else
                    429:                last_movable->next = m;
                    430:              last_movable = m;
1.1.1.2 ! root      431:              /* Skip the consecutive insns, if there are any.  */
        !           432:              for (count = m->consec - 1; count >= 0; count--)
        !           433:                {
        !           434:                  do p = NEXT_INSN (p);
        !           435:                  while (GET_CODE (p) == NOTE);
        !           436:                }
1.1       root      437:            }
1.1.1.2 ! root      438:          /* If this register is always set within a STRICT_LOW_PART
        !           439:             or set to zero, then its high bytes are constant.
1.1       root      440:             So clear them outside the loop and within the loop
                    441:             just load the low bytes.
                    442:             We must check that the machine has an instruction to do so.
                    443:             Also, if the value loaded into the register
                    444:             depends on the same register, this cannot be done.  */
1.1.1.2 ! root      445:          else if (SET_SRC (PATTERN (p)) == const0_rtx
        !           446:                   && GET_CODE (NEXT_INSN (p)) == INSN
        !           447:                   && GET_CODE (PATTERN (NEXT_INSN (p))) == SET
        !           448:                   && (GET_CODE (SET_DEST (PATTERN (NEXT_INSN (p))))
        !           449:                       == STRICT_LOW_PART)
        !           450:                   && (GET_CODE (XEXP (SET_DEST (PATTERN (NEXT_INSN (p))), 0))
        !           451:                       == SUBREG)
        !           452:                   && (SUBREG_REG (XEXP (SET_DEST (PATTERN (NEXT_INSN (p))), 0))
        !           453:                       == SET_DEST (PATTERN (p)))
1.1       root      454:                   && !reg_mentioned_p (SET_DEST (PATTERN (p)),
1.1.1.2 ! root      455:                                        SET_SRC (PATTERN (NEXT_INSN (p)))))
1.1       root      456:            {
                    457:              register int regno = REGNO (SET_DEST (PATTERN (p)));
1.1.1.2 ! root      458:              if (n_times_set[regno] == 2)
        !           459:                {
        !           460:                  register struct movable *m;
        !           461:                  int count;
        !           462:                  m = (struct movable *) alloca (sizeof (struct movable));
        !           463:                  m->next = 0;
        !           464:                  m->insn = p;
        !           465:                  m->force = 0;
        !           466:                  m->consec = 0;
        !           467:                  m->done = 0;
        !           468:                  m->forces = 0;
        !           469:                  m->partial = 1;
        !           470:                  m->regno = regno;
        !           471:                  m->cond = 0;
        !           472:                  /* Say "global" so this register is not combined
        !           473:                     with any other.  In fact, it is sometimes possible
        !           474:                     to combine two of these registers, but the criteria
        !           475:                     are special and have not been programmed in.  */
        !           476:                  m->global = 1;
        !           477:                  m->match = 0;
        !           478:                  m->lifetime = (uid_luid[regno_last_uid[regno]]
        !           479:                                 - uid_luid[regno_first_uid[regno]]);
        !           480:                  m->times_used = n_times_used[regno];
        !           481:                  n_times_set[regno] = -1;
        !           482:                  /* Add M to the end of the chain MOVABLES.  */
        !           483:                  if (movables == 0)
        !           484:                    movables = m;
        !           485:                  else
        !           486:                    last_movable->next = m;
        !           487:                  last_movable = m;
        !           488:                  /* Skip the consecutive insns, if there are any.  */
        !           489:                  for (count = m->consec - 1; count >= 0; count--)
        !           490:                    {
        !           491:                      do p = NEXT_INSN (p);
        !           492:                      while (GET_CODE (p) == NOTE);
        !           493:                    }
        !           494:                }
1.1       root      495:            }
                    496:        }
                    497:       /* Past a label or a jump, we get to insns for which we
                    498:         can't count on whether or how many times they will be
                    499:         executed during each iteration.  Therefore, we can
                    500:         only move out sets of trivial variables
                    501:         (those not used after the loop).  */
                    502:       else if (GET_CODE (p) == CODE_LABEL || GET_CODE (p) == JUMP_INSN)
                    503:        maybe_never = 1;
                    504:     }
                    505: 
                    506:   /* For each movable insn, see if the reg that it loads
1.1.1.2 ! root      507:      leads when it dies right into another conditionally movable insn.
        !           508:      If so, record that the second insn "forces" the first one,
        !           509:      since the second can be moved only if the first is.  */
        !           510: 
1.1       root      511:   {
                    512:     register struct movable *m, *m1;
                    513:     for (m1 = movables; m1; m1 = m1->next)
                    514:       {
                    515:        int regno = m1->regno;
                    516:        for (m = m1->next; m; m = m->next)
                    517:          if (INSN_UID (m->insn) == regno_last_uid[regno])
                    518:            break;
                    519:        if (m != 0 && SET_SRC (PATTERN (m->insn)) == SET_DEST (PATTERN (m1->insn)))
                    520:          m = 0;
1.1.1.2 ! root      521: 
        !           522:        /* Increase the priority of the moving the first insn
        !           523:           since it permits the second to be moved as well.  */
        !           524:        if (m != 0)
        !           525:          {
        !           526:            m->forces = m1;
        !           527:            m1->lifetime += m->lifetime;
        !           528:            m1->times_used += m1->times_used;
        !           529:          }
1.1       root      530:       }
                    531:   }
                    532: 
                    533:   /* See if there are multiple movable insns that load the same value.
                    534:      If there are, make all but the first point at the first one
                    535:      through the `match' field, and add the priorities of them
                    536:      all together as the priority of the first.  */
1.1.1.2 ! root      537: 
1.1       root      538:   {
                    539:     register struct movable *m;
                    540:     char *matched_regs = (char *) alloca (nregs);
                    541: 
1.1.1.2 ! root      542:     /* Regs that are used more than once are not allowed to match
        !           543:        or be matched.  I'm no longer sure why not.  */
1.1       root      544: 
                    545:     for (m = movables; m; m = m->next)
1.1.1.2 ! root      546:       if (m->match == 0 && n_times_used[m->regno] == 1)
1.1       root      547:        {
                    548:          register struct movable *m1;
1.1.1.2 ! root      549:          int regno = m->regno;
1.1       root      550: 
                    551:          bzero (matched_regs, nregs);
1.1.1.2 ! root      552:          matched_regs[regno] = 1;
1.1       root      553: 
                    554:          for (m1 = m->next; m1; m1 = m1->next)
1.1.1.2 ! root      555:            if (m1->match == 0 && n_times_used[m1->regno] == 1
        !           556:                /* A reg used outside the loop mustn't be eliminated.  */
        !           557:                && !m1->global
        !           558:                && (matched_regs[m1->regno]
        !           559:                    ||
        !           560:                    (
        !           561:                     /* Can't combine regs with different modes
        !           562:                        even if loaded from the same constant.  */
        !           563:                     (GET_MODE (SET_DEST (PATTERN (m->insn)))
        !           564:                      == GET_MODE (SET_DEST (PATTERN (m1->insn))))
        !           565:                     /* See if the source of M1 says it matches M.  */
        !           566:                     && ((GET_CODE (SET_SRC (PATTERN (m1->insn))) == REG
        !           567:                          && matched_regs[REGNO (SET_SRC (PATTERN (m1->insn)))])
        !           568:                         || rtx_equal_p (SET_SRC (PATTERN (m->insn)),
        !           569:                                         SET_SRC (PATTERN (m1->insn)))
        !           570:                         || (REG_NOTES (m->insn) && REG_NOTES (m1->insn)
        !           571:                             && REG_NOTE_KIND (REG_NOTES (m->insn)) == REG_EQUIV
        !           572:                             && REG_NOTE_KIND (REG_NOTES (m1->insn)) == REG_EQUIV
        !           573:                             && rtx_equal_p (XEXP (REG_NOTES (m->insn), 0),
        !           574:                                             XEXP (REG_NOTES (m1->insn), 0)))))))
        !           575:              {
        !           576:                m->lifetime += m1->lifetime;
        !           577:                m->times_used += m1->times_used;
        !           578:                m1->match = m;
        !           579:                matched_regs[m1->regno] = 1;
        !           580:              }
        !           581:        }
        !           582:   }
        !           583:        
        !           584:   /* Now consider each movable insn to decide whether it is worth moving.  */
        !           585: 
        !           586:   move_movables (movables, n_times_set, n_times_used, threshold,
        !           587:                 insn_count, loop_start, end, nregs);
        !           588: }
        !           589: 
        !           590: /* Scan MOVABLES, and move the insns that deserve to be moved.
        !           591:    If two matching movables are combined, replace one reg with the
        !           592:    other throughout.  */
        !           593: 
        !           594: static void
        !           595: move_movables (movables, n_times_set, n_times_used, threshold,
        !           596:               insn_count, loop_start, end, nregs)
        !           597:      struct movable *movables;
        !           598:      short *n_times_set;
        !           599:      short *n_times_used;
        !           600:      int threshold;
        !           601:      int insn_count;
        !           602:      rtx loop_start;
        !           603:      rtx end;
        !           604:      int nregs;
        !           605: {
        !           606:   rtx new_start = 0;
        !           607:   register struct movable *m;
        !           608:   register rtx p;
        !           609:   /* Map of pseudo-register replacements to handle combining
        !           610:      when we move several insns that load the same value
        !           611:      into different pseudo-registers.  */
        !           612:   rtx *reg_map = (rtx *) alloca (nregs * sizeof (rtx));
        !           613:   char *already_moved = (char *) alloca (nregs);
        !           614: 
        !           615:   bzero (already_moved, nregs);
        !           616:   bzero (reg_map, nregs * sizeof (rtx));
        !           617: 
        !           618:   for (m = movables; m; m = m->next)
        !           619:     {
        !           620:       /* Describe this movable insn.  */
        !           621: 
        !           622:       if (loop_dump_stream)
        !           623:        {
        !           624:          fprintf (loop_dump_stream, "Insn %d: regno %d (life %d), ",
        !           625:                   INSN_UID (m->insn), m->regno, m->lifetime);
        !           626:          if (m->consec > 0)
        !           627:            fprintf (loop_dump_stream, "consec %d, ", m->consec);
        !           628:          if (m->cond)
        !           629:            fprintf (loop_dump_stream, "cond ");
        !           630:          if (m->force)
        !           631:            fprintf (loop_dump_stream, "force ");
        !           632:          if (m->global)
        !           633:            fprintf (loop_dump_stream, "global ");
        !           634:          if (m->done)
        !           635:            fprintf (loop_dump_stream, "done ");
        !           636:          if (m->match)
        !           637:            fprintf (loop_dump_stream, "matches %d ",
        !           638:                     INSN_UID (m->match->insn));
        !           639:          if (m->forces)
        !           640:            fprintf (loop_dump_stream, "forces %d ",
        !           641:                     INSN_UID (m->forces->insn));
        !           642:        }
        !           643: 
        !           644:       /* Ignore the insn if it's already done (it matched something else).
        !           645:         Otherwise, see if it is now safe to move.  */
        !           646: 
        !           647:       if (!m->done
        !           648:          && (! m->cond
        !           649:              || 1 == invariant_p (SET_SRC (PATTERN (m->insn)), n_times_set))
        !           650:          && (! m->forces || m->forces->done))
        !           651:        {
        !           652:          register int regno;
        !           653:          register rtx p;
        !           654:          int times_used = m->times_used + m->consec;
        !           655: 
        !           656:          /* We have an insn that is safe to move.
        !           657:             Compute its desirability.  */
        !           658: 
        !           659:          p = m->insn;
        !           660:          regno = m->regno;
        !           661: 
        !           662:          if (loop_dump_stream)
        !           663:            fprintf (loop_dump_stream, "reg uses %d ", times_used);
        !           664: 
        !           665:          /* An insn MUST be moved if we already moved something else
        !           666:             which is safe only if this one is moved too: that is,
        !           667:             if already_moved[REGNO] is nonzero.  */
        !           668: 
        !           669:          /* An insn is desirable to move if the new lifetime of the
        !           670:             register is no more than THRESHOLD times the old lifetime.
        !           671:             If it's not desirable, it means the loop is so big
        !           672:             that moving won't speed things up much,
        !           673:             and it is liable to make register usage worse.  */
        !           674: 
        !           675:          /* It is also desirable to move if it can be moved at no
        !           676:             extra cost because something else was already moved.  */
        !           677: 
        !           678:          if (already_moved[regno]
        !           679:              || (threshold * times_used * m->lifetime) >= insn_count
        !           680:              || (m->forces && m->forces->done
        !           681:                  && n_times_used[m->forces->regno] == 1))
1.1       root      682:            {
1.1.1.2 ! root      683:              int count;
        !           684:              register struct movable *m1;
        !           685: 
        !           686:              for (count = m->consec; count >= 0; count--)
1.1       root      687:                {
1.1.1.2 ! root      688:                  rtx i1 = emit_insn_before (PATTERN (p), loop_start);
        !           689:                  if (new_start == 0)
        !           690:                    new_start = i1;
        !           691: 
        !           692:                  if (loop_dump_stream)
        !           693:                    fprintf (loop_dump_stream, "moved to %d", INSN_UID (i1));
        !           694: 
        !           695:                  /* Mark the moved, invariant reg as being equivalent to
        !           696:                     its constant value.  */
        !           697:                  REG_NOTES (i1) = REG_NOTES (p);
        !           698:                  if (REG_NOTES (i1) == 0
        !           699:                      && ! m->partial /* But not if its a zero-extend clr. */
        !           700:                      && ! m->global /* and not if used outside the loop
        !           701:                                        (since it might get set outside).  */
        !           702:                      && CONSTANT_P (SET_SRC (PATTERN (p))))
        !           703:                    REG_NOTES (i1)
        !           704:                      = gen_rtx (EXPR_LIST, REG_EQUIV,
        !           705:                                 SET_SRC (PATTERN (p)), REG_NOTES (i1));
        !           706:                  delete_insn (p);
        !           707:                  do p = NEXT_INSN (p);
        !           708:                  while (GET_CODE (p) == NOTE);
        !           709: 
        !           710:                  /* The more insns we move, the less we like moving them.  */
        !           711:                  threshold -= 2;
1.1       root      712:                }
1.1.1.2 ! root      713: 
        !           714:              /* Any other movable that loads the same register
        !           715:                 MUST be moved.  */
        !           716:              already_moved[regno] = 1;
        !           717: 
        !           718:              /* The reg set here is now invariant.  */
        !           719:              if (! m->partial)
        !           720:                n_times_set[regno] = 0;
        !           721: 
        !           722:              m->done = 1;
        !           723: 
        !           724:              /* Combine with this moved insn any other matching movables.  */
1.1       root      725: 
                    726:              for (m1 = m->next; m1; m1 = m1->next)
                    727:                if (m1->match == m)
                    728:                  {
                    729:                    /* Schedule the reg loaded by M1
                    730:                       for replacement so that shares the reg of M.  */
                    731:                    reg_map[m1->regno] = SET_DEST (PATTERN (m->insn));
1.1.1.2 ! root      732:                    /* Get rid of the matching insn
1.1       root      733:                       and prevent further processing of it.  */
1.1.1.2 ! root      734:                    m1->done = 1;
1.1       root      735:                    delete_insn (m1->insn);
1.1.1.2 ! root      736: 
        !           737:                    /* Any other movable that loads the same register
        !           738:                       MUST be moved.  */
        !           739:                    already_moved[m1->regno] = 1;
        !           740: 
        !           741:                    /* The reg merged here is now invariant.  */
        !           742:                    if (m->partial)
        !           743:                      n_times_set[m1->regno] = 0;
1.1       root      744:                  }
                    745:            }
1.1.1.2 ! root      746:          else if (loop_dump_stream)
        !           747:            fprintf (loop_dump_stream, "not desirable");
1.1       root      748:        }
1.1.1.2 ! root      749:       else if (loop_dump_stream && !m->match)
        !           750:        fprintf (loop_dump_stream, "not safe");
1.1       root      751: 
1.1.1.2 ! root      752:       if (loop_dump_stream)
        !           753:        fprintf (loop_dump_stream, "\n");
        !           754:     }
1.1       root      755: 
1.1.1.2 ! root      756:   if (new_start == 0)
        !           757:     new_start = loop_start;
1.1       root      758: 
1.1.1.2 ! root      759:   /* Go through all the instructions in the loop, making
        !           760:      all the register substitutions scheduled in REG_MAP.  */
        !           761:   for (p = new_start; p != end; p = NEXT_INSN (p))
        !           762:     if (GET_CODE (p) == INSN || GET_CODE (p) == JUMP_INSN
        !           763:        || GET_CODE (p) == CALL_INSN)
        !           764:       replace_regs (PATTERN (p), reg_map);
        !           765: }
        !           766: 
        !           767: /* Optionally change a loop which enters just before the endtest
        !           768:    to one which falls straight in
        !           769:    after skipping around the entire loop if the endtest would drop out.
        !           770:    Returns 1 if the change was made, 0 if the loop was not really suitable.  */
        !           771: 
        !           772: int
        !           773: loop_skip_over (start, end, loop_entry_jump)
        !           774:      rtx start;
        !           775:      rtx end;
        !           776:      rtx loop_entry_jump;
        !           777: {
        !           778:   rtx endtestjump;
        !           779:   register rtx p = JUMP_LABEL (loop_entry_jump);
1.1       root      780: 
1.1.1.2 ! root      781:   while (GET_CODE (p) != INSN && GET_CODE (p) != JUMP_INSN
        !           782:         && GET_CODE (p) != CALL_INSN)
        !           783:     p = NEXT_INSN (p);
        !           784:   endtestjump = next_real_insn (p);
        !           785: 
        !           786:   /* Check that we (1) enter at a compare insn and (2)
        !           787:      the insn (presumably a jump) following that compare
        !           788:      is the last in the loop and jumps back to the loop beginning.  */
        !           789: 
        !           790:   if (GET_CODE (PATTERN (p)) == SET
        !           791:       && SET_DEST (PATTERN (p)) == cc0_rtx
        !           792:       && endtestjump == prev_real_insn (end)
        !           793:       && prev_real_insn (JUMP_LABEL (endtestjump)) == loop_entry_jump)
1.1       root      794:     {
1.1.1.2 ! root      795:       rtx newlab;
        !           796:       /* This is the jump that we insert.  */
        !           797:       rtx new_jump;
        !           798: 
        !           799:       /* Ok, duplicate that test before start of loop.  */
        !           800:       emit_insn_before (copy_rtx (PATTERN (p)), start);
        !           801:       /* Make a new entry-jump (before the original one)
        !           802:         whose condition is opposite to the loop-around endtest
        !           803:         and which jumps around the loop (to just after the endtest).  */
        !           804:       newlab = gen_label_rtx ();
        !           805:       emit_label_after (newlab, endtestjump);
        !           806:       emit_jump_insn_before (copy_rtx (PATTERN (endtestjump)), start);
        !           807:       new_jump = PREV_INSN (start);
        !           808:       JUMP_LABEL (new_jump) = JUMP_LABEL (endtestjump);
        !           809:       LABEL_NUSES (JUMP_LABEL (endtestjump))++;
        !           810:       invert_jump (new_jump, newlab);
        !           811:       /* Delete the original entry-jump.  */
        !           812:       delete_insn (loop_entry_jump);
1.1       root      813: 
1.1.1.2 ! root      814:       return 1;
1.1       root      815:     }
1.1.1.2 ! root      816: 
        !           817:   return 0;
1.1       root      818: }
                    819: 
                    820: /* Throughout the rtx X, replace many registers according to REG_MAP.
                    821:    Return the replacement for X (which may be X with altered contents).
                    822:    REG_MAP[R] is the replacement for register R, or 0 for don't replace.  */
                    823: 
                    824: static rtx
                    825: replace_regs (x, reg_map)
                    826:      rtx x;
                    827:      rtx *reg_map;
                    828: {
                    829:   register RTX_CODE code = GET_CODE (x);
                    830:   register int i;
                    831:   register char *fmt;
                    832: 
                    833:   switch (code)
                    834:     {
                    835:     case PC:
                    836:     case CC0:
                    837:     case CONST_INT:
                    838:     case CONST_DOUBLE:
                    839:     case CONST:
                    840:     case SYMBOL_REF:
                    841:     case LABEL_REF:
                    842:       return x;
                    843: 
                    844:     case REG:
                    845:       if (reg_map[REGNO (x)] != 0)
                    846:        return reg_map[REGNO (x)];
                    847:       return x;
                    848:     }
                    849: 
                    850:   fmt = GET_RTX_FORMAT (code);
                    851:   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
                    852:     {
                    853:       if (fmt[i] == 'e')
                    854:        XEXP (x, i) = replace_regs (XEXP (x, i), reg_map);
                    855:       if (fmt[i] == 'E')
                    856:        {
                    857:          register int j;
                    858:          for (j = 0; j < XVECLEN (x, i); j++)
                    859:            XVECEXP (x, i, j) = replace_regs (XVECEXP (x, i, j), reg_map);
                    860:        }
                    861:     }
                    862:   return x;
                    863: }
                    864: 
                    865: /* P is an instruction that sets a register to the result of a ZERO_EXTEND.
                    866:    Replace it with an instruction to load just the low bytes
                    867:    if the machine supports such an instruction,
                    868:    and insert above LOOP_START an instruction to clear the register.  */
                    869: 
                    870: static void
                    871: constant_high_bytes (p, loop_start)
                    872:      rtx p, loop_start;
                    873: {
                    874:   register rtx new;
                    875:   register int insn_code_number;
                    876: 
                    877:   /* Try to change (SET (REG ...) (ZERO_EXTEND (..:B ...)))
                    878:      to (SET (STRICT_LOW_PART (SUBREG:B (REG...))) ...).  */
                    879: 
                    880:   new = gen_rtx (SET, VOIDmode,
                    881:                 gen_rtx (STRICT_LOW_PART, VOIDmode,
                    882:                          gen_rtx (SUBREG, GET_MODE (XEXP (SET_SRC (PATTERN (p)), 0)),
                    883:                                   SET_DEST (PATTERN (p)),
                    884:                                   0)),
                    885:                 XEXP (SET_SRC (PATTERN (p)), 0));
                    886:   insn_code_number = recog (new, p);
                    887: 
                    888:   if (insn_code_number)
                    889:     {
                    890:       register int i;
                    891: 
                    892:       /* Clear destination register before the loop.  */
                    893:       emit_insn_before (gen_rtx (SET, VOIDmode,
                    894:                                 SET_DEST (PATTERN (p)),
                    895:                                 const0_rtx),
                    896:                        loop_start);
                    897: 
                    898:       /* Inside the loop, just load the low part.  */
                    899:       PATTERN (p) = new;
                    900:     }
                    901: }
                    902: 
                    903: /* Verify that the ostensible loop starting at START
                    904:    really is a loop: nothing jumps into it from outside.
                    905:    Return the marker for the end of the loop, or zero if not a real loop.
                    906: 
                    907:    Also set the variables `unknown_*_altered' and `loop_has_call',
                    908:    and fill in the array `loop_store_addrs'.  */
                    909: 
                    910: static rtx
                    911: verify_loop (f, start)
                    912:      rtx f, start;
                    913: {
                    914:   register int level = 1;
                    915:   register rtx insn, end;
                    916: 
                    917:   /* First find the LOOP_END that matches.
                    918:      Also check each insn for storing in memory and record where.  */
                    919: 
                    920:   unknown_address_altered = 0;
                    921:   unknown_aggregate_altered = 0;
                    922:   fixed_aggregate_altered = 0;
                    923:   loop_has_call = 0;
                    924:   loop_store_addrs_idx = 0;
                    925: 
                    926:   for (insn = NEXT_INSN (start); level > 0; insn = NEXT_INSN (insn))
                    927:     {
                    928:       if (insn == 0)
1.1.1.2 ! root      929:        /* Parse errors can cause a loop-beg with no loop-end.  */
        !           930:        return 0;
1.1       root      931:       if (GET_CODE (insn) == NOTE)
                    932:        {
                    933:          if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
                    934:            ++level;
                    935:          else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END)
1.1.1.2 ! root      936:            {
        !           937:              --level;
        !           938:              if (level == 0)
        !           939:                {
        !           940:                  end = insn;
        !           941:                  break;
        !           942:                }
        !           943:            }
1.1       root      944:        }
                    945:       else if (GET_CODE (insn) == CALL_INSN)
                    946:        {
                    947:          unknown_address_altered = 1;
                    948:          loop_has_call = 1;
                    949:        }
                    950:       else if (! unknown_address_altered)
                    951:        {
                    952:          if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN)
                    953:            note_stores (PATTERN (insn), note_addr_stored);
                    954:        }
                    955:     }
                    956: 
                    957:   /* Now scan all jumps in the function and see if any of them can
                    958:      reach a label within the range of the loop.  */
                    959: 
                    960:   for (insn = f; insn; insn = NEXT_INSN (insn))
                    961:     if (GET_CODE (insn) == JUMP_INSN
                    962:        /* Don't get fooled by jumps inserted by loop-optimize.
                    963:           They don't have valid LUIDs, and they never jump into loops.  */
                    964:        && INSN_UID (insn) < max_uid
                    965:        && (INSN_LUID (insn) < INSN_LUID (start)
                    966:            || INSN_LUID (insn) > INSN_LUID (end))
                    967:        /* We have a jump that is outside the loop.
                    968:           Does it jump into the loop?  */
                    969:        && can_jump_into_range_p (PATTERN (insn),
                    970:                                  INSN_LUID (start), INSN_LUID (end)))
                    971:       return 0;
                    972: 
                    973: #if 0      
                    974:   /* Now scan all labels between them and check for any jumps from outside.
                    975:      This uses the ref-chains set up by find_basic_blocks.
                    976:      This code is not used because it's more convenient for other reasons
                    977:      to do the loop optimization before find_basic_blocks.  */
                    978: 
                    979:   for (insn = start; insn != end; insn = NEXT_INSN (insn))
                    980:     if (GET_CODE (insn) == CODE_LABEL)
                    981:       {
                    982:        register rtx y;
                    983:        for (y = LABEL_REFS (insn); y != insn; y = LABEL_NEXTREF (y))
                    984:          if (INSN_LUID (CONTAINING_INSN (y)) < INSN_LUID (start)
                    985:              || INSN_LUID (CONTAINING_INSN (y)) > INSN_LUID (end))
                    986:            return 0;
                    987:       }
                    988: #endif
                    989: 
                    990:   return end;
                    991: }
                    992: 
                    993: /* Return 1 if somewhere in X is a LABEL_REF to a label
                    994:    located between BEG and END.  */
                    995: 
                    996: static int
                    997: can_jump_into_range_p (x, beg, end)
                    998:      rtx x;
                    999:      int beg, end;
                   1000: {
                   1001:   register RTX_CODE code = GET_CODE (x);
                   1002:   register int i;
                   1003:   register char *fmt;
                   1004: 
                   1005:   if (code == LABEL_REF)
                   1006:     {
                   1007:       register int luid = INSN_LUID (XEXP (x, 0));
                   1008:       return luid > beg && luid < end;
                   1009:     }
                   1010: 
                   1011:   fmt = GET_RTX_FORMAT (code);
                   1012:   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
                   1013:     {
                   1014:       if (fmt[i] == 'e')
                   1015:        {
                   1016:          if (can_jump_into_range_p (XEXP (x, i), beg, end))
                   1017:            return 1;
                   1018:        }
                   1019:       else if (fmt[i] == 'E')
                   1020:        {
                   1021:          register int j;
                   1022:          for (j = 0; j < XVECLEN (x, i); j++)
                   1023:            if (can_jump_into_range_p (XVECEXP (x, i, j), beg, end))
                   1024:              return 1;
                   1025:        }
                   1026:     }
                   1027: 
                   1028:   return 0;
                   1029: }
                   1030: 
                   1031: /* Record that a memory reference X is being set.  */
                   1032: 
                   1033: static void
                   1034: note_addr_stored (x)
                   1035:      rtx x;
                   1036: {
                   1037:   rtx addr;
                   1038:   if (x == 0 || GET_CODE (x) != MEM)
                   1039:     return;
1.1.1.2 ! root     1040:   if (GET_MODE (x) == BLKmode)
        !          1041:     unknown_address_altered = 1;
        !          1042:   else if (rtx_addr_varies_p (x))
1.1       root     1043:     {
                   1044:       if (GET_CODE (XEXP (x, 0)) == PLUS)
                   1045:        unknown_aggregate_altered = 1;
                   1046:       else
                   1047:        unknown_address_altered = 1;
                   1048:     }
                   1049:   else
                   1050:     {
                   1051:       register int i;
                   1052:       register rtx addr = XEXP (x, 0);
                   1053: 
                   1054:       if (x->in_struct)
                   1055:        fixed_aggregate_altered = 1;
                   1056:       for (i = 0; i < loop_store_addrs_idx; i++)
                   1057:        if (rtx_equal_p (loop_store_addrs[i], addr))
                   1058:          {
                   1059:            if (loop_store_widths[i] < GET_MODE_SIZE (GET_MODE (x)))
                   1060:              loop_store_widths[i] = GET_MODE_SIZE (GET_MODE (x));
                   1061:            break;
                   1062:          }
                   1063:       if (i == NUM_STORES)
                   1064:        unknown_address_altered = 1;
                   1065:       else if (i == loop_store_addrs_idx)
                   1066:        {
1.1.1.2 ! root     1067:          loop_store_widths[i] = GET_MODE_SIZE (GET_MODE (x));
1.1       root     1068:          loop_store_addrs[loop_store_addrs_idx++] = addr;
                   1069:        }
                   1070:     }
                   1071: }
                   1072: 
                   1073: /* Return nonzero if the rtx X is invariant over the current loop.
                   1074:    N_TIMES_SET is a vector whose element I is nonzero if register I
                   1075:    is set during the loop.
                   1076: 
                   1077:    The value is 2 if we refer to something only conditionally invariant.
                   1078: 
                   1079:    If `unknown_address_altered' is nonzero, no memory ref is invariant.
                   1080:    Otherwise if `unknown_aggregate_altered' is nonzero,
                   1081:    a memory ref is invariant if it is not part of an aggregate
                   1082:    and its address is fixed and not in `loop_store_addrs'.
                   1083:    Otherwise if `fixed_aggregate_altered' is nonzero,
                   1084:    a memory ref is invariant
                   1085:    if its address is fixed and not in `loop_store_addrs'.
                   1086:    Otherwise, a memory ref is invariant if its address is fixed and not in
                   1087:    `loop_store_addrs' or if it is not an aggregate.  */
                   1088: 
                   1089: static int
                   1090: invariant_p (x, n_times_set)
                   1091:      register rtx x;
                   1092:      short *n_times_set;
                   1093: {
                   1094:   register int i;
                   1095:   register RTX_CODE code = GET_CODE (x);
                   1096:   register char *fmt;
                   1097:   int conditional = 0;
                   1098: 
                   1099:   switch (code)
                   1100:     {
                   1101:     case CONST_INT:
                   1102:     case CONST_DOUBLE:
                   1103:     case SYMBOL_REF:
                   1104:     case LABEL_REF:
                   1105:     case CONST:
                   1106:       return 1;
                   1107: 
                   1108:     case PC:
                   1109:     case CC0:
                   1110:       return 0;
                   1111: 
                   1112:     case REG:
1.1.1.2 ! root     1113:       if (x == frame_pointer_rtx || x == arg_pointer_rtx
        !          1114:          || x->unchanging)
        !          1115:        return 1;
1.1       root     1116:       if (n_times_set[REGNO (x)] == -1)
                   1117:        return 2;
                   1118:       return n_times_set[REGNO (x)] == 0;
                   1119: 
                   1120:     case MEM:
                   1121:       /* A store in a varying-address scalar (or a subroutine call)
                   1122:         could clobber anything in memory.  */
                   1123:       if (unknown_address_altered)
                   1124:        return 0;
1.1.1.2 ! root     1125:       /* Don't mess with volatile memory references.  */
        !          1126:       if (x->volatil)
        !          1127:        return 0;
        !          1128:       /* If it's declared read-only, it is invariant
        !          1129:         if its address is invariant.  */
        !          1130:       if (x->unchanging)
        !          1131:        return invariant_p (XEXP (x, 0), n_times_set);
1.1       root     1132:       /* A store in a varying-address aggregate component
                   1133:         could clobber anything except a scalar with a fixed address.  */
                   1134:       if (unknown_aggregate_altered
                   1135:          && ((x->in_struct || GET_CODE (XEXP (x, 0)) == PLUS)
                   1136:              || rtx_addr_varies_p (x)))
                   1137:        return 0;
                   1138:       /* A store in a fixed-address aggregate component
                   1139:         could clobber anything whose address is not fixed,
                   1140:         even an aggregate component.  */
                   1141:       if (fixed_aggregate_altered
                   1142:          && rtx_addr_varies_p (x))
                   1143:        return 0;
                   1144:       /* Any store could clobber a varying-address scalar.  */
                   1145:       if (loop_store_addrs_idx
                   1146:          && !(x->in_struct || GET_CODE (XEXP (x, 0)) == PLUS)
                   1147:          && rtx_addr_varies_p (x))
                   1148:        return 0;
                   1149:       /* A store in a fixed address clobbers overlapping references.  */
                   1150:       for (i = loop_store_addrs_idx - 1; i >= 0; i--)
1.1.1.2 ! root     1151:        if (addr_overlap_p (x, loop_store_addrs[i], loop_store_widths[i]))
1.1       root     1152:          return 0;
                   1153:       /* It's not invalidated by a store in memory
                   1154:         but we must still verify the address is invariant.  */
1.1.1.2 ! root     1155:       break;
        !          1156: 
        !          1157:     case ASM_OPERANDS:
        !          1158:       /* Don't mess with insns declared volatile.  */
        !          1159:       if (x->volatil)
        !          1160:        return 0;
1.1       root     1161:     }
                   1162: 
                   1163:   fmt = GET_RTX_FORMAT (code);
                   1164:   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
                   1165:     {
                   1166:       if (fmt[i] == 'e')
                   1167:        {
                   1168:          int tem = invariant_p (XEXP (x, i), n_times_set);
                   1169:          if (tem == 0)
                   1170:            return 0;
                   1171:          if (tem == 2)
                   1172:            conditional = 1;
                   1173:        }
1.1.1.2 ! root     1174:       else if (fmt[i] == 'E')
        !          1175:        {
        !          1176:          register int j;
        !          1177:          for (j = 0; j < XVECLEN (x, i); j++)
        !          1178:            {
        !          1179:              int tem = invariant_p (XVECEXP (x, i, j), n_times_set);
        !          1180:              if (tem == 0)
        !          1181:                return 0;
        !          1182:              if (tem == 2)
        !          1183:                conditional = 1;
        !          1184:            }
        !          1185: 
        !          1186:        }
1.1       root     1187:     }
                   1188: 
                   1189:   return 1 + conditional;
                   1190: }
                   1191: 
                   1192: /* Return 1 if OTHER (a mem ref) overlaps the area of memory
                   1193:    which is SIZE bytes starting at BASE.  */
                   1194: 
                   1195: int
                   1196: addr_overlap_p (other, base, size)
                   1197:      rtx other;
                   1198:      rtx base;
                   1199:      int size;
                   1200: {
                   1201:   int start = 0, end;
                   1202: 
                   1203:   if (GET_CODE (base) == CONST)
                   1204:     base = XEXP (base, 0);
                   1205:   if (GET_CODE (base) == PLUS
                   1206:       && GET_CODE (XEXP (base, 1)) == CONST_INT)
                   1207:     {
                   1208:       start = INTVAL (XEXP (base, 1));
                   1209:       base = XEXP (base, 0);
                   1210:     }
                   1211: 
                   1212:   end = start + size;
                   1213:   return refers_to_mem_p (other, base, start, end);
                   1214: }
1.1.1.2 ! root     1215: 
        !          1216: /* Return 1 if all the insns in the loop that set REG
        !          1217:    are INSN and the immediately following insns,
        !          1218:    and if each of those insns sets REG in an invariant way
        !          1219:    according to TABLE (not counting uses of REG in them).
        !          1220: 
        !          1221:    We assume that INSN itself is the first set of REG
        !          1222:    and that its source is invariant.  */
        !          1223: 
        !          1224: static int
        !          1225: consec_sets_invariant_p (reg, insn, table)
        !          1226:      rtx reg, insn;
        !          1227:      short *table;
        !          1228: {
        !          1229:   register rtx p = insn;
        !          1230:   register int regno = REGNO (reg);
        !          1231:   /* Number of sets we have to insist on finding after INSN.  */
        !          1232:   int count = table[regno] - 1;
        !          1233:   int old = table[regno];
        !          1234: 
        !          1235:   table[regno] = 0;
        !          1236: 
        !          1237:   while (count > 0)
        !          1238:     {
        !          1239:       register enum rtx_code code;
        !          1240:       p = NEXT_INSN (p);
        !          1241:       code = GET_CODE (p);
        !          1242:       if (code == INSN && GET_CODE (PATTERN (p)) == SET
        !          1243:          && GET_CODE (SET_DEST (PATTERN (p))) == REG
        !          1244:          && REGNO (SET_DEST (PATTERN (p))) == regno
        !          1245:          && invariant_p (SET_SRC (PATTERN (p)), table))
        !          1246:        count--;
        !          1247:       else if (code != NOTE)
        !          1248:        {
        !          1249:          table[regno] = old;
        !          1250:          return 0;
        !          1251:        }
        !          1252:     }
        !          1253: 
        !          1254:   table[regno] = old;
        !          1255:   return 1;
        !          1256: }
        !          1257: 
        !          1258: #if 0
        !          1259: /* I don't think this condition is sufficient to allow INSN
        !          1260:    to be moved, so we no longer test it.  */
1.1       root     1261: 
                   1262: /* Return 1 if all insns in the basic block of INSN and following INSN
                   1263:    that set REG are invariant according to TABLE.  */
                   1264: 
                   1265: static int
                   1266: all_sets_invariant_p (reg, insn, table)
                   1267:      rtx reg, insn;
1.1.1.2 ! root     1268:      short *table;
1.1       root     1269: {
                   1270:   register rtx p = insn;
                   1271:   register int regno = REGNO (reg);
                   1272: 
                   1273:   while (1)
                   1274:     {
                   1275:       register enum rtx_code code;
                   1276:       p = NEXT_INSN (p);
                   1277:       code = GET_CODE (p);
                   1278:       if (code == CODE_LABEL || code == JUMP_INSN)
                   1279:        return 1;
                   1280:       if (code == INSN && GET_CODE (PATTERN (p)) == SET
                   1281:          && GET_CODE (SET_DEST (PATTERN (p))) == REG
                   1282:          && REGNO (SET_DEST (PATTERN (p))) == regno)
                   1283:        {
                   1284:          if (!invariant_p (SET_SRC (PATTERN (p)), table))
                   1285:            return 0;
                   1286:        }
                   1287:     }
                   1288: }
1.1.1.2 ! root     1289: #endif /* 0 */
1.1       root     1290: 
                   1291: /* Increment N_TIMES_SET at the index of each register
                   1292:    that is modified by an insn between FROM and TO.
                   1293:    If the value of an element of N_TIMES_SET becomes 2 or more,
                   1294:    do not keep incrementing it; all values >= 2 would be
                   1295:    equivalent anyway, and this way we avoid danger of overflow.
                   1296: 
                   1297:    Store in *COUNT_PTR the number of actual instruction
                   1298:    in the loop.  We use this to decide what is worth moving out.  */
                   1299: 
                   1300: /* last_set[n] is nonzero iff reg n has been set in the current basic block.
                   1301:    In that case, it is the insn that last set reg n.  */
                   1302: 
                   1303: static void
                   1304: count_loop_regs_set (from, to, n_times_set, may_not_move, count_ptr, nregs)
                   1305:      register rtx from, to;
                   1306:      short *n_times_set;
                   1307:      char *may_not_move;
                   1308:      int *count_ptr;
                   1309:      int nregs;
                   1310: {
                   1311:   register rtx *last_set = (rtx *) alloca (nregs * sizeof (rtx));
                   1312:   register rtx insn;
                   1313:   register int count = 0;
                   1314:   register rtx dest;
                   1315: 
                   1316:   bzero (last_set, nregs * sizeof (rtx));
                   1317:   for (insn = from; insn != to; insn = NEXT_INSN (insn))
                   1318:     {
1.1.1.2 ! root     1319:       if (GET_CODE (insn) == CALL_INSN)
        !          1320:        {
        !          1321:          /* If a register is used as a subroutine address,
        !          1322:             don't allow this register's setting to be moved out of the loop.
        !          1323:             This condition is not at all logically correct
        !          1324:             but it averts a very common lossage pattern
        !          1325:             and creates lossage much less often.  */
        !          1326:          if (GET_CODE (PATTERN (insn)) == CALL
        !          1327:              && GET_CODE (XEXP (PATTERN (insn), 0)) == MEM
        !          1328:              && GET_CODE (XEXP (XEXP (PATTERN (insn), 0), 0)) == REG)
        !          1329:            {
        !          1330:              register int regno
        !          1331:                = REGNO (XEXP (XEXP (PATTERN (insn), 0), 0));
        !          1332:              may_not_move[regno] = 1;
        !          1333:            }
        !          1334:          else if (GET_CODE (PATTERN (insn)) == SET
        !          1335:              && GET_CODE (SET_SRC (PATTERN (insn))) == CALL
        !          1336:              && GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 0)) == MEM
        !          1337:              && GET_CODE (XEXP (XEXP (SET_SRC (PATTERN (insn)), 0), 0)) == REG)
        !          1338:            {
        !          1339:              register int regno
        !          1340:                = REGNO (XEXP (XEXP (SET_SRC (PATTERN (insn)), 0), 0));
        !          1341:              may_not_move[regno] = 1;
        !          1342:              /* The call insn itself sets a reg, which cannot be moved.  */
        !          1343:              may_not_move[REGNO (SET_DEST (PATTERN (insn)))] = 1;
        !          1344:              n_times_set[REGNO (SET_DEST (PATTERN (insn)))]++;
        !          1345:            }
        !          1346:        }
        !          1347:       if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN) 
1.1       root     1348:        {
                   1349:          ++count;
1.1.1.2 ! root     1350:          if (GET_CODE (PATTERN (insn)) == CLOBBER
        !          1351:              && GET_CODE (XEXP (PATTERN (insn), 0)) == REG)
        !          1352:            /* Don't move a reg that has an explicit clobber.
        !          1353:               We might do so sometimes, but it's not worth the pain.  */
        !          1354:            may_not_move[REGNO (XEXP (PATTERN (insn), 0))] = 1;
        !          1355:          else if (GET_CODE (PATTERN (insn)) == SET)
1.1       root     1356:            {
                   1357:              dest = SET_DEST (PATTERN (insn));
                   1358:              while (GET_CODE (dest) == SUBREG
                   1359:                     || GET_CODE (dest) == ZERO_EXTRACT
                   1360:                     || GET_CODE (dest) == SIGN_EXTRACT
                   1361:                     || GET_CODE (dest) == STRICT_LOW_PART)
                   1362:                dest = XEXP (dest, 0);
                   1363:              if (GET_CODE (dest) == REG)
                   1364:                {
                   1365:                  register int regno = REGNO (dest);
                   1366:                  /* If this is the first setting of this reg
                   1367:                     in current basic block, and it was set before,
                   1368:                     it must be set in two basic blocks, so it cannot
                   1369:                     be moved out of the loop.  */
                   1370:                  if (n_times_set[regno] > 0 && last_set[regno] == 0)
                   1371:                    may_not_move[regno] = 1;
                   1372:                  /* If this is not first setting in current basic block,
                   1373:                     see if reg was used in between previous one and this.
                   1374:                     If so, neither one can be moved.  */
                   1375:                  if (last_set[regno] != 0
                   1376:                      && reg_used_between_p (dest, last_set[regno], insn))
                   1377:                    may_not_move[regno] = 1;
                   1378:                  ++n_times_set[regno];
                   1379:                  last_set[regno] = insn;
                   1380:                }
                   1381:            }
                   1382:          else if (GET_CODE (PATTERN (insn)) == PARALLEL)
                   1383:            {
                   1384:              register int i;
                   1385:              for (i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--)
                   1386:                {
                   1387:                  register rtx x = XVECEXP (PATTERN (insn), 0, i);
1.1.1.2 ! root     1388:                  if (GET_CODE (x) == CLOBBER && GET_CODE (XEXP (x, 0)) == REG)
        !          1389:                    /* Don't move a reg that has an explicit clobber.
        !          1390:                       It's not worth the pain to try to do it correctly.  */
        !          1391:                    may_not_move[REGNO (XEXP (x, 0))] = 1;
1.1       root     1392:                  if (GET_CODE (x) == SET)
                   1393:                    {
                   1394:                      dest = SET_DEST (x);
                   1395:                      while (GET_CODE (dest) == SUBREG
                   1396:                             || GET_CODE (dest) == ZERO_EXTRACT
                   1397:                             || GET_CODE (dest) == SIGN_EXTRACT
                   1398:                             || GET_CODE (dest) == STRICT_LOW_PART)
                   1399:                        dest = XEXP (dest, 0);
                   1400:                      if (GET_CODE (dest) == REG)
                   1401:                        {
                   1402:                          register int regno = REGNO (dest);
                   1403:                          ++n_times_set[regno];
                   1404:                          may_not_move[regno] = 1;
                   1405:                          last_set[regno] = insn;
                   1406:                        }
                   1407:                    }
                   1408:                }
                   1409:            }
                   1410:        }
                   1411:       if (GET_CODE (insn) == CODE_LABEL || GET_CODE (insn) == JUMP_INSN)
                   1412:        bzero (last_set, nregs * sizeof (rtx));
                   1413:     }
                   1414:   *count_ptr = count;
                   1415: }
                   1416: 
                   1417: /* Given a loop that is bounded by LOOP_START and LOOP_END
                   1418:    and that is entered at SCAN_START,
                   1419:    return 1 if the register set by insn INSN is used by
                   1420:    any insn that precedes INSN in cyclic order starting
                   1421:    from the loop entry point.  */
                   1422: 
                   1423: static int
                   1424: loop_reg_used_before_p (insn, loop_start, scan_start, loop_end)
                   1425:      rtx insn, loop_start, scan_start, loop_end;
                   1426: {
                   1427:   rtx reg = SET_DEST (PATTERN (insn));
                   1428:   if (INSN_LUID (scan_start) > INSN_LUID (insn))
                   1429:     return (reg_used_between_p (reg, scan_start, loop_end)
                   1430:            || reg_used_between_p (reg, loop_start, insn));
                   1431:   else
                   1432:     return reg_used_between_p (reg, scan_start, insn);
                   1433: }
1.1.1.2 ! root     1434: 
        !          1435: /* Return nonzero if X is a division that might trap.  */
        !          1436: 
        !          1437: static int
        !          1438: may_trap_p (x)
        !          1439:      rtx x;
        !          1440: {
        !          1441:   switch (GET_CODE (x))
        !          1442:     {
        !          1443:     case DIV:
        !          1444:     case MOD:
        !          1445:     case UDIV:
        !          1446:     case UMOD:
        !          1447:       if (! CONSTANT_P (XEXP (x, 1))
        !          1448:          && GET_CODE (XEXP (x, 1)) != CONST_DOUBLE)
        !          1449:        return 1;
        !          1450:     }
        !          1451:   return 0;
        !          1452: }

unix.superglobalmegacorp.com

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