Annotation of gcc/loop.c, revision 1.1.1.6

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

unix.superglobalmegacorp.com

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