|
|
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
1.1.1.8 ! root 24: to the beginning of the loop. Then it identifies basic and
! 25: general induction variables. Strength reduction is applied to the general
! 26: induction variables, and induction variable elimination is applied to
! 27: the basic induction variables.
1.1 root 28:
29: It also finds cases where
30: a register is set within the loop by zero-extending a narrower value
31: and changes these to zero the entire register once before the loop
32: and merely copy the low part within the loop.
33:
34: Most of the complexity is in heuristics to decide when it is worth
35: while to do these things. */
36:
37: /* ??? verify_loop would run faster if we made one table
38: of the minimum and maximum luids from which each label is reached.
39: Also, it would be faster if loop_store_addrs were a hash table. */
40:
41: #include "config.h"
42: #include "rtl.h"
43: #include "insn-config.h"
44: #include "regs.h"
45: #include "recog.h"
1.1.1.8 ! root 46: #include "flags.h"
1.1.1.2 root 47: #include <stdio.h>
1.1 root 48:
49: /* Vector mapping INSN_UIDs to luids.
50: The luids are like uids but increase monononically always.
51: We use them to see whether a jump comes from outside a given loop. */
52:
53: static short *uid_luid;
54:
55: /* Get the luid of an insn. */
56:
57: #define INSN_LUID(INSN) (uid_luid[INSN_UID (INSN)])
58:
59: /* 1 + largest uid of any insn. */
60:
61: static int max_uid;
62:
63: /* 1 + luid of last insn. */
64:
65: static int max_luid;
66:
67: /* Nonzero if somewhere in the current loop
68: there is either a subroutine call,
69: or a store into a memory address that is not fixed,
70: or a store in a BLKmode memory operand,
71: or too many different fixed addresses stored in
72: to record them all in `loop_store_addrs'.
73:
74: In any of these cases, no memory location can be regarded
75: as invariant. */
76:
77: static int unknown_address_altered;
78:
79: /* Nonzero if somewhere in the current loop there is a store
80: into a memory address that is not fixed but is known to be
81: part of an aggregate.
82:
83: In this case, no memory reference in an aggregate may be
84: considered invariant. */
85:
86: static int unknown_aggregate_altered;
87:
88: /* Nonzero if somewhere in the current loop there is a store
89: into a memory address other than a fixed address not in an aggregate.
90:
91: In this case, no memory reference in an aggregate at a varying address
92: may be considered invariant. */
93:
94: static int fixed_aggregate_altered;
95:
96: /* Nonzero if there is a subroutine call in the current loop.
97: (unknown_address_altered is also nonzero in this case.) */
98:
99: static int loop_has_call;
100:
1.1.1.8 ! root 101: /* Indexed by register number, contains the number of times the reg
! 102: is set during the loop being scanned, or -1 if the insns that set it
! 103: have all been scanned as candidates for being moved out of the loop.
! 104: 0 indicates an invariant register; -1 a conditionally invariant one. */
! 105:
! 106: static short *n_times_set;
! 107:
! 108: /* Indexed by register number, contains the number of times the reg
! 109: was used during the loop being scanned, not counting changes due
! 110: to moving these insns out of the loop. */
! 111:
! 112: static short *n_times_used;
! 113:
1.1 root 114: /* Array of fixed memory addresses that are stored in this loop.
115: If there are too many to fit here,
116: we just turn on unknown_address_altered. */
117:
118: #define NUM_STORES 10
119: static rtx loop_store_addrs[NUM_STORES];
120: static int loop_store_widths[NUM_STORES];
121:
122: /* Index of first available slot in above array. */
123: static int loop_store_addrs_idx;
124:
1.1.1.8 ! root 125: /* Count of movable (i.e. invariant) instructions discovered in the loop. */
! 126: static int num_movables;
! 127:
! 128: /* Count of memory write instructions discovered in the loop. */
! 129: static int num_mem_sets;
! 130:
! 131: /* Number of loops contained within the current one, including itself. */
! 132: static int loops_enclosed;
! 133:
! 134: /* Bound on pseudo register number before loop optimization.
! 135: A pseudo has valid regscan info if its number is < old_max_reg. */
! 136: static int old_max_reg;
! 137:
1.1 root 138: /* During the analysis of a loop, a chain of `struct movable's
139: is made to record all the movable insns found.
140: Then the entire chain can be scanned to decide which to move. */
141:
142: struct movable
143: {
144: rtx insn; /* A movable insn */
1.1.1.8 ! root 145: rtx set_src; /* The expression this reg is set from.
! 146: Either SET_SRC (body) or a REG_EQUAL. */
1.1.1.2 root 147: int consec; /* Number of consecutive following insns
148: that must be moved with this one. */
1.1 root 149: int regno; /* The register it sets */
150: short lifetime; /* lifetime of that register;
151: may be adjusted when matching movables
152: that load the same value are found. */
1.1.1.2 root 153: short times_used; /* Number of times the register is used,
154: plus uses of related insns that could
155: be moved if this one is. */
1.1 root 156: unsigned int cond : 1; /* 1 if only conditionally movable */
157: unsigned int force : 1; /* 1 means MUST move this insn */
158: unsigned int global : 1; /* 1 means reg is live outside this loop */
1.1.1.2 root 159: unsigned int done : 1; /* 1 inhibits further processing of this */
160: unsigned int partial : 1; /* Moving this doesn't make it invariant. */
1.1 root 161: struct movable *match; /* First entry for same value */
162: struct movable *forces; /* An insn that must be moved if this is */
163: struct movable *next;
164: };
165:
1.1.1.2 root 166: static FILE *loop_dump_stream;
167:
1.1 root 168: static rtx verify_loop ();
169: static int invariant_p ();
1.1.1.4 root 170: static int consec_sets_invariant_p ();
1.1 root 171: static int can_jump_into_range_p ();
172: static void count_loop_regs_set ();
173: static void note_addr_stored ();
174: static int loop_reg_used_before_p ();
175: static void constant_high_bytes ();
176: static void scan_loop ();
177: static rtx replace_regs ();
1.1.1.2 root 178: static void move_movables ();
179: static int may_trap_p ();
1.1.1.8 ! root 180: static void strength_reduce ();
! 181: static void find_mem_givs ();
! 182: static void record_giv ();
! 183: static void delete_insn_forces ();
! 184: static int basic_induction_var ();
! 185: static int general_induction_var ();
! 186: static int consec_sets_giv ();
! 187: static int check_dbra_loop ();
! 188: static void emit_iv_init_code ();
! 189: static int product_cheap_p ();
! 190: static void emit_iv_inc ();
! 191: static int can_eliminate_biv_p ();
! 192: static void eliminate_biv ();
! 193: static rtx final_biv_value ();
1.1 root 194:
195: /* Entry point of this file. Perform loop optimization
196: on the current function. F is the first insn of the function
197: and NREGS is the number of register numbers used. */
198:
1.1.1.2 root 199: void
1.1.1.8 ! root 200: loop_optimize (f, dumpfile)
1.1 root 201: /* f is the first instruction of a chain of insns for one function */
202: rtx f;
1.1.1.2 root 203: FILE *dumpfile;
1.1 root 204: {
205: register rtx insn;
206: register int i;
207: rtx end;
208: rtx last_insn;
209:
1.1.1.2 root 210: loop_dump_stream = dumpfile;
211:
1.1 root 212: init_recog ();
213:
1.1.1.8 ! root 214: old_max_reg = max_reg_num();
! 215:
1.1 root 216: /* First find the last real insn, and count the number of insns,
217: and assign insns their suids. */
218:
219: for (insn = f, i = 0; insn; insn = NEXT_INSN (insn))
220: if (INSN_UID (insn) > i)
221: i = INSN_UID (insn);
222:
223: max_uid = i + 1;
224: uid_luid = (short *) alloca ((i + 1) * sizeof (short));
225: bzero (uid_luid, (i + 1) * sizeof (short));
226:
227: /* Compute the mapping from uids to luids.
228: LUIDs are numbers assigned to insns, like uids,
229: except that luids increase monotonically through the code. */
230:
231: for (insn = f, i = 0; insn; insn = NEXT_INSN (insn))
232: {
233: last_insn = insn;
234: INSN_LUID (insn) = ++i;
235: }
236:
237: max_luid = i;
238:
239: /* Don't leave gaps in uid_luid for insns that have been
240: deleted. It is possible that the first or last insn
241: using some register has been deleted by cross-jumping.
242: Make sure that uid_luid for that former insn's uid
243: points to the general area where that insn used to be. */
244: for (i = 0; i < max_uid; i++)
1.1.1.2 root 245: {
246: uid_luid[0] = uid_luid[i];
247: if (uid_luid[0] != 0)
248: break;
249: }
250: for (i = 0; i < max_uid; i++)
1.1 root 251: if (uid_luid[i] == 0)
252: uid_luid[i] = uid_luid[i - 1];
253:
254: /* Find and process each loop.
255: We scan from the end, and process each loop when its start is seen,
256: so we process innermost loops first. */
257:
258: for (insn = last_insn; insn; insn = PREV_INSN (insn))
259: if (GET_CODE (insn) == NOTE
1.1.1.4 root 260: && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
261: {
1.1 root 262: /* Make sure it really is a loop -- no jumps in from outside. */
1.1.1.4 root 263: end = verify_loop (f, insn);
264: if (end != 0)
265: /* If so, optimize this loop. */
1.1.1.8 ! root 266: scan_loop (insn, end, max_reg_num ());
1.1.1.4 root 267: else if (loop_dump_stream)
268: fprintf (loop_dump_stream,
269: "\nLoop at %d ignored due to multiple entry points.\n",
270: INSN_UID (insn));
271: }
1.1 root 272: }
273:
274: /* Optimize one loop whose start is LOOP_START and end is END.
275: LOOP_START is the NOTE_INSN_LOOP_BEG and END is the matching
276: NOTE_INSN_LOOP_END. */
277:
1.1.1.8 ! root 278: /* ??? can also move memory writes out of loop if destination
! 279: address is invariant? */
! 280:
1.1 root 281: static void
282: scan_loop (loop_start, end, nregs)
283: rtx loop_start, end;
284: int nregs;
285: {
286: register int i;
287: register rtx p = NEXT_INSN (loop_start);
288: /* 1 if we are scanning insns that could be executed zero times. */
289: int maybe_never = 0;
1.1.1.3 root 290: /* 1 if we are scanning insns that might never be executed
291: due to a subroutine call which might exit before they are reached. */
292: int call_passed = 0;
1.1 root 293: /* For a rotated loop that is entered near the bottom,
294: this is the label at the top. Otherwise it is zero. */
295: rtx loop_top = 0;
1.1.1.2 root 296: /* This is the insn (whatever kind) before the NOTE that starts the loop.
297: Any insns moved out of the loop will follow it. */
298: rtx before_start = PREV_INSN (loop_start);
1.1 root 299: /* Jump insn that enters the loop, or 0 if control drops in. */
300: rtx loop_entry_jump = 0;
301: /* Place in the loop where control enters. */
302: rtx scan_start;
303: /* Number of insns in the loop. */
304: int insn_count;
305: int tem;
1.1.1.8 ! root 306: rtx temp;
1.1 root 307: /* Indexed by register number, contains 1 for a register whose
308: assignments may not be moved out of the loop. */
309: char *may_not_move;
310: /* Chain describing insns movable in current loop. */
311: struct movable *movables = 0;
312: /* Last element in `movables' -- so we can add elements at the end. */
313: struct movable *last_movable = 0;
314: /* Ratio of extra register life span we can justify
315: for saving an instruction. More if loop doesn't call subroutines
316: since in that case saving an insn makes more difference
317: and more registers are available. */
1.1.1.2 root 318: int threshold = loop_has_call ? 17 : 34;
1.1.1.7 root 319: /* Nonzero if the insn that jumps into the real loop
320: is not the very first thing after the loop-beginning note. */
321: int something_before_entry_jump = 0;
1.1 root 322:
323: n_times_set = (short *) alloca (nregs * sizeof (short));
324: n_times_used = (short *) alloca (nregs * sizeof (short));
325: may_not_move = (char *) alloca (nregs);
326:
327: /* Determine whether this loop starts with a jump down
328: to a test at the end. */
329: while (p != end
330: && GET_CODE (p) != CODE_LABEL && GET_CODE (p) != JUMP_INSN)
1.1.1.7 root 331: {
332: if (GET_CODE (p) == CALL_INSN || GET_CODE (p) == INSN)
333: something_before_entry_jump = 1;
334: p = NEXT_INSN (p);
335: }
1.1 root 336:
337: /* "Loop" contains neither jumps nor labels;
338: it must have been a dummy. Think no more about it. */
339: if (p == end)
340: return;
341:
1.1.1.2 root 342: scan_start = p;
343:
1.1 root 344: /* If loop has a jump before the first label,
345: the true entry is the target of that jump.
346: Start scan from there.
347: But record in LOOP_TOP the place where the end-test jumps
348: back to so we can scan that after the end of the loop. */
349: if (GET_CODE (p) == JUMP_INSN)
350: {
351: loop_entry_jump = p;
352: loop_top = NEXT_INSN (p);
353: /* Loop entry will never be a conditional jump.
1.1.1.8 ! root 354: If we see one, this must not be a real loop.
! 355: Also, a return-insn isn't a jump to enter the loop. */
! 356: if (GET_CODE (loop_top) != BARRIER
! 357: || GET_CODE (PATTERN (p)) != SET)
1.1 root 358: return;
1.1.1.5 root 359: /* Get the label at which the loop is entered. */
360: p = XEXP (SET_SRC (PATTERN (p)), 0);
1.1 root 361: /* Check to see whether the jump actually
362: jumps out of the loop (meaning it's no loop).
363: This case can happen for things like
364: do {..} while (0). */
1.1.1.2 root 365: if (p == 0
366: || INSN_LUID (p) < INSN_LUID (loop_start)
1.1 root 367: || INSN_LUID (p) >= INSN_LUID (end))
1.1.1.2 root 368: {
369: if (loop_dump_stream)
370: fprintf (loop_dump_stream, "\nLoop from %d to %d is phony.\n\n",
371: INSN_UID (loop_start), INSN_UID (end));
372: return;
373: }
374:
375: /* Find the first label after the entry-jump. */
376: while (GET_CODE (loop_top) != CODE_LABEL)
377: {
378: loop_top = NEXT_INSN (loop_top);
379: if (loop_top == 0)
380: abort ();
381: }
382:
383: /* Maybe rearrange the loop to drop straight in
384: with a new test to jump around it entirely.
385: (The latter is considered outside the loop.)
386: If this is done, we no longer enter with a jump. */
1.1.1.7 root 387: if (! something_before_entry_jump
388: && loop_skip_over (loop_start, end, loop_entry_jump))
1.1.1.8 ! root 389: {
! 390: scan_start = loop_top;
! 391: loop_top = 0;
! 392: }
1.1.1.2 root 393: else
394: /* We really do enter with a jump;
395: scan the loop from the place where the jump jumps to. */
396: scan_start = p;
1.1 root 397: }
398:
399: /* Count number of times each reg is set during this loop.
400: Set MAY_NOT_MOVE[I] if it is not safe to move out
401: the setting of register I. */
402:
403: bzero (n_times_set, nregs * sizeof (short));
404: bzero (may_not_move, nregs);
1.1.1.2 root 405: count_loop_regs_set (loop_top ? loop_top : loop_start, end,
1.1.1.8 ! root 406: may_not_move, &insn_count, nregs);
1.1 root 407: for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
408: may_not_move[i] = 1, n_times_set[i] = 1;
409: bcopy (n_times_set, n_times_used, nregs * sizeof (short));
410:
1.1.1.2 root 411: if (loop_dump_stream)
412: fprintf (loop_dump_stream, "\nLoop from %d to %d: %d real insns\n\n",
413: INSN_UID (loop_start), INSN_UID (end), insn_count);
414:
1.1 root 415: /* Scan through the loop finding insns that are safe to move.
416: In each such insn, store QImode as the mode, to mark it.
417: Then set n_times_set to -1 for the reg being set, so that
418: this reg will be considered invariant for subsequent insns.
419: We consider whether subsequent insns use the reg
420: in deciding whether it is worth actually moving.
421:
422: MAYBE_NEVER is nonzero if we have passed a conditional jump insn
423: and therefore it is possible that the insns we are scanning
424: would never be executed. At such times, we must make sure
425: that it is safe to execute the insn once instead of zero times.
426: When MAYBE_NEVER is 0, all insns will be executed at least once
427: so that is not a problem. */
428:
1.1.1.2 root 429: p = scan_start;
1.1 root 430: while (1)
431: {
432: p = NEXT_INSN (p);
433: /* At end of a straight-in loop, we are done.
434: At end of a loop entered at the bottom, scan the top. */
435: if (p == scan_start)
436: break;
437: if (p == end)
438: {
439: if (loop_top != 0)
440: p = NEXT_INSN (loop_top);
441: else
442: break;
443: if (p == scan_start)
444: break;
445: }
446: if (GET_CODE (p) == INSN
447: && GET_CODE (PATTERN (p)) == SET
448: && GET_CODE (SET_DEST (PATTERN (p))) == REG
449: && ! may_not_move[REGNO (SET_DEST (PATTERN (p)))])
450: {
1.1.1.4 root 451: int tem1 = 0;
1.1 root 452: /* If this register is used or set outside the loop,
453: then we can move it only if we know this insn is
454: executed exactly once per iteration,
455: and we can check all the insns executed before it
456: to make sure none of them used the value that
457: was lying around at entry to the loop. */
1.1.1.8 ! root 458: /* Make sure that regscan info exists for this register;
! 459: it must be less than old_max_reg. */
! 460: if ((REGNO (SET_DEST (PATTERN (p))) >= old_max_reg
! 461: || uid_luid[regno_last_uid[REGNO (SET_DEST (PATTERN (p)))]] > INSN_LUID (end)
1.1 root 462: || uid_luid[regno_first_uid[REGNO (SET_DEST (PATTERN (p)))]] < INSN_LUID (loop_start))
463: && (maybe_never
464: || loop_reg_used_before_p (p, loop_start, scan_start, end)))
465: ;
1.1.1.8 ! root 466: else if (((tem = invariant_p (SET_SRC (PATTERN (p))))
! 467: || ((temp = find_reg_note (p, REG_EQUAL, 0))
! 468: && (tem = invariant_p (XEXP (temp, 0)))))
1.1 root 469: && (n_times_set[REGNO (SET_DEST (PATTERN (p)))] == 1
1.1.1.4 root 470: || (tem1
471: = consec_sets_invariant_p (SET_DEST (PATTERN (p)),
472: n_times_set[REGNO (SET_DEST (PATTERN (p)))],
1.1.1.8 ! root 473: p)))
1.1.1.3 root 474: /* If the insn can cause a trap (such as divide by zero),
475: can't move it unless it's guaranteed to be executed
476: once loop is entered. Even a function call might
477: prevent the trap insn from being reached
478: (since it might exit!) */
479: && ! ((maybe_never || call_passed)
1.1.1.8 ! root 480: && (may_trap_p (SET_SRC (PATTERN (p)))
! 481: || ((temp = find_reg_note (p, REG_EQUAL, 0))
! 482: && may_trap_p (XEXP (temp, 0))))))
1.1 root 483: {
484: register struct movable *m;
485: register int regno = REGNO (SET_DEST (PATTERN (p)));
1.1.1.2 root 486: int count;
1.1 root 487: m = (struct movable *) alloca (sizeof (struct movable));
488: m->next = 0;
489: m->insn = p;
1.1.1.8 ! root 490: temp = find_reg_note (p, REG_EQUAL, 0);
! 491: if (temp)
! 492: m->set_src = XEXP (temp, 0);
! 493: else
! 494: m->set_src = SET_SRC (PATTERN (p));
1.1 root 495: m->force = 0;
1.1.1.2 root 496: m->consec = n_times_set[REGNO (SET_DEST (PATTERN (p)))] - 1;
497: m->done = 0;
1.1 root 498: m->forces = 0;
1.1.1.2 root 499: m->partial = 0;
1.1 root 500: m->regno = regno;
1.1.1.4 root 501: /* Set M->cond if either invariant_p or consec_sets_invariant_p
502: returned 2 (only conditionally invariant). */
503: m->cond = ((tem | tem1) > 1);
1.1 root 504: m->global = (uid_luid[regno_last_uid[regno]] > INSN_LUID (end)
505: || uid_luid[regno_first_uid[regno]] < INSN_LUID (loop_start));
506: m->match = 0;
507: m->lifetime = (uid_luid[regno_last_uid[regno]]
508: - uid_luid[regno_first_uid[regno]]);
1.1.1.2 root 509: m->times_used = n_times_used[regno];
1.1 root 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;
1.1.1.2 root 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: }
1.1 root 523: }
1.1.1.2 root 524: /* If this register is always set within a STRICT_LOW_PART
525: or set to zero, then its high bytes are constant.
1.1 root 526: So clear them outside the loop and within the loop
527: just load the low bytes.
528: We must check that the machine has an instruction to do so.
529: Also, if the value loaded into the register
530: depends on the same register, this cannot be done. */
1.1.1.2 root 531: else if (SET_SRC (PATTERN (p)) == const0_rtx
532: && GET_CODE (NEXT_INSN (p)) == INSN
533: && GET_CODE (PATTERN (NEXT_INSN (p))) == SET
534: && (GET_CODE (SET_DEST (PATTERN (NEXT_INSN (p))))
535: == STRICT_LOW_PART)
536: && (GET_CODE (XEXP (SET_DEST (PATTERN (NEXT_INSN (p))), 0))
537: == SUBREG)
538: && (SUBREG_REG (XEXP (SET_DEST (PATTERN (NEXT_INSN (p))), 0))
539: == SET_DEST (PATTERN (p)))
1.1 root 540: && !reg_mentioned_p (SET_DEST (PATTERN (p)),
1.1.1.2 root 541: SET_SRC (PATTERN (NEXT_INSN (p)))))
1.1 root 542: {
543: register int regno = REGNO (SET_DEST (PATTERN (p)));
1.1.1.2 root 544: if (n_times_set[regno] == 2)
545: {
546: register struct movable *m;
547: int count;
548: m = (struct movable *) alloca (sizeof (struct movable));
549: m->next = 0;
550: m->insn = p;
551: m->force = 0;
552: m->consec = 0;
553: m->done = 0;
554: m->forces = 0;
555: m->partial = 1;
556: m->regno = regno;
557: m->cond = 0;
558: /* Say "global" so this register is not combined
559: with any other. In fact, it is sometimes possible
560: to combine two of these registers, but the criteria
561: are special and have not been programmed in. */
562: m->global = 1;
563: m->match = 0;
564: m->lifetime = (uid_luid[regno_last_uid[regno]]
565: - uid_luid[regno_first_uid[regno]]);
566: m->times_used = n_times_used[regno];
567: n_times_set[regno] = -1;
568: /* Add M to the end of the chain MOVABLES. */
569: if (movables == 0)
570: movables = m;
571: else
572: last_movable->next = m;
573: last_movable = m;
574: /* Skip the consecutive insns, if there are any. */
575: for (count = m->consec - 1; count >= 0; count--)
576: {
1.1.1.8 ! root 577: /* If first insn of libcall sequence, skip to end. */
! 578: /* Do this at start of loop, since p is guaranteed to
! 579: be an insn here. */
! 580: if (temp = find_reg_note (p, REG_LIBCALL, 0))
! 581: {
! 582: p = XEXP (temp, 0);
! 583: /* Count the libcall as ten insns in terms of
! 584: importance of moving it. */
! 585: m->consec += 10;
! 586: }
! 587:
1.1.1.2 root 588: do p = NEXT_INSN (p);
589: while (GET_CODE (p) == NOTE);
590: }
591: }
1.1 root 592: }
593: }
1.1.1.3 root 594: /* Past a call insn, we get to insns which might not be executed
595: because the call might exit. This matters for insns that trap. */
596: else if (GET_CODE (p) == CALL_INSN)
597: call_passed = 1;
1.1 root 598: /* Past a label or a jump, we get to insns for which we
599: can't count on whether or how many times they will be
600: executed during each iteration. Therefore, we can
601: only move out sets of trivial variables
602: (those not used after the loop). */
603: else if (GET_CODE (p) == CODE_LABEL || GET_CODE (p) == JUMP_INSN)
604: maybe_never = 1;
605: }
606:
607: /* For each movable insn, see if the reg that it loads
1.1.1.2 root 608: leads when it dies right into another conditionally movable insn.
609: If so, record that the second insn "forces" the first one,
610: since the second can be moved only if the first is. */
611:
1.1 root 612: {
613: register struct movable *m, *m1;
614: for (m1 = movables; m1; m1 = m1->next)
615: {
616: int regno = m1->regno;
617: for (m = m1->next; m; m = m->next)
618: if (INSN_UID (m->insn) == regno_last_uid[regno])
619: break;
1.1.1.8 ! root 620: if (m != 0 && m->set_src == SET_DEST (PATTERN (m1->insn)))
1.1 root 621: m = 0;
1.1.1.2 root 622:
623: /* Increase the priority of the moving the first insn
624: since it permits the second to be moved as well. */
625: if (m != 0)
626: {
627: m->forces = m1;
628: m1->lifetime += m->lifetime;
629: m1->times_used += m1->times_used;
630: }
1.1 root 631: }
632: }
633:
634: /* See if there are multiple movable insns that load the same value.
635: If there are, make all but the first point at the first one
636: through the `match' field, and add the priorities of them
637: all together as the priority of the first. */
1.1.1.2 root 638:
1.1 root 639: {
640: register struct movable *m;
641: char *matched_regs = (char *) alloca (nregs);
642:
1.1.1.2 root 643: /* Regs that are used more than once are not allowed to match
644: or be matched. I'm no longer sure why not. */
1.1.1.8 ! root 645: /* Perhaps testing m->consec_sets would be more appropriate here? */
1.1 root 646:
647: for (m = movables; m; m = m->next)
1.1.1.2 root 648: if (m->match == 0 && n_times_used[m->regno] == 1)
1.1 root 649: {
650: register struct movable *m1;
1.1.1.2 root 651: int regno = m->regno;
1.1 root 652:
653: bzero (matched_regs, nregs);
1.1.1.2 root 654: matched_regs[regno] = 1;
1.1 root 655:
656: for (m1 = m->next; m1; m1 = m1->next)
1.1.1.2 root 657: if (m1->match == 0 && n_times_used[m1->regno] == 1
658: /* A reg used outside the loop mustn't be eliminated. */
659: && !m1->global
660: && (matched_regs[m1->regno]
661: ||
662: (
663: /* Can't combine regs with different modes
664: even if loaded from the same constant. */
665: (GET_MODE (SET_DEST (PATTERN (m->insn)))
666: == GET_MODE (SET_DEST (PATTERN (m1->insn))))
667: /* See if the source of M1 says it matches M. */
1.1.1.8 ! root 668: && ((GET_CODE (m1->set_src) == REG
! 669: && matched_regs[REGNO (m1->set_src)])
! 670: || rtx_equal_p (m->set_src, m1->set_src)
1.1.1.2 root 671: || (REG_NOTES (m->insn) && REG_NOTES (m1->insn)
672: && REG_NOTE_KIND (REG_NOTES (m->insn)) == REG_EQUIV
673: && REG_NOTE_KIND (REG_NOTES (m1->insn)) == REG_EQUIV
674: && rtx_equal_p (XEXP (REG_NOTES (m->insn), 0),
675: XEXP (REG_NOTES (m1->insn), 0)))))))
676: {
677: m->lifetime += m1->lifetime;
678: m->times_used += m1->times_used;
679: m1->match = m;
680: matched_regs[m1->regno] = 1;
681: }
682: }
683: }
684:
685: /* Now consider each movable insn to decide whether it is worth moving. */
686:
1.1.1.8 ! root 687: move_movables (movables, threshold,
1.1.1.2 root 688: insn_count, loop_start, end, nregs);
1.1.1.8 ! root 689:
! 690: if (flag_strength_reduce)
! 691: strength_reduce (scan_start, end, loop_top,
! 692: insn_count, loop_start, end, nregs);
1.1.1.2 root 693: }
694:
695: /* Scan MOVABLES, and move the insns that deserve to be moved.
696: If two matching movables are combined, replace one reg with the
697: other throughout. */
698:
699: static void
1.1.1.8 ! root 700: move_movables (movables, threshold, insn_count, loop_start, end, nregs)
1.1.1.2 root 701: struct movable *movables;
702: int threshold;
703: int insn_count;
704: rtx loop_start;
705: rtx end;
706: int nregs;
707: {
708: rtx new_start = 0;
709: register struct movable *m;
710: register rtx p;
711: /* Map of pseudo-register replacements to handle combining
712: when we move several insns that load the same value
713: into different pseudo-registers. */
714: rtx *reg_map = (rtx *) alloca (nregs * sizeof (rtx));
715: char *already_moved = (char *) alloca (nregs);
716:
717: bzero (already_moved, nregs);
718: bzero (reg_map, nregs * sizeof (rtx));
719:
1.1.1.8 ! root 720: num_movables = 0;
! 721:
1.1.1.2 root 722: for (m = movables; m; m = m->next)
723: {
724: /* Describe this movable insn. */
725:
726: if (loop_dump_stream)
727: {
728: fprintf (loop_dump_stream, "Insn %d: regno %d (life %d), ",
729: INSN_UID (m->insn), m->regno, m->lifetime);
730: if (m->consec > 0)
731: fprintf (loop_dump_stream, "consec %d, ", m->consec);
732: if (m->cond)
733: fprintf (loop_dump_stream, "cond ");
734: if (m->force)
735: fprintf (loop_dump_stream, "force ");
736: if (m->global)
737: fprintf (loop_dump_stream, "global ");
738: if (m->done)
739: fprintf (loop_dump_stream, "done ");
740: if (m->match)
741: fprintf (loop_dump_stream, "matches %d ",
742: INSN_UID (m->match->insn));
743: if (m->forces)
744: fprintf (loop_dump_stream, "forces %d ",
745: INSN_UID (m->forces->insn));
746: }
747:
1.1.1.8 ! root 748: /* Count movables. Value used in heuristics in strength_reduce. */
! 749: num_movables++;
! 750:
1.1.1.2 root 751: /* Ignore the insn if it's already done (it matched something else).
752: Otherwise, see if it is now safe to move. */
753:
754: if (!m->done
755: && (! m->cond
1.1.1.8 ! root 756: || (1 == invariant_p (m->set_src)
1.1.1.4 root 757: && (m->consec == 0
758: || 1 == consec_sets_invariant_p (SET_DEST (PATTERN (m->insn)),
759: m->consec + 1,
1.1.1.8 ! root 760: m->insn))))
1.1.1.2 root 761: && (! m->forces || m->forces->done))
762: {
763: register int regno;
764: register rtx p;
765: int times_used = m->times_used + m->consec;
766:
767: /* We have an insn that is safe to move.
768: Compute its desirability. */
769:
770: p = m->insn;
771: regno = m->regno;
772:
773: if (loop_dump_stream)
774: fprintf (loop_dump_stream, "reg uses %d ", times_used);
775:
776: /* An insn MUST be moved if we already moved something else
777: which is safe only if this one is moved too: that is,
778: if already_moved[REGNO] is nonzero. */
779:
780: /* An insn is desirable to move if the new lifetime of the
781: register is no more than THRESHOLD times the old lifetime.
782: If it's not desirable, it means the loop is so big
783: that moving won't speed things up much,
784: and it is liable to make register usage worse. */
785:
786: /* It is also desirable to move if it can be moved at no
787: extra cost because something else was already moved. */
788:
789: if (already_moved[regno]
790: || (threshold * times_used * m->lifetime) >= insn_count
791: || (m->forces && m->forces->done
792: && n_times_used[m->forces->regno] == 1))
1.1 root 793: {
1.1.1.2 root 794: int count;
795: register struct movable *m1;
1.1.1.8 ! root 796: rtx first;
1.1.1.2 root 797:
798: for (count = m->consec; count >= 0; count--)
1.1 root 799: {
1.1.1.8 ! root 800: rtx i1, temp;
! 801:
! 802: /* If first insn of gnulib call sequence, skip to end. */
! 803: /* Do this at start of loop, since p is guaranteed to
! 804: be an insn here. */
! 805: if (temp = find_reg_note (p, REG_LIBCALL, 0))
! 806: p = XEXP (temp, 0);
! 807:
! 808: /* If last insn of gnulib call sequence, move all
! 809: insns except the last before the loop. The last insn is
! 810: handled in the normal manner. */
! 811: if (temp = find_reg_note (p, REG_RETVAL, 0))
! 812: {
! 813: first = 0;
! 814: for (temp = XEXP (temp, 0); temp != p;
! 815: temp = NEXT_INSN (temp))
! 816: {
! 817: i1 = emit_insn_before (PATTERN (temp), loop_start);
! 818: if (first == 0)
! 819: first = i1;
! 820: REG_NOTES (i1) = REG_NOTES (temp);
! 821: delete_insn (temp);
! 822: }
! 823: }
! 824: i1 = emit_insn_before (PATTERN (p), loop_start);
! 825:
1.1.1.2 root 826: if (new_start == 0)
827: new_start = i1;
828:
829: if (loop_dump_stream)
830: fprintf (loop_dump_stream, "moved to %d", INSN_UID (i1));
831:
832: /* Mark the moved, invariant reg as being equivalent to
833: its constant value. */
834: REG_NOTES (i1) = REG_NOTES (p);
835: if (REG_NOTES (i1) == 0
1.1.1.8 ! root 836: && ! m->partial /* But not if it's a zero-extend clr. */
1.1.1.2 root 837: && ! m->global /* and not if used outside the loop
838: (since it might get set outside). */
839: && CONSTANT_P (SET_SRC (PATTERN (p))))
840: REG_NOTES (i1)
841: = gen_rtx (EXPR_LIST, REG_EQUIV,
842: SET_SRC (PATTERN (p)), REG_NOTES (i1));
1.1.1.8 ! root 843:
! 844: /* If library call, now fix the REG_NOTES that contain
! 845: insn pointers, namely REG_LIBCALL on FIRST
! 846: and REG_RETVAL on I1. */
! 847: if (temp = find_reg_note (i1, REG_RETVAL, 0))
! 848: {
! 849: XEXP (temp, 0) = first;
! 850: temp = find_reg_note (first, REG_LIBCALL, 0);
! 851: XEXP (temp, 0) = i1;
! 852: }
! 853:
1.1.1.2 root 854: delete_insn (p);
855: do p = NEXT_INSN (p);
856: while (GET_CODE (p) == NOTE);
857:
858: /* The more insns we move, the less we like moving them. */
859: threshold -= 2;
1.1 root 860: }
1.1.1.2 root 861:
862: /* Any other movable that loads the same register
863: MUST be moved. */
864: already_moved[regno] = 1;
865:
866: /* The reg set here is now invariant. */
867: if (! m->partial)
868: n_times_set[regno] = 0;
869:
870: m->done = 1;
871:
872: /* Combine with this moved insn any other matching movables. */
1.1 root 873:
874: for (m1 = m->next; m1; m1 = m1->next)
875: if (m1->match == m)
876: {
1.1.1.8 ! root 877: rtx temp;
! 878:
1.1 root 879: /* Schedule the reg loaded by M1
880: for replacement so that shares the reg of M. */
881: reg_map[m1->regno] = SET_DEST (PATTERN (m->insn));
1.1.1.2 root 882: /* Get rid of the matching insn
1.1 root 883: and prevent further processing of it. */
1.1.1.2 root 884: m1->done = 1;
1.1.1.8 ! root 885:
! 886: /* if library call, delete all insn except last, which
! 887: is deleted below */
! 888: if (temp = find_reg_note (m1->insn, REG_RETVAL, 0))
! 889: {
! 890: for (temp = XEXP (temp, 0); temp != m1->insn;
! 891: temp = NEXT_INSN (temp))
! 892: delete_insn (temp);
! 893: }
1.1 root 894: delete_insn (m1->insn);
1.1.1.2 root 895:
896: /* Any other movable that loads the same register
897: MUST be moved. */
898: already_moved[m1->regno] = 1;
899:
900: /* The reg merged here is now invariant. */
901: if (m->partial)
902: n_times_set[m1->regno] = 0;
1.1 root 903: }
904: }
1.1.1.2 root 905: else if (loop_dump_stream)
906: fprintf (loop_dump_stream, "not desirable");
1.1 root 907: }
1.1.1.2 root 908: else if (loop_dump_stream && !m->match)
909: fprintf (loop_dump_stream, "not safe");
1.1 root 910:
1.1.1.2 root 911: if (loop_dump_stream)
912: fprintf (loop_dump_stream, "\n");
913: }
1.1 root 914:
1.1.1.2 root 915: if (new_start == 0)
916: new_start = loop_start;
1.1 root 917:
1.1.1.2 root 918: /* Go through all the instructions in the loop, making
919: all the register substitutions scheduled in REG_MAP. */
920: for (p = new_start; p != end; p = NEXT_INSN (p))
921: if (GET_CODE (p) == INSN || GET_CODE (p) == JUMP_INSN
922: || GET_CODE (p) == CALL_INSN)
1.1.1.8 ! root 923: replace_regs (PATTERN (p), reg_map, nregs);
1.1.1.2 root 924: }
925:
926: /* Optionally change a loop which enters just before the endtest
927: to one which falls straight in
928: after skipping around the entire loop if the endtest would drop out.
929: Returns 1 if the change was made, 0 if the loop was not really suitable. */
930:
931: int
932: loop_skip_over (start, end, loop_entry_jump)
933: rtx start;
934: rtx end;
935: rtx loop_entry_jump;
936: {
937: rtx endtestjump;
938: register rtx p = JUMP_LABEL (loop_entry_jump);
1.1 root 939:
1.1.1.2 root 940: while (GET_CODE (p) != INSN && GET_CODE (p) != JUMP_INSN
941: && GET_CODE (p) != CALL_INSN)
942: p = NEXT_INSN (p);
943: endtestjump = next_real_insn (p);
944:
945: /* Check that we (1) enter at a compare insn and (2)
946: the insn (presumably a jump) following that compare
947: is the last in the loop and jumps back to the loop beginning. */
948:
1.1.1.8 ! root 949: if (sets_cc0_p (PATTERN (p)) > 0
1.1.1.2 root 950: && endtestjump == prev_real_insn (end)
951: && prev_real_insn (JUMP_LABEL (endtestjump)) == loop_entry_jump)
1.1 root 952: {
1.1.1.2 root 953: rtx newlab;
954: /* This is the jump that we insert. */
955: rtx new_jump;
956:
957: /* Ok, duplicate that test before start of loop. */
958: emit_insn_before (copy_rtx (PATTERN (p)), start);
959: /* Make a new entry-jump (before the original one)
960: whose condition is opposite to the loop-around endtest
1.1.1.8 ! root 961: and which jumps around the loop (to just after the ending NOTE). */
1.1.1.2 root 962: newlab = gen_label_rtx ();
1.1.1.8 ! root 963: emit_label_after (newlab, end);
1.1.1.2 root 964: emit_jump_insn_before (copy_rtx (PATTERN (endtestjump)), start);
965: new_jump = PREV_INSN (start);
966: JUMP_LABEL (new_jump) = JUMP_LABEL (endtestjump);
967: LABEL_NUSES (JUMP_LABEL (endtestjump))++;
968: invert_jump (new_jump, newlab);
969: /* Delete the original entry-jump. */
970: delete_insn (loop_entry_jump);
1.1 root 971:
1.1.1.2 root 972: return 1;
1.1 root 973: }
1.1.1.2 root 974:
975: return 0;
1.1 root 976: }
977:
978: /* Throughout the rtx X, replace many registers according to REG_MAP.
979: Return the replacement for X (which may be X with altered contents).
1.1.1.8 ! root 980: REG_MAP[R] is the replacement for register R, or 0 for don't replace.
! 981: NREGS is the length of REG_MAP; regs >= NREGS are not mapped. */
1.1 root 982:
983: static rtx
1.1.1.8 ! root 984: replace_regs (x, reg_map, nregs)
1.1 root 985: rtx x;
986: rtx *reg_map;
1.1.1.8 ! root 987: int nregs;
1.1 root 988: {
989: register RTX_CODE code = GET_CODE (x);
990: register int i;
991: register char *fmt;
992:
993: switch (code)
994: {
995: case PC:
996: case CC0:
997: case CONST_INT:
998: case CONST_DOUBLE:
999: case CONST:
1000: case SYMBOL_REF:
1001: case LABEL_REF:
1002: return x;
1003:
1004: case REG:
1.1.1.8 ! root 1005: /* Verify that the register has an entry before trying to access it. */
! 1006: if (REGNO (x) < nregs && reg_map[REGNO (x)] != 0)
1.1 root 1007: return reg_map[REGNO (x)];
1008: return x;
1009: }
1010:
1011: fmt = GET_RTX_FORMAT (code);
1012: for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
1013: {
1014: if (fmt[i] == 'e')
1.1.1.8 ! root 1015: XEXP (x, i) = replace_regs (XEXP (x, i), reg_map, nregs);
1.1 root 1016: if (fmt[i] == 'E')
1017: {
1018: register int j;
1019: for (j = 0; j < XVECLEN (x, i); j++)
1.1.1.8 ! root 1020: XVECEXP (x, i, j) = replace_regs (XVECEXP (x, i, j), reg_map, nregs);
1.1 root 1021: }
1022: }
1023: return x;
1024: }
1025:
1.1.1.4 root 1026: #if 0
1.1 root 1027: /* P is an instruction that sets a register to the result of a ZERO_EXTEND.
1028: Replace it with an instruction to load just the low bytes
1029: if the machine supports such an instruction,
1030: and insert above LOOP_START an instruction to clear the register. */
1031:
1032: static void
1033: constant_high_bytes (p, loop_start)
1034: rtx p, loop_start;
1035: {
1036: register rtx new;
1037: register int insn_code_number;
1038:
1039: /* Try to change (SET (REG ...) (ZERO_EXTEND (..:B ...)))
1040: to (SET (STRICT_LOW_PART (SUBREG:B (REG...))) ...). */
1041:
1042: new = gen_rtx (SET, VOIDmode,
1043: gen_rtx (STRICT_LOW_PART, VOIDmode,
1044: gen_rtx (SUBREG, GET_MODE (XEXP (SET_SRC (PATTERN (p)), 0)),
1045: SET_DEST (PATTERN (p)),
1046: 0)),
1047: XEXP (SET_SRC (PATTERN (p)), 0));
1048: insn_code_number = recog (new, p);
1049:
1050: if (insn_code_number)
1051: {
1052: register int i;
1053:
1054: /* Clear destination register before the loop. */
1055: emit_insn_before (gen_rtx (SET, VOIDmode,
1056: SET_DEST (PATTERN (p)),
1057: const0_rtx),
1058: loop_start);
1059:
1060: /* Inside the loop, just load the low part. */
1061: PATTERN (p) = new;
1062: }
1063: }
1.1.1.4 root 1064: #endif
1.1 root 1065:
1066: /* Verify that the ostensible loop starting at START
1067: really is a loop: nothing jumps into it from outside.
1068: Return the marker for the end of the loop, or zero if not a real loop.
1069:
1070: Also set the variables `unknown_*_altered' and `loop_has_call',
1071: and fill in the array `loop_store_addrs'. */
1072:
1073: static rtx
1074: verify_loop (f, start)
1075: rtx f, start;
1076: {
1077: register int level = 1;
1078: register rtx insn, end;
1079:
1080: /* First find the LOOP_END that matches.
1081: Also check each insn for storing in memory and record where. */
1082:
1083: unknown_address_altered = 0;
1084: unknown_aggregate_altered = 0;
1085: fixed_aggregate_altered = 0;
1086: loop_has_call = 0;
1087: loop_store_addrs_idx = 0;
1088:
1.1.1.8 ! root 1089: num_mem_sets = 0;
! 1090: loops_enclosed = 1;
! 1091:
1.1 root 1092: for (insn = NEXT_INSN (start); level > 0; insn = NEXT_INSN (insn))
1093: {
1094: if (insn == 0)
1.1.1.2 root 1095: /* Parse errors can cause a loop-beg with no loop-end. */
1096: return 0;
1.1 root 1097: if (GET_CODE (insn) == NOTE)
1098: {
1099: if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
1.1.1.8 ! root 1100: {
! 1101: ++level;
! 1102: /* Count number of loops contained in this one. */
! 1103: loops_enclosed++;
! 1104: }
1.1 root 1105: else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END)
1.1.1.2 root 1106: {
1107: --level;
1108: if (level == 0)
1109: {
1110: end = insn;
1111: break;
1112: }
1113: }
1.1 root 1114: }
1115: else if (GET_CODE (insn) == CALL_INSN)
1116: {
1117: unknown_address_altered = 1;
1118: loop_has_call = 1;
1119: }
1.1.1.8 ! root 1120: /* ???
! 1121: else if (! unknown_address_altered) */
! 1122: else
1.1 root 1123: {
1124: if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN)
1125: note_stores (PATTERN (insn), note_addr_stored);
1126: }
1127: }
1128:
1129: /* Now scan all jumps in the function and see if any of them can
1130: reach a label within the range of the loop. */
1131:
1132: for (insn = f; insn; insn = NEXT_INSN (insn))
1133: if (GET_CODE (insn) == JUMP_INSN
1134: /* Don't get fooled by jumps inserted by loop-optimize.
1135: They don't have valid LUIDs, and they never jump into loops. */
1136: && INSN_UID (insn) < max_uid
1137: && (INSN_LUID (insn) < INSN_LUID (start)
1138: || INSN_LUID (insn) > INSN_LUID (end))
1139: /* We have a jump that is outside the loop.
1140: Does it jump into the loop? */
1141: && can_jump_into_range_p (PATTERN (insn),
1142: INSN_LUID (start), INSN_LUID (end)))
1143: return 0;
1144:
1145: #if 0
1146: /* Now scan all labels between them and check for any jumps from outside.
1147: This uses the ref-chains set up by find_basic_blocks.
1148: This code is not used because it's more convenient for other reasons
1149: to do the loop optimization before find_basic_blocks. */
1150:
1151: for (insn = start; insn != end; insn = NEXT_INSN (insn))
1152: if (GET_CODE (insn) == CODE_LABEL)
1153: {
1154: register rtx y;
1155: for (y = LABEL_REFS (insn); y != insn; y = LABEL_NEXTREF (y))
1156: if (INSN_LUID (CONTAINING_INSN (y)) < INSN_LUID (start)
1157: || INSN_LUID (CONTAINING_INSN (y)) > INSN_LUID (end))
1158: return 0;
1159: }
1160: #endif
1161:
1162: return end;
1163: }
1164:
1165: /* Return 1 if somewhere in X is a LABEL_REF to a label
1166: located between BEG and END. */
1167:
1168: static int
1169: can_jump_into_range_p (x, beg, end)
1170: rtx x;
1171: int beg, end;
1172: {
1173: register RTX_CODE code = GET_CODE (x);
1174: register int i;
1175: register char *fmt;
1176:
1177: if (code == LABEL_REF)
1178: {
1179: register int luid = INSN_LUID (XEXP (x, 0));
1180: return luid > beg && luid < end;
1181: }
1182:
1183: fmt = GET_RTX_FORMAT (code);
1184: for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
1185: {
1186: if (fmt[i] == 'e')
1187: {
1188: if (can_jump_into_range_p (XEXP (x, i), beg, end))
1189: return 1;
1190: }
1191: else if (fmt[i] == 'E')
1192: {
1193: register int j;
1194: for (j = 0; j < XVECLEN (x, i); j++)
1195: if (can_jump_into_range_p (XVECEXP (x, i, j), beg, end))
1196: return 1;
1197: }
1198: }
1199:
1200: return 0;
1201: }
1202:
1203: /* Record that a memory reference X is being set. */
1204:
1205: static void
1206: note_addr_stored (x)
1207: rtx x;
1208: {
1209: if (x == 0 || GET_CODE (x) != MEM)
1210: return;
1.1.1.8 ! root 1211:
! 1212: /* Count number of memory writes.
! 1213: This affects heuristics in strength_reduce. */
! 1214: num_mem_sets++;
! 1215: if (unknown_address_altered)
! 1216: return;
! 1217:
1.1.1.2 root 1218: if (GET_MODE (x) == BLKmode)
1219: unknown_address_altered = 1;
1220: else if (rtx_addr_varies_p (x))
1.1 root 1221: {
1222: if (GET_CODE (XEXP (x, 0)) == PLUS)
1223: unknown_aggregate_altered = 1;
1224: else
1225: unknown_address_altered = 1;
1226: }
1227: else
1228: {
1229: register int i;
1230: register rtx addr = XEXP (x, 0);
1231:
1.1.1.8 ! root 1232: if (MEM_IN_STRUCT_P (x))
1.1 root 1233: fixed_aggregate_altered = 1;
1234: for (i = 0; i < loop_store_addrs_idx; i++)
1235: if (rtx_equal_p (loop_store_addrs[i], addr))
1236: {
1237: if (loop_store_widths[i] < GET_MODE_SIZE (GET_MODE (x)))
1238: loop_store_widths[i] = GET_MODE_SIZE (GET_MODE (x));
1239: break;
1240: }
1241: if (i == NUM_STORES)
1242: unknown_address_altered = 1;
1243: else if (i == loop_store_addrs_idx)
1244: {
1.1.1.2 root 1245: loop_store_widths[i] = GET_MODE_SIZE (GET_MODE (x));
1.1 root 1246: loop_store_addrs[loop_store_addrs_idx++] = addr;
1247: }
1248: }
1249: }
1250:
1251: /* Return nonzero if the rtx X is invariant over the current loop.
1252:
1253: The value is 2 if we refer to something only conditionally invariant.
1254:
1255: If `unknown_address_altered' is nonzero, no memory ref is invariant.
1256: Otherwise if `unknown_aggregate_altered' is nonzero,
1257: a memory ref is invariant if it is not part of an aggregate
1258: and its address is fixed and not in `loop_store_addrs'.
1259: Otherwise if `fixed_aggregate_altered' is nonzero,
1260: a memory ref is invariant
1261: if its address is fixed and not in `loop_store_addrs'.
1262: Otherwise, a memory ref is invariant if its address is fixed and not in
1263: `loop_store_addrs' or if it is not an aggregate. */
1264:
1265: static int
1.1.1.8 ! root 1266: invariant_p (x)
1.1 root 1267: register rtx x;
1268: {
1269: register int i;
1270: register RTX_CODE code = GET_CODE (x);
1271: register char *fmt;
1272: int conditional = 0;
1273:
1274: switch (code)
1275: {
1276: case CONST_INT:
1277: case CONST_DOUBLE:
1278: case SYMBOL_REF:
1279: case LABEL_REF:
1280: case CONST:
1281: return 1;
1282:
1283: case PC:
1284: case CC0:
1285: return 0;
1286:
1287: case REG:
1.1.1.8 ! root 1288: /* We used to check RTX_UNCHANGING_P (x) here, but that is invalid
1.1.1.6 root 1289: since the reg might be set by initialization within the loop. */
1290: if (x == frame_pointer_rtx || x == arg_pointer_rtx)
1.1.1.2 root 1291: return 1;
1.1 root 1292: if (n_times_set[REGNO (x)] == -1)
1293: return 2;
1294: return n_times_set[REGNO (x)] == 0;
1295:
1296: case MEM:
1297: /* A store in a varying-address scalar (or a subroutine call)
1298: could clobber anything in memory. */
1299: if (unknown_address_altered)
1300: return 0;
1.1.1.2 root 1301: /* Don't mess with volatile memory references. */
1.1.1.8 ! root 1302: if (MEM_VOLATILE_P (x))
1.1.1.2 root 1303: return 0;
1.1.1.6 root 1304: #if 0
1.1.1.2 root 1305: /* If it's declared read-only, it is invariant
1306: if its address is invariant. */
1.1.1.8 ! root 1307: if (RTX_UNCHANGING_P (x))
! 1308: return invariant_p (XEXP (x, 0));
1.1.1.6 root 1309: #endif
1.1 root 1310: /* A store in a varying-address aggregate component
1311: could clobber anything except a scalar with a fixed address. */
1312: if (unknown_aggregate_altered
1.1.1.8 ! root 1313: && ((MEM_IN_STRUCT_P (x) || GET_CODE (XEXP (x, 0)) == PLUS)
1.1 root 1314: || rtx_addr_varies_p (x)))
1315: return 0;
1316: /* A store in a fixed-address aggregate component
1317: could clobber anything whose address is not fixed,
1318: even an aggregate component. */
1319: if (fixed_aggregate_altered
1320: && rtx_addr_varies_p (x))
1321: return 0;
1322: /* Any store could clobber a varying-address scalar. */
1323: if (loop_store_addrs_idx
1.1.1.8 ! root 1324: && !(MEM_IN_STRUCT_P (x) || GET_CODE (XEXP (x, 0)) == PLUS)
1.1 root 1325: && rtx_addr_varies_p (x))
1326: return 0;
1327: /* A store in a fixed address clobbers overlapping references. */
1328: for (i = loop_store_addrs_idx - 1; i >= 0; i--)
1.1.1.2 root 1329: if (addr_overlap_p (x, loop_store_addrs[i], loop_store_widths[i]))
1.1 root 1330: return 0;
1331: /* It's not invalidated by a store in memory
1332: but we must still verify the address is invariant. */
1.1.1.2 root 1333: break;
1334:
1335: case ASM_OPERANDS:
1336: /* Don't mess with insns declared volatile. */
1.1.1.8 ! root 1337: if (MEM_VOLATILE_P (x))
1.1.1.2 root 1338: return 0;
1.1 root 1339: }
1340:
1341: fmt = GET_RTX_FORMAT (code);
1342: for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
1343: {
1344: if (fmt[i] == 'e')
1345: {
1.1.1.8 ! root 1346: int tem = invariant_p (XEXP (x, i));
1.1 root 1347: if (tem == 0)
1348: return 0;
1349: if (tem == 2)
1350: conditional = 1;
1351: }
1.1.1.2 root 1352: else if (fmt[i] == 'E')
1353: {
1354: register int j;
1355: for (j = 0; j < XVECLEN (x, i); j++)
1356: {
1.1.1.8 ! root 1357: int tem = invariant_p (XVECEXP (x, i, j));
1.1.1.2 root 1358: if (tem == 0)
1359: return 0;
1360: if (tem == 2)
1361: conditional = 1;
1362: }
1363:
1364: }
1.1 root 1365: }
1366:
1367: return 1 + conditional;
1368: }
1369:
1370: /* Return 1 if OTHER (a mem ref) overlaps the area of memory
1371: which is SIZE bytes starting at BASE. */
1372:
1373: int
1374: addr_overlap_p (other, base, size)
1375: rtx other;
1376: rtx base;
1377: int size;
1378: {
1379: int start = 0, end;
1380:
1381: if (GET_CODE (base) == CONST)
1382: base = XEXP (base, 0);
1383: if (GET_CODE (base) == PLUS
1384: && GET_CODE (XEXP (base, 1)) == CONST_INT)
1385: {
1386: start = INTVAL (XEXP (base, 1));
1387: base = XEXP (base, 0);
1388: }
1389:
1390: end = start + size;
1391: return refers_to_mem_p (other, base, start, end);
1392: }
1.1.1.2 root 1393:
1.1.1.4 root 1394: /* Return nonzero if all the insns in the loop that set REG
1.1.1.2 root 1395: are INSN and the immediately following insns,
1396: and if each of those insns sets REG in an invariant way
1.1.1.8 ! root 1397: (not counting uses of REG in them).
1.1.1.2 root 1398:
1.1.1.4 root 1399: The value is 2 if some of these insns are only conditionally invariant.
1400:
1.1.1.2 root 1401: We assume that INSN itself is the first set of REG
1402: and that its source is invariant. */
1403:
1404: static int
1.1.1.8 ! root 1405: consec_sets_invariant_p (reg, n_sets, insn)
1.1.1.4 root 1406: int n_sets;
1.1.1.2 root 1407: rtx reg, insn;
1408: {
1409: register rtx p = insn;
1410: register int regno = REGNO (reg);
1.1.1.8 ! root 1411: rtx temp;
1.1.1.2 root 1412: /* Number of sets we have to insist on finding after INSN. */
1.1.1.4 root 1413: int count = n_sets - 1;
1.1.1.8 ! root 1414: int old = n_times_set[regno];
1.1.1.4 root 1415: int tem = 0;
1.1.1.2 root 1416:
1.1.1.8 ! root 1417: /* If N_SETS hit the limit, we can't rely on its value. */
! 1418: if (n_sets == 127)
! 1419: return 0;
! 1420:
! 1421: n_times_set[regno] = 0;
1.1.1.2 root 1422:
1423: while (count > 0)
1424: {
1425: register enum rtx_code code;
1426: p = NEXT_INSN (p);
1427: code = GET_CODE (p);
1.1.1.8 ! root 1428:
! 1429: /* If library call, skip to end of of it. */
! 1430: if (code == INSN && (temp = find_reg_note (p, REG_LIBCALL, 0)))
! 1431: p = XEXP (temp, 0);
! 1432:
1.1.1.2 root 1433: if (code == INSN && GET_CODE (PATTERN (p)) == SET
1434: && GET_CODE (SET_DEST (PATTERN (p))) == REG
1435: && REGNO (SET_DEST (PATTERN (p))) == regno
1.1.1.8 ! root 1436: && (tem |= invariant_p (SET_SRC (PATTERN (p)))
! 1437: || ((temp = find_reg_note (p, REG_EQUAL, 0))
! 1438: && (tem |= invariant_p (XEXP (temp, 0))))))
1.1.1.2 root 1439: count--;
1440: else if (code != NOTE)
1441: {
1.1.1.8 ! root 1442: n_times_set[regno] = old;
1.1.1.2 root 1443: return 0;
1444: }
1445: }
1446:
1.1.1.8 ! root 1447: n_times_set[regno] = old;
1.1.1.4 root 1448: /* If invariant_p ever returned 2, we return 2. */
1449: return 1 + (tem & 2);
1.1.1.2 root 1450: }
1451:
1452: #if 0
1453: /* I don't think this condition is sufficient to allow INSN
1454: to be moved, so we no longer test it. */
1.1 root 1455:
1456: /* Return 1 if all insns in the basic block of INSN and following INSN
1457: that set REG are invariant according to TABLE. */
1458:
1459: static int
1460: all_sets_invariant_p (reg, insn, table)
1461: rtx reg, insn;
1.1.1.2 root 1462: short *table;
1.1 root 1463: {
1464: register rtx p = insn;
1465: register int regno = REGNO (reg);
1466:
1467: while (1)
1468: {
1469: register enum rtx_code code;
1470: p = NEXT_INSN (p);
1471: code = GET_CODE (p);
1472: if (code == CODE_LABEL || code == JUMP_INSN)
1473: return 1;
1474: if (code == INSN && GET_CODE (PATTERN (p)) == SET
1475: && GET_CODE (SET_DEST (PATTERN (p))) == REG
1476: && REGNO (SET_DEST (PATTERN (p))) == regno)
1477: {
1478: if (!invariant_p (SET_SRC (PATTERN (p)), table))
1479: return 0;
1480: }
1481: }
1482: }
1.1.1.2 root 1483: #endif /* 0 */
1.1 root 1484:
1485: /* Increment N_TIMES_SET at the index of each register
1486: that is modified by an insn between FROM and TO.
1.1.1.8 ! root 1487: If the value of an element of N_TIMES_SET becomes 127 or more,
! 1488: stop incrementing it, to avoid overflow.
1.1 root 1489:
1490: Store in *COUNT_PTR the number of actual instruction
1491: in the loop. We use this to decide what is worth moving out. */
1492:
1493: /* last_set[n] is nonzero iff reg n has been set in the current basic block.
1494: In that case, it is the insn that last set reg n. */
1495:
1496: static void
1.1.1.8 ! root 1497: count_loop_regs_set (from, to, may_not_move, count_ptr, nregs)
1.1 root 1498: register rtx from, to;
1499: char *may_not_move;
1500: int *count_ptr;
1501: int nregs;
1502: {
1503: register rtx *last_set = (rtx *) alloca (nregs * sizeof (rtx));
1504: register rtx insn;
1505: register int count = 0;
1506: register rtx dest;
1507:
1508: bzero (last_set, nregs * sizeof (rtx));
1509: for (insn = from; insn != to; insn = NEXT_INSN (insn))
1510: {
1.1.1.2 root 1511: if (GET_CODE (insn) == CALL_INSN)
1512: {
1513: /* If a register is used as a subroutine address,
1514: don't allow this register's setting to be moved out of the loop.
1515: This condition is not at all logically correct
1516: but it averts a very common lossage pattern
1517: and creates lossage much less often. */
1518: if (GET_CODE (PATTERN (insn)) == CALL
1519: && GET_CODE (XEXP (PATTERN (insn), 0)) == MEM
1520: && GET_CODE (XEXP (XEXP (PATTERN (insn), 0), 0)) == REG)
1521: {
1522: register int regno
1523: = REGNO (XEXP (XEXP (PATTERN (insn), 0), 0));
1524: may_not_move[regno] = 1;
1525: }
1526: else if (GET_CODE (PATTERN (insn)) == SET
1527: && GET_CODE (SET_SRC (PATTERN (insn))) == CALL
1528: && GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 0)) == MEM
1529: && GET_CODE (XEXP (XEXP (SET_SRC (PATTERN (insn)), 0), 0)) == REG)
1530: {
1531: register int regno
1532: = REGNO (XEXP (XEXP (SET_SRC (PATTERN (insn)), 0), 0));
1533: may_not_move[regno] = 1;
1534: /* The call insn itself sets a reg, which cannot be moved. */
1535: may_not_move[REGNO (SET_DEST (PATTERN (insn)))] = 1;
1.1.1.8 ! root 1536: if (n_times_set[REGNO (SET_DEST (PATTERN (insn)))] < 127)
! 1537: n_times_set[REGNO (SET_DEST (PATTERN (insn)))]++;
1.1.1.2 root 1538: }
1539: }
1540: if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN)
1.1 root 1541: {
1542: ++count;
1.1.1.2 root 1543: if (GET_CODE (PATTERN (insn)) == CLOBBER
1544: && GET_CODE (XEXP (PATTERN (insn), 0)) == REG)
1545: /* Don't move a reg that has an explicit clobber.
1546: We might do so sometimes, but it's not worth the pain. */
1547: may_not_move[REGNO (XEXP (PATTERN (insn), 0))] = 1;
1548: else if (GET_CODE (PATTERN (insn)) == SET)
1.1 root 1549: {
1550: dest = SET_DEST (PATTERN (insn));
1551: while (GET_CODE (dest) == SUBREG
1552: || GET_CODE (dest) == ZERO_EXTRACT
1553: || GET_CODE (dest) == SIGN_EXTRACT
1554: || GET_CODE (dest) == STRICT_LOW_PART)
1555: dest = XEXP (dest, 0);
1556: if (GET_CODE (dest) == REG)
1557: {
1558: register int regno = REGNO (dest);
1559: /* If this is the first setting of this reg
1560: in current basic block, and it was set before,
1561: it must be set in two basic blocks, so it cannot
1562: be moved out of the loop. */
1563: if (n_times_set[regno] > 0 && last_set[regno] == 0)
1564: may_not_move[regno] = 1;
1565: /* If this is not first setting in current basic block,
1566: see if reg was used in between previous one and this.
1567: If so, neither one can be moved. */
1568: if (last_set[regno] != 0
1569: && reg_used_between_p (dest, last_set[regno], insn))
1570: may_not_move[regno] = 1;
1.1.1.8 ! root 1571: if (n_times_set[regno] < 127)
! 1572: ++n_times_set[regno];
1.1 root 1573: last_set[regno] = insn;
1574: }
1575: }
1576: else if (GET_CODE (PATTERN (insn)) == PARALLEL)
1577: {
1578: register int i;
1579: for (i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--)
1580: {
1581: register rtx x = XVECEXP (PATTERN (insn), 0, i);
1.1.1.2 root 1582: if (GET_CODE (x) == CLOBBER && GET_CODE (XEXP (x, 0)) == REG)
1583: /* Don't move a reg that has an explicit clobber.
1584: It's not worth the pain to try to do it correctly. */
1585: may_not_move[REGNO (XEXP (x, 0))] = 1;
1.1 root 1586: if (GET_CODE (x) == SET)
1587: {
1588: dest = SET_DEST (x);
1589: while (GET_CODE (dest) == SUBREG
1590: || GET_CODE (dest) == ZERO_EXTRACT
1591: || GET_CODE (dest) == SIGN_EXTRACT
1592: || GET_CODE (dest) == STRICT_LOW_PART)
1593: dest = XEXP (dest, 0);
1594: if (GET_CODE (dest) == REG)
1595: {
1596: register int regno = REGNO (dest);
1.1.1.8 ! root 1597: if (n_times_set[regno] < 127)
! 1598: ++n_times_set[regno];
1.1 root 1599: may_not_move[regno] = 1;
1600: last_set[regno] = insn;
1601: }
1602: }
1603: }
1604: }
1605: }
1606: if (GET_CODE (insn) == CODE_LABEL || GET_CODE (insn) == JUMP_INSN)
1607: bzero (last_set, nregs * sizeof (rtx));
1608: }
1609: *count_ptr = count;
1610: }
1611:
1612: /* Given a loop that is bounded by LOOP_START and LOOP_END
1613: and that is entered at SCAN_START,
1614: return 1 if the register set by insn INSN is used by
1615: any insn that precedes INSN in cyclic order starting
1616: from the loop entry point. */
1617:
1618: static int
1619: loop_reg_used_before_p (insn, loop_start, scan_start, loop_end)
1620: rtx insn, loop_start, scan_start, loop_end;
1621: {
1622: rtx reg = SET_DEST (PATTERN (insn));
1623: if (INSN_LUID (scan_start) > INSN_LUID (insn))
1624: return (reg_used_between_p (reg, scan_start, loop_end)
1625: || reg_used_between_p (reg, loop_start, insn));
1626: else
1627: return reg_used_between_p (reg, scan_start, insn);
1628: }
1.1.1.2 root 1629:
1.1.1.3 root 1630: /* Return nonzero if evaluating rtx X might cause a trap. */
1.1.1.2 root 1631:
1632: static int
1633: may_trap_p (x)
1634: rtx x;
1635: {
1.1.1.3 root 1636: int i;
1637: enum rtx_code code = GET_CODE (x);
1638: char *fmt;
1639:
1640: switch (code)
1.1.1.2 root 1641: {
1.1.1.3 root 1642: /* Handle these cases fast. */
1643: case CONST_INT:
1644: case CONST_DOUBLE:
1645: case SYMBOL_REF:
1646: case LABEL_REF:
1647: case CONST:
1648: case PC:
1649: case CC0:
1650: case REG:
1651: return 0;
1652:
1.1.1.5 root 1653: /* Memory ref can trap unless it's a static var or a stack slot. */
1654: case MEM:
1655: return rtx_varies_p (XEXP (x, 0));
1656:
1.1.1.3 root 1657: /* Division by a non-constant might trap. */
1.1.1.2 root 1658: case DIV:
1659: case MOD:
1660: case UDIV:
1661: case UMOD:
1662: if (! CONSTANT_P (XEXP (x, 1))
1663: && GET_CODE (XEXP (x, 1)) != CONST_DOUBLE)
1664: return 1;
1.1.1.5 root 1665: default:
1.1.1.4 root 1666: /* Any floating arithmetic may trap. */
1.1.1.5 root 1667: if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
1.1.1.4 root 1668: return 1;
1.1.1.3 root 1669: }
1670:
1671: fmt = GET_RTX_FORMAT (code);
1672: for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
1673: {
1674: if (fmt[i] == 'e')
1675: {
1676: if (may_trap_p (XEXP (x, i)))
1677: return 1;
1678: }
1679: else if (fmt[i] == 'E')
1680: {
1681: register int j;
1682: for (j = 0; j < XVECLEN (x, i); j++)
1683: if (may_trap_p (XVECEXP (x, i, j)))
1684: return 1;
1685: }
1.1.1.2 root 1686: }
1687: return 0;
1688: }
1.1.1.8 ! root 1689:
! 1690: /* A "basic induction variable" or biv is a pseudo reg that is set
! 1691: (within this loop) only by incrementing or decrementing it. */
! 1692: /* A "general induction variable" or giv is a pseudo reg whose
! 1693: value is a linear function of a biv. */
! 1694:
! 1695: /* Bivs are recognized by `basic_induction_var';
! 1696: Givs by `general_induct_var'. */
! 1697:
! 1698: /* An enum for the two different types of givs, those that are used
! 1699: as memory addresses and those that are calculated into registers. */
! 1700: enum g_types { DEST_ADDR, DEST_REG };
! 1701:
! 1702: /* A `struct induction' is created for every instruction that sets
! 1703: an induction variable (either a biv or a giv). */
! 1704:
! 1705: struct induction
! 1706: {
! 1707: rtx insn; /* The insn that sets a biv or giv */
! 1708: rtx new_reg; /* New register, containing strength reduced
! 1709: version of this giv. */
! 1710: int src_regno; /* Biv from which this giv is computed.
! 1711: (If this is a biv, then this is the biv.) */
! 1712: enum g_types giv_type; /* Indicate whether DEST_ADDR or DEST_REG giv */
! 1713: int dest_regno; /* Destination register for insn: this is the
! 1714: register which was the biv or giv.
! 1715: For a biv, this equals src_reg.
! 1716: For a DEST_ADDR type giv, this is 0. */
! 1717: rtx *location; /* Place in the insn where this giv occurs.
! 1718: If GIV_TYPE is DEST_REG, this is 0. */
! 1719: rtx mult_val; /* Multiplicative factor for src_reg. */
! 1720: rtx add_val; /* Additive constant for that product. */
! 1721: int benefit; /* Gain from eliminating this insn. */
! 1722: int consec; /* The number of consecutive insn that set this
! 1723: register; they are all eliminated if this
! 1724: one is. */
! 1725: char replaceable; /* 1 if we can substitute the strength-reduced
! 1726: variable for the original variable.
! 1727: 0 means they must be kept separate and the
! 1728: new one must be copied into the old pseudo
! 1729: reg each time the old one is set. */
! 1730: char ignore; /* 1 prohibits further processing of this giv */
! 1731: int lifetime; /* Length of life of this giv */
! 1732: int times_used; /* # times this giv is used. */
! 1733: struct induction *family; /* Links together all induction variables that
! 1734: have the same src register. */
! 1735: struct induction *forces; /* Points to an induction variable insn which
! 1736: is used only once, to compute this giv,
! 1737: and hence can be deleted if this insn is
! 1738: strength reduced. */
! 1739: struct induction *forces2; /* Likewise. */
! 1740: struct induction *same; /* Links together all induction variables that
! 1741: have the same tuple (src, mult, add). */
! 1742: };
! 1743:
! 1744: /* A `struct iv_class' is created for each biv. */
! 1745:
! 1746: struct iv_class {
! 1747: int regno; /* Pseudo reg which is the biv. */
! 1748: int biv_count; /* Number of insns setting this reg. */
! 1749: struct induction *biv; /* List of all insns that set this reg. */
! 1750: int giv_count; /* Number of givs computed from this biv. */
! 1751: struct induction *giv; /* List of all insns that compute a giv
! 1752: from this reg. */
! 1753: int total_benefit; /* Sum of BENEFITs of all those givs */
! 1754: rtx initial_value; /* Value of reg at loop start */
! 1755: struct iv_class *next; /* Links all class structures together */
! 1756: char init_val_set; /* Used during scan for initial value,
! 1757: 1 if assignment seen, 0 otherwise. */
! 1758: char eliminable; /* 1 if plausible candidate for elimination. */
! 1759: char nonneg; /* 1 if we added a REG_NONNEG note for this. */
! 1760: };
! 1761:
! 1762: /* Definitions used by the basic induction variable discovery code. */
! 1763: enum iv_mode { UNKNOWN_INDUCT, BASIC_INDUCT, NOT_BASIC_INDUCT,
! 1764: GENERAL_INDUCT };
! 1765:
! 1766: /* Relative gain of eliminating various kinds of operations. */
! 1767: #define NO_BENEFIT 0
! 1768: #define ADD_BENEFIT 1
! 1769: #define SHIFT_BENEFIT 2
! 1770: #define MULT_BENEFIT 4
! 1771: #define LIBCALL_BENEFIT 15
! 1772: /* Benefit penalty, if a giv is not replaceable, i.e. must emit an insn to
! 1773: copy the value of the strength reduced giv to its original register. */
! 1774: #define COPY_PENALTY 2
! 1775:
! 1776: /* Indexed by register number, indicates whether or not register is an
! 1777: induction variable, and if so what type. */
! 1778:
! 1779: static enum iv_mode *induct_var;
! 1780:
! 1781: /* Indexed by register number, contains pointer to `struct induction'
! 1782: if register is a general induction variable. */
! 1783:
! 1784: static struct induction **induct_struct;
! 1785:
! 1786: /* Indexed by register number, contains pointer to `struct iv_class'
! 1787: if register is a basic induction variable. */
! 1788:
! 1789: static struct iv_class **class_struct;
! 1790:
! 1791: /*********************************/
! 1792:
! 1793: /* ??? Unfinished optimizations, [email protected] */
! 1794:
! 1795: /* strength reduce addresses found in sources (set () (mem ())*/
! 1796:
! 1797: /* There is one more optimization you might be interested in doing: to
! 1798: allocate pseudo registers for frequently-accessed memory locations.
! 1799: If the same memory location is referenced each time around, it might
! 1800: be possible to copy it into a register before and out after.
! 1801: This is especially useful when the memory location is a variable which
! 1802: is in a stack slot because somewhere its address is taken. If the
! 1803: loop doesn't contain a function call and the variable isn't volatile,
! 1804: it is safe to keep the value in a register for the duration of the
! 1805: loop. One tricky thing is that the copying of the value back from the
! 1806: register has to be done on all exits from the loop. You need to check that
! 1807: all the exits from the loop go to the same place. */
! 1808:
! 1809: /* WARNING: the interaction of biv elimination, and recognizing 'constant'
! 1810: bivs may cause problems */
! 1811:
! 1812: /* add heuristic so that DEST_ADDR strength reduction does not cause
! 1813: performance problems */
! 1814:
! 1815: /* don't eliminate things that can be combined with an addressing mode?
! 1816: find all giv that have same biv and mult_val (now must also have
! 1817: same add_val), then for each giv, check to see if its only use
! 1818: dies in a following memory address, generate a new memory address
! 1819: and check to see if valid, if valid then store modified mem addr,
! 1820: else if not valid addr mark giv as not done so that it will get its
! 1821: own iv */
! 1822:
! 1823: /* consec_sets_giv does not calculate replaceable and forces correctly,
! 1824: forces should be a more general linked list instead of two entries */
! 1825:
! 1826: /* try to optimize branches when it is known that a biv is always positive */
! 1827:
! 1828: /* when replace biv in compare insn, should replace with closest giv so that
! 1829: an optimized branch can still be recognized by combiner, i.e. VAXen acb */
! 1830:
! 1831: /* should merge final_value calculation in check_dbra_loop with the
! 1832: new final_biv_value function */
! 1833:
! 1834: /* many of the checks involving uid_luid could be simplified if regscan
! 1835: was rerun in loop_optimize() whenever a register was added or moved,
! 1836: also some of the optimizations could be a little less conservative */
! 1837:
! 1838: /* Perform strength reduction and induction variable elimination. */
! 1839:
! 1840: /* Pseudo registers created during this function will be beyond the last
! 1841: valid index in several tables including n_times_set and regno_last_uid.
! 1842: This does not cause a problem here, because the added registers cannot be
! 1843: givs outside of their loop, and hence will never be reconsidered.
! 1844: But scan_loop must check regnos to make sure they are in bounds. */
! 1845:
! 1846: static void
! 1847: strength_reduce (scan_start, end, loop_top, insn_count,
! 1848: loop_start, loop_end, nregs)
! 1849: rtx scan_start;
! 1850: rtx end;
! 1851: rtx loop_top;
! 1852: int insn_count;
! 1853: rtx loop_start;
! 1854: rtx loop_end;
! 1855: int nregs;
! 1856: {
! 1857: rtx p;
! 1858: rtx inc_val;
! 1859: rtx mult_val;
! 1860: int dest_regno;
! 1861: int biv_found;
! 1862: /* This is 1 if current insn could be executed zero times in the loop. */
! 1863: int maybe_never = 0;
! 1864: /* List of all possible basic induction variables. */
! 1865: struct iv_class *iv_list = 0;
! 1866: /* Temporary list pointers for traversing iv_list. */
! 1867: struct iv_class *bl, *backbl;
! 1868: /* Ratio of extra register life span we can justify
! 1869: for saving an instruction. More if loop doesn't call subroutines
! 1870: since in that case saving an insn makes more difference
! 1871: and more registers are available. */
! 1872: /* ??? could set this to last value of threshold in move_movables */
! 1873: int threshold = loop_has_call ? 17 : 34;
! 1874: /* Map of pseudo-register replacements. */
! 1875: rtx *reg_map;
! 1876:
! 1877: induct_var = (enum iv_mode *) alloca (nregs * sizeof (induct_var[0]));
! 1878: bzero ((char *)induct_var, nregs * sizeof (induct_var[0]));
! 1879: induct_struct = (struct induction **)
! 1880: alloca (nregs * sizeof (struct induction *));
! 1881: bzero ((char *)induct_struct, nregs * sizeof (struct induction *));
! 1882: class_struct = (struct iv_class **)
! 1883: alloca (nregs * sizeof (struct iv_class *));
! 1884: bzero ((char *)class_struct, nregs * sizeof (struct iv_class *));
! 1885:
! 1886: /* Scan through loop to find all possible bivs. */
! 1887:
! 1888: for (p = NEXT_INSN (loop_start); p != end; p = NEXT_INSN (p))
! 1889: {
! 1890: if (GET_CODE (p) == INSN
! 1891: && GET_CODE (PATTERN (p)) == SET
! 1892: && GET_CODE (SET_DEST (PATTERN (p))) == REG)
! 1893: {
! 1894: dest_regno = REGNO (SET_DEST (PATTERN (p)));
! 1895: if (induct_var[dest_regno] != NOT_BASIC_INDUCT)
! 1896: {
! 1897: if (basic_induction_var (SET_SRC (PATTERN (p)), dest_regno,
! 1898: &inc_val, &mult_val))
! 1899: {
! 1900: /* It is a possible basic induction variable.
! 1901: Create and initialize an induction structure for it. */
! 1902:
! 1903: struct induction *v =
! 1904: (struct induction *) alloca (sizeof (struct induction));
! 1905:
! 1906: v->insn = p;
! 1907: v->src_regno = dest_regno;
! 1908: v->dest_regno = dest_regno;
! 1909: v->mult_val = mult_val;
! 1910: v->add_val = inc_val;
! 1911:
! 1912: /* Add this to the reg's iv_class, creating a class
! 1913: if this is the first incrementation of the reg. */
! 1914:
! 1915: bl = class_struct[dest_regno];
! 1916: if (bl)
! 1917: {
! 1918: v->family = bl->biv;
! 1919: bl->biv = v;
! 1920: bl->biv_count++;
! 1921: }
! 1922: else
! 1923: {
! 1924: /* Create and initialize new iv_class. */
! 1925:
! 1926: bl = (struct iv_class *) alloca (sizeof (struct iv_class));
! 1927:
! 1928: bl->regno = dest_regno;
! 1929: bl->biv = v;
! 1930: v->family = 0;
! 1931: bl->giv = 0;
! 1932: bl->biv_count = 1;
! 1933: bl->giv_count = 0;
! 1934:
! 1935: /* Set initial value to the reg itself. */
! 1936: bl->initial_value = SET_DEST (PATTERN (p));
! 1937: bl->init_val_set = 0;
! 1938: bl->eliminable = 0;
! 1939: bl->nonneg = 0;
! 1940:
! 1941: /* Add this insn to iv_list. */
! 1942: bl->next = iv_list;
! 1943: iv_list = bl;
! 1944:
! 1945: /* Put it in the array of iv_lists. */
! 1946: class_struct[dest_regno] = bl;
! 1947: }
! 1948:
! 1949: induct_var[dest_regno] = BASIC_INDUCT;
! 1950:
! 1951: if (loop_dump_stream)
! 1952: {
! 1953: fprintf (loop_dump_stream,
! 1954: "Insn %d: possible biv, reg %d,",
! 1955: INSN_UID (p), dest_regno);
! 1956: if (GET_CODE (inc_val) == CONST_INT)
! 1957: fprintf (loop_dump_stream, " const = %d\n",
! 1958: INTVAL (inc_val));
! 1959: else
! 1960: {
! 1961: fprintf (loop_dump_stream, " const = ");
! 1962: print_rtl (loop_dump_stream, inc_val);
! 1963: fprintf (loop_dump_stream, "\n");
! 1964: }
! 1965: }
! 1966: }
! 1967: else
! 1968: induct_var[dest_regno] = NOT_BASIC_INDUCT;
! 1969: }
! 1970: }
! 1971: }
! 1972:
! 1973: /* Scan iv_list to remove all regs that proved not to be bivs.
! 1974: Make a sanity check against n_times_set. */
! 1975:
! 1976: biv_found = 0;
! 1977:
! 1978: for (backbl = bl = iv_list; bl; backbl = bl, bl = bl->next)
! 1979: {
! 1980: if (induct_var[bl->regno] != BASIC_INDUCT)
! 1981: {
! 1982: /* Not a basic induction variable, remove this iv_class. */
! 1983:
! 1984: if (backbl == bl)
! 1985: iv_list = bl->next;
! 1986: else
! 1987: backbl->next = bl->next;
! 1988:
! 1989: if (loop_dump_stream)
! 1990: fprintf (loop_dump_stream, "Reg %d: biv discarded, not induct\n",
! 1991: bl->regno);
! 1992: }
! 1993: else if (n_times_set[bl->regno] != bl->biv_count)
! 1994: {
! 1995: /* This happens if register modified by subreg, etc. */
! 1996: /* Make sure it is not recognized as a basic induction var: */
! 1997: /* remove this iv_class from iv_list. */
! 1998:
! 1999: induct_var[bl->regno] = NOT_BASIC_INDUCT;
! 2000:
! 2001: if (backbl == bl)
! 2002: iv_list = bl->next;
! 2003: else
! 2004: backbl->next = bl->next;
! 2005:
! 2006: if (loop_dump_stream)
! 2007: fprintf (loop_dump_stream, "Reg %d: biv discarded, count error\n",
! 2008: bl->regno);
! 2009: }
! 2010: else
! 2011: {
! 2012: /* This is a valid basic induction variable. */
! 2013:
! 2014: biv_found++;
! 2015:
! 2016: if (loop_dump_stream)
! 2017: fprintf (loop_dump_stream, "Reg %d: biv verified\n", bl->regno);
! 2018: }
! 2019: }
! 2020:
! 2021: /* Exit if there are no bivs. */
! 2022: if (!iv_list)
! 2023: return;
! 2024:
! 2025: /* Find initial value for each biv. */
! 2026: /* Search backwards from loop_start, halting at first label
! 2027: or when all bivs have been seen. */
! 2028:
! 2029: p = loop_start;
! 2030: while (biv_found)
! 2031: {
! 2032: p = PREV_INSN (p);
! 2033: if (p == 0)
! 2034: break;
! 2035:
! 2036: if (GET_CODE (p) == INSN
! 2037: && GET_CODE (PATTERN (p)) == SET
! 2038: && GET_CODE (SET_DEST (PATTERN (p))) == REG)
! 2039: {
! 2040: int dest_regno = REGNO (SET_DEST (PATTERN (p)));
! 2041:
! 2042: if (induct_var[dest_regno] == BASIC_INDUCT
! 2043: && class_struct[dest_regno]->init_val_set == 0)
! 2044: {
! 2045: /* This is the first modification found for this reg. */
! 2046:
! 2047: /* Save value if it is a constant or register. */
! 2048: if (GET_CODE (SET_SRC (PATTERN (p))) == CONST_INT
! 2049: || GET_CODE (SET_SRC (PATTERN (p))) == REG)
! 2050: {
! 2051: class_struct[dest_regno]->initial_value
! 2052: = SET_SRC (PATTERN (p));
! 2053:
! 2054: if (loop_dump_stream)
! 2055: fprintf (loop_dump_stream, "Reg %d: initial value ",
! 2056: dest_regno);
! 2057: if (loop_dump_stream)
! 2058: {
! 2059: if (GET_CODE (SET_SRC (PATTERN (p))) == CONST_INT)
! 2060: fprintf (loop_dump_stream, "%d\n",
! 2061: INTVAL (SET_SRC (PATTERN (p))));
! 2062: else
! 2063: fprintf (loop_dump_stream, "reg %d\n",
! 2064: REGNO (SET_SRC (PATTERN (p))));
! 2065: }
! 2066: }
! 2067: else
! 2068: {
! 2069: /* Biv initial value is not simple move,
! 2070: so let it keep intial value of "itself". */
! 2071:
! 2072: if (loop_dump_stream)
! 2073: fprintf (loop_dump_stream, "Reg %d: complex initial value\n",
! 2074: dest_regno);
! 2075: }
! 2076:
! 2077: class_struct[dest_regno]->init_val_set = 1;
! 2078: biv_found--;
! 2079: }
! 2080: }
! 2081: else if (GET_CODE (p) == CODE_LABEL)
! 2082: break;
! 2083: }
! 2084:
! 2085: /* Search the loop for general induction variables. */
! 2086:
! 2087: /* A register is a giv if: it is only set once, it is a function of a
! 2088: biv and a constant (or invariant), and it is not a biv. */
! 2089:
! 2090: p = scan_start;
! 2091: while (1)
! 2092: {
! 2093: p = NEXT_INSN (p);
! 2094: /* At end of a straight-in loop, we are done.
! 2095: At end of a loop entered at the bottom, scan the top. */
! 2096: if (p == scan_start)
! 2097: break;
! 2098: if (p == end)
! 2099: {
! 2100: if (loop_top != 0)
! 2101: p = NEXT_INSN (loop_top);
! 2102: else
! 2103: break;
! 2104: if (p == scan_start)
! 2105: break;
! 2106: }
! 2107:
! 2108: /* Look for a general induction variable in a register. */
! 2109: if (GET_CODE (p) == INSN
! 2110: && GET_CODE (PATTERN (p)) == SET
! 2111: && GET_CODE (SET_DEST (PATTERN (p))) == REG)
! 2112: {
! 2113: int src_regno;
! 2114: rtx add_val;
! 2115: rtx mult_val;
! 2116: int benefit;
! 2117: rtx regnote = 0;
! 2118: struct induction *forces = 0;
! 2119: struct induction *forces2 = 0;
! 2120:
! 2121: dest_regno = REGNO (SET_DEST (PATTERN (p)));
! 2122:
! 2123: if (/* Normal giv. */
! 2124: ((benefit = general_induction_var (SET_SRC (PATTERN (p)),
! 2125: &src_regno, &add_val,
! 2126: &mult_val,
! 2127: &forces, &forces2))
! 2128: /* Giv set with call to a library routine. */
! 2129: || ((regnote = find_reg_note (p, REG_EQUAL, 0))
! 2130: &&
! 2131: (benefit = general_induction_var (XEXP (regnote, 0),
! 2132: &src_regno,
! 2133: &add_val, &mult_val,
! 2134: &forces, &forces2))))
! 2135: /* Don't recognize a BASIC_INDUCT_VAR here. */
! 2136: && dest_regno != src_regno
! 2137: /* This must be the only place where the register is set. */
! 2138: && (n_times_set[dest_regno] == 1
! 2139: || (benefit = consec_sets_giv (benefit, p,
! 2140: src_regno, dest_regno,
! 2141: &add_val, &mult_val))))
! 2142: {
! 2143: int count;
! 2144: struct induction *v =
! 2145: (struct induction *) alloca (sizeof (struct induction));
! 2146: rtx temp;
! 2147:
! 2148: record_giv (v, p, src_regno, dest_regno, mult_val, add_val, benefit,
! 2149: forces, forces2, DEST_REG, maybe_never, 0);
! 2150:
! 2151: /* Skip the consecutive insns, if there are any. */
! 2152: for (count = v->consec - 1; count >= 0; count--)
! 2153: {
! 2154: /* If first insn of libcall sequence, skip to end. */
! 2155: /* Do this at start of loop, since INSN is guaranteed to
! 2156: be an insn here. */
! 2157: if (temp = find_reg_note (p, REG_LIBCALL, 0))
! 2158: {
! 2159: /* Eliminating a libcall does more good than
! 2160: eliminating a single insn to do the same job. */
! 2161: benefit += LIBCALL_BENEFIT;
! 2162: p = XEXP (temp, 0);
! 2163: }
! 2164:
! 2165: do p = NEXT_INSN (p);
! 2166: while (GET_CODE (p) == NOTE);
! 2167: }
! 2168: }
! 2169: }
! 2170:
! 2171: #ifndef DONT_REDUCE_ADDR
! 2172: /* Look for givs which are memory addresses. */
! 2173: /* This resulted in worse code on a VAX 8600. I wonder if it
! 2174: still does. */
! 2175: if (GET_CODE (p) == INSN)
! 2176: find_mem_givs (PATTERN (p), p, maybe_never);
! 2177: #endif
! 2178:
! 2179: /* Past a label or a jump, we get to insns for which we can't count
! 2180: on whether or how many times they will be executed during each
! 2181: iteration. Givs found afterwards cannot be marked replaceable. */
! 2182: if (GET_CODE (p) == CODE_LABEL || GET_CODE (p) == JUMP_INSN)
! 2183: maybe_never = 1;
! 2184: }
! 2185:
! 2186: /* Try to prove that the loop counter variable (if any) is always
! 2187: nonnegative; if so, record that fact with a REG_NONNEG note
! 2188: so that "decrement and branch until zero" insn can be used. */
! 2189: check_dbra_loop (loop_end, iv_list, insn_count, loop_start);
! 2190:
! 2191: /* Create reg_map to hold substitutions for replaceable giv regs. */
! 2192: reg_map = (rtx *) alloca (nregs * sizeof (rtx));
! 2193: bzero ((char *)reg_map, nregs * sizeof (rtx));
! 2194:
! 2195: /* Examine each iv class for feasibility of strength reduction/induction
! 2196: variable elimination. */
! 2197:
! 2198: for (bl = iv_list; bl; bl = bl->next)
! 2199: {
! 2200: struct induction *v;
! 2201: int benefit;
! 2202: int replaceable;
! 2203: int all_reduced;
! 2204: rtx final_value = 0;
! 2205:
! 2206: /* Test whether it will be possible to eliminate this biv
! 2207: provided all givs are reduced.
! 2208:
! 2209: Don't try if we put a REG_NONNEG note on the endtest for this biv.
! 2210: ??? That should be only on machines that have dbra insns. */
! 2211:
! 2212: if ((uid_luid[regno_last_uid[bl->regno]] < INSN_LUID (loop_end)
! 2213: && bl->init_val_set && ! bl->nonneg)
! 2214: || (final_value = final_biv_value (bl, loop_end)))
! 2215: {
! 2216: /* Get the REG rtx for the biv. */
! 2217: rtx reg = SET_DEST (PATTERN (bl->biv->insn));
! 2218:
! 2219: for (p = loop_start; p != end; p = NEXT_INSN (p))
! 2220: {
! 2221: enum rtx_code code = GET_CODE (p);
! 2222: if ((code == INSN || code == JUMP_INSN || code == CALL_INSN)
! 2223: && reg_mentioned_p (reg, PATTERN (p)))
! 2224: {
! 2225: /* This insn uses the biv. If we can't understand it,
! 2226: then we can't eliminate the biv. */
! 2227: if (GET_CODE (PATTERN (p)) != SET)
! 2228: break;
! 2229:
! 2230: /* The insns that increment the biv are no problem. */
! 2231: if (SET_DEST (PATTERN (p)) == reg)
! 2232: continue;
! 2233:
! 2234: /* If can rewrite this insn not to use the biv, it's ok. */
! 2235: if (can_eliminate_biv_p (p, bl))
! 2236: continue;
! 2237:
! 2238: /* If this is an insn which computes a giv, no problem,
! 2239: because it will go away if the giv is reduced. */
! 2240: for (v = bl->giv; v; v = v->family)
! 2241: if (!v->ignore && v->insn == p && v->giv_type == DEST_REG)
! 2242: break;
! 2243: if (v)
! 2244: continue;
! 2245:
! 2246: /* Biv is used in a way we cannot eliminate. */
! 2247: break;
! 2248: }
! 2249: }
! 2250:
! 2251: if (p == end)
! 2252: {
! 2253: bl->eliminable = 1;
! 2254: if (loop_dump_stream)
! 2255: fprintf (loop_dump_stream, "Can eliminate biv %d.\n",
! 2256: bl->regno);
! 2257: }
! 2258: else if (loop_dump_stream)
! 2259: fprintf (loop_dump_stream,
! 2260: "Cannot eliminate biv %d due to insn %d.\n",
! 2261: bl->regno, INSN_UID (p));
! 2262: }
! 2263: else
! 2264: {
! 2265: if (loop_dump_stream)
! 2266: fprintf (loop_dump_stream,
! 2267: "Cannot eliminate biv %d: used outside the loop\n",
! 2268: bl->regno);
! 2269: }
! 2270:
! 2271: /* This will be true at the end, if all givs which depend on this
! 2272: biv have been strength reduced.
! 2273: We can't (currently) eliminate the biv unless this is so. */
! 2274: all_reduced = 1;
! 2275:
! 2276: /* Check each giv in this class. */
! 2277:
! 2278: for (v = bl->giv; v; v = v->family)
! 2279: {
! 2280: struct induction *tv;
! 2281:
! 2282: if (v->ignore)
! 2283: continue;
! 2284:
! 2285: benefit = v->benefit;
! 2286: replaceable = v->replaceable;
! 2287:
! 2288: /* Reduce benefit if not replaceable, since we will insert
! 2289: a move-insn to replace the insn that calculates this giv. */
! 2290: if (!replaceable && ! bl->eliminable)
! 2291: benefit -= COPY_PENALTY;
! 2292:
! 2293: /* Decrease the benefit to count the add-insns that we will
! 2294: insert to increment the reduced reg for the giv. */
! 2295: benefit -= ADD_BENEFIT * bl->biv_count;
! 2296:
! 2297: /* Find all equivalent givs (that bear same relation to the biv).
! 2298: Link them via the `same' field and add their benefits together.
! 2299: They can be replaced with a single register. */
! 2300:
! 2301: for (tv = v->family; tv; tv = tv->family)
! 2302: {
! 2303: if (tv->ignore == 0
! 2304: && tv->src_regno == v->src_regno
! 2305: && rtx_equal_p (tv->mult_val, v->mult_val)
! 2306: && rtx_equal_p (tv->add_val, v->add_val))
! 2307: {
! 2308: benefit += tv->benefit;
! 2309: if (! tv->replaceable)
! 2310: benefit -= COPY_PENALTY;
! 2311: v->lifetime += tv->lifetime;
! 2312: v->times_used += tv->times_used;
! 2313: tv->ignore = 1;
! 2314:
! 2315: /* Link them together via `same' field. */
! 2316: tv->same = v->same;
! 2317: v->same = tv;
! 2318:
! 2319: if (loop_dump_stream)
! 2320: fprintf (loop_dump_stream,
! 2321: "giv of insn %d combined with that of %d.\n",
! 2322: INSN_UID (v->insn), INSN_UID (tv->insn));
! 2323: }
! 2324: }
! 2325:
! 2326: /* Decide whether to strength-reduce this giv
! 2327: or to leave the code unchanged
! 2328: (recompute it from the biv each time it is used).
! 2329: This decision can be made independently for each giv. */
! 2330:
! 2331: /* ??? Perhaps attempt to guess whether autoincrement will handle
! 2332: some of the new add insns; if so, can increase BENEFIT
! 2333: (undo the subtraction of ADD_BENEFIT that was done above). */
! 2334:
! 2335: /* Is it right to consider times_used? */
! 2336:
! 2337: if (benefit <= 0)
! 2338: {
! 2339: if (loop_dump_stream)
! 2340: fprintf (loop_dump_stream, "giv of insn %d, no benefit\n",
! 2341: INSN_UID (v->insn));
! 2342: v->ignore = 1;
! 2343: }
! 2344:
! 2345: if (v->lifetime * threshold * benefit < insn_count)
! 2346: {
! 2347: if (loop_dump_stream)
! 2348: fprintf (loop_dump_stream,
! 2349: "giv of insn %d not worth while, %d vs %d.\n",
! 2350: INSN_UID (v->insn),
! 2351: v->lifetime * threshold * benefit, insn_count);
! 2352: v->ignore = 1;
! 2353: }
! 2354:
! 2355: /* Now check that we can increment the reduced giv
! 2356: without needing a multiply insn. If not, reject it. */
! 2357:
! 2358: if (! v->ignore)
! 2359: {
! 2360: int success = 1;
! 2361:
! 2362: for (tv = bl->biv; tv; tv = tv->family)
! 2363: if (tv->mult_val == const1_rtx)
! 2364: success &= product_cheap_p (tv->add_val, v->mult_val);
! 2365:
! 2366: if (! success)
! 2367: {
! 2368: if (loop_dump_stream)
! 2369: fprintf (loop_dump_stream,
! 2370: "giv of insn %d: would need a multiply.\n",
! 2371: INSN_UID (v->insn));
! 2372: v->ignore = 1;
! 2373: }
! 2374: }
! 2375: }
! 2376:
! 2377: /* Reduce each giv that we decided to reduce. */
! 2378:
! 2379: for (v = bl->giv; v; v = v->family)
! 2380: {
! 2381: struct induction *tv;
! 2382: if (! v->ignore)
! 2383: {
! 2384: rtx new_reg = gen_reg_rtx (v->giv_type == DEST_ADDR ? Pmode
! 2385: : GET_MODE (SET_DEST (PATTERN (v->insn))));
! 2386:
! 2387: /* For each place where the biv is incremented,
! 2388: add an insn to increment the new, reduced reg for the giv.
! 2389: Insert it before the insn that sets the biv,
! 2390: so that the biv increment remains last before the endtest,
! 2391: so that dbra will still be recognized. */
! 2392:
! 2393: for (tv = bl->biv; tv; tv = tv->family)
! 2394: {
! 2395: if (tv->mult_val == const1_rtx)
! 2396: emit_iv_inc (tv->add_val, v->mult_val,
! 2397: new_reg, tv->insn);
! 2398: else /* tv->mult_val == const0_rtx */
! 2399: /* A multiply is acceptable here
! 2400: since this is presumed to be seldom executed. */
! 2401: emit_iv_init_code (tv->add_val, v->mult_val,
! 2402: v->add_val, new_reg, tv->insn);
! 2403: }
! 2404:
! 2405: /* Add code at loop start to initialize giv's reduced reg. */
! 2406:
! 2407: emit_iv_init_code (bl->initial_value, v->mult_val,
! 2408: v->add_val, new_reg, loop_start);
! 2409:
! 2410: /* For each giv register that can be reduced now:
! 2411: delete old insn that modifies the giv,
! 2412: if replaceable, substitute reduced reg
! 2413: wherever the old giv occurs;
! 2414: else add new move insn "giv_reg = reduced_reg". */
! 2415:
! 2416: for (tv = v; tv; tv = tv->same)
! 2417: {
! 2418: /* Record the identity of the reduced reg. */
! 2419: tv->new_reg = new_reg;
! 2420:
! 2421: if (tv->giv_type == DEST_ADDR)
! 2422: {
! 2423: /* Store reduced reg as the address in the memref
! 2424: where we found this giv. */
! 2425: * tv->location = new_reg;
! 2426: }
! 2427: else if (tv->replaceable)
! 2428: {
! 2429: reg_map[tv->dest_regno] = new_reg;
! 2430: /* If giv lives after end of loop,
! 2431: emit insn to copy reduced reg into old reg,
! 2432: at the end of the loop. */
! 2433: if (uid_luid[regno_last_uid[tv->dest_regno]]
! 2434: > uid_luid[INSN_UID (loop_end)])
! 2435: emit_insn_after (gen_rtx (SET, VOIDmode,
! 2436: SET_DEST (PATTERN (tv->insn)),
! 2437: new_reg),
! 2438: loop_end);
! 2439: }
! 2440: else
! 2441: {
! 2442: emit_insn_before (gen_rtx (SET, VOIDmode,
! 2443: SET_DEST (PATTERN (tv->insn)),
! 2444: new_reg),
! 2445: tv->insn);
! 2446: }
! 2447:
! 2448: /* Delete the insn that used to set the old giv reg,
! 2449: unless we modified an address in it.
! 2450: In any case, delete the other insns used for this one. */
! 2451: delete_insn_forces (tv, tv->giv_type != DEST_ADDR);
! 2452:
! 2453: if (loop_dump_stream)
! 2454: fprintf (loop_dump_stream, "giv at %d reduced to reg %d\n",
! 2455: INSN_UID (tv->insn), REGNO (new_reg));
! 2456: }
! 2457: /* One set of equivalent givs has been strength-reduced. */
! 2458: }
! 2459: else if (v->new_reg == 0)
! 2460: {
! 2461: /* This giv wasn't reduced and is not worth reducing. */
! 2462:
! 2463: for (tv = v; tv; tv = tv->same)
! 2464: if (loop_dump_stream)
! 2465: fprintf (loop_dump_stream, "giv at %d not reduced\n",
! 2466: INSN_UID (tv->insn));
! 2467:
! 2468: all_reduced = 0;
! 2469: }
! 2470: }
! 2471:
! 2472: /* All the givs in this family have been reduced if they merit it. */
! 2473:
! 2474: /* Try to eliminate the biv, if it is a candidate.
! 2475: This won't work if ! all_reduced,
! 2476: since the givs we planned to use might not have been reduced. */
! 2477:
! 2478: if (all_reduced == 1 && bl->eliminable)
! 2479: {
! 2480: /* Get the REG rtx for the biv. */
! 2481: rtx reg = SET_DEST (PATTERN (bl->biv->insn));
! 2482:
! 2483: for (p = loop_start; p != end; p = NEXT_INSN (p))
! 2484: {
! 2485: enum rtx_code code = GET_CODE (p);
! 2486: if ((code == INSN || code == JUMP_INSN || code == CALL_INSN)
! 2487: && reg_mentioned_p (reg, PATTERN (p))
! 2488: && SET_DEST (PATTERN (p)) == cc0_rtx)
! 2489: /* Found a compare instruction using this biv;
! 2490: rewrite it to use a related giv. */
! 2491: eliminate_biv (p, bl, loop_start);
! 2492: }
! 2493:
! 2494: /* Biv is no longer really needed inside the loop,
! 2495: so delete all insns that set the biv. */
! 2496:
! 2497: for (v = bl->biv; v; v = v->family)
! 2498: delete_insn (v->insn);
! 2499:
! 2500: /* If final_value != 0, then biv may be used after loop end
! 2501: and we must emit an insn to set it just in case. */
! 2502: if (final_value != 0)
! 2503: emit_insn_after (gen_rtx (SET, VOIDmode, reg, final_value),
! 2504: loop_end);
! 2505:
! 2506: if (loop_dump_stream)
! 2507: fprintf (loop_dump_stream, "Reg %d: biv eliminated\n",
! 2508: bl->regno);
! 2509: }
! 2510: }
! 2511:
! 2512: /* Go through all the instructions in the loop, making all the
! 2513: register substitutions scheduled in REG_MAP. */
! 2514:
! 2515: for (p = loop_start; p != end; p = NEXT_INSN (p))
! 2516: if (GET_CODE (p) == INSN || GET_CODE (p) == JUMP_INSN
! 2517: || GET_CODE (p) == CALL_INSN)
! 2518: replace_regs (PATTERN (p), reg_map, nregs);
! 2519: }
! 2520:
! 2521: /* Scan X for memory refs and check each memory address
! 2522: as a possible giv. INSN is the insn whose pattern X comes from.
! 2523: MAYBE_NEVER is 1 if the loop might execute INSN zero times. */
! 2524:
! 2525: static void
! 2526: find_mem_givs (x, insn, maybe_never)
! 2527: rtx x;
! 2528: rtx insn;
! 2529: int maybe_never;
! 2530: {
! 2531: register int i, j;
! 2532: register enum rtx_code code;
! 2533: register char *fmt;
! 2534:
! 2535: if (x == 0)
! 2536: return;
! 2537:
! 2538: code = GET_CODE (x);
! 2539: switch (code)
! 2540: {
! 2541: case REG:
! 2542: case CONST_INT:
! 2543: case CONST:
! 2544: case CONST_DOUBLE:
! 2545: case SYMBOL_REF:
! 2546: case LABEL_REF:
! 2547: case PC:
! 2548: case CC0:
! 2549: case ADDR_VEC:
! 2550: case ADDR_DIFF_VEC:
! 2551: case USE:
! 2552: case CLOBBER:
! 2553: return;
! 2554:
! 2555: case MEM:
! 2556: {
! 2557: int src_regno;
! 2558: rtx add_val;
! 2559: rtx mult_val;
! 2560: int benefit;
! 2561: struct induction *forces = 0;
! 2562: struct induction *forces2 = 0;
! 2563:
! 2564: benefit = general_induction_var (XEXP (x, 0),
! 2565: &src_regno, &add_val, &mult_val,
! 2566: &forces, &forces2);
! 2567: if (benefit > 0)
! 2568: {
! 2569: /* Found one; record it. */
! 2570: struct induction *v =
! 2571: (struct induction *) oballoc (sizeof (struct induction));
! 2572:
! 2573: record_giv (v, insn, src_regno, 0, mult_val, add_val, benefit,
! 2574: forces, forces2, DEST_ADDR, maybe_never, &XEXP (x, 0));
! 2575: }
! 2576: return;
! 2577: }
! 2578: }
! 2579:
! 2580: /* Recursively scan the subexpressions for other mem refs. */
! 2581:
! 2582: fmt = GET_RTX_FORMAT (code);
! 2583: for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
! 2584: if (fmt[i] == 'e')
! 2585: find_mem_givs (XEXP (x, i), insn, maybe_never);
! 2586: else if (fmt[i] == 'E')
! 2587: for (j = 0; j < XVECLEN (x, i); j++)
! 2588: find_mem_givs (XVECEXP (x, i, j), insn, maybe_never);
! 2589: }
! 2590:
! 2591: /* Fill in the data about one giv.
! 2592: V is the `struct induction' in which we record the giv. (It is
! 2593: allocated by the caller, with alloca.)
! 2594: INSN is the insn that sets it.
! 2595: BENEFIT estimates the savings from deleting this insn.
! 2596: TYPE is DEST_REG or DEST_ADDR; it says whether the giv is computed
! 2597: into a register or is used as a memory address.
! 2598:
! 2599: SRC_REGNO is the biv reg number which the giv is computed from.
! 2600: DEST_REGNO is the giv's reg number (if the giv is stored in a reg).
! 2601: MULT_VAL and ADD_VAL are the coefficients used to compute the giv.
! 2602: FORCES and FORCES2, if nonzero, are other `struct induction's for
! 2603: other givs which are used to compute this giv indirectly.
! 2604: LOCATION points to the place where this giv's value appears in INSN. */
! 2605:
! 2606: static void
! 2607: record_giv (v, insn, src_regno, dest_regno, mult_val, add_val, benefit,
! 2608: forces, forces2, type, maybe_never, location)
! 2609: struct induction *v;
! 2610: rtx insn;
! 2611: int src_regno, dest_regno;
! 2612: rtx mult_val, add_val;
! 2613: int benefit;
! 2614: struct induction *forces, *forces2;
! 2615: enum g_types type;
! 2616: int maybe_never;
! 2617: rtx *location;
! 2618: {
! 2619: struct induction *b;
! 2620: struct iv_class *bl;
! 2621:
! 2622: v->insn = insn;
! 2623: v->src_regno = src_regno;
! 2624: v->giv_type = type;
! 2625: v->dest_regno = dest_regno;
! 2626: v->mult_val = mult_val;
! 2627: v->add_val = add_val;
! 2628: v->benefit = benefit;
! 2629: v->location = location;
! 2630:
! 2631: if (type == DEST_ADDR)
! 2632: {
! 2633: v->consec = 0;
! 2634: v->lifetime = 1;
! 2635: v->times_used = 1;
! 2636: }
! 2637: else
! 2638: {
! 2639: v->consec = n_times_set[dest_regno] - 1;
! 2640: v->lifetime = (uid_luid[regno_last_uid[dest_regno]]
! 2641: - uid_luid[regno_first_uid[dest_regno]]);
! 2642: v->times_used = n_times_used[dest_regno];
! 2643: }
! 2644:
! 2645: v->same = 0;
! 2646: v->forces = 0;
! 2647: v->forces2 = 0;
! 2648: v->ignore = 0;
! 2649: v->new_reg = 0;
! 2650:
! 2651: /* Mark giv as forced if it is only used to compute another giv. */
! 2652:
! 2653: /* This check is not sufficient as INSN may have been moved giving
! 2654: it a new uid, so make another check by calculating lifetimes.
! 2655: This is overconservative but seems to be correct. */
! 2656:
! 2657: if (forces)
! 2658: {
! 2659: v->benefit += forces->benefit;
! 2660: if ((regno_last_uid[forces->dest_regno] == INSN_UID (insn)
! 2661: ||
! 2662: ((uid_luid[regno_last_uid[forces->dest_regno]]
! 2663: - uid_luid[regno_first_uid[forces->dest_regno]])
! 2664: == (INSN_UID (insn) - INSN_UID (forces->insn))))
! 2665: && !reg_used_between_p (SET_DEST (PATTERN (forces->insn)),
! 2666: forces->insn, insn))
! 2667: {
! 2668: v->forces = forces;
! 2669: forces->ignore = 1;
! 2670: }
! 2671: }
! 2672:
! 2673: if (forces2)
! 2674: {
! 2675: v->benefit += forces2->benefit;
! 2676: if ((regno_last_uid[forces2->dest_regno] == INSN_UID (insn)
! 2677: ||
! 2678: ((uid_luid[regno_last_uid[forces2->dest_regno]]
! 2679: - uid_luid[regno_first_uid[forces2->dest_regno]])
! 2680: == (INSN_UID (insn) - INSN_UID (forces2->insn))))
! 2681: && !reg_used_between_p (SET_DEST (PATTERN (forces2->insn)),
! 2682: forces2->insn, insn))
! 2683: {
! 2684: if (v->forces)
! 2685: v->forces2 = forces2;
! 2686: else
! 2687: v->forces = forces2;
! 2688: forces2->ignore = 1;
! 2689: }
! 2690: }
! 2691:
! 2692: if (type == DEST_REG)
! 2693: {
! 2694: induct_var[dest_regno] = GENERAL_INDUCT;
! 2695: induct_struct[dest_regno] = v;
! 2696: }
! 2697:
! 2698: /* Add the giv to the class of givs computed from one biv. */
! 2699:
! 2700: bl = class_struct[src_regno];
! 2701: if (bl)
! 2702: {
! 2703: v->family = bl->giv;
! 2704: bl->giv = v;
! 2705: bl->giv_count++;
! 2706: bl->total_benefit += benefit;
! 2707: }
! 2708: else
! 2709: {
! 2710: /* Fatal error, biv missing for this giv? */
! 2711: fflush (loop_dump_stream);
! 2712: abort ();
! 2713: }
! 2714:
! 2715: if (type == DEST_ADDR)
! 2716: v->replaceable = 1;
! 2717: else
! 2718: {
! 2719: /* The giv can be replaced outright by the reduced register if
! 2720: - the insn that sets the giv is always executed,
! 2721: - the giv is not used before the insn that sets it,
! 2722: i.e. no definition outside loop reaches into loop
! 2723: ??? the test used below will fail if the insn has been moved
! 2724: - no assignments to the biv occur during the giv's lifetime. */
! 2725:
! 2726: if (!maybe_never
! 2727: && (regno_first_uid[dest_regno] == INSN_UID (insn)))
! 2728: {
! 2729: v->replaceable = 1;
! 2730: for (b = bl->biv; b; b = b->family)
! 2731: {
! 2732: if ((uid_luid[INSN_UID (b->insn)] >= uid_luid[regno_first_uid[dest_regno]])
! 2733: &&
! 2734: (uid_luid[INSN_UID (b->insn)]
! 2735: <= uid_luid[regno_last_uid[dest_regno]]))
! 2736: {
! 2737: v->replaceable = 0;
! 2738: break;
! 2739: }
! 2740: }
! 2741: }
! 2742: else
! 2743: v->replaceable = 0;
! 2744: }
! 2745:
! 2746: if (loop_dump_stream)
! 2747: {
! 2748: if (type == DEST_REG)
! 2749: fprintf (loop_dump_stream, "Insn %d: giv reg %d",
! 2750: INSN_UID (insn), dest_regno);
! 2751: else
! 2752: fprintf (loop_dump_stream, "Insn %d: dest address",
! 2753: INSN_UID (insn));
! 2754:
! 2755: fprintf (loop_dump_stream, " src reg %d benefit %d",
! 2756: src_regno, v->benefit);
! 2757: fprintf (loop_dump_stream, " used %d lifetime %d",
! 2758: v->times_used, v->lifetime);
! 2759:
! 2760: if (v->replaceable)
! 2761: fprintf (loop_dump_stream, " replaceable");
! 2762:
! 2763: if (GET_CODE (mult_val) == CONST_INT)
! 2764: fprintf (loop_dump_stream, " mult %d",
! 2765: INTVAL (mult_val));
! 2766: else
! 2767: {
! 2768: fprintf (loop_dump_stream, " mult ");
! 2769: print_rtl (loop_dump_stream, mult_val);
! 2770: }
! 2771:
! 2772: if (GET_CODE (add_val) == CONST_INT)
! 2773: fprintf (loop_dump_stream, " add %d",
! 2774: INTVAL (add_val));
! 2775: else
! 2776: {
! 2777: fprintf (loop_dump_stream, " add ");
! 2778: print_rtl (loop_dump_stream, add_val);
! 2779: }
! 2780: }
! 2781:
! 2782: if (loop_dump_stream && v->forces)
! 2783: fprintf (loop_dump_stream, " forces insn %d", INSN_UID (v->forces->insn));
! 2784: if (loop_dump_stream && v->forces2)
! 2785: fprintf (loop_dump_stream, " forces insn %d", INSN_UID (v->forces2->insn));
! 2786: if (loop_dump_stream && v->consec)
! 2787: fprintf (loop_dump_stream, " consec %d", v->consec);
! 2788: if (loop_dump_stream)
! 2789: fprintf (loop_dump_stream, "\n");
! 2790: }
! 2791:
! 2792: /* Delete the insns forced by the insn described by V.
! 2793: If THIS_TOO is nonzero, delete that insn itself as well. */
! 2794:
! 2795: static void
! 2796: delete_insn_forces (v, this_too)
! 2797: struct induction *v;
! 2798: int this_too;
! 2799: {
! 2800: rtx x, p;
! 2801: int count;
! 2802: rtx insn;
! 2803:
! 2804: if (this_too)
! 2805: {
! 2806: insn = v->insn;
! 2807: for (count = v->consec; count >= 0; count--)
! 2808: {
! 2809: /* If first insn of libcall sequence, skip to end. */
! 2810: /* Do this at start of loop, since p is guaranteed to
! 2811: be an insn here. */
! 2812: if (x = find_reg_note (insn, REG_LIBCALL, 0))
! 2813: insn = XEXP (x, 0);
! 2814:
! 2815: if (x = find_reg_note (insn, REG_EQUAL, 0))
! 2816: {
! 2817: /* This is a library call; delete all insns backward until get to
! 2818: first insn in this group. */
! 2819: rtx first = XEXP (find_reg_note (insn, REG_RETVAL, 0), 0);
! 2820: for (p = insn; p != first; p = PREV_INSN (p))
! 2821: delete_insn (p);
! 2822: /* Delete first insn also. */
! 2823: delete_insn (p);
! 2824: }
! 2825: else
! 2826: delete_insn (insn);
! 2827:
! 2828: do insn = NEXT_INSN (insn);
! 2829: while (GET_CODE (insn) == NOTE);
! 2830: }
! 2831: }
! 2832:
! 2833: if (v->forces)
! 2834: delete_insn_forces (v->forces, 1);
! 2835: if (v->forces2)
! 2836: delete_insn_forces (v->forces2, 1);
! 2837: }
! 2838:
! 2839: /* Check whether an insn is an increment legitimate for a basic induction var.
! 2840: X is the source of the insn.
! 2841: DEST_REG is the putative biv, also the destination of the insn.
! 2842: We accept patterns of these forms:
! 2843: REG = REG + INVARIANT
! 2844: REG = INVARIANT + REG
! 2845: REG = REG - CONSTANT
! 2846:
! 2847: If X is suitable, we return 1,
! 2848: and store the factor multiplying REF in X into *MULT_VAL
! 2849: and the additive term into *INC_VAL.
! 2850: Otherwise we return 0. */
! 2851:
! 2852: static int
! 2853: basic_induction_var (x, dest_regno, inc_val, mult_val)
! 2854: register rtx x;
! 2855: int dest_regno;
! 2856: rtx *inc_val;
! 2857: rtx *mult_val;
! 2858: {
! 2859: register RTX_CODE code = GET_CODE (x);
! 2860: rtx arg;
! 2861:
! 2862: switch (code)
! 2863: {
! 2864: case PLUS:
! 2865: if (GET_CODE (XEXP (x, 0)) == REG
! 2866: && REGNO (XEXP (x, 0)) == dest_regno)
! 2867: arg = XEXP (x, 1);
! 2868: else if (GET_CODE (XEXP (x, 1)) == REG
! 2869: && REGNO (XEXP (x, 1)) == dest_regno)
! 2870: arg = XEXP (x, 0);
! 2871: else
! 2872: return 0;
! 2873:
! 2874: if (invariant_p (arg) == 1)
! 2875: *inc_val = arg;
! 2876: else
! 2877: return 0;
! 2878:
! 2879: *mult_val = const1_rtx;
! 2880: return 1;
! 2881:
! 2882: case MINUS:
! 2883: if (GET_CODE (XEXP (x, 0)) == REG
! 2884: && REGNO (XEXP (x, 0)) == dest_regno
! 2885: && GET_CODE (XEXP (x, 1)) == CONST_INT)
! 2886: *inc_val = gen_rtx (CONST_INT, VOIDmode,
! 2887: - INTVAL (XEXP (x, 1)));
! 2888: else
! 2889: return 0;
! 2890: *mult_val = const1_rtx;
! 2891: return 1;
! 2892:
! 2893: /* Can accept constant setting of biv only when inside inner most loop.
! 2894: Otherwise, a biv of an inner loop may be incorrectly recognized
! 2895: as a biv of the outer loop,
! 2896: causing code to be moved INTO the inner loop. */
! 2897: case REG:
! 2898: if (!invariant_p (x))
! 2899: return 0;
! 2900: case CONST_INT:
! 2901: case SYMBOL_REF:
! 2902: case CONST:
! 2903: if (loops_enclosed == 1)
! 2904: {
! 2905: *inc_val = x;
! 2906: *mult_val = const0_rtx;
! 2907: return 1;
! 2908: }
! 2909: else
! 2910: return 0;
! 2911:
! 2912: default:
! 2913: return 0;
! 2914: }
! 2915: }
! 2916:
! 2917: /* A general induction variable (giv) is any quantity that is a linear function
! 2918: of a basic induction variable, i.e. giv = biv * mult_val + add_val.
! 2919: The coefficients can be any loop invariant quantity.
! 2920: A giv need not be computed directly from the biv;
! 2921: it can be computed by way of other givs. */
! 2922:
! 2923: /* Determine whether X computes a giv.
! 2924: If it does, return a nonzero value
! 2925: which is the benefit from eliminating the computation of X;
! 2926: set *SRC_REGNO to the register number of the biv that it is computed from;
! 2927: set *ADD_VAL and *MULT_VAL to the coefficients,
! 2928: such that the value of X is biv * mult + add;
! 2929: set forces (and forces2) to identify any other givs that are used
! 2930: solely to compute this one. */
! 2931:
! 2932: /* This routine recognizes four types of patterns that generate givs:
! 2933: - giv = biv op invariant v = 0, g = 0
! 2934: - giv1 = giv2 op invariant v = 0, g = giv2
! 2935: where giv1 and giv2 are functions of the same biv
! 2936: - giv1 = biv op giv2 v = giv2, g = 0
! 2937: where giv2 is a function of biv
! 2938: - giv1 = giv2 op giv3 v = giv3, g = giv2
! 2939: where giv2 and giv3 are functions of the save biv */
! 2940:
! 2941: static int
! 2942: general_induction_var (x, src_regno, add_val, mult_val, forces, forces2)
! 2943: rtx x;
! 2944: int *src_regno;
! 2945: rtx *add_val;
! 2946: rtx *mult_val;
! 2947: struct induction **forces;
! 2948: struct induction **forces2;
! 2949: {
! 2950: register RTX_CODE code = GET_CODE (x);
! 2951: rtx arg;
! 2952: struct induction *g = 0;
! 2953: struct induction *v = 0;
! 2954: int subexp = 0;
! 2955: int tem;
! 2956:
! 2957: switch (code)
! 2958: {
! 2959: case NEG:
! 2960: /* This can generate givs also, but it is not handled. */
! 2961: return 0;
! 2962:
! 2963: case PLUS:
! 2964: case MINUS:
! 2965: case MULT:
! 2966: case UMULT:
! 2967: /* Result is linear in both operands. */
! 2968: /* Determine which operand is the biv, and put the other in ARG. */
! 2969: if (GET_CODE (XEXP (x, 0)) == REG
! 2970: && induct_var[REGNO (XEXP (x, 0))] == BASIC_INDUCT)
! 2971: {
! 2972: *src_regno = REGNO (XEXP (x, 0));
! 2973: arg = XEXP (x, 1);
! 2974:
! 2975: }
! 2976: else if (GET_CODE (XEXP (x, 1)) == REG
! 2977: && induct_var[REGNO (XEXP (x, 1))] == BASIC_INDUCT)
! 2978: {
! 2979: *src_regno = REGNO (XEXP (x, 1));
! 2980: arg = XEXP (x, 0);
! 2981:
! 2982: }
! 2983: /* Check for an rtl subexpression that is a giv. Memory address
! 2984: givs often look like (plus (reg) (mult (biv) (const))). */
! 2985: /* Do this before checking for a giv operand, as this function will
! 2986: fail if this special operand is not recognized. */
! 2987: #ifndef DONT_REDUCE_ADDR
! 2988: else if (tem = general_induction_var (XEXP (x, 1), src_regno,
! 2989: add_val, mult_val,
! 2990: forces, forces2))
! 2991: {
! 2992: /* Set subexp true so that this can be handled a little
! 2993: differently from the normal case of g set. */
! 2994: /* Note that SRC_REGNO is already set. */
! 2995: subexp = TRUE;
! 2996: g = (struct induction *) alloca (sizeof (struct induction));
! 2997: g->mult_val = *mult_val;
! 2998: g->add_val = *add_val;
! 2999: /* Count this multiply as a shift, since that's what it
! 3000: really will do. */
! 3001: if (tem == MULT_BENEFIT)
! 3002: g->benefit = SHIFT_BENEFIT;
! 3003: else
! 3004: g->benefit = tem;
! 3005: arg = XEXP (x, 0);
! 3006: }
! 3007: #endif
! 3008: /* Also allow general induction variables.
! 3009: Could have a mult followed by an add (i.e. an address calculation),
! 3010: thereby generating two related general induction variables
! 3011: of which only the second is actually used. */
! 3012: /* Do this after checking both args for basic induction variables. */
! 3013: else if (GET_CODE (XEXP (x, 0)) == REG
! 3014: && induct_var[REGNO (XEXP (x, 0))] == GENERAL_INDUCT)
! 3015: {
! 3016: g = induct_struct[REGNO (XEXP (x, 0))];
! 3017: *src_regno = g->src_regno;
! 3018: arg = XEXP (x, 1);
! 3019: }
! 3020: else if (GET_CODE (XEXP (x, 1)) == REG
! 3021: && induct_var[REGNO (XEXP (x, 1))] == GENERAL_INDUCT)
! 3022: {
! 3023: g = induct_struct[REGNO (XEXP (x, 1))];
! 3024: *src_regno = g->src_regno;
! 3025: arg = XEXP (x, 0);
! 3026: }
! 3027: else
! 3028: return 0;
! 3029:
! 3030: /* Overall form of expression looks good. */
! 3031: break;
! 3032:
! 3033: /* Could handle these also. */
! 3034: case DIV:
! 3035: case UDIV:
! 3036: /* For a 68020 could handle these? */
! 3037: case LSHIFT:
! 3038: case ASHIFT:
! 3039: case ASHIFTRT:
! 3040: case LSHIFTRT:
! 3041: /* These operations are linear only in first operand.
! 3042: Check for a biv or giv there; if found, put other operand in ARG. */
! 3043: if (GET_CODE (XEXP (x, 0)) == REG
! 3044: && induct_var[REGNO (XEXP (x, 0))] == BASIC_INDUCT)
! 3045: {
! 3046: *src_regno = REGNO (XEXP (x, 0));
! 3047: arg = XEXP (x, 1);
! 3048: }
! 3049: /* Also allow general induction variable. */
! 3050: else if (GET_CODE (XEXP (x, 0)) == REG
! 3051: && induct_var[REGNO (XEXP (x, 0))] == GENERAL_INDUCT)
! 3052: {
! 3053: g = induct_struct[REGNO (XEXP (x, 0))];
! 3054: *src_regno = g->src_regno;
! 3055: arg = XEXP (x, 1);
! 3056: }
! 3057: else
! 3058: return 0;
! 3059:
! 3060: /* Overall form of expression looks good. */
! 3061: break;
! 3062:
! 3063: default:
! 3064: return 0;
! 3065: }
! 3066:
! 3067: /* ARG is the operand that is NOT a biv or giv.
! 3068: Test it for superficial validity. */
! 3069:
! 3070: /* This is just a special case of invariant values,
! 3071: it is not really needed, but it's a shortcut. */
! 3072: if (GET_CODE (arg) == CONST_INT)
! 3073: ;
! 3074:
! 3075: /* Depends on previous general induction variable, which has
! 3076: the same basic induction variable */
! 3077: /* This code detects mults that have been generated as shift and add. */
! 3078: else if (GET_CODE (arg) == REG
! 3079: && induct_var[REGNO (arg)] == GENERAL_INDUCT
! 3080: && induct_struct[REGNO (arg)]->src_regno == *src_regno)
! 3081: {
! 3082: v = induct_struct[REGNO (arg)];
! 3083: /* Dependence indicated by forces, sort of kludgey. */
! 3084: }
! 3085:
! 3086: /* Invariant expression, could be a constant-valued register. */
! 3087: else if (invariant_p (arg) == 1)
! 3088: ;
! 3089:
! 3090: /* Failure */
! 3091: else
! 3092: return 0;
! 3093:
! 3094: /* Now we know looks like a giv; extract the coefficients.
! 3095: We can still fail if the coefficients are not what we can handle. */
! 3096:
! 3097: /* Only succeed if result mult_val and add_val are only one level of rtl,
! 3098: for example, (NEG:SI (REG:SI 34)) is not accepted.
! 3099: This mainly causes problems with the MINUS code. */
! 3100:
! 3101: switch (code)
! 3102: {
! 3103: case PLUS:
! 3104: if (v && g)
! 3105: {
! 3106: if (GET_CODE (g->mult_val) == CONST_INT)
! 3107: {
! 3108: if (g->mult_val == const0_rtx)
! 3109: *mult_val = v->mult_val;
! 3110: else if (GET_CODE (v->mult_val) == CONST_INT)
! 3111: *mult_val = gen_rtx (CONST_INT, VOIDmode,
! 3112: INTVAL (g->mult_val)
! 3113: + INTVAL (v->mult_val));
! 3114: else
! 3115: return 0;
! 3116: }
! 3117: else if (v->mult_val == const0_rtx)
! 3118: *mult_val = g->mult_val;
! 3119: else
! 3120: return 0;
! 3121:
! 3122: if (GET_CODE (g->add_val) == CONST_INT)
! 3123: {
! 3124: if (g->add_val == const0_rtx)
! 3125: *add_val = v->add_val;
! 3126: else if (GET_CODE (v->add_val) == CONST_INT)
! 3127: *add_val = gen_rtx (CONST_INT, VOIDmode,
! 3128: INTVAL (g->add_val)
! 3129: + INTVAL (v->add_val));
! 3130: else
! 3131: return 0;
! 3132: }
! 3133: else if (v->add_val == const0_rtx)
! 3134: *add_val = g->add_val;
! 3135: else
! 3136: return 0;
! 3137:
! 3138: if (subexp)
! 3139: {
! 3140: /* g deleted when return, can't return pointer to it */
! 3141: if (*forces2 == 0)
! 3142: *forces2 = v;
! 3143: return ADD_BENEFIT + g->benefit;
! 3144: }
! 3145: else
! 3146: {
! 3147: *forces = g;
! 3148: *forces2 = v;
! 3149: return ADD_BENEFIT;
! 3150: }
! 3151: }
! 3152: else if (v)
! 3153: {
! 3154: if (GET_CODE (v->mult_val) == CONST_INT)
! 3155: *mult_val = gen_rtx (CONST_INT, VOIDmode,
! 3156: INTVAL (v->mult_val) + 1);
! 3157: else
! 3158: return 0;
! 3159: *add_val = v->add_val;
! 3160: *forces = v;
! 3161: return ADD_BENEFIT;
! 3162: }
! 3163: else if (g)
! 3164: {
! 3165: *mult_val = g->mult_val;
! 3166: if (GET_CODE (g->add_val) == CONST_INT)
! 3167: {
! 3168: if (g->add_val == const0_rtx)
! 3169: *add_val = arg;
! 3170: else if (GET_CODE (arg) == CONST_INT)
! 3171: *add_val = gen_rtx (CONST_INT, VOIDmode,
! 3172: INTVAL (g->add_val) + INTVAL (arg));
! 3173: else
! 3174: return 0;
! 3175: }
! 3176: else
! 3177: /* Could succeed if arg == 0, but that will never occur. */
! 3178: return 0;
! 3179:
! 3180: if (subexp)
! 3181: /* g deleted when return, can't return pointer to it */
! 3182: return ADD_BENEFIT + g->benefit;
! 3183: else
! 3184: {
! 3185: *forces = g;
! 3186: return ADD_BENEFIT;
! 3187: }
! 3188: }
! 3189: else
! 3190: {
! 3191: *mult_val = const1_rtx;
! 3192: *add_val = arg;
! 3193: return ADD_BENEFIT;
! 3194: }
! 3195:
! 3196: /* Takes a lot of code and will rarely succeed. */
! 3197: case MINUS:
! 3198: if (v && g)
! 3199: {
! 3200: /* G is the first argument of MINUS. */
! 3201:
! 3202: if (GET_CODE (g->mult_val) == CONST_INT)
! 3203: {
! 3204: if (g->mult_val == const0_rtx)
! 3205: #if 0 /* Should not have to fail here */
! 3206: *mult_val = gen_rtx (NEG, SImode, v->mult_val);
! 3207: #endif
! 3208: return 0;
! 3209: else if (GET_CODE (v->mult_val) == CONST_INT)
! 3210: *mult_val = gen_rtx (CONST_INT, VOIDmode,
! 3211: INTVAL (g->mult_val)
! 3212: - INTVAL (v->mult_val));
! 3213: else
! 3214: return 0;
! 3215: }
! 3216: else if (v->mult_val == const0_rtx)
! 3217: *mult_val = g->mult_val;
! 3218: else
! 3219: return 0;
! 3220:
! 3221: if (GET_CODE (g->add_val) == CONST_INT)
! 3222: {
! 3223: if (g->add_val == const0_rtx)
! 3224: #if 0 /* should not have to fail here */
! 3225: *add_val = v->add_val;
! 3226: #endif
! 3227: return 0;
! 3228: else if (GET_CODE (v->add_val) == CONST_INT)
! 3229: *add_val = gen_rtx (CONST_INT, VOIDmode,
! 3230: INTVAL (g->add_val)
! 3231: - INTVAL (v->add_val));
! 3232: else
! 3233: return 0;
! 3234: }
! 3235: else if (v->add_val == const0_rtx)
! 3236: *add_val = g->add_val;
! 3237: else
! 3238: return 0;
! 3239:
! 3240: if (subexp)
! 3241: {
! 3242: /* G deleted when return, can't return pointer to it */
! 3243: if (*forces2 == 0)
! 3244: *forces2 = v;
! 3245: return ADD_BENEFIT + g->benefit;
! 3246: }
! 3247: else
! 3248: {
! 3249: *forces = g;
! 3250: *forces2 = v;
! 3251: return ADD_BENEFIT;
! 3252: }
! 3253: }
! 3254: else if (v)
! 3255: {
! 3256: if (GET_CODE (v->mult_val) != CONST_INT)
! 3257: return 0;
! 3258: if (arg == XEXP (x, 0)) /* giv1 = giv2 - biv */
! 3259: {
! 3260: *mult_val = gen_rtx (CONST_INT, VOIDmode,
! 3261: INTVAL (v->mult_val) - 1);
! 3262: *add_val = v->add_val;
! 3263: }
! 3264: else /* giv1 = biv - giv2 */
! 3265: {
! 3266: *mult_val = gen_rtx (CONST_INT, VOIDmode,
! 3267: 1 - INTVAL (v->mult_val));
! 3268: if (GET_CODE (v->add_val) == CONST_INT)
! 3269: *add_val = gen_rtx (CONST_INT, VOIDmode,
! 3270: - INTVAL (v->add_val));
! 3271: else
! 3272: return 0;
! 3273: }
! 3274: *forces = v;
! 3275: return ADD_BENEFIT;
! 3276: }
! 3277: else if (g)
! 3278: {
! 3279: if (arg == XEXP (x, 1))
! 3280: *mult_val = g->mult_val;
! 3281: else
! 3282: {
! 3283: if (GET_CODE (g->mult_val) == CONST_INT)
! 3284: *mult_val = gen_rtx (CONST_INT, VOIDmode,
! 3285: - INTVAL (g->mult_val));
! 3286: else
! 3287: return 0;
! 3288: }
! 3289: if (GET_CODE (g->add_val) == CONST_INT)
! 3290: {
! 3291: if (g->add_val == const0_rtx)
! 3292: {
! 3293: if (arg == XEXP (x, 1)) /* giv1 = giv2 - arg */
! 3294: {
! 3295: /* Fail unless arg is a constant. */
! 3296: if (GET_CODE (arg) == CONST_INT)
! 3297: *add_val = gen_rtx (CONST_INT, VOIDmode,
! 3298: -INTVAL (arg));
! 3299: else
! 3300: return 0;
! 3301: }
! 3302: else /* giv1 = arg - giv2 */
! 3303: *add_val = arg;
! 3304: }
! 3305: else if (GET_CODE (arg) == CONST_INT)
! 3306: {
! 3307: if (arg == XEXP (x, 1)) /* giv1 = giv2 - arg */
! 3308: *add_val = gen_rtx (CONST_INT, VOIDmode,
! 3309: INTVAL (g->add_val)
! 3310: - INTVAL (arg));
! 3311: else /* giv1 = arg - giv2 */
! 3312: *add_val = gen_rtx (CONST_INT, VOIDmode,
! 3313: INTVAL (arg),
! 3314: - INTVAL (g->add_val));
! 3315: }
! 3316: else
! 3317: return 0;
! 3318: }
! 3319: else
! 3320: /* Could succeed if arg == 0, but that will never occur. */
! 3321: return 0;
! 3322:
! 3323: if (subexp)
! 3324: /* G deleted when return, can't return pointer to it. */
! 3325: return ADD_BENEFIT + g->benefit;
! 3326: else
! 3327: {
! 3328: *forces = g;
! 3329: return ADD_BENEFIT;
! 3330: }
! 3331: }
! 3332: else if (GET_CODE (arg) == CONST_INT)
! 3333: {
! 3334: if (arg == XEXP (x, 1))
! 3335: {
! 3336: *add_val = gen_rtx (CONST_INT, VOIDmode, - INTVAL (arg));
! 3337: *mult_val = const1_rtx;
! 3338: }
! 3339: else
! 3340: {
! 3341: *add_val = arg;
! 3342: *mult_val = gen_rtx (CONST_INT, VOIDmode, -1);
! 3343: }
! 3344: return ADD_BENEFIT;
! 3345: }
! 3346: else
! 3347: return 0;
! 3348:
! 3349: /* UMULT can be handled like MULT since C ignores overflows. */
! 3350: case MULT:
! 3351: case UMULT:
! 3352: if (v && g)
! 3353: {
! 3354: /* Quadratic term, just fail. */
! 3355: return 0;
! 3356: }
! 3357: else if (v)
! 3358: {
! 3359: /* Quadratic term, just fail. */
! 3360: return 0;
! 3361: }
! 3362: else if (g)
! 3363: {
! 3364: /* Takes a lot of code and will rarely succeed. */
! 3365: /* dest = m * arg * b + a * arg */
! 3366: if (GET_CODE (g->mult_val) == CONST_INT)
! 3367: {
! 3368: if (g->mult_val == const0_rtx)
! 3369: *mult_val = const0_rtx;
! 3370: else if (g->mult_val == const1_rtx)
! 3371: *mult_val = arg;
! 3372: else if (GET_CODE (arg) == CONST_INT)
! 3373: *mult_val = gen_rtx (CONST_INT, VOIDmode,
! 3374: INTVAL (g->mult_val) * INTVAL (arg));
! 3375: else
! 3376: return 0;
! 3377: }
! 3378: else
! 3379: /* Could suceed if arg == 1 or 0, but this will never occur. */
! 3380: return 0;
! 3381:
! 3382: if (GET_CODE (g->add_val) == CONST_INT)
! 3383: {
! 3384: if (g->add_val == const0_rtx)
! 3385: *add_val = const0_rtx;
! 3386: else if (g->add_val == const1_rtx)
! 3387: *add_val = arg;
! 3388: else if (GET_CODE (arg) == CONST_INT)
! 3389: *add_val = gen_rtx (CONST_INT, VOIDmode,
! 3390: INTVAL (g->add_val) * INTVAL (arg));
! 3391: else
! 3392: return 0;
! 3393: }
! 3394: else
! 3395: /* Could suceed if arg == 1 or 0, but this will never occur. */
! 3396: return 0;
! 3397:
! 3398: if (subexp)
! 3399: /* G deleted when return, can't return pointer to it. */
! 3400: return MULT_BENEFIT + g->benefit;
! 3401: else
! 3402: {
! 3403: *forces = g;
! 3404: return MULT_BENEFIT;
! 3405: }
! 3406: }
! 3407: else
! 3408: {
! 3409: *mult_val = arg;
! 3410: *add_val = const0_rtx;
! 3411: return MULT_BENEFIT;
! 3412: }
! 3413:
! 3414: /* These are not worth the trouble. */
! 3415: case DIV:
! 3416: case UDIV:
! 3417: return 0;
! 3418:
! 3419: /* Handle these, but only for left shift. */
! 3420: case LSHIFT:
! 3421: case ASHIFT:
! 3422: if (v && g)
! 3423: {
! 3424: /* Quadratic term, just fail. */
! 3425: return 0;
! 3426: }
! 3427: else if (v)
! 3428: {
! 3429: /* Quadratic term, just fail. */
! 3430: return 0;
! 3431: }
! 3432: else if (g)
! 3433: {
! 3434: /* Takes a lot of code and will rarely succeed. */
! 3435: /* dest = ((m * b) << arg) + (a << arg) */
! 3436: if (GET_CODE (g->mult_val) == CONST_INT)
! 3437: {
! 3438: if (g->mult_val == const0_rtx)
! 3439: *mult_val = const0_rtx;
! 3440: else if (GET_CODE (arg) == CONST_INT && INTVAL (arg) >= 0)
! 3441: *mult_val = gen_rtx (CONST_INT, VOIDmode,
! 3442: INTVAL (g->mult_val)
! 3443: * (1 << INTVAL (arg)));
! 3444: else
! 3445: return 0;
! 3446: }
! 3447: else
! 3448: /* Could suceed if arg == 0, but this will never occur. */
! 3449: return 0;
! 3450:
! 3451: if (GET_CODE (g->add_val) == CONST_INT)
! 3452: {
! 3453: if (g->add_val == const0_rtx)
! 3454: *add_val = const0_rtx;
! 3455: else if (GET_CODE (arg) == CONST_INT)
! 3456: *add_val = gen_rtx (CONST_INT, VOIDmode,
! 3457: INTVAL (g->add_val)
! 3458: * (1 << INTVAL (arg)));
! 3459: else
! 3460: return 0;
! 3461: }
! 3462: else
! 3463: /* Could suceed if arg == 0, but this will never occur. */
! 3464: return 0;
! 3465:
! 3466: if (subexp)
! 3467: /* G deleted when return, can't return pointer to it. */
! 3468: return SHIFT_BENEFIT + g->benefit;
! 3469: else
! 3470: {
! 3471: *forces = g;
! 3472: return SHIFT_BENEFIT;
! 3473: }
! 3474: }
! 3475:
! 3476: if (GET_CODE (arg) == CONST_INT && INTVAL (arg) >= 0)
! 3477: *mult_val = gen_rtx (CONST_INT, VOIDmode, 1 << INTVAL (arg));
! 3478: else
! 3479: return 0;
! 3480: *add_val = const0_rtx;
! 3481: return SHIFT_BENEFIT;
! 3482:
! 3483: /* These are not worth the trouble. */
! 3484: case ASHIFTRT:
! 3485: case LSHIFTRT:
! 3486: return 0;
! 3487:
! 3488: /* should never reach here */
! 3489: default:
! 3490: abort ();
! 3491: return 0;
! 3492: }
! 3493: }
! 3494:
! 3495: /* Help detect a giv that is calculated by several consecutive insns;
! 3496: for example,
! 3497: giv = biv * M
! 3498: giv = giv + A
! 3499: The caller has already identified the first insn P as having a giv as dest;
! 3500: we check that all other insns that set the same register follow
! 3501: immediately after P, that they alter nothing else,
! 3502: and that the result of the last is still a giv.
! 3503:
! 3504: The value is 0 if the reg set in P is not really a giv.
! 3505: Otherwise, the value is the amount gained by eliminating
! 3506: all the consecutive insns that compute the value.
! 3507:
! 3508: FIRST_BENEFIT is the amount gained by eliminating the first insn, P.
! 3509: SRC_REGNO is the regno of the biv; DEST_REGNO is that of the giv.
! 3510:
! 3511: The coefficients of the ultimate giv value are stored in
! 3512: *MULT_VAL and *ADD_VAL. */
! 3513:
! 3514: static int
! 3515: consec_sets_giv (first_benefit, p, src_regno, dest_regno,
! 3516: add_val, mult_val)
! 3517: int first_benefit;
! 3518: rtx p;
! 3519: int src_regno;
! 3520: int dest_regno;
! 3521: rtx *add_val;
! 3522: rtx *mult_val;
! 3523: {
! 3524: int count;
! 3525: int benefit = first_benefit;
! 3526: enum rtx_code code;
! 3527: rtx forces, forces2;
! 3528: rtx temp;
! 3529: int tem;
! 3530:
! 3531: /* Initialize info used by general_induction_var. */
! 3532: struct induction *v =
! 3533: (struct induction *) oballoc (sizeof (struct induction));
! 3534: v->src_regno = src_regno;
! 3535: v->mult_val = *mult_val;
! 3536: v->add_val = *add_val;
! 3537:
! 3538: induct_var[dest_regno] = GENERAL_INDUCT;
! 3539: induct_struct[dest_regno] = v;
! 3540:
! 3541: count = n_times_set[dest_regno] - 1;
! 3542:
! 3543: while (count > 0)
! 3544: {
! 3545: p = NEXT_INSN (p);
! 3546: code = GET_CODE (p);
! 3547:
! 3548: /* If libcall, skip to end of call sequence. */
! 3549: if (code == INSN && (temp = find_reg_note (p, REG_LIBCALL, 0)))
! 3550: p = XEXP (temp, 0);
! 3551:
! 3552: if (code == INSN && GET_CODE (PATTERN (p)) == SET
! 3553: && GET_CODE (SET_DEST (PATTERN (p))) == REG
! 3554: && REGNO (SET_DEST (PATTERN (p))) == dest_regno
! 3555: && ((tem = general_induction_var (SET_SRC (PATTERN (p)), &src_regno,
! 3556: add_val, mult_val,
! 3557: &forces, &forces2))
! 3558: /* Giv created by call to library routine. */
! 3559: || ((temp = find_reg_note (p, REG_EQUAL, 0)) &&
! 3560: (tem = general_induction_var (XEXP (temp, 0), &src_regno,
! 3561: add_val, mult_val,
! 3562: &forces, &forces2))))
! 3563: && src_regno == v->src_regno)
! 3564: {
! 3565: count--;
! 3566: benefit += tem;
! 3567: v->mult_val = *mult_val;
! 3568: v->add_val = *add_val;
! 3569: }
! 3570: else if (code != NOTE)
! 3571: {
! 3572: induct_var[dest_regno] = UNKNOWN_INDUCT;
! 3573: return 0;
! 3574: }
! 3575: }
! 3576:
! 3577: return benefit;
! 3578: }
! 3579:
! 3580: /* Generate a SEQUENCE to multiply OP0 and OP1 with result in TARGET.
! 3581: Use expand_mult to "optimally" do the multiply.
! 3582: This also works for machines that do not have multiply insns. */
! 3583:
! 3584: static rtx
! 3585: gen_iv_mult (mode, op0, op1, target)
! 3586: enum machine_mode mode;
! 3587: register rtx op0, op1, target;
! 3588: {
! 3589: extern rtx gen_sequence ();
! 3590: extern rtx start_sequence ();
! 3591: rtx saved, result;
! 3592:
! 3593: saved = start_sequence ();
! 3594:
! 3595: /* UNSIGNEDP arg can be zero since operands/target always same width. */
! 3596: expand_mult (mode, op0, op1, target, 0);
! 3597:
! 3598: result = gen_sequence ();
! 3599: end_sequence (saved);
! 3600:
! 3601: return result;
! 3602: }
! 3603:
! 3604: /* Emit code to initialize an induction variable created by strength
! 3605: reduction. */
! 3606:
! 3607: /* This is necessarily long and messy because cse has already been done,
! 3608: so we have to be careful to generate near optimal code for the sequence
! 3609: reg = b * m;
! 3610: reg += a
! 3611: */
! 3612:
! 3613: static void
! 3614: emit_iv_init_code (b, m, a, reg, loop_start)
! 3615: rtx b; /* initial value of basic induction variable */
! 3616: rtx m; /* multiplicative constant */
! 3617: rtx a; /* additive constant */
! 3618: rtx reg; /* destination register */
! 3619: rtx loop_start;
! 3620: {
! 3621: /* Indicates which of B/M/A are constants. */
! 3622: int status = 0;
! 3623: int const_val;
! 3624: rtx tmp;
! 3625:
! 3626: if (GET_CODE (b) == CONST_INT)
! 3627: status |= 0x1;
! 3628: if (GET_CODE (m) == CONST_INT)
! 3629: status |= 0x2;
! 3630: if (GET_CODE (a) == CONST_INT)
! 3631: status |= 0x4;
! 3632:
! 3633: switch (status)
! 3634: {
! 3635: case 0: /* nothing constant */
! 3636: case 4: /* A constant */
! 3637: emit_insn_before (gen_iv_mult (GET_MODE (reg), b, m, reg), loop_start);
! 3638: /* Don't emit add unless it is necessary. */
! 3639: if (a != const0_rtx)
! 3640: emit_insn_before (gen_rtx (SET, VOIDmode, reg,
! 3641: gen_rtx (PLUS, GET_MODE (reg), reg, a)),
! 3642: loop_start);
! 3643: break;
! 3644:
! 3645: case 1: /* B constant */
! 3646: /* Equivalent to state 2, just need to switch values of B and M
! 3647: and fall through. */
! 3648: case 5: /* B, a constant */
! 3649: /* Equivalent to state 6, just need to switch values of B and M
! 3650: and fall through. */
! 3651: tmp = b;
! 3652: b = m;
! 3653: m = tmp;
! 3654:
! 3655: case 2: /* M constant */
! 3656: case 6: /* M, A constant */
! 3657: const_val = INTVAL (m);
! 3658: if (const_val == 0)
! 3659: /* REG = A */
! 3660: emit_insn_before (gen_rtx (SET, VOIDmode, reg, a),
! 3661: loop_start);
! 3662: else if (const_val == 1)
! 3663: {
! 3664: /* REG = A + B */
! 3665: if (a != const0_rtx)
! 3666: emit_insn_before (gen_rtx (SET, VOIDmode, reg,
! 3667: gen_rtx (PLUS, GET_MODE (reg), b, a)),
! 3668: loop_start);
! 3669: else
! 3670: emit_insn_before (gen_rtx (SET, VOIDmode, reg, b), loop_start);
! 3671: }
! 3672: else if (const_val == -1)
! 3673: {
! 3674: /* REG = A - B */
! 3675: if (a != const0_rtx)
! 3676: emit_insn_before (gen_rtx (SET, VOIDmode, reg,
! 3677: gen_rtx (MINUS, GET_MODE (reg), a, b)),
! 3678: loop_start);
! 3679: else
! 3680: emit_insn_before (gen_rtx (SET, VOIDmode, reg,
! 3681: gen_rtx (NEG, GET_MODE (reg), b)),
! 3682: loop_start);
! 3683: }
! 3684: else
! 3685: {
! 3686: /* Must generate a `multiply' instruction. */
! 3687: emit_insn_before (gen_iv_mult (GET_MODE (reg), b, m, reg),
! 3688: loop_start);
! 3689:
! 3690: if (a != const0_rtx)
! 3691: emit_insn_before (gen_rtx (SET, VOIDmode, reg,
! 3692: gen_rtx (PLUS, GET_MODE (reg), reg, a)),
! 3693: loop_start);
! 3694: }
! 3695: break;
! 3696:
! 3697: case 3: /* B, M constant */
! 3698: const_val = INTVAL (b) * INTVAL (m);
! 3699: if (const_val == 0)
! 3700: emit_insn_before (gen_rtx (SET, VOIDmode, reg, a),
! 3701: loop_start);
! 3702: else
! 3703: emit_insn_before (gen_rtx (SET, VOIDmode, reg,
! 3704: gen_rtx (PLUS, GET_MODE (reg),
! 3705: gen_rtx (CONST_INT, VOIDmode,
! 3706: const_val),
! 3707: a)),
! 3708: loop_start);
! 3709: break;
! 3710:
! 3711: case 7: /* all are constant */
! 3712: emit_insn_before (gen_rtx (SET, VOIDmode, reg,
! 3713: gen_rtx (CONST_INT, VOIDmode,
! 3714: INTVAL (b) * INTVAL (m) + INTVAL (a))),
! 3715: loop_start);
! 3716: break;
! 3717:
! 3718: default:
! 3719: abort ();
! 3720: }
! 3721: }
! 3722:
! 3723: /* Test whethen BIV_ADD * GIV_MULT can be computed without
! 3724: an actual multiply insn. Value is 1 if so. */
! 3725:
! 3726: static int
! 3727: product_cheap_p (biv_add, giv_mult)
! 3728: rtx biv_add;
! 3729: rtx giv_mult;
! 3730: {
! 3731: /* Indicates which of MULT/ADD are constants. */
! 3732: int status = 0;
! 3733: int const_val;
! 3734: rtx tmp;
! 3735:
! 3736: if (GET_CODE (biv_add) == CONST_INT)
! 3737: status |= 0x1;
! 3738: if (GET_CODE (giv_mult) == CONST_INT)
! 3739: status |= 0x2;
! 3740:
! 3741: switch (status)
! 3742: {
! 3743: case 0:
! 3744: /* Neither is constant: would need a multiply insn, so fail. */
! 3745: return 0;
! 3746:
! 3747: case 1:
! 3748: /* BIV_ADD value is constant */
! 3749: /* Equivalent to state 2, just switch values of BIV_ADD and GIV_MULT
! 3750: and fall through. */
! 3751: tmp = biv_add;
! 3752: biv_add = giv_mult;
! 3753: giv_mult = tmp;
! 3754:
! 3755: case 2:
! 3756: /* GIV_MULT value is constant.
! 3757: If it is 1, 0 or -1 then we win. */
! 3758: const_val = INTVAL (giv_mult);
! 3759: if (const_val < -1 || const_val > 1)
! 3760: {
! 3761: tmp = gen_iv_mult (GET_MODE (biv_add), biv_add, giv_mult, 0);
! 3762: /* Don't emit a multiply insn, just fail instead. */
! 3763: if ((GET_CODE (tmp) == SET && GET_CODE (SET_SRC (tmp)) == MULT)
! 3764: /* Also fail if library call (which generates more
! 3765: then two insn) is needed. */
! 3766: || (GET_CODE (tmp) == SEQUENCE && XVECLEN (tmp, 0) > 2))
! 3767: return 0;
! 3768: }
! 3769: return 1;
! 3770:
! 3771: case 3:
! 3772: /* Both BIV_ADD and GIV_MULT are constant;
! 3773: can compute the product at compile time. */
! 3774: return 1;
! 3775:
! 3776: default:
! 3777: abort ();
! 3778: }
! 3779: }
! 3780:
! 3781:
! 3782: /* Emit code to increment the induction variable inside the loop.
! 3783: Try to emit optimal code for the expression
! 3784: REG = REG + BIV_ADD * GIV_MULT. */
! 3785:
! 3786: static void
! 3787: emit_iv_inc (biv_add, giv_mult, reg, insn)
! 3788: rtx biv_add; /* increment value for biv */
! 3789: rtx giv_mult; /* multiply value of giv */
! 3790: rtx reg; /* create insn to set this reg */
! 3791: rtx insn; /* where to insert the new insn */
! 3792: {
! 3793: /* Indicates which of MULT/ADD are constants. */
! 3794: int status = 0;
! 3795: int const_val;
! 3796: rtx tmp, tempreg;
! 3797: enum machine_mode mode = GET_MODE (reg);
! 3798:
! 3799: if (GET_CODE (biv_add) == CONST_INT)
! 3800: status |= 0x1;
! 3801: if (GET_CODE (giv_mult) == CONST_INT)
! 3802: status |= 0x2;
! 3803:
! 3804: switch (status)
! 3805: {
! 3806: case 1:
! 3807: /* BIV_ADD value is constant */
! 3808: /* Equivalent to state 2, just switch values of BIV_ADD and GIV_MULT
! 3809: and fall through. */
! 3810: tmp = biv_add;
! 3811: biv_add = giv_mult;
! 3812: giv_mult = tmp;
! 3813:
! 3814: case 2:
! 3815: /* GIV_MULT value is constant */
! 3816: const_val = INTVAL (giv_mult);
! 3817: if (const_val == 0)
! 3818: /* No code necessary. This should be VERY rare. */
! 3819: break;
! 3820: else if (const_val == 1)
! 3821: {
! 3822: emit_insn_before (gen_rtx (SET, VOIDmode, reg,
! 3823: gen_rtx (PLUS, mode, reg, biv_add)),
! 3824: insn);
! 3825: break;
! 3826: }
! 3827: else if (const_val == -1)
! 3828: {
! 3829: emit_insn_before (gen_rtx (SET, VOIDmode, reg,
! 3830: gen_rtx (MINUS, mode, reg, biv_add)),
! 3831: insn);
! 3832: break;
! 3833: }
! 3834:
! 3835: case 0:
! 3836: /* Variable times variable,
! 3837: or variable times constant (not 0, -1 or 1):
! 3838: emit a real multiply. */
! 3839: tempreg = gen_reg_rtx (mode);
! 3840: tmp = gen_iv_mult (mode, biv_add, giv_mult, tempreg);
! 3841: emit_insn_before (tmp, insn);
! 3842: emit_insn_before (gen_rtx (SET, VOIDmode, reg,
! 3843: gen_rtx (PLUS, mode, reg, tempreg)),
! 3844: insn);
! 3845: break;
! 3846:
! 3847: case 3:
! 3848: /* Both BIV_ADD and GIV_MULT are constant */
! 3849: emit_insn_before (gen_rtx (SET, VOIDmode, reg,
! 3850: gen_rtx (PLUS, mode, reg,
! 3851: gen_rtx (CONST_INT, VOIDmode,
! 3852: INTVAL (biv_add)
! 3853: * INTVAL (giv_mult)))),
! 3854: insn);
! 3855: break;
! 3856:
! 3857: default:
! 3858: abort ();
! 3859: }
! 3860: }
! 3861:
! 3862: /* Check to see if loop can be terminated by a "decrement and branch until
! 3863: zero" instruction. If so, add a REG_NONNEG note to the branch insn if so.
! 3864: Also try reversing an increment loop to a decrement loop
! 3865: to see if the optimization can be performed.
! 3866: Value is nonzero if optimization was performed. */
! 3867:
! 3868: static int
! 3869: check_dbra_loop (loop_end, iv_list, insn_count, loop_start)
! 3870: rtx loop_end;
! 3871: struct iv_class *iv_list;
! 3872: int insn_count;
! 3873: rtx loop_start;
! 3874: {
! 3875: struct iv_class *bl;
! 3876: rtx reg;
! 3877: rtx jump_label;
! 3878: rtx final_value;
! 3879: rtx start_value;
! 3880: enum rtx_code branch_code;
! 3881: rtx new_add_val;
! 3882: rtx tested_before_loop = 0;
! 3883: rtx p;
! 3884:
! 3885: /* See if the loop is contained in `if (X >= 0)' for some reg X.
! 3886: If so, then we know X is initially nonnegative even though
! 3887: we don't know its initial value.
! 3888: Record X in TESTED_BEFORE_LOOP. */
! 3889:
! 3890: for (p = loop_start; p != 0; p = PREV_INSN (p))
! 3891: if (GET_CODE (p) != NOTE)
! 3892: break;
! 3893:
! 3894: /* See if a conditional branch preceeds the loop.
! 3895: There may be no other insns or labels between it and
! 3896: the beginning of the loop. */
! 3897: if (p != 0 && GET_CODE (p) == JUMP_INSN && condjump_p (p)
! 3898: && SET_SRC (PATTERN (p)) != pc_rtx
! 3899: && ((GET_CODE (XEXP (SET_SRC (PATTERN (p)), 0)) == LT
! 3900: && XEXP (SET_SRC (PATTERN (p)), 2) == pc_rtx)
! 3901: ||
! 3902: (GET_CODE (XEXP (SET_SRC (PATTERN (p)), 0)) == GE
! 3903: && XEXP (SET_SRC (PATTERN (p)), 1) == pc_rtx))
! 3904: && next_real_insn (JUMP_LABEL (p)) == next_real_insn (loop_end))
! 3905: {
! 3906: /* Before the branch should be a test or compare.
! 3907: See if we are comparing something against zero. */
! 3908: p = PREV_INSN (p);
! 3909: if (GET_CODE (p) == INSN && GET_CODE (PATTERN (p)) == SET
! 3910: && SET_DEST (PATTERN (p)) == cc0_rtx)
! 3911: {
! 3912: if (GET_CODE (SET_SRC (PATTERN (p))) == REG)
! 3913: tested_before_loop = SET_SRC (PATTERN (p));
! 3914: else if (GET_CODE (SET_SRC (PATTERN (p))) == MINUS
! 3915: && GET_CODE (XEXP (SET_SRC (PATTERN (p)), 1)) == REG
! 3916: && XEXP (SET_SRC (PATTERN (p)), 1) == const0_rtx)
! 3917: tested_before_loop = XEXP (SET_SRC (PATTERN (p)), 0);
! 3918: }
! 3919: }
! 3920:
! 3921: /* If last insn is a conditional branch, and the insn before tests a register
! 3922: value, then try to optimize it. */
! 3923:
! 3924: if (GET_CODE (PREV_INSN (loop_end)) == JUMP_INSN
! 3925: && GET_CODE (PATTERN (PREV_INSN (loop_end))) == SET
! 3926: && GET_CODE (SET_SRC (PATTERN (PREV_INSN (loop_end)))) == IF_THEN_ELSE
! 3927: && GET_CODE (PREV_INSN (PREV_INSN (loop_end))) == INSN
! 3928: && GET_CODE (PATTERN (PREV_INSN (PREV_INSN (loop_end)))) == SET
! 3929: && (GET_CODE (SET_DEST (PATTERN (PREV_INSN (PREV_INSN (loop_end))))) ==
! 3930: CC0))
! 3931: {
! 3932: /* Check all of the bivs to see if the compare uses one of them. */
! 3933:
! 3934: for (bl = iv_list; bl; bl = bl->next)
! 3935: {
! 3936: if (reg_mentioned_p (SET_DEST (PATTERN (bl->biv->insn)),
! 3937: PREV_INSN (PREV_INSN (loop_end))))
! 3938: break;
! 3939: }
! 3940:
! 3941: /* If biv set more than once, then give up.
! 3942: We can't guarantee that it will be zero on the last iteration. */
! 3943: if (bl && bl->biv_count == 1)
! 3944: {
! 3945: /* Look for the case where the basic induction variable is always
! 3946: nonnegative, and equals zero on the last iteration.
! 3947: In this case, add a reg_note REG_NONNEG, which allows the
! 3948: m68k DBRA instruction to be used. */
! 3949:
! 3950: /* the decrement case */
! 3951:
! 3952: if (GET_CODE (bl->biv->add_val) == CONST_INT
! 3953: && INTVAL (bl->biv->add_val) < 0)
! 3954: {
! 3955: /* Initial value must be greater than 0,
! 3956: init_val % -dec_value == 0 to ensure that it equals zero on
! 3957: the last iteration */
! 3958:
! 3959: if (GET_CODE (bl->initial_value) == CONST_INT
! 3960: && INTVAL (bl->initial_value) > 0
! 3961: && (INTVAL (bl->initial_value) %
! 3962: (-INTVAL (bl->biv->add_val))) == 0)
! 3963: {
! 3964: /* register always nonnegative, add REG_NOTE to branch */
! 3965: REG_NOTES (PREV_INSN (loop_end))
! 3966: = gen_rtx (EXPR_LIST, REG_NONNEG, 0,
! 3967: REG_NOTES (PREV_INSN (loop_end)));
! 3968: bl->nonneg = 1;
! 3969:
! 3970: return 1;
! 3971: }
! 3972:
! 3973: /* If the decrement is 1 and the value was tested as >= 0 before
! 3974: the loop, then we can safely optimize. */
! 3975: if (SET_DEST (PATTERN (bl->biv->insn)) == tested_before_loop
! 3976: && INTVAL (bl->biv->add_val) == -1)
! 3977: {
! 3978: REG_NOTES (PREV_INSN (loop_end))
! 3979: = gen_rtx (EXPR_LIST, REG_NONNEG, 0,
! 3980: REG_NOTES (PREV_INSN (loop_end)));
! 3981: bl->nonneg = 1;
! 3982:
! 3983: return 1;
! 3984: }
! 3985: }
! 3986: else
! 3987: {
! 3988: /* Try to change inc to dec, so can apply above optimization. */
! 3989: /* Can do this if:
! 3990: all registers modified are induction variables or invariant,
! 3991: all memory references have non-overlapping addresses
! 3992: (obviously true if only one write)
! 3993: allow 2 insns for the compare/jump at the end of the loop. */
! 3994:
! 3995: /* This code only acts for innermost loops. Also it simplifies
! 3996: the memory address check by only reversing loops with
! 3997: zero or one memory access. */
! 3998:
! 3999: if (num_mem_sets <= 1
! 4000: && !loop_has_call
! 4001: && (bl->giv_count + bl->biv_count + num_mem_sets
! 4002: + num_movables + 2 == insn_count))
! 4003: {
! 4004: rtx src_two_before_end;
! 4005:
! 4006: /* Loop can be reversed. */
! 4007: if (loop_dump_stream)
! 4008: fprintf (loop_dump_stream, "Can reverse loop\n");
! 4009:
! 4010: /* Now check other conditions:
! 4011: initial_value must be zero,
! 4012: final_value % add_val == 0, so that when reversed, the
! 4013: biv will be zero on the last iteration. */
! 4014:
! 4015: /* Calculating the final value non trivial.
! 4016: If branch is (LT (CC0) (CONST 0),
! 4017: then value in compare is final value.
! 4018: If branch is (LE (CC0) (CONST 0),
! 4019: then value in compare is final_value - add_val */
! 4020:
! 4021: branch_code
! 4022: = GET_CODE (XEXP (SET_SRC (PATTERN (PREV_INSN (loop_end))), 0));
! 4023: src_two_before_end
! 4024: = PATTERN (PREV_INSN (PREV_INSN (loop_end)));
! 4025:
! 4026: if (bl->initial_value == const0_rtx
! 4027: && (branch_code == LT || branch_code == LE)
! 4028: && XEXP (XEXP (SET_SRC (PATTERN (PREV_INSN (loop_end))), 0), 1) == const0_rtx
! 4029: && GET_CODE (XEXP (src_two_before_end, 1)) == CONST_INT
! 4030: && (INTVAL (XEXP (src_two_before_end, 1)) % INTVAL (bl->biv->add_val)) == 0)
! 4031: {
! 4032: /* Register will always be nonnegative, with value
! 4033: 0 on last iteration if loop reversed */
! 4034:
! 4035: /* Save some info needed to produce the new insns. */
! 4036: reg = SET_DEST (PATTERN (bl->biv->insn));
! 4037: jump_label = XEXP (SET_SRC (PATTERN (PREV_INSN (loop_end))), 1);
! 4038: new_add_val = gen_rtx (CONST_INT, VOIDmode,
! 4039: - INTVAL (bl->biv->add_val));
! 4040:
! 4041:
! 4042: if (branch_code == LT)
! 4043: {
! 4044: final_value = XEXP (src_two_before_end, 1);
! 4045: start_value
! 4046: = gen_rtx (CONST_INT, VOIDmode,
! 4047: (INTVAL (XEXP (src_two_before_end, 1))
! 4048: - INTVAL (bl->biv->add_val)));
! 4049: }
! 4050: else /* branch_code == LE */
! 4051: {
! 4052: start_value = XEXP (src_two_before_end, 1);
! 4053: final_value
! 4054: = gen_rtx (CONST_INT, VOIDmode,
! 4055: (INTVAL (XEXP (src_two_before_end, 1))
! 4056: + INTVAL (bl->biv->add_val)));
! 4057: }
! 4058:
! 4059: /* Initialize biv to start_value before loop start.
! 4060: The old initializing insn will be deleted as a
! 4061: dead store by flow.c. */
! 4062: emit_insn_before (gen_rtx (SET, VOIDmode, reg,
! 4063: start_value),
! 4064: loop_start);
! 4065:
! 4066: /* Add insn to decrement register, and delete insn
! 4067: that incremented the register. */
! 4068: emit_insn_before (gen_rtx (SET, VOIDmode, reg,
! 4069: gen_rtx (PLUS, GET_MODE (reg), reg,
! 4070: new_add_val)),
! 4071: bl->biv->insn);
! 4072: /* Update biv info to reflect its new status. */
! 4073: bl->biv->insn = PREV_INSN (bl->biv->insn);
! 4074: delete_insn (NEXT_INSN (bl->biv->insn));
! 4075:
! 4076: /* Set LABEL_NUSES to two so that delete_insn will
! 4077: not delete the label. */
! 4078: LABEL_NUSES (XEXP (jump_label, 0)) = 2;
! 4079:
! 4080: if (regno_last_uid[bl->regno] != INSN_UID (PREV_INSN (loop_end)))
! 4081: emit_insn_after (gen_rtx (SET, VOIDmode, reg,
! 4082: final_value),
! 4083: loop_end);
! 4084:
! 4085: /* Delete compare/branch at end of loop. */
! 4086: delete_insn (PREV_INSN (loop_end));
! 4087: delete_insn (PREV_INSN (loop_end));
! 4088:
! 4089: /* Add new compare/branch insn at end of loop. */
! 4090: emit_insn_before (gen_rtx (SET, VOIDmode, cc0_rtx, reg),
! 4091: loop_end);
! 4092: emit_jump_insn_before (gen_rtx (SET, VOIDmode, pc_rtx,
! 4093: gen_rtx (IF_THEN_ELSE, VOIDmode,
! 4094: gen_rtx (GE, VOIDmode, cc0_rtx,
! 4095: const0_rtx),
! 4096: jump_label,
! 4097: pc_rtx)),
! 4098: loop_end);
! 4099:
! 4100: /* Register is now always nonnegative,
! 4101: so add REG_NONNEG note to the branch. */
! 4102: REG_NOTES (PREV_INSN (loop_end))
! 4103: = gen_rtx (EXPR_LIST, REG_NONNEG, 0,
! 4104: REG_NOTES (PREV_INSN (loop_end)));
! 4105: bl->nonneg = 1;
! 4106:
! 4107: /* Update rest of biv info. */
! 4108: bl->initial_value = start_value;
! 4109: bl->biv->add_val = new_add_val;
! 4110:
! 4111: if (loop_dump_stream)
! 4112: fprintf (loop_dump_stream, "Reversed loop and added reg_nonneg\n");
! 4113:
! 4114: return 1;
! 4115: }
! 4116: }
! 4117: }
! 4118: }
! 4119: }
! 4120: return 0;
! 4121: }
! 4122:
! 4123: /* Return 1 if INSN, a compare insn which tests the biv described by BL,
! 4124: can be rewritten to use instead some reduced giv related to that biv.
! 4125: Does not change the rtl.
! 4126:
! 4127: We make the assumption that all the givs depending on this biv
! 4128: will be reduced, since only in that case will an attempt to eliminate
! 4129: the biv actually be made.
! 4130:
! 4131: The following function is very parallel to this one. */
! 4132:
! 4133: static int
! 4134: can_eliminate_biv_p (insn, bl)
! 4135: rtx insn;
! 4136: struct iv_class *bl;
! 4137: {
! 4138: rtx src;
! 4139: enum rtx_code code;
! 4140: struct induction *v, *tv;
! 4141: rtx arg;
! 4142: int arg_operand;
! 4143: /* Mode of this biv. */
! 4144: enum machine_mode mode = GET_MODE (SET_DEST (PATTERN (bl->biv->insn)));
! 4145:
! 4146: if (SET_DEST (PATTERN (insn)) != cc0_rtx)
! 4147: return 0;
! 4148:
! 4149: src = SET_SRC (PATTERN (insn));
! 4150: code = GET_CODE (src);
! 4151:
! 4152: switch (code)
! 4153: {
! 4154: /* a test insn */
! 4155: case REG:
! 4156: /* Can replace with any giv that has (MULT_VAL != 0) and (ADD_VAL == 0)
! 4157: and make sure it was strength reduced by checking for NEW_REG != 0 */
! 4158:
! 4159: for (v = bl->giv; v; v = v->family)
! 4160: if (v->mult_val != const0_rtx && v->add_val == const0_rtx
! 4161: && GET_MODE (SET_DEST (PATTERN (v->insn))) == mode)
! 4162: return 1;
! 4163:
! 4164: /* Look for a giv with (MULT_VAL != 0) and (ADD_VAL != 0);
! 4165: replace test insn with a compare insn (cmp REDUCED_GIV ADD_VAL) */
! 4166:
! 4167: for (v = bl->giv; v; v = v->family)
! 4168: if (v->mult_val != const0_rtx
! 4169: && GET_MODE (SET_DEST (PATTERN (v->insn))) == mode)
! 4170: return 1;
! 4171: return 0;
! 4172:
! 4173: /* a compare insn */
! 4174: case MINUS:
! 4175: /* Figure out which operand is the biv. */
! 4176: if ((GET_CODE (XEXP (src, 0)) == REG)
! 4177: && (REGNO (XEXP (src, 0)) == bl->regno))
! 4178: {
! 4179: arg = XEXP (src, 1);
! 4180: arg_operand = 1;
! 4181: }
! 4182: else
! 4183: {
! 4184: arg = XEXP (src, 0);
! 4185: arg_operand = 0;
! 4186: }
! 4187:
! 4188: if (GET_CODE (arg) == CONST_INT)
! 4189: {
! 4190: /* Can replace with any giv that has constant coefficients. */
! 4191:
! 4192: for (v = bl->giv; v; v = v->family)
! 4193: if (GET_CODE (v->mult_val) == CONST_INT
! 4194: && GET_CODE (v->add_val) == CONST_INT
! 4195: && GET_MODE (SET_DEST (PATTERN (v->insn))) == mode)
! 4196: return 1;
! 4197:
! 4198: /* Look for giv with constant mult_val and nonconst add_val,
! 4199: since we can insert add insn before loop
! 4200: to calculate new compare value. */
! 4201:
! 4202: for (v = bl->giv; v; v = v->family)
! 4203: if (GET_CODE (v->mult_val) == CONST_INT
! 4204: && GET_MODE (SET_DEST (PATTERN (v->insn))) == mode)
! 4205: return 1;
! 4206: }
! 4207: else if (GET_CODE (arg) == REG || GET_CODE (arg) == MEM)
! 4208: {
! 4209: /* Comparing against invariant register or memref can be handled. */
! 4210:
! 4211: if (invariant_p (arg))
! 4212: {
! 4213: /* Look for giv with constant mult_val and nonconst add_val.
! 4214: Insert add-insn before loop to compute new compare value. */
! 4215:
! 4216: for (v = bl->giv; v; v = v->family)
! 4217: if ((GET_CODE (v->mult_val) == CONST_INT)
! 4218: && GET_MODE (SET_DEST (PATTERN (v->insn))) == mode)
! 4219: return 1;
! 4220: }
! 4221:
! 4222: /* Otherwise, only comparing against a biv can be handled. */
! 4223: if (GET_CODE (arg) != REG
! 4224: || induct_var[REGNO (arg)] != BASIC_INDUCT)
! 4225: return 0;
! 4226:
! 4227: /* Look for a giv for each biv that have identical
! 4228: values for mult_val and add_val. */
! 4229: for (v = bl->giv; v; v = v->family)
! 4230: if (GET_MODE (SET_DEST (PATTERN (v->insn))) == mode)
! 4231: {
! 4232: for (tv = class_struct[REGNO (arg)]->giv; tv; tv = tv->family)
! 4233: if ((tv->new_reg != 0)
! 4234: && rtx_equal_p (tv->mult_val, v->mult_val)
! 4235: && rtx_equal_p (tv->mult_val, v->mult_val)
! 4236: && GET_MODE (SET_DEST (PATTERN (tv->insn))) == mode)
! 4237: return 1;
! 4238: }
! 4239: }
! 4240: return 0;
! 4241:
! 4242: default:
! 4243: return 0;
! 4244: }
! 4245: }
! 4246:
! 4247: /* Rewrite a compare insn INSN which uses the biv described by BL
! 4248: so that it doesn't use that biv any more.
! 4249: Instead it will use some reduced giv related to that biv.
! 4250:
! 4251: The preceding function is very parallel to this one. */
! 4252:
! 4253: static void
! 4254: eliminate_biv (insn, bl, loop_start)
! 4255: rtx insn;
! 4256: struct iv_class *bl;
! 4257: rtx loop_start;
! 4258: {
! 4259: rtx src = SET_SRC (PATTERN (insn));
! 4260: enum rtx_code code = GET_CODE (src);
! 4261: struct induction *v, *tv;
! 4262: rtx arg;
! 4263: int arg_operand;
! 4264: /* Mode of this biv. */
! 4265: enum machine_mode mode = GET_MODE (SET_DEST (PATTERN (bl->biv->insn)));
! 4266:
! 4267: switch (code)
! 4268: {
! 4269: /* a test insn */
! 4270: case REG:
! 4271: /* Can replace with any giv
! 4272: that has (MULT_VAL != 0) and (ADD_VAL == 0). */
! 4273:
! 4274: for (v = bl->giv; v; v = v->family)
! 4275: if (v->mult_val != const0_rtx && v->add_val == const0_rtx
! 4276: && v->new_reg != 0
! 4277: && GET_MODE (SET_DEST (PATTERN (v->insn))) == mode)
! 4278: break;
! 4279: if (v)
! 4280: {
! 4281: /* We can test the sign of that giv's reduced reg. */
! 4282: SET_SRC (PATTERN (insn)) = v->new_reg;
! 4283: return;
! 4284: }
! 4285:
! 4286: /* Look for a giv with (MULT_VAL != 0) and (ADD_VAL != 0);
! 4287: replace test insn with a compare insn (cmp REDUCED_GIV ADD_VAL) */
! 4288:
! 4289: for (v = bl->giv; v; v = v->family)
! 4290: if (v->mult_val != const0_rtx && v->new_reg != 0
! 4291: && GET_MODE (SET_DEST (PATTERN (v->insn))) == mode)
! 4292: break;
! 4293: if (v)
! 4294: {
! 4295: /* Replace biv with the giv's reduced register. */
! 4296: SET_SRC (PATTERN (insn)) = gen_rtx (MINUS, GET_MODE (v->new_reg),
! 4297: v->new_reg, v->add_val);
! 4298:
! 4299: #if 0
! 4300: /* add_val must be invariant, so don't bother storing in a register */
! 4301: /* calculate the appropriate constant to compare against */
! 4302: emit_insn_before (gen_rtx (SET, VOIDmode, compare_value,
! 4303: v->add_val),
! 4304: loop_start);
! 4305: #endif
! 4306: return;
! 4307: }
! 4308: abort ();
! 4309: break;
! 4310:
! 4311: /* a compare insn */
! 4312: case MINUS:
! 4313: /* Figure out which operand is the biv. */
! 4314: if ((GET_CODE (XEXP (src, 0)) == REG)
! 4315: && (REGNO (XEXP (src, 0)) == bl->regno))
! 4316: {
! 4317: arg = XEXP (src, 1);
! 4318: arg_operand = 1;
! 4319: }
! 4320: else
! 4321: {
! 4322: arg = XEXP (src, 0);
! 4323: arg_operand = 0;
! 4324: }
! 4325:
! 4326: if (GET_CODE (arg) == CONST_INT)
! 4327: {
! 4328: /* Can replace with any giv that has constant mult_val and add_val.
! 4329: Make sure it was strength reduced by checking new_reg != 0. */
! 4330:
! 4331: for (v = bl->giv; v; v = v->family)
! 4332: if (GET_CODE (v->mult_val) == CONST_INT
! 4333: && GET_CODE (v->add_val) == CONST_INT
! 4334: && v->new_reg
! 4335: && GET_MODE (SET_DEST (PATTERN (v->insn))) == mode)
! 4336: break;
! 4337: if (v)
! 4338: {
! 4339: /* Replace biv with the giv's reduced reg. */
! 4340: XEXP (src, 1-arg_operand) = v->new_reg;
! 4341: /* Calculate the appropriate constant to compare against. */
! 4342: XEXP (src, arg_operand) = gen_rtx (CONST_INT, VOIDmode,
! 4343: (INTVAL (arg) * INTVAL (v->mult_val)
! 4344: + INTVAL (v->add_val)));
! 4345: return;
! 4346: }
! 4347:
! 4348: /* Look for giv with constant mult_val and nonconst add_val.
! 4349: Insert add insn before loop to calculate new compare value. */
! 4350:
! 4351: for (v = bl->giv; v; v = v->family)
! 4352: if (GET_CODE (v->mult_val) == CONST_INT
! 4353: && v->new_reg
! 4354: && GET_MODE (SET_DEST (PATTERN (v->insn))) == mode)
! 4355: break;
! 4356: if (v)
! 4357: {
! 4358: rtx compare_value = gen_reg_rtx (mode);
! 4359:
! 4360: /* Replace biv with giv's reduced register. */
! 4361: XEXP (src, 1-arg_operand) = v->new_reg;
! 4362:
! 4363: /* At start of loop, compute value to compare against. */
! 4364: emit_insn_before (gen_rtx (SET, VOIDmode, compare_value,
! 4365: gen_rtx (PLUS, mode, v->add_val,
! 4366: gen_rtx (CONST_INT, VOIDmode,
! 4367: INTVAL (arg) * INTVAL (v->mult_val)))),
! 4368: loop_start);
! 4369: XEXP (src, arg_operand) = compare_value;
! 4370: return;
! 4371: }
! 4372: abort ();
! 4373: }
! 4374: else if (GET_CODE (arg) == REG || GET_CODE (arg) == MEM)
! 4375: {
! 4376: if (invariant_p (arg))
! 4377: {
! 4378: /* Look for giv with constant mult_val and nonconst add_val.
! 4379: Insert add-insn before loop to compute new compare value. */
! 4380:
! 4381: for (v = bl->giv; v; v = v->family)
! 4382: if (GET_CODE (v->mult_val) == CONST_INT
! 4383: && v->new_reg
! 4384: && GET_MODE (SET_DEST (PATTERN (v->insn))) == mode)
! 4385: break;
! 4386: if (v)
! 4387: {
! 4388: rtx compare_value = gen_reg_rtx (mode);
! 4389:
! 4390: /* Replace biv with giv's reduced register. */
! 4391: XEXP (src, 1-arg_operand) = v->new_reg;
! 4392:
! 4393: /* Calculate the appropriate constant to compare against. */
! 4394: emit_insn_before (gen_iv_mult (mode, v->mult_val, arg,
! 4395: compare_value),
! 4396: loop_start);
! 4397: emit_insn_before (gen_rtx (SET, VOIDmode, compare_value,
! 4398: gen_rtx (PLUS, mode, v->add_val,
! 4399: compare_value)),
! 4400: loop_start);
! 4401: XEXP (src, arg_operand) = compare_value;
! 4402: return;
! 4403: }
! 4404: }
! 4405:
! 4406: /* Otherwise the reg compared with had better be a biv. */
! 4407: if (GET_CODE (arg) != REG
! 4408: || induct_var[REGNO (arg)] != BASIC_INDUCT)
! 4409: abort ();
! 4410:
! 4411: /* Look for a pair of givs, one for each biv,
! 4412: with identical coefficients. */
! 4413: for (v = bl->giv; v; v = v->family)
! 4414: {
! 4415: if (!v->new_reg
! 4416: && GET_MODE (SET_DEST (PATTERN (v->insn))) == mode)
! 4417: continue;
! 4418: for (tv = class_struct[REGNO (arg)]->giv; tv; tv = tv->family)
! 4419: if ((tv->new_reg != 0)
! 4420: && rtx_equal_p (tv->mult_val, v->mult_val)
! 4421: && rtx_equal_p (tv->mult_val, v->mult_val)
! 4422: && GET_MODE (SET_DEST (PATTERN (tv->insn))) == mode)
! 4423: break;
! 4424: if (tv)
! 4425: break;
! 4426: }
! 4427: if (v)
! 4428: {
! 4429: /* Replace biv with its giv's reduced reg. */
! 4430: XEXP (src, 1-arg_operand) = v->new_reg;
! 4431: /* Replace other operand with the other giv's reduced reg. */
! 4432: XEXP (src, arg_operand) = tv->new_reg;
! 4433: return;
! 4434: }
! 4435: }
! 4436: abort ();
! 4437:
! 4438: default:
! 4439: abort ();
! 4440: }
! 4441: }
! 4442:
! 4443: /* Try to calculate the final value of the biv,
! 4444: the value it will have at the end of the loop.
! 4445: If we can do it, return that value. */
! 4446:
! 4447: static rtx
! 4448: final_biv_value (bl, loop_end)
! 4449: struct iv_class *bl;
! 4450: rtx loop_end;
! 4451: {
! 4452: /* wimpy, but guaranteed to work */
! 4453: return 0;
! 4454: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.