Annotation of gcc/loop.c, revision 1.1.1.7

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

unix.superglobalmegacorp.com

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