|
|
1.1 root 1: /* Move constant computations out of loops.
2: Copyright (C) 1987 Free Software Foundation, Inc.
3:
4: This file is part of GNU CC.
5:
6: GNU CC is distributed in the hope that it will be useful,
7: but WITHOUT ANY WARRANTY. No author or distributor
8: accepts responsibility to anyone for the consequences of using it
9: or for whether it serves any particular purpose or works at all,
10: unless he says so in writing. Refer to the GNU CC General Public
11: License for full details.
12:
13: Everyone is granted permission to copy, modify and redistribute
14: GNU CC, but only under the conditions described in the
15: GNU CC General Public License. A copy of this license is
16: supposed to have been given to you along with GNU CC so you
17: can know your rights and responsibilities. It should be in a
18: file named COPYING. Among other things, the copyright notice
19: and this notice must be preserved on all copies. */
20:
21:
22: /* This is the loop optimization pass of the compiler.
23: It finds invariant computations within loops and moves them
24: to the beginning of the loop.
25:
26: It also finds cases where
27: a register is set within the loop by zero-extending a narrower value
28: and changes these to zero the entire register once before the loop
29: and merely copy the low part within the loop.
30:
31: Most of the complexity is in heuristics to decide when it is worth
32: while to do these things. */
33:
34: /* ??? verify_loop would run faster if we made one table
35: of the minimum and maximum luids from which each label is reached.
36: Also, it would be faster if loop_store_addrs were a hash table. */
37:
38: #include "config.h"
39: #include "rtl.h"
40: #include "insn-config.h"
41: #include "regs.h"
42: #include "recog.h"
43:
44: /* Vector mapping INSN_UIDs to luids.
45: The luids are like uids but increase monononically always.
46: We use them to see whether a jump comes from outside a given loop. */
47:
48: static short *uid_luid;
49:
50: /* Get the luid of an insn. */
51:
52: #define INSN_LUID(INSN) (uid_luid[INSN_UID (INSN)])
53:
54: /* 1 + largest uid of any insn. */
55:
56: static int max_uid;
57:
58: /* 1 + luid of last insn. */
59:
60: static int max_luid;
61:
62: /* Nonzero if somewhere in the current loop
63: there is either a subroutine call,
64: or a store into a memory address that is not fixed,
65: or a store in a BLKmode memory operand,
66: or too many different fixed addresses stored in
67: to record them all in `loop_store_addrs'.
68:
69: In any of these cases, no memory location can be regarded
70: as invariant. */
71:
72: static int unknown_address_altered;
73:
74: /* Nonzero if somewhere in the current loop there is a store
75: into a memory address that is not fixed but is known to be
76: part of an aggregate.
77:
78: In this case, no memory reference in an aggregate may be
79: considered invariant. */
80:
81: static int unknown_aggregate_altered;
82:
83: /* Nonzero if somewhere in the current loop there is a store
84: into a memory address other than a fixed address not in an aggregate.
85:
86: In this case, no memory reference in an aggregate at a varying address
87: may be considered invariant. */
88:
89: static int fixed_aggregate_altered;
90:
91: /* Nonzero if there is a subroutine call in the current loop.
92: (unknown_address_altered is also nonzero in this case.) */
93:
94: static int loop_has_call;
95:
96: /* Array of fixed memory addresses that are stored in this loop.
97: If there are too many to fit here,
98: we just turn on unknown_address_altered. */
99:
100: #define NUM_STORES 10
101: static rtx loop_store_addrs[NUM_STORES];
102: static int loop_store_widths[NUM_STORES];
103:
104: /* Index of first available slot in above array. */
105: static int loop_store_addrs_idx;
106:
107: /* During the analysis of a loop, a chain of `struct movable's
108: is made to record all the movable insns found.
109: Then the entire chain can be scanned to decide which to move. */
110:
111: struct movable
112: {
113: rtx insn; /* A movable insn */
114: int regno; /* The register it sets */
115: short lifetime; /* lifetime of that register;
116: may be adjusted when matching movables
117: that load the same value are found. */
118: unsigned int cond : 1; /* 1 if only conditionally movable */
119: unsigned int force : 1; /* 1 means MUST move this insn */
120: unsigned int global : 1; /* 1 means reg is live outside this loop */
121: unsigned int dont : 1; /* 1 inhibits further processing of this */
122: struct movable *match; /* First entry for same value */
123: struct movable *forces; /* An insn that must be moved if this is */
124: struct movable *next;
125: };
126:
127: static rtx verify_loop ();
128: static int invariant_p ();
129: static int can_jump_into_range_p ();
130: static void count_loop_regs_set ();
131: static void note_addr_stored ();
132: static int loop_reg_used_before_p ();
133: static void constant_high_bytes ();
134: static void scan_loop ();
135: static rtx replace_regs ();
136:
137: /* Entry point of this file. Perform loop optimization
138: on the current function. F is the first insn of the function
139: and NREGS is the number of register numbers used. */
140:
141: int
142: loop_optimize (f, nregs)
143: /* f is the first instruction of a chain of insns for one function */
144: rtx f;
145: /* nregs is the total number of registers used in it */
146: int nregs;
147: {
148: register rtx insn;
149: register int i;
150: rtx end;
151: rtx last_insn;
152:
153: init_recog ();
154:
155: /* First find the last real insn, and count the number of insns,
156: and assign insns their suids. */
157:
158: for (insn = f, i = 0; insn; insn = NEXT_INSN (insn))
159: if (INSN_UID (insn) > i)
160: i = INSN_UID (insn);
161:
162: max_uid = i + 1;
163: uid_luid = (short *) alloca ((i + 1) * sizeof (short));
164: bzero (uid_luid, (i + 1) * sizeof (short));
165:
166: /* Compute the mapping from uids to luids.
167: LUIDs are numbers assigned to insns, like uids,
168: except that luids increase monotonically through the code. */
169:
170: for (insn = f, i = 0; insn; insn = NEXT_INSN (insn))
171: {
172: last_insn = insn;
173: INSN_LUID (insn) = ++i;
174: }
175:
176: max_luid = i;
177:
178: /* Don't leave gaps in uid_luid for insns that have been
179: deleted. It is possible that the first or last insn
180: using some register has been deleted by cross-jumping.
181: Make sure that uid_luid for that former insn's uid
182: points to the general area where that insn used to be. */
183: for (i = 0; i < max_uid; i++)
184: if (uid_luid[i] == 0)
185: uid_luid[i] = uid_luid[i - 1];
186:
187: /* Find and process each loop.
188: We scan from the end, and process each loop when its start is seen,
189: so we process innermost loops first. */
190:
191: for (insn = last_insn; insn; insn = PREV_INSN (insn))
192: if (GET_CODE (insn) == NOTE
193: && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG
194: /* Make sure it really is a loop -- no jumps in from outside. */
195: && (end = verify_loop (f, insn)))
196: scan_loop (insn, end, nregs);
197: }
198:
199: /* Optimize one loop whose start is LOOP_START and end is END.
200: LOOP_START is the NOTE_INSN_LOOP_BEG and END is the matching
201: NOTE_INSN_LOOP_END. */
202:
203: static void
204: scan_loop (loop_start, end, nregs)
205: rtx loop_start, end;
206: int nregs;
207: {
208: register int i;
209: register rtx p = NEXT_INSN (loop_start);
210: /* 1 if we are scanning insns that could be executed zero times. */
211: int maybe_never = 0;
212: /* For a rotated loop that is entered near the bottom,
213: this is the label at the top. Otherwise it is zero. */
214: rtx loop_top = 0;
215: /* Jump insn that enters the loop, or 0 if control drops in. */
216: rtx loop_entry_jump = 0;
217: /* Place in the loop where control enters. */
218: rtx scan_start;
219: /* Number of insns in the loop. */
220: int insn_count;
221: int tem;
222: /* Indexed by register number, contains the number of times the reg
223: is set during the loop being scanned, or -1 if the insns that set it
224: have all been scanned as candidates for being moved out of the loop.
225: 0 indicates an invariant register; -1 a conditionally invariant one. */
226: short *n_times_set;
227: /* Indexed by register number, contains the number of times the reg
228: was set during the loop being scanned, not counting changes due
229: to moving these insns out of the loop. */
230: short *n_times_used;
231: /* Indexed by register number, contains 1 for a register whose
232: assignments may not be moved out of the loop. */
233: char *may_not_move;
234: /* Chain describing insns movable in current loop. */
235: struct movable *movables = 0;
236: /* Last element in `movables' -- so we can add elements at the end. */
237: struct movable *last_movable = 0;
238: /* Ratio of extra register life span we can justify
239: for saving an instruction. More if loop doesn't call subroutines
240: since in that case saving an insn makes more difference
241: and more registers are available. */
242: int threshold = loop_has_call ? 15 : 30;
243:
244: n_times_set = (short *) alloca (nregs * sizeof (short));
245: n_times_used = (short *) alloca (nregs * sizeof (short));
246: may_not_move = (char *) alloca (nregs);
247:
248: /* Determine whether this loop starts with a jump down
249: to a test at the end. */
250: while (p != end
251: && GET_CODE (p) != CODE_LABEL && GET_CODE (p) != JUMP_INSN)
252: p = NEXT_INSN (p);
253:
254: /* "Loop" contains neither jumps nor labels;
255: it must have been a dummy. Think no more about it. */
256: if (p == end)
257: return;
258:
259: /* If loop has a jump before the first label,
260: the true entry is the target of that jump.
261: Start scan from there.
262: But record in LOOP_TOP the place where the end-test jumps
263: back to so we can scan that after the end of the loop. */
264: if (GET_CODE (p) == JUMP_INSN)
265: {
266: loop_entry_jump = p;
267: loop_top = NEXT_INSN (p);
268: /* Loop entry will never be a conditional jump.
269: If we see one, this must not be a real loop. */
270: if (GET_CODE (loop_top) != BARRIER)
271: return;
272: while (GET_CODE (loop_top) != CODE_LABEL)
273: loop_top = NEXT_INSN (loop_top);
274: p = JUMP_LABEL (p);
275: /* Check to see whether the jump actually
276: jumps out of the loop (meaning it's no loop).
277: This case can happen for things like
278: do {..} while (0). */
279: if (INSN_LUID (p) < INSN_LUID (loop_start)
280: || INSN_LUID (p) >= INSN_LUID (end))
281: return;
282: }
283:
284: /* Count number of times each reg is set during this loop.
285: Set MAY_NOT_MOVE[I] if it is not safe to move out
286: the setting of register I. */
287:
288: bzero (n_times_set, nregs * sizeof (short));
289: bzero (may_not_move, nregs);
290: count_loop_regs_set (loop_start, end, n_times_set, may_not_move,
291: &insn_count, nregs);
292: for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
293: may_not_move[i] = 1, n_times_set[i] = 1;
294: bcopy (n_times_set, n_times_used, nregs * sizeof (short));
295:
296: /* Scan through the loop finding insns that are safe to move.
297: In each such insn, store QImode as the mode, to mark it.
298: Then set n_times_set to -1 for the reg being set, so that
299: this reg will be considered invariant for subsequent insns.
300: We consider whether subsequent insns use the reg
301: in deciding whether it is worth actually moving.
302:
303: MAYBE_NEVER is nonzero if we have passed a conditional jump insn
304: and therefore it is possible that the insns we are scanning
305: would never be executed. At such times, we must make sure
306: that it is safe to execute the insn once instead of zero times.
307: When MAYBE_NEVER is 0, all insns will be executed at least once
308: so that is not a problem. */
309:
310: scan_start = p;
311: while (1)
312: {
313: p = NEXT_INSN (p);
314: /* At end of a straight-in loop, we are done.
315: At end of a loop entered at the bottom, scan the top. */
316: if (p == scan_start)
317: break;
318: if (p == end)
319: {
320: if (loop_top != 0)
321: p = NEXT_INSN (loop_top);
322: else
323: break;
324: if (p == scan_start)
325: break;
326: }
327: if (GET_CODE (p) == INSN
328: && GET_CODE (PATTERN (p)) == SET
329: && GET_CODE (SET_DEST (PATTERN (p))) == REG
330: && ! may_not_move[REGNO (SET_DEST (PATTERN (p)))])
331: {
332: /* If this register is used or set outside the loop,
333: then we can move it only if we know this insn is
334: executed exactly once per iteration,
335: and we can check all the insns executed before it
336: to make sure none of them used the value that
337: was lying around at entry to the loop. */
338: if ((uid_luid[regno_last_uid[REGNO (SET_DEST (PATTERN (p)))]] > INSN_LUID (end)
339: || uid_luid[regno_first_uid[REGNO (SET_DEST (PATTERN (p)))]] < INSN_LUID (loop_start))
340: && (maybe_never
341: || loop_reg_used_before_p (p, loop_start, scan_start, end)))
342: ;
343: else if ((tem = invariant_p (SET_SRC (PATTERN (p)), n_times_set))
344: && (n_times_set[REGNO (SET_DEST (PATTERN (p)))] == 1
345: || all_sets_invariant_p (SET_DEST (PATTERN (p)),
346: p, n_times_set)))
347: {
348: register struct movable *m;
349: register int regno = REGNO (SET_DEST (PATTERN (p)));
350: m = (struct movable *) alloca (sizeof (struct movable));
351: m->next = 0;
352: m->insn = p;
353: m->force = 0;
354: m->dont = 0;
355: m->forces = 0;
356: m->regno = regno;
357: m->cond = (tem > 1);
358: m->global = (uid_luid[regno_last_uid[regno]] > INSN_LUID (end)
359: || uid_luid[regno_first_uid[regno]] < INSN_LUID (loop_start));
360: m->match = 0;
361: m->lifetime = (uid_luid[regno_last_uid[regno]]
362: - uid_luid[regno_first_uid[regno]]);
363: n_times_set[regno] = -1;
364: /* Add M to the end of the chain MOVABLES. */
365: if (movables == 0)
366: movables = m;
367: else
368: last_movable->next = m;
369: last_movable = m;
370: }
371: #ifdef SLOW_ZERO_EXTEND
372: /* If this register is set only once, and by zero-extending,
373: that means its high bytes are constant.
374: So clear them outside the loop and within the loop
375: just load the low bytes.
376: We must check that the machine has an instruction to do so.
377: Also, if the value loaded into the register
378: depends on the same register, this cannot be done. */
379:
380: else if (GET_CODE (SET_SRC (PATTERN (p))) == ZERO_EXTEND
381: && !reg_mentioned_p (SET_DEST (PATTERN (p)),
382: SET_SRC (PATTERN (p))))
383: {
384: register int regno = REGNO (SET_DEST (PATTERN (p)));
385: if ((threshold
386: * (uid_luid[regno_last_uid[regno]]
387: - uid_luid[regno_first_uid[regno]]))
388: >= insn_count)
389: constant_high_bytes (p, loop_start);
390: }
391: #endif /* SLOW_ZERO_EXTEND */
392: }
393: /* Past a label or a jump, we get to insns for which we
394: can't count on whether or how many times they will be
395: executed during each iteration. Therefore, we can
396: only move out sets of trivial variables
397: (those not used after the loop). */
398: else if (GET_CODE (p) == CODE_LABEL || GET_CODE (p) == JUMP_INSN)
399: maybe_never = 1;
400: }
401:
402: /* For each movable insn, see if the reg that it loads
403: leads when it dies right into another conditionally movable insn. */
404: {
405: register struct movable *m, *m1;
406: for (m1 = movables; m1; m1 = m1->next)
407: {
408: int regno = m1->regno;
409: for (m = m1->next; m; m = m->next)
410: if (INSN_UID (m->insn) == regno_last_uid[regno])
411: break;
412: if (m != 0 && SET_SRC (PATTERN (m->insn)) == SET_DEST (PATTERN (m1->insn)))
413: m = 0;
414: m1->forces = m;
415: }
416: }
417:
418: /* See if there are multiple movable insns that load the same value.
419: If there are, make all but the first point at the first one
420: through the `match' field, and add the priorities of them
421: all together as the priority of the first. */
422: {
423: register struct movable *m;
424: rtx *reg_map = (rtx *) alloca (nregs * sizeof (rtx));
425: char *matched_regs = (char *) alloca (nregs);
426:
427: bzero (reg_map, nregs * sizeof (rtx));
428:
429: for (m = movables; m; m = m->next)
430: if (m->match == 0 && n_times_used[m->regno] == 1 && !m->global
431: && (! movables->cond
432: || 1 == invariant_p (SET_SRC (PATTERN (movables->insn)), n_times_set)))
433: {
434: register struct movable *m1;
435: int matched = 0;
436: int lifetime = m->lifetime;
437: int times_used = n_times_used[m->regno];
438:
439: if (m->forces != 0) times_used++;
440:
441: bzero (matched_regs, nregs);
442: matched_regs[m->regno] = 1;
443:
444: for (m1 = m->next; m1; m1 = m1->next)
445: {
446: if (m1->match == 0 && n_times_used[m1->regno] == 1
447: && !m1->global
448: /* Perform already-scheduled replacements
449: on M1's insn before comparing them! */
450: && (replace_regs (PATTERN (m1->insn), reg_map),
451: ((GET_CODE (SET_SRC (PATTERN (m1->insn))) == REG
452: && matched_regs[REGNO (SET_SRC (PATTERN (m1->insn)))])
453: || rtx_equal_p (SET_SRC (PATTERN (m->insn)),
454: SET_SRC (PATTERN (m1->insn))))))
455: {
456: lifetime += m1->lifetime;
457: times_used += n_times_used[m1->regno];
458: if (m1->forces != 0) times_used++;
459: m1->match = m;
460: matched_regs[m1->regno] = 1;
461: matched = 1;
462: }
463: }
464:
465: /* If the movable insn M has others that match it
466: and all together they merit being moved,
467: go through the others now and replace their registers
468: with M's register. Mark the others with the `dont' field
469: and do all processing on them now. */
470: if (matched
471: && ((threshold * times_used * lifetime) >= insn_count
472: || m->force
473: || n_times_set[m->regno] == 0))
474: {
475: m->force = 1;
476: m->lifetime = lifetime;
477:
478: for (m1 = m->next; m1; m1 = m1->next)
479: if (m1->match == m)
480: {
481: /* Schedule the reg loaded by M1
482: for replacement so that shares the reg of M. */
483: reg_map[m1->regno] = SET_DEST (PATTERN (m->insn));
484: /* Get rid of the replaced reg
485: and prevent further processing of it. */
486: m1->dont = 1;
487: delete_insn (m1->insn);
488: }
489: }
490: }
491: /* Go through all the instructions in the loop, making
492: all the register substitutions scheduled above. */
493: for (p = loop_start; p != end; p = NEXT_INSN (p))
494: if (GET_CODE (p) == INSN || GET_CODE (p) == JUMP_INSN
495: || GET_CODE (p) == CALL_INSN)
496: replace_regs (PATTERN (p), reg_map);
497: }
498:
499: /* Now consider each movable insn to decide whether it is worth moving. */
500:
501: {
502: register struct movable *m;
503: for (m = movables; m; m = m->next)
504: if (!m->dont
505: && (! m->cond
506: || 1 == invariant_p (SET_SRC (PATTERN (m->insn)), n_times_set)))
507: /* We have an insn that is safe to move. */
508: {
509: register int regno;
510:
511: p = m->insn;
512: regno = m->regno;
513: if (m->forces != 0)
514: n_times_used[regno]++;
515:
516: /* Don't move something out of the loop
517: if that would cause it to be live over a range
518: THRESHOLD times as long. That means the loop is so big
519: that moving won't speed things up much,
520: and it is liable to make register usage worse. */
521: if (m->force
522: || (threshold * n_times_used[regno] * m->lifetime) >= insn_count
523: || n_times_set[regno] == 0)
524: {
525: rtx i1 = emit_insn_before (PATTERN (p), loop_start);
526: if (CONSTANT_ADDRESS_P (SET_SRC (PATTERN (p))))
527: REG_NOTES (i1)
528: = gen_rtx (EXPR_LIST, REG_CONST,
529: SET_DEST (PATTERN (p)), REG_NOTES (i1));
530: delete_insn (p);
531: n_times_set[regno] = 0;
532: /* Signal any other movables that match this one
533: that they should be moved too. */
534: m->force = 1;
535: /* Signal any conditionally movable computation
536: that uses this one that it should be moved too. */
537: if (m->forces != 0)
538: m->forces->force = 1;
539: }
540: }
541: }
542:
543: /* Now maybe duplicate the end-test before the loop. */
544: if (loop_entry_jump != 0)
545: {
546: rtx endtestjump;
547: p = scan_start;
548: while (GET_CODE (p) != INSN && GET_CODE (p) != JUMP_INSN
549: && GET_CODE (p) != CALL_INSN)
550: p = NEXT_INSN (p);
551: endtestjump = next_real_insn (p);
552: /* Check that we (1) enter at a compare insn and (2)
553: the insn (presumably a jump) following that compare
554: is the last in the loop and jumps back to the loop beginning. */
555: if (GET_CODE (PATTERN (p)) == SET
556: && SET_DEST (PATTERN (p)) == cc0_rtx
557: && endtestjump == prev_real_insn (end)
558: && prev_real_insn (JUMP_LABEL (endtestjump)) == loop_entry_jump)
559: {
560: rtx newlab;
561:
562: /* Ok, duplicate that test before loop entry. */
563: emit_insn_before (copy_rtx (PATTERN (p)), loop_entry_jump);
564: /* Make a new entry-jump (before the original)
565: that uses the opposite condition and jumps in
566: after this conitional jump. */
567: newlab = gen_label_rtx ();
568: emit_label_after (newlab, endtestjump);
569: emit_jump_insn_before (copy_rtx (PATTERN (endtestjump)), loop_entry_jump);
570: JUMP_LABEL (PREV_INSN (loop_entry_jump)) = JUMP_LABEL (endtestjump);
571: LABEL_NUSES (JUMP_LABEL (endtestjump))++;
572: invert_jump (PREV_INSN (loop_entry_jump), newlab);
573: /* Delete the original entry-jump. */
574: delete_insn (loop_entry_jump);
575: }
576: }
577: }
578:
579: /* Throughout the rtx X, replace many registers according to REG_MAP.
580: Return the replacement for X (which may be X with altered contents).
581: REG_MAP[R] is the replacement for register R, or 0 for don't replace. */
582:
583: static rtx
584: replace_regs (x, reg_map)
585: rtx x;
586: rtx *reg_map;
587: {
588: register RTX_CODE code = GET_CODE (x);
589: register int i;
590: register char *fmt;
591:
592: switch (code)
593: {
594: case PC:
595: case CC0:
596: case CONST_INT:
597: case CONST_DOUBLE:
598: case CONST:
599: case SYMBOL_REF:
600: case LABEL_REF:
601: return x;
602:
603: case REG:
604: if (reg_map[REGNO (x)] != 0)
605: return reg_map[REGNO (x)];
606: return x;
607: }
608:
609: fmt = GET_RTX_FORMAT (code);
610: for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
611: {
612: if (fmt[i] == 'e')
613: XEXP (x, i) = replace_regs (XEXP (x, i), reg_map);
614: if (fmt[i] == 'E')
615: {
616: register int j;
617: for (j = 0; j < XVECLEN (x, i); j++)
618: XVECEXP (x, i, j) = replace_regs (XVECEXP (x, i, j), reg_map);
619: }
620: }
621: return x;
622: }
623:
624: /* P is an instruction that sets a register to the result of a ZERO_EXTEND.
625: Replace it with an instruction to load just the low bytes
626: if the machine supports such an instruction,
627: and insert above LOOP_START an instruction to clear the register. */
628:
629: static void
630: constant_high_bytes (p, loop_start)
631: rtx p, loop_start;
632: {
633: register rtx new;
634: register int insn_code_number;
635:
636: /* Try to change (SET (REG ...) (ZERO_EXTEND (..:B ...)))
637: to (SET (STRICT_LOW_PART (SUBREG:B (REG...))) ...). */
638:
639: new = gen_rtx (SET, VOIDmode,
640: gen_rtx (STRICT_LOW_PART, VOIDmode,
641: gen_rtx (SUBREG, GET_MODE (XEXP (SET_SRC (PATTERN (p)), 0)),
642: SET_DEST (PATTERN (p)),
643: 0)),
644: XEXP (SET_SRC (PATTERN (p)), 0));
645: insn_code_number = recog (new, p);
646:
647: if (insn_code_number)
648: {
649: register int i;
650:
651: /* Clear destination register before the loop. */
652: emit_insn_before (gen_rtx (SET, VOIDmode,
653: SET_DEST (PATTERN (p)),
654: const0_rtx),
655: loop_start);
656:
657: /* Inside the loop, just load the low part. */
658: PATTERN (p) = new;
659: }
660: }
661:
662: /* Verify that the ostensible loop starting at START
663: really is a loop: nothing jumps into it from outside.
664: Return the marker for the end of the loop, or zero if not a real loop.
665:
666: Also set the variables `unknown_*_altered' and `loop_has_call',
667: and fill in the array `loop_store_addrs'. */
668:
669: static rtx
670: verify_loop (f, start)
671: rtx f, start;
672: {
673: register int level = 1;
674: register rtx insn, end;
675:
676: /* First find the LOOP_END that matches.
677: Also check each insn for storing in memory and record where. */
678:
679: unknown_address_altered = 0;
680: unknown_aggregate_altered = 0;
681: fixed_aggregate_altered = 0;
682: loop_has_call = 0;
683: loop_store_addrs_idx = 0;
684:
685: for (insn = NEXT_INSN (start); level > 0; insn = NEXT_INSN (insn))
686: {
687: if (insn == 0)
688: abort ();
689: if (GET_CODE (insn) == NOTE)
690: {
691: if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
692: ++level;
693: else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END)
694: --level;
695: }
696: else if (GET_CODE (insn) == CALL_INSN)
697: {
698: unknown_address_altered = 1;
699: loop_has_call = 1;
700: }
701: else if (! unknown_address_altered)
702: {
703: if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN)
704: note_stores (PATTERN (insn), note_addr_stored);
705: }
706: }
707:
708: end = insn;
709:
710: /* Now scan all jumps in the function and see if any of them can
711: reach a label within the range of the loop. */
712:
713: for (insn = f; insn; insn = NEXT_INSN (insn))
714: if (GET_CODE (insn) == JUMP_INSN
715: /* Don't get fooled by jumps inserted by loop-optimize.
716: They don't have valid LUIDs, and they never jump into loops. */
717: && INSN_UID (insn) < max_uid
718: && (INSN_LUID (insn) < INSN_LUID (start)
719: || INSN_LUID (insn) > INSN_LUID (end))
720: /* We have a jump that is outside the loop.
721: Does it jump into the loop? */
722: && can_jump_into_range_p (PATTERN (insn),
723: INSN_LUID (start), INSN_LUID (end)))
724: return 0;
725:
726: #if 0
727: /* Now scan all labels between them and check for any jumps from outside.
728: This uses the ref-chains set up by find_basic_blocks.
729: This code is not used because it's more convenient for other reasons
730: to do the loop optimization before find_basic_blocks. */
731:
732: for (insn = start; insn != end; insn = NEXT_INSN (insn))
733: if (GET_CODE (insn) == CODE_LABEL)
734: {
735: register rtx y;
736: for (y = LABEL_REFS (insn); y != insn; y = LABEL_NEXTREF (y))
737: if (INSN_LUID (CONTAINING_INSN (y)) < INSN_LUID (start)
738: || INSN_LUID (CONTAINING_INSN (y)) > INSN_LUID (end))
739: return 0;
740: }
741: #endif
742:
743: return end;
744: }
745:
746: /* Return 1 if somewhere in X is a LABEL_REF to a label
747: located between BEG and END. */
748:
749: static int
750: can_jump_into_range_p (x, beg, end)
751: rtx x;
752: int beg, end;
753: {
754: register RTX_CODE code = GET_CODE (x);
755: register int i;
756: register char *fmt;
757:
758: if (code == LABEL_REF)
759: {
760: register int luid = INSN_LUID (XEXP (x, 0));
761: return luid > beg && luid < end;
762: }
763:
764: fmt = GET_RTX_FORMAT (code);
765: for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
766: {
767: if (fmt[i] == 'e')
768: {
769: if (can_jump_into_range_p (XEXP (x, i), beg, end))
770: return 1;
771: }
772: else if (fmt[i] == 'E')
773: {
774: register int j;
775: for (j = 0; j < XVECLEN (x, i); j++)
776: if (can_jump_into_range_p (XVECEXP (x, i, j), beg, end))
777: return 1;
778: }
779: }
780:
781: return 0;
782: }
783:
784: /* Record that a memory reference X is being set. */
785:
786: static void
787: note_addr_stored (x)
788: rtx x;
789: {
790: rtx addr;
791: if (x == 0 || GET_CODE (x) != MEM)
792: return;
793: if (rtx_addr_varies_p (x))
794: {
795: if (GET_CODE (XEXP (x, 0)) == PLUS)
796: unknown_aggregate_altered = 1;
797: else
798: unknown_address_altered = 1;
799: }
800: else if (GET_MODE (x) == BLKmode)
801: unknown_address_altered = 1;
802: else
803: {
804: register int i;
805: register rtx addr = XEXP (x, 0);
806:
807: if (x->in_struct)
808: fixed_aggregate_altered = 1;
809: for (i = 0; i < loop_store_addrs_idx; i++)
810: if (rtx_equal_p (loop_store_addrs[i], addr))
811: {
812: if (loop_store_widths[i] < GET_MODE_SIZE (GET_MODE (x)))
813: loop_store_widths[i] = GET_MODE_SIZE (GET_MODE (x));
814: break;
815: }
816: if (i == NUM_STORES)
817: unknown_address_altered = 1;
818: else if (i == loop_store_addrs_idx)
819: {
820: loop_store_widths[i] == GET_MODE_SIZE (GET_MODE (x));
821: loop_store_addrs[loop_store_addrs_idx++] = addr;
822: }
823: }
824: }
825:
826: /* Return nonzero if the rtx X is invariant over the current loop.
827: N_TIMES_SET is a vector whose element I is nonzero if register I
828: is set during the loop.
829:
830: The value is 2 if we refer to something only conditionally invariant.
831:
832: If `unknown_address_altered' is nonzero, no memory ref is invariant.
833: Otherwise if `unknown_aggregate_altered' is nonzero,
834: a memory ref is invariant if it is not part of an aggregate
835: and its address is fixed and not in `loop_store_addrs'.
836: Otherwise if `fixed_aggregate_altered' is nonzero,
837: a memory ref is invariant
838: if its address is fixed and not in `loop_store_addrs'.
839: Otherwise, a memory ref is invariant if its address is fixed and not in
840: `loop_store_addrs' or if it is not an aggregate. */
841:
842: static int
843: invariant_p (x, n_times_set)
844: register rtx x;
845: short *n_times_set;
846: {
847: register int i;
848: register RTX_CODE code = GET_CODE (x);
849: register char *fmt;
850: int conditional = 0;
851:
852: switch (code)
853: {
854: case CONST_INT:
855: case CONST_DOUBLE:
856: case SYMBOL_REF:
857: case LABEL_REF:
858: case CONST:
859: case UNCHANGING:
860: return 1;
861:
862: case PC:
863: case VOLATILE:
864: case CC0:
865: return 0;
866:
867: case REG:
868: if (n_times_set[REGNO (x)] == -1)
869: return 2;
870: return n_times_set[REGNO (x)] == 0;
871:
872: case MEM:
873: /* A store in a varying-address scalar (or a subroutine call)
874: could clobber anything in memory. */
875: if (unknown_address_altered)
876: return 0;
877: /* A store in a varying-address aggregate component
878: could clobber anything except a scalar with a fixed address. */
879: if (unknown_aggregate_altered
880: && ((x->in_struct || GET_CODE (XEXP (x, 0)) == PLUS)
881: || rtx_addr_varies_p (x)))
882: return 0;
883: /* A store in a fixed-address aggregate component
884: could clobber anything whose address is not fixed,
885: even an aggregate component. */
886: if (fixed_aggregate_altered
887: && rtx_addr_varies_p (x))
888: return 0;
889: /* Any store could clobber a varying-address scalar. */
890: if (loop_store_addrs_idx
891: && !(x->in_struct || GET_CODE (XEXP (x, 0)) == PLUS)
892: && rtx_addr_varies_p (x))
893: return 0;
894: /* A store in a fixed address clobbers overlapping references. */
895: for (i = loop_store_addrs_idx - 1; i >= 0; i--)
896: if (addr_overlap_p (XEXP (x, 0), loop_store_addrs[i],
897: loop_store_widths[i]))
898: return 0;
899: /* It's not invalidated by a store in memory
900: but we must still verify the address is invariant. */
901: }
902:
903: fmt = GET_RTX_FORMAT (code);
904: for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
905: {
906: if (fmt[i] == 'E')
907: abort ();
908: if (fmt[i] == 'e')
909: {
910: int tem = invariant_p (XEXP (x, i), n_times_set);
911: if (tem == 0)
912: return 0;
913: if (tem == 2)
914: conditional = 1;
915: }
916: }
917:
918: return 1 + conditional;
919: }
920:
921: /* Return 1 if OTHER (a mem ref) overlaps the area of memory
922: which is SIZE bytes starting at BASE. */
923:
924: int
925: addr_overlap_p (other, base, size)
926: rtx other;
927: rtx base;
928: int size;
929: {
930: int start = 0, end;
931:
932: if (GET_CODE (base) == CONST)
933: base = XEXP (base, 0);
934: if (GET_CODE (base) == PLUS
935: && GET_CODE (XEXP (base, 1)) == CONST_INT)
936: {
937: start = INTVAL (XEXP (base, 1));
938: base = XEXP (base, 0);
939: }
940:
941: end = start + size;
942: return refers_to_mem_p (other, base, start, end);
943: }
944:
945: /* Return 1 if all insns in the basic block of INSN and following INSN
946: that set REG are invariant according to TABLE. */
947:
948: static int
949: all_sets_invariant_p (reg, insn, table)
950: rtx reg, insn;
951: char *table;
952: {
953: register rtx p = insn;
954: register int regno = REGNO (reg);
955:
956: while (1)
957: {
958: register enum rtx_code code;
959: p = NEXT_INSN (p);
960: code = GET_CODE (p);
961: if (code == CODE_LABEL || code == JUMP_INSN)
962: return 1;
963: if (code == INSN && GET_CODE (PATTERN (p)) == SET
964: && GET_CODE (SET_DEST (PATTERN (p))) == REG
965: && REGNO (SET_DEST (PATTERN (p))) == regno)
966: {
967: if (!invariant_p (SET_SRC (PATTERN (p)), table))
968: return 0;
969: }
970: }
971: }
972:
973: /* Increment N_TIMES_SET at the index of each register
974: that is modified by an insn between FROM and TO.
975: If the value of an element of N_TIMES_SET becomes 2 or more,
976: do not keep incrementing it; all values >= 2 would be
977: equivalent anyway, and this way we avoid danger of overflow.
978:
979: Store in *COUNT_PTR the number of actual instruction
980: in the loop. We use this to decide what is worth moving out. */
981:
982: /* last_set[n] is nonzero iff reg n has been set in the current basic block.
983: In that case, it is the insn that last set reg n. */
984:
985: static void
986: count_loop_regs_set (from, to, n_times_set, may_not_move, count_ptr, nregs)
987: register rtx from, to;
988: short *n_times_set;
989: char *may_not_move;
990: int *count_ptr;
991: int nregs;
992: {
993: register rtx *last_set = (rtx *) alloca (nregs * sizeof (rtx));
994: register rtx insn;
995: register int count = 0;
996: register rtx dest;
997:
998: bzero (last_set, nregs * sizeof (rtx));
999: for (insn = from; insn != to; insn = NEXT_INSN (insn))
1000: {
1001: if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN
1002: || GET_CODE (insn) == CALL_INSN)
1003: {
1004: ++count;
1005: if (GET_CODE (PATTERN (insn)) == SET)
1006: {
1007: dest = SET_DEST (PATTERN (insn));
1008: while (GET_CODE (dest) == SUBREG
1009: || GET_CODE (dest) == ZERO_EXTRACT
1010: || GET_CODE (dest) == SIGN_EXTRACT
1011: || GET_CODE (dest) == STRICT_LOW_PART)
1012: dest = XEXP (dest, 0);
1013: if (GET_CODE (dest) == REG)
1014: {
1015: register int regno = REGNO (dest);
1016: /* If this is the first setting of this reg
1017: in current basic block, and it was set before,
1018: it must be set in two basic blocks, so it cannot
1019: be moved out of the loop. */
1020: if (n_times_set[regno] > 0 && last_set[regno] == 0)
1021: may_not_move[regno] = 1;
1022: /* If this is not first setting in current basic block,
1023: see if reg was used in between previous one and this.
1024: If so, neither one can be moved. */
1025: if (last_set[regno] != 0
1026: && reg_used_between_p (dest, last_set[regno], insn))
1027: may_not_move[regno] = 1;
1028: ++n_times_set[regno];
1029: last_set[regno] = insn;
1030: }
1031: }
1032: else if (GET_CODE (PATTERN (insn)) == PARALLEL)
1033: {
1034: register int i;
1035: for (i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--)
1036: {
1037: register rtx x = XVECEXP (PATTERN (insn), 0, i);
1038: if (GET_CODE (x) == SET)
1039: {
1040: dest = SET_DEST (x);
1041: while (GET_CODE (dest) == SUBREG
1042: || GET_CODE (dest) == ZERO_EXTRACT
1043: || GET_CODE (dest) == SIGN_EXTRACT
1044: || GET_CODE (dest) == STRICT_LOW_PART)
1045: dest = XEXP (dest, 0);
1046: if (GET_CODE (dest) == REG)
1047: {
1048: register int regno = REGNO (dest);
1049: ++n_times_set[regno];
1050: may_not_move[regno] = 1;
1051: last_set[regno] = insn;
1052: }
1053: }
1054: }
1055: }
1056: /* If a register is used as a subroutine address,
1057: don't allow this register's setting to be moved out of the loop.
1058: This condition is not at all logically correct
1059: but it averts a very common lossage pattern
1060: and creates lossage much less often. */
1061: else if (GET_CODE (PATTERN (insn)) == CALL
1062: && GET_CODE (XEXP (PATTERN (insn), 0)) == MEM
1063: && GET_CODE (XEXP (XEXP (PATTERN (insn), 0), 0)) == REG)
1064: {
1065: register int regno
1066: = REGNO (XEXP (XEXP (PATTERN (insn), 0), 0));
1067: may_not_move[regno] = 1;
1068: }
1069: }
1070: if (GET_CODE (insn) == CODE_LABEL || GET_CODE (insn) == JUMP_INSN)
1071: bzero (last_set, nregs * sizeof (rtx));
1072: }
1073: *count_ptr = count;
1074: }
1075:
1076: /* Given a loop that is bounded by LOOP_START and LOOP_END
1077: and that is entered at SCAN_START,
1078: return 1 if the register set by insn INSN is used by
1079: any insn that precedes INSN in cyclic order starting
1080: from the loop entry point. */
1081:
1082: static int
1083: loop_reg_used_before_p (insn, loop_start, scan_start, loop_end)
1084: rtx insn, loop_start, scan_start, loop_end;
1085: {
1086: rtx reg = SET_DEST (PATTERN (insn));
1087: if (INSN_LUID (scan_start) > INSN_LUID (insn))
1088: return (reg_used_between_p (reg, scan_start, loop_end)
1089: || reg_used_between_p (reg, loop_start, insn));
1090: else
1091: return reg_used_between_p (reg, scan_start, insn);
1092: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.