|
|
1.1 root 1: /* Perform instruction reorganizations for delay slot filling.
2: Copyright (C) 1992 Free Software Foundation, Inc.
3: Contributed by Richard Kenner ([email protected]).
4: Hacked by Michael Tiemann ([email protected]).
5:
6: This file is part of GNU CC.
7:
8: GNU CC is free software; you can redistribute it and/or modify
9: it under the terms of the GNU General Public License as published by
10: the Free Software Foundation; either version 2, or (at your option)
11: any later version.
12:
13: GNU CC is distributed in the hope that it will be useful,
14: but WITHOUT ANY WARRANTY; without even the implied warranty of
15: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16: GNU General Public License for more details.
17:
18: You should have received a copy of the GNU General Public License
19: along with GNU CC; see the file COPYING. If not, write to
20: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
21:
22: /* Instruction reorganization pass.
23:
24: This pass runs after register allocation and final jump
25: optimization. It should be the last pass to run before peephole.
26: It serves primarily to fill delay slots of insns, typically branch
27: and call insns. Other insns typically involve more complicated
1.1.1.3 root 28: interactions of data dependencies and resource constraints, and
1.1 root 29: are better handled by scheduling before register allocation (by the
30: function `schedule_insns').
31:
32: The Branch Penalty is the number of extra cycles that are needed to
33: execute a branch insn. On an ideal machine, branches take a single
34: cycle, and the Branch Penalty is 0. Several RISC machines approach
35: branch delays differently:
36:
37: The MIPS and AMD 29000 have a single branch delay slot. Most insns
38: (except other branches) can be used to fill this slot. When the
39: slot is filled, two insns execute in two cycles, reducing the
40: branch penalty to zero.
41:
42: The Motorola 88000 conditionally exposes its branch delay slot,
43: so code is shorter when it is turned off, but will run faster
44: when useful insns are scheduled there.
45:
46: The IBM ROMP has two forms of branch and call insns, both with and
47: without a delay slot. Much like the 88k, insns not using the delay
48: slot can be shorted (2 bytes vs. 4 bytes), but will run slowed.
49:
50: The SPARC always has a branch delay slot, but its effects can be
51: annulled when the branch is not taken. This means that failing to
52: find other sources of insns, we can hoist an insn from the branch
53: target that would only be safe to execute knowing that the branch
54: is taken.
55:
56: Three techniques for filling delay slots have been implemented so far:
57:
58: (1) `fill_simple_delay_slots' is the simplest, most efficient way
59: to fill delay slots. This pass first looks for insns which come
60: from before the branch and which are safe to execute after the
61: branch. Then it searches after the insn requiring delay slots or,
62: in the case of a branch, for insns that are after the point at
63: which the branch merges into the fallthrough code, if such a point
64: exists. When such insns are found, the branch penalty decreases
65: and no code expansion takes place.
66:
67: (2) `fill_eager_delay_slots' is more complicated: it is used for
68: scheduling conditional jumps, or for scheduling jumps which cannot
69: be filled using (1). A machine need not have annulled jumps to use
70: this strategy, but it helps (by keeping more options open).
71: `fill_eager_delay_slots' tries to guess the direction the branch
72: will go; if it guesses right 100% of the time, it can reduce the
1.1.1.4 ! root 73: branch penalty as much as `fill_simple_delay_slots' does. If it
1.1 root 74: guesses wrong 100% of the time, it might as well schedule nops (or
75: on the m88k, unexpose the branch slot). When
76: `fill_eager_delay_slots' takes insns from the fall-through path of
77: the jump, usually there is no code expansion; when it takes insns
78: from the branch target, there is code expansion if it is not the
79: only way to reach that target.
80:
81: (3) `relax_delay_slots' uses a set of rules to simplify code that
82: has been reorganized by (1) and (2). It finds cases where
83: conditional test can be eliminated, jumps can be threaded, extra
84: insns can be eliminated, etc. It is the job of (1) and (2) to do a
85: good job of scheduling locally; `relax_delay_slots' takes care of
86: making the various individual schedules work well together. It is
87: especially tuned to handle the control flow interactions of branch
88: insns. It does nothing for insns with delay slots that do not
89: branch.
90:
91: On machines that use CC0, we are very conservative. We will not make
92: a copy of an insn involving CC0 since we want to maintain a 1-1
1.1.1.2 root 93: correspondence between the insn that sets and uses CC0. The insns are
1.1 root 94: allowed to be separated by placing an insn that sets CC0 (but not an insn
95: that uses CC0; we could do this, but it doesn't seem worthwhile) in a
96: delay slot. In that case, we point each insn at the other with REG_CC_USER
97: and REG_CC_SETTER notes. Note that these restrictions affect very few
98: machines because most RISC machines with delay slots will not use CC0
99: (the RT is the only known exception at this point).
100:
101: Not yet implemented:
102:
103: The Acorn Risc Machine can conditionally execute most insns, so
104: it is profitable to move single insns into a position to execute
105: based on the condition code of the previous insn.
106:
107: The HP-PA can conditionally nullify insns, providing a similar
108: effect to the ARM, differing mostly in which insn is "in charge". */
109:
110: #include <stdio.h>
111: #include "config.h"
112: #include "rtl.h"
113: #include "insn-config.h"
114: #include "conditions.h"
115: #include "hard-reg-set.h"
116: #include "basic-block.h"
117: #include "regs.h"
118: #include "insn-flags.h"
119: #include "recog.h"
120: #include "flags.h"
121: #include "output.h"
122: #include "obstack.h"
1.1.1.4 ! root 123: #include "insn-attr.h"
! 124:
! 125: #ifdef DELAY_SLOTS
1.1 root 126:
127: #define obstack_chunk_alloc xmalloc
128: #define obstack_chunk_free free
129:
130: #ifndef ANNUL_IFTRUE_SLOTS
131: #define eligible_for_annul_true(INSN, SLOTS, TRIAL) 0
132: #endif
133: #ifndef ANNUL_IFFALSE_SLOTS
134: #define eligible_for_annul_false(INSN, SLOTS, TRIAL) 0
135: #endif
136:
137: /* Insns which have delay slots that have not yet been filled. */
138:
139: static struct obstack unfilled_slots_obstack;
140: static rtx *unfilled_firstobj;
141:
142: /* Define macros to refer to the first and last slot containing unfilled
143: insns. These are used because the list may move and its address
144: should be recomputed at each use. */
145:
146: #define unfilled_slots_base \
147: ((rtx *) obstack_base (&unfilled_slots_obstack))
148:
149: #define unfilled_slots_next \
150: ((rtx *) obstack_next_free (&unfilled_slots_obstack))
151:
152: /* This structure is used to indicate which hardware resources are set or
153: needed by insns so far. */
154:
155: struct resources
156: {
157: char memory; /* Insn sets or needs a memory location. */
158: char volatil; /* Insn sets or needs a volatile memory loc. */
159: char cc; /* Insn sets or needs the condition codes. */
160: HARD_REG_SET regs; /* Which registers are set or needed. */
161: };
162:
163: /* Macro to clear all resources. */
164: #define CLEAR_RESOURCE(RES) \
165: do { (RES)->memory = (RES)->volatil = (RES)->cc = 0; \
166: CLEAR_HARD_REG_SET ((RES)->regs); } while (0)
167:
1.1.1.4 ! root 168: /* Indicates what resources are required at the beginning of the epilogue. */
! 169: static struct resources start_of_epilogue_needs;
! 170:
1.1 root 171: /* Indicates what resources are required at function end. */
172: static struct resources end_of_function_needs;
173:
174: /* Points to the label before the end of the function. */
175: static rtx end_of_function_label;
176:
1.1.1.3 root 177: /* This structure is used to record liveness information at the targets or
1.1 root 178: fallthrough insns of branches. We will most likely need the information
179: at targets again, so save them in a hash table rather than recomputing them
180: each time. */
181:
182: struct target_info
183: {
184: int uid; /* INSN_UID of target. */
185: struct target_info *next; /* Next info for same hash bucket. */
186: HARD_REG_SET live_regs; /* Registers live at target. */
187: int block; /* Basic block number containing target. */
188: int bb_tick; /* Generation count of basic block info. */
189: };
190:
191: #define TARGET_HASH_PRIME 257
192:
193: /* Define the hash table itself. */
194: static struct target_info **target_hash_table;
195:
196: /* For each basic block, we maintain a generation number of its basic
197: block info, which is updated each time we move an insn from the
198: target of a jump. This is the generation number indexed by block
199: number. */
200:
201: static int *bb_ticks;
202:
203: /* Mapping between INSN_UID's and position in the code since INSN_UID's do
204: not always monotonically increase. */
205: static int *uid_to_ruid;
206:
207: /* Highest valid index in `uid_to_ruid'. */
208: static int max_uid;
209:
210: /* Forward references: */
211:
212: static int redundant_insn_p ();
213: static void update_block ();
214:
215: /* Given X, some rtl, and RES, a pointer to a `struct resource', mark
216: which resources are references by the insn. If INCLUDE_CALLED_ROUTINE
217: is TRUE, resources used by the called routine will be included for
218: CALL_INSNs. */
219:
220: static void
221: mark_referenced_resources (x, res, include_called_routine)
222: register rtx x;
223: register struct resources *res;
224: register int include_called_routine;
225: {
226: register enum rtx_code code = GET_CODE (x);
227: register int i, j;
228: register char *format_ptr;
229:
230: /* Handle leaf items for which we set resource flags. Also, special-case
231: CALL, SET and CLOBBER operators. */
232: switch (code)
233: {
234: case CONST:
235: case CONST_INT:
236: case CONST_DOUBLE:
237: case PC:
238: case SYMBOL_REF:
239: case LABEL_REF:
240: return;
241:
242: case SUBREG:
243: if (GET_CODE (SUBREG_REG (x)) != REG)
244: mark_referenced_resources (SUBREG_REG (x), res, 0);
245: else
246: {
247: int regno = REGNO (SUBREG_REG (x)) + SUBREG_WORD (x);
248: int last_regno = regno + HARD_REGNO_NREGS (regno, GET_MODE (x));
249: for (i = regno; i < last_regno; i++)
250: SET_HARD_REG_BIT (res->regs, i);
251: }
252: return;
253:
254: case REG:
255: for (i = 0; i < HARD_REGNO_NREGS (REGNO (x), GET_MODE (x)); i++)
256: SET_HARD_REG_BIT (res->regs, REGNO (x) + i);
257: return;
258:
259: case MEM:
260: /* If this memory shouldn't change, it really isn't referencing
261: memory. */
262: if (! RTX_UNCHANGING_P (x))
263: res->memory = 1;
264: res->volatil = MEM_VOLATILE_P (x);
265:
266: /* Mark registers used to access memory. */
267: mark_referenced_resources (XEXP (x, 0), res, 0);
268: return;
269:
270: case CC0:
271: res->cc = 1;
272: return;
273:
274: case UNSPEC_VOLATILE:
275: case ASM_INPUT:
276: /* Traditional asm's are always volatile. */
277: res->volatil = 1;
278: return;
279:
280: case ASM_OPERANDS:
281: res->volatil = MEM_VOLATILE_P (x);
282:
283: /* For all ASM_OPERANDS, we must traverse the vector of input operands.
284: We can not just fall through here since then we would be confused
285: by the ASM_INPUT rtx inside ASM_OPERANDS, which do not indicate
286: traditional asms unlike their normal usage. */
287:
288: for (i = 0; i < ASM_OPERANDS_INPUT_LENGTH (x); i++)
289: mark_referenced_resources (ASM_OPERANDS_INPUT (x, i), res, 0);
290: return;
291:
292: case CALL:
293: /* The first operand will be a (MEM (xxx)) but doesn't really reference
294: memory. The second operand may be referenced, though. */
295: mark_referenced_resources (XEXP (XEXP (x, 0), 0), res, 0);
296: mark_referenced_resources (XEXP (x, 1), res, 0);
297: return;
298:
299: case SET:
300: /* Usually, the first operand of SET is set, not referenced. But
301: registers used to access memory are referenced. SET_DEST is
302: also referenced if it is a ZERO_EXTRACT or SIGN_EXTRACT. */
303:
304: mark_referenced_resources (SET_SRC (x), res, 0);
305:
306: x = SET_DEST (x);
307: if (GET_CODE (x) == SIGN_EXTRACT || GET_CODE (x) == ZERO_EXTRACT)
308: mark_referenced_resources (x, res, 0);
309: else if (GET_CODE (x) == SUBREG)
310: x = SUBREG_REG (x);
311: if (GET_CODE (x) == MEM)
312: mark_referenced_resources (XEXP (x, 0), res, 0);
313: return;
314:
315: case CLOBBER:
316: return;
317:
318: case CALL_INSN:
319: if (include_called_routine)
320: {
321: /* A CALL references memory, the frame pointer if it exists, the
322: stack pointer, any global registers and any registers given in
323: USE insns immediately in front of the CALL.
324:
325: However, we may have moved some of the parameter loading insns
326: into the delay slot of this CALL. If so, the USE's for them
327: don't count and should be skipped. */
328: rtx insn = PREV_INSN (x);
329: rtx sequence = 0;
330: int seq_size = 0;
331: int i;
332:
333: /* If we are part of a delay slot sequence, point at the SEQUENCE. */
334: if (NEXT_INSN (insn) != x)
335: {
336: sequence = PATTERN (NEXT_INSN (insn));
337: seq_size = XVECLEN (sequence, 0);
338: if (GET_CODE (sequence) != SEQUENCE)
339: abort ();
340: }
341:
342: res->memory = 1;
343: SET_HARD_REG_BIT (res->regs, STACK_POINTER_REGNUM);
344: if (frame_pointer_needed)
345: SET_HARD_REG_BIT (res->regs, FRAME_POINTER_REGNUM);
346:
347: for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
348: if (global_regs[i])
349: SET_HARD_REG_BIT (res->regs, i);
350:
351: /* Skip any labels between the CALL_INSN and possible USE insns. */
352: while (GET_CODE (insn) == CODE_LABEL)
353: insn = PREV_INSN (insn);
354:
355: for ( ; (insn && GET_CODE (insn) == INSN
356: && GET_CODE (PATTERN (insn)) == USE);
357: insn = PREV_INSN (insn))
358: {
359: for (i = 1; i < seq_size; i++)
360: {
361: rtx slot_pat = PATTERN (XVECEXP (sequence, 0, i));
362: if (GET_CODE (slot_pat) == SET
363: && rtx_equal_p (SET_DEST (slot_pat),
364: XEXP (PATTERN (insn), 0)))
365: break;
366: }
367: if (i >= seq_size)
368: mark_referenced_resources (XEXP (PATTERN (insn), 0), res, 0);
369: }
370: }
371:
1.1.1.3 root 372: /* ... fall through to other INSN processing ... */
1.1 root 373:
374: case INSN:
375: case JUMP_INSN:
376: /* No special processing, just speed up. */
377: mark_referenced_resources (PATTERN (x), res, include_called_routine);
378: return;
379: }
380:
381: /* Process each sub-expression and flag what it needs. */
382: format_ptr = GET_RTX_FORMAT (code);
383: for (i = 0; i < GET_RTX_LENGTH (code); i++)
384: switch (*format_ptr++)
385: {
386: case 'e':
387: mark_referenced_resources (XEXP (x, i), res, include_called_routine);
388: break;
389:
390: case 'E':
391: for (j = 0; j < XVECLEN (x, i); j++)
392: mark_referenced_resources (XVECEXP (x, i, j), res,
393: include_called_routine);
394: break;
395: }
396: }
397:
1.1.1.4 ! root 398: /* Given X, a part of an insn, and a pointer to a `struct resource', RES,
! 399: indicate which resources are modified by the insn. If INCLUDE_CALLED_ROUTINE
! 400: is nonzero, also mark resources potentially set by the called routine.
! 401:
! 402: If IN_DEST is nonzero, it means we are inside a SET. Otherwise,
! 403: objects are being referenced instead of set.
1.1 root 404:
405: We never mark the insn as modifying the condition code unless it explicitly
406: SETs CC0 even though this is not totally correct. The reason for this is
1.1.1.3 root 407: that we require a SET of CC0 to immediately precede the reference to CC0.
1.1 root 408: So if some other insn sets CC0 as a side-effect, we know it cannot affect
409: our computation and thus may be placed in a delay slot. */
410:
411: static void
1.1.1.4 ! root 412: mark_set_resources (x, res, in_dest, include_called_routine)
! 413: register rtx x;
1.1 root 414: register struct resources *res;
1.1.1.4 ! root 415: int in_dest;
1.1 root 416: int include_called_routine;
417: {
1.1.1.4 ! root 418: register enum rtx_code code;
! 419: register int i, j;
! 420: register char *format_ptr;
1.1 root 421:
1.1.1.4 ! root 422: restart:
! 423:
! 424: code = GET_CODE (x);
! 425:
! 426: switch (code)
1.1 root 427: {
428: case NOTE:
429: case BARRIER:
430: case CODE_LABEL:
1.1.1.4 ! root 431: case USE:
! 432: case CONST_INT:
! 433: case CONST_DOUBLE:
! 434: case LABEL_REF:
! 435: case SYMBOL_REF:
! 436: case CONST:
! 437: case PC:
1.1 root 438: /* These don't set any resources. */
439: return;
440:
1.1.1.4 ! root 441: case CC0:
! 442: if (in_dest)
! 443: res->cc = 1;
! 444: return;
! 445:
1.1 root 446: case CALL_INSN:
447: /* Called routine modifies the condition code, memory, any registers
448: that aren't saved across calls, global registers and anything
449: explicitly CLOBBERed immediately after the CALL_INSN. */
450:
451: if (include_called_routine)
452: {
1.1.1.4 ! root 453: rtx next = NEXT_INSN (x);
1.1 root 454:
455: res->cc = res->memory = 1;
456: for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
457: if (call_used_regs[i] || global_regs[i])
458: SET_HARD_REG_BIT (res->regs, i);
459:
460: /* Skip any possible labels between the CALL_INSN and CLOBBERs. */
461: while (GET_CODE (next) == CODE_LABEL)
462: next = NEXT_INSN (next);
463:
464: for (; (next && GET_CODE (next) == INSN
465: && GET_CODE (PATTERN (next)) == CLOBBER);
466: next = NEXT_INSN (next))
1.1.1.4 ! root 467: mark_set_resources (XEXP (PATTERN (next), 0), res, 1, 0);
1.1 root 468: }
469:
470: /* ... and also what it's RTL says it modifies, if anything. */
471:
472: case JUMP_INSN:
473: case INSN:
474:
1.1.1.4 ! root 475: /* An insn consisting of just a CLOBBER (or USE) is just for flow
! 476: and doesn't actually do anything, so we ignore it. */
1.1 root 477:
1.1.1.4 ! root 478: x = PATTERN (x);
! 479: if (GET_CODE (x) != USE && GET_CODE (x) != CLOBBER)
! 480: goto restart;
! 481: return;
! 482:
! 483: case SET:
! 484: /* If the source of a SET is a CALL, this is actually done by
! 485: the called routine. So only include it if we are to include the
! 486: effects of the calling routine. */
! 487:
! 488: mark_set_resources (SET_DEST (x), res,
! 489: (include_called_routine
! 490: || GET_CODE (SET_SRC (x)) != CALL),
! 491: 0);
! 492:
! 493: mark_set_resources (SET_SRC (x), res, 0, 0);
! 494: return;
! 495:
! 496: case CLOBBER:
! 497: mark_set_resources (XEXP (x, 0), res, 1, 0);
! 498: return;
! 499:
! 500: case SEQUENCE:
! 501: for (i = 0; i < XVECLEN (x, 0); i++)
! 502: if (! (INSN_ANNULLED_BRANCH_P (XVECEXP (x, 0, 0))
! 503: && INSN_FROM_TARGET_P (XVECEXP (x, 0, i))))
! 504: mark_set_resources (XVECEXP (x, 0, i), res, 0,
! 505: include_called_routine);
! 506: return;
! 507:
! 508: case POST_INC:
! 509: case PRE_INC:
! 510: case POST_DEC:
! 511: case PRE_DEC:
! 512: mark_set_resources (XEXP (x, 0), res, 1, 0);
! 513: return;
! 514:
! 515: case ZERO_EXTRACT:
! 516: mark_set_resources (XEXP (x, 0), res, in_dest, 0);
! 517: mark_set_resources (XEXP (x, 1), res, 0, 0);
! 518: mark_set_resources (XEXP (x, 2), res, 0, 0);
! 519: return;
! 520:
! 521: case MEM:
! 522: if (in_dest)
! 523: {
! 524: res->memory = 1;
! 525: res->volatil = MEM_VOLATILE_P (x);
! 526: }
! 527:
! 528: mark_set_resources (XEXP (x, 0), res, 0, 0);
! 529: return;
! 530:
! 531: case REG:
! 532: if (in_dest)
! 533: for (i = 0; i < HARD_REGNO_NREGS (REGNO (x), GET_MODE (x)); i++)
! 534: SET_HARD_REG_BIT (res->regs, REGNO (x) + i);
! 535: return;
1.1 root 536: }
1.1.1.4 ! root 537:
! 538: /* Process each sub-expression and flag what it needs. */
! 539: format_ptr = GET_RTX_FORMAT (code);
! 540: for (i = 0; i < GET_RTX_LENGTH (code); i++)
! 541: switch (*format_ptr++)
! 542: {
! 543: case 'e':
! 544: mark_set_resources (XEXP (x, i), res, in_dest, include_called_routine);
! 545: break;
! 546:
! 547: case 'E':
! 548: for (j = 0; j < XVECLEN (x, i); j++)
! 549: mark_set_resources (XVECEXP (x, i, j), res, in_dest,
! 550: include_called_routine);
! 551: break;
! 552: }
1.1 root 553: }
554:
555: /* Return TRUE if this insn should stop the search for insn to fill delay
556: slots. LABELS_P indicates that labels should terminate the search.
557: In all cases, jumps terminate the search. */
558:
559: static int
560: stop_search_p (insn, labels_p)
561: rtx insn;
562: int labels_p;
563: {
564: if (insn == 0)
565: return 1;
566:
567: switch (GET_CODE (insn))
568: {
569: case NOTE:
570: case CALL_INSN:
571: return 0;
572:
573: case CODE_LABEL:
574: return labels_p;
575:
576: case JUMP_INSN:
577: case BARRIER:
578: return 1;
579:
580: case INSN:
581: /* OK unless it contains a delay slot or is an `asm' insn of some type.
582: We don't know anything about these. */
583: return (GET_CODE (PATTERN (insn)) == SEQUENCE
584: || GET_CODE (PATTERN (insn)) == ASM_INPUT
585: || asm_noperands (PATTERN (insn)) >= 0);
586:
587: default:
588: abort ();
589: }
590: }
591:
592: /* Return TRUE if any resources are marked in both RES1 and RES2 or if either
593: resource set contains a volatile memory reference. Otherwise, return FALSE. */
594:
595: static int
596: resource_conflicts_p (res1, res2)
597: struct resources *res1, *res2;
598: {
599: if ((res1->cc && res2->cc) || (res1->memory && res2->memory)
600: || res1->volatil || res2->volatil)
601: return 1;
602:
603: #ifdef HARD_REG_SET
604: return (res1->regs & res2->regs) != HARD_CONST (0);
605: #else
606: {
607: int i;
608:
609: for (i = 0; i < HARD_REG_SET_LONGS; i++)
610: if ((res1->regs[i] & res2->regs[i]) != 0)
611: return 1;
612: return 0;
613: }
614: #endif
615: }
616:
617: /* Return TRUE if any resource marked in RES, a `struct resources', is
618: referenced by INSN. If INCLUDE_CALLED_ROUTINE is set, return if the called
619: routine is using those resources.
620:
621: We compute this by computing all the resources referenced by INSN and
622: seeing if this conflicts with RES. It might be faster to directly check
623: ourselves, and this is the way it used to work, but it means duplicating
624: a large block of complex code. */
625:
626: static int
627: insn_references_resource_p (insn, res, include_called_routine)
628: register rtx insn;
629: register struct resources *res;
630: int include_called_routine;
631: {
632: struct resources insn_res;
633:
634: CLEAR_RESOURCE (&insn_res);
635: mark_referenced_resources (insn, &insn_res, include_called_routine);
636: return resource_conflicts_p (&insn_res, res);
637: }
638:
639: /* Return TRUE if INSN modifies resources that are marked in RES.
640: INCLUDE_CALLED_ROUTINE is set if the actions of that routine should be
641: included. CC0 is only modified if it is explicitly set; see comments
642: in front of mark_set_resources for details. */
643:
644: static int
645: insn_sets_resource_p (insn, res, include_called_routine)
646: register rtx insn;
647: register struct resources *res;
648: int include_called_routine;
649: {
650: struct resources insn_sets;
651:
652: CLEAR_RESOURCE (&insn_sets);
1.1.1.4 ! root 653: mark_set_resources (insn, &insn_sets, 0, include_called_routine);
1.1 root 654: return resource_conflicts_p (&insn_sets, res);
655: }
656:
657: /* Find a label at the end of the function or before a RETURN. If there is
658: none, make one. */
659:
660: static rtx
661: find_end_label ()
662: {
663: rtx insn;
664:
665: /* If we found one previously, return it. */
666: if (end_of_function_label)
667: return end_of_function_label;
668:
669: /* Otherwise, see if there is a label at the end of the function. If there
670: is, it must be that RETURN insns aren't needed, so that is our return
671: label and we don't have to do anything else. */
672:
673: insn = get_last_insn ();
674: while (GET_CODE (insn) == NOTE
675: || (GET_CODE (insn) == INSN
676: && (GET_CODE (PATTERN (insn)) == USE
677: || GET_CODE (PATTERN (insn)) == CLOBBER)))
678: insn = PREV_INSN (insn);
679:
680: if (GET_CODE (insn) == CODE_LABEL)
681: end_of_function_label = insn;
682: else
683: {
684: /* Otherwise, make a new label and emit a RETURN and BARRIER,
685: if needed. */
686: end_of_function_label = gen_label_rtx ();
687: LABEL_NUSES (end_of_function_label) = 0;
688: emit_label (end_of_function_label);
689: #ifdef HAVE_return
690: if (HAVE_return)
691: {
692: emit_jump_insn (gen_return ());
693: emit_barrier ();
694: }
695: #endif
696: }
697:
698: /* Show one additional use for this label so it won't go away until
699: we are done. */
700: ++LABEL_NUSES (end_of_function_label);
701:
702: return end_of_function_label;
703: }
704:
705: /* Put INSN and LIST together in a SEQUENCE rtx of LENGTH, and replace
706: the pattern of INSN with the SEQUENCE.
707:
708: Chain the insns so that NEXT_INSN of each insn in the sequence points to
709: the next and NEXT_INSN of the last insn in the sequence points to
710: the first insn after the sequence. Similarly for PREV_INSN. This makes
711: it easier to scan all insns.
712:
713: Returns the SEQUENCE that replaces INSN. */
714:
715: static rtx
716: emit_delay_sequence (insn, list, length, avail)
717: rtx insn;
718: rtx list;
719: int length;
720: int avail;
721: {
722: register int i = 1;
723: register rtx li;
724: int had_barrier = 0;
725:
726: /* Allocate the the rtvec to hold the insns and the SEQUENCE. */
727: rtvec seqv = rtvec_alloc (length + 1);
728: rtx seq = gen_rtx (SEQUENCE, VOIDmode, seqv);
729: rtx seq_insn = make_insn_raw (seq);
730: rtx first = get_insns ();
731: rtx last = get_last_insn ();
732:
733: /* Make a copy of the insn having delay slots. */
734: rtx delay_insn = copy_rtx (insn);
735:
736: /* If INSN is followed by a BARRIER, delete the BARRIER since it will only
737: confuse further processing. Update LAST in case it was the last insn.
738: We will put the BARRIER back in later. */
739: if (NEXT_INSN (insn) && GET_CODE (NEXT_INSN (insn)) == BARRIER)
740: {
741: delete_insn (NEXT_INSN (insn));
742: last = get_last_insn ();
743: had_barrier = 1;
744: }
745:
746: /* Splice our SEQUENCE into the insn stream where INSN used to be. */
747: NEXT_INSN (seq_insn) = NEXT_INSN (insn);
748: PREV_INSN (seq_insn) = PREV_INSN (insn);
749:
750: if (insn == last)
751: set_new_first_and_last_insn (first, seq_insn);
752: else
753: PREV_INSN (NEXT_INSN (seq_insn)) = seq_insn;
754:
755: if (insn == first)
756: set_new_first_and_last_insn (seq_insn, last);
757: else
758: NEXT_INSN (PREV_INSN (seq_insn)) = seq_insn;
759:
760: /* Build our SEQUENCE and rebuild the insn chain. */
761: XVECEXP (seq, 0, 0) = delay_insn;
762: INSN_DELETED_P (delay_insn) = 0;
763: PREV_INSN (delay_insn) = PREV_INSN (seq_insn);
764:
765: for (li = list; li; li = XEXP (li, 1), i++)
766: {
767: rtx tem = XEXP (li, 0);
768: rtx note;
769:
770: /* Show that this copy of the insn isn't deleted. */
771: INSN_DELETED_P (tem) = 0;
772:
773: XVECEXP (seq, 0, i) = tem;
774: PREV_INSN (tem) = XVECEXP (seq, 0, i - 1);
775: NEXT_INSN (XVECEXP (seq, 0, i - 1)) = tem;
776:
777: /* Remove any REG_DEAD notes because we can't rely on them now
778: that the insn has been moved. */
779: for (note = REG_NOTES (tem); note; note = XEXP (note, 1))
780: if (REG_NOTE_KIND (note) == REG_DEAD)
781: XEXP (note, 0) = const0_rtx;
782: }
783:
784: NEXT_INSN (XVECEXP (seq, 0, length)) = NEXT_INSN (seq_insn);
785:
786: /* If the previous insn is a SEQUENCE, update the NEXT_INSN pointer on the
787: last insn in that SEQUENCE to point to us. Similarly for the first
788: insn in the following insn if it is a SEQUENCE. */
789:
790: if (PREV_INSN (seq_insn) && GET_CODE (PREV_INSN (seq_insn)) == INSN
791: && GET_CODE (PATTERN (PREV_INSN (seq_insn))) == SEQUENCE)
792: NEXT_INSN (XVECEXP (PATTERN (PREV_INSN (seq_insn)), 0,
793: XVECLEN (PATTERN (PREV_INSN (seq_insn)), 0) - 1))
794: = seq_insn;
795:
796: if (NEXT_INSN (seq_insn) && GET_CODE (NEXT_INSN (seq_insn)) == INSN
797: && GET_CODE (PATTERN (NEXT_INSN (seq_insn))) == SEQUENCE)
798: PREV_INSN (XVECEXP (PATTERN (NEXT_INSN (seq_insn)), 0, 0)) = seq_insn;
799:
800: /* If there used to be a BARRIER, put it back. */
801: if (had_barrier)
802: emit_barrier_after (seq_insn);
803:
804: if (i != length + 1)
805: abort ();
806:
807: return seq_insn;
808: }
809:
810: /* Add INSN to DELAY_LIST and return the head of the new list. The list must
811: be in the order in which the insns are to be executed. */
812:
813: static rtx
814: add_to_delay_list (insn, delay_list)
815: rtx insn;
816: rtx delay_list;
817: {
818: /* If we have an empty list, just make a new list element. */
819: if (delay_list == 0)
1.1.1.4 ! root 820: return gen_rtx (INSN_LIST, VOIDmode, insn, NULL_RTX);
1.1 root 821:
822: /* Otherwise this must be an INSN_LIST. Add INSN to the end of the
823: list. */
824: XEXP (delay_list, 1) = add_to_delay_list (insn, XEXP (delay_list, 1));
825:
826: return delay_list;
827: }
828:
829: /* Delete INSN from the the delay slot of the insn that it is in. This may
830: produce an insn without anything in its delay slots. */
831:
832: static void
833: delete_from_delay_slot (insn)
834: rtx insn;
835: {
836: rtx trial, seq_insn, seq, prev;
837: rtx delay_list = 0;
838: int i;
839:
840: /* We first must find the insn containing the SEQUENCE with INSN in its
841: delay slot. Do this by finding an insn, TRIAL, where
842: PREV_INSN (NEXT_INSN (TRIAL)) != TRIAL. */
843:
844: for (trial = insn;
845: PREV_INSN (NEXT_INSN (trial)) == trial;
846: trial = NEXT_INSN (trial))
847: ;
848:
849: seq_insn = PREV_INSN (NEXT_INSN (trial));
850: seq = PATTERN (seq_insn);
851:
852: /* Create a delay list consisting of all the insns other than the one
853: we are deleting (unless we were the only one). */
854: if (XVECLEN (seq, 0) > 2)
855: for (i = 1; i < XVECLEN (seq, 0); i++)
856: if (XVECEXP (seq, 0, i) != insn)
857: delay_list = add_to_delay_list (XVECEXP (seq, 0, i), delay_list);
858:
859: /* Delete the old SEQUENCE, re-emit the insn that used to have the delay
860: list, and rebuild the delay list if non-empty. */
861: prev = PREV_INSN (seq_insn);
862: trial = XVECEXP (seq, 0, 0);
863: delete_insn (seq_insn);
864: add_insn_after (trial, prev);
865:
866: if (GET_CODE (trial) == JUMP_INSN
867: && (simplejump_p (trial) || GET_CODE (PATTERN (trial)) == RETURN))
868: emit_barrier_after (trial);
869:
870: /* If there are any delay insns, remit them. Otherwise clear the
871: annul flag. */
872: if (delay_list)
873: trial = emit_delay_sequence (trial, delay_list, XVECLEN (seq, 0) - 2, 0);
874: else
875: INSN_ANNULLED_BRANCH_P (trial) = 0;
876:
877: INSN_FROM_TARGET_P (insn) = 0;
878:
879: /* Show we need to fill this insn again. */
880: obstack_ptr_grow (&unfilled_slots_obstack, trial);
881: }
882:
883: /* Delete INSN, a JUMP_INSN. If it is a conditional jump, we must track down
884: the insn that sets CC0 for it and delete it too. */
885:
886: static void
887: delete_scheduled_jump (insn)
888: rtx insn;
889: {
890: /* Delete the insn that sets cc0 for us. On machines without cc0, we could
891: delete the insn that sets the condition code, but it is hard to find it.
892: Since this case is rare anyway, don't bother trying; there would likely
893: be other insns that became dead anyway, which we wouldn't know to
894: delete. */
895:
896: #ifdef HAVE_cc0
897: if (reg_mentioned_p (cc0_rtx, insn))
898: {
1.1.1.4 ! root 899: rtx note = find_reg_note (insn, REG_CC_SETTER, NULL_RTX);
1.1 root 900:
901: /* If a reg-note was found, it points to an insn to set CC0. This
902: insn is in the delay list of some other insn. So delete it from
903: the delay list it was in. */
904: if (note)
905: {
1.1.1.4 ! root 906: if (! FIND_REG_INC_NOTE (XEXP (note, 0), NULL_RTX)
1.1 root 907: && sets_cc0_p (PATTERN (XEXP (note, 0))) == 1)
908: delete_from_delay_slot (XEXP (note, 0));
909: }
910: else
911: {
912: /* The insn setting CC0 is our previous insn, but it may be in
913: a delay slot. It will be the last insn in the delay slot, if
914: it is. */
915: rtx trial = previous_insn (insn);
916: if (GET_CODE (trial) == NOTE)
917: trial = prev_nonnote_insn (trial);
918: if (sets_cc0_p (PATTERN (trial)) != 1
919: || FIND_REG_INC_NOTE (trial, 0))
920: return;
921: if (PREV_INSN (NEXT_INSN (trial)) == trial)
922: delete_insn (trial);
923: else
924: delete_from_delay_slot (trial);
925: }
926: }
927: #endif
928:
929: delete_insn (insn);
930: }
931:
932: /* Counters for delay-slot filling. */
933:
934: #define NUM_REORG_FUNCTIONS 2
935: #define MAX_DELAY_HISTOGRAM 3
936: #define MAX_REORG_PASSES 2
937:
938: static int num_insns_needing_delays[NUM_REORG_FUNCTIONS][MAX_REORG_PASSES];
939:
940: static int num_filled_delays[NUM_REORG_FUNCTIONS][MAX_DELAY_HISTOGRAM+1][MAX_REORG_PASSES];
941:
942: static int reorg_pass_number;
943:
944: static void
945: note_delay_statistics (slots_filled, index)
946: int slots_filled, index;
947: {
948: num_insns_needing_delays[index][reorg_pass_number]++;
949: if (slots_filled > MAX_DELAY_HISTOGRAM)
950: slots_filled = MAX_DELAY_HISTOGRAM;
951: num_filled_delays[index][slots_filled][reorg_pass_number]++;
952: }
953:
954: #if defined(ANNUL_IFFALSE_SLOTS) || defined(ANNUL_IFTRUE_SLOTS)
955:
956: /* Optimize the following cases:
957:
958: 1. When a conditional branch skips over only one instruction,
959: use an annulling branch and put that insn in the delay slot.
1.1.1.3 root 960: Use either a branch that annuls when the condition if true or
961: invert the test with a branch that annuls when the condition is
1.1 root 962: false. This saves insns, since otherwise we must copy an insn
963: from the L1 target.
964:
965: (orig) (skip) (otherwise)
966: Bcc.n L1 Bcc',a L1 Bcc,a L1'
967: insn insn insn2
968: L1: L1: L1:
969: insn2 insn2 insn2
970: insn3 insn3 L1':
971: insn3
972:
973: 2. When a conditional branch skips over only one instruction,
974: and after that, it unconditionally branches somewhere else,
975: perform the similar optimization. This saves executing the
976: second branch in the case where the inverted condition is true.
977:
978: Bcc.n L1 Bcc',a L2
979: insn insn
980: L1: L1:
981: Bra L2 Bra L2
982:
983: INSN is a JUMP_INSN.
984:
985: This should be expanded to skip over N insns, where N is the number
986: of delay slots required. */
987:
988: static rtx
989: optimize_skip (insn)
990: register rtx insn;
991: {
992: register rtx trial = next_nonnote_insn (insn);
993: rtx next_trial = next_active_insn (trial);
994: rtx delay_list = 0;
995: rtx target_label;
996:
997: if (trial == 0
998: || GET_CODE (trial) != INSN
999: || GET_CODE (PATTERN (trial)) == SEQUENCE
1000: || recog_memoized (trial) < 0
1001: || (! eligible_for_annul_false (insn, 0, trial)
1002: && ! eligible_for_annul_true (insn, 0, trial)))
1003: return 0;
1004:
1005: /* There are two cases where we are just executing one insn (we assume
1006: here that a branch requires only one insn; this should be generalized
1007: at some point): Where the branch goes around a single insn or where
1008: we have one insn followed by a branch to the same label we branch to.
1009: In both of these cases, inverting the jump and annulling the delay
1010: slot give the same effect in fewer insns. */
1011: if ((next_trial == next_active_insn (JUMP_LABEL (insn)))
1012: || (next_trial != 0
1013: && GET_CODE (next_trial) == JUMP_INSN
1014: && JUMP_LABEL (insn) == JUMP_LABEL (next_trial)
1015: && (simplejump_p (next_trial)
1016: || GET_CODE (PATTERN (next_trial)) == RETURN)))
1017: {
1018: if (eligible_for_annul_false (insn, 0, trial))
1019: {
1020: if (invert_jump (insn, JUMP_LABEL (insn)))
1021: INSN_FROM_TARGET_P (trial) = 1;
1022: else if (! eligible_for_annul_true (insn, 0, trial))
1023: return 0;
1024: }
1025:
1.1.1.4 ! root 1026: delay_list = add_to_delay_list (trial, NULL_RTX);
1.1 root 1027: next_trial = next_active_insn (trial);
1028: update_block (trial, trial);
1029: delete_insn (trial);
1030:
1031: /* Also, if we are targeting an unconditional
1032: branch, thread our jump to the target of that branch. Don't
1033: change this into a RETURN here, because it may not accept what
1034: we have in the delay slot. We'll fix this up later. */
1035: if (next_trial && GET_CODE (next_trial) == JUMP_INSN
1036: && (simplejump_p (next_trial)
1037: || GET_CODE (PATTERN (next_trial)) == RETURN))
1038: {
1039: target_label = JUMP_LABEL (next_trial);
1040: if (target_label == 0)
1041: target_label = find_end_label ();
1042: redirect_jump (insn, target_label);
1043: }
1044:
1045: INSN_ANNULLED_BRANCH_P (insn) = 1;
1046: }
1047:
1048: return delay_list;
1049: }
1050: #endif
1051:
1052: /* Return truth value of the statement that this branch
1053: is mostly taken. If we think that the branch is extremely likely
1054: to be taken, we return 2. If the branch is slightly more likely to be
1055: taken, return 1. Otherwise, return 0.
1056:
1057: CONDITION, if non-zero, is the condition that JUMP_INSN is testing. */
1058:
1059: static int
1060: mostly_true_jump (jump_insn, condition)
1061: rtx jump_insn, condition;
1062: {
1063: rtx target_label = JUMP_LABEL (jump_insn);
1064: rtx insn;
1065:
1066: /* If this is a conditional return insn, assume it won't return. */
1067: if (target_label == 0)
1068: return 0;
1069:
1070: /* If TARGET_LABEL has no jumps between it and the end of the function,
1071: this is essentially a conditional return, so predict it as false. */
1072: for (insn = NEXT_INSN (target_label);
1073: insn && GET_CODE (insn) != JUMP_INSN;
1074: insn = NEXT_INSN (insn))
1075: ;
1076:
1077: if (insn == 0)
1078: return 0;
1079:
1080: /* If this is the test of a loop, it is very likely true. We scan backwards
1081: from the target label. If we find a NOTE_INSN_LOOP_BEG before the next
1082: real insn, we assume the branch is to the top of the loop. */
1083: for (insn = PREV_INSN (target_label);
1084: insn && GET_CODE (insn) == NOTE;
1085: insn = PREV_INSN (insn))
1086: if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
1087: return 2;
1088:
1089: /* If we couldn't figure out what this jump was, assume it won't be
1090: taken. This should be rare. */
1091: if (condition == 0)
1092: return 0;
1093:
1094: /* EQ tests are usually false and NE tests are usually true. Also,
1095: most quantities are positive, so we can make the appropriate guesses
1096: about signed comparisons against zero. */
1097: switch (GET_CODE (condition))
1098: {
1099: case CONST_INT:
1100: /* Unconditional branch. */
1101: return 1;
1102: case EQ:
1103: return 0;
1104: case NE:
1105: return 1;
1106: case LE:
1107: case LT:
1108: if (XEXP (condition, 1) == const0_rtx)
1109: return 0;
1110: break;
1111: case GE:
1112: case GT:
1113: if (XEXP (condition, 1) == const0_rtx)
1114: return 1;
1115: break;
1116: }
1117:
1118: /* Predict backward branches usually take, forward branches usually not. If
1119: we don't know whether this is forward or backward, assume the branch
1120: will be taken, since most are. */
1121: return (INSN_UID (jump_insn) > max_uid || INSN_UID (target_label) > max_uid
1122: || (uid_to_ruid[INSN_UID (jump_insn)]
1123: > uid_to_ruid[INSN_UID (target_label)]));;
1124: }
1125:
1126: /* Return the condition under which INSN will branch to TARGET. If TARGET
1127: is zero, return the condition under which INSN will return. If INSN is
1128: an unconditional branch, return const_true_rtx. If INSN isn't a simple
1129: type of jump, or it doesn't go to TARGET, return 0. */
1130:
1131: static rtx
1132: get_branch_condition (insn, target)
1133: rtx insn;
1134: rtx target;
1135: {
1136: rtx pat = PATTERN (insn);
1137: rtx src;
1138:
1139: if (GET_CODE (pat) == RETURN)
1140: return target == 0 ? const_true_rtx : 0;
1141:
1142: else if (GET_CODE (pat) != SET || SET_DEST (pat) != pc_rtx)
1143: return 0;
1144:
1145: src = SET_SRC (pat);
1146: if (GET_CODE (src) == LABEL_REF && XEXP (src, 0) == target)
1147: return const_true_rtx;
1148:
1149: else if (GET_CODE (src) == IF_THEN_ELSE
1150: && ((target == 0 && GET_CODE (XEXP (src, 1)) == RETURN)
1151: || (GET_CODE (XEXP (src, 1)) == LABEL_REF
1152: && XEXP (XEXP (src, 1), 0) == target))
1153: && XEXP (src, 2) == pc_rtx)
1154: return XEXP (src, 0);
1155:
1156: else if (GET_CODE (src) == IF_THEN_ELSE
1157: && ((target == 0 && GET_CODE (XEXP (src, 2)) == RETURN)
1158: || (GET_CODE (XEXP (src, 2)) == LABEL_REF
1159: && XEXP (XEXP (src, 2), 0) == target))
1160: && XEXP (src, 1) == pc_rtx)
1161: return gen_rtx (reverse_condition (GET_CODE (XEXP (src, 0))),
1162: GET_MODE (XEXP (src, 0)),
1163: XEXP (XEXP (src, 0), 0), XEXP (XEXP (src, 0), 1));
1.1.1.4 ! root 1164:
! 1165: return 0;
1.1 root 1166: }
1167:
1168: /* Return non-zero if CONDITION is more strict than the condition of
1169: INSN, i.e., if INSN will always branch if CONDITION is true. */
1170:
1171: static int
1172: condition_dominates_p (condition, insn)
1173: rtx condition;
1174: rtx insn;
1175: {
1176: rtx other_condition = get_branch_condition (insn, JUMP_LABEL (insn));
1177: enum rtx_code code = GET_CODE (condition);
1178: enum rtx_code other_code;
1179:
1180: if (rtx_equal_p (condition, other_condition)
1181: || other_condition == const_true_rtx)
1182: return 1;
1183:
1184: else if (condition == const_true_rtx || other_condition == 0)
1185: return 0;
1186:
1187: other_code = GET_CODE (other_condition);
1188: if (GET_RTX_LENGTH (code) != 2 || GET_RTX_LENGTH (other_code) != 2
1189: || ! rtx_equal_p (XEXP (condition, 0), XEXP (other_condition, 0))
1190: || ! rtx_equal_p (XEXP (condition, 1), XEXP (other_condition, 1)))
1191: return 0;
1192:
1193: return comparison_dominates_p (code, other_code);
1194: }
1195:
1196: /* INSN branches to an insn whose pattern SEQ is a SEQUENCE. Given that
1197: the condition tested by INSN is CONDITION and the resources shown in
1198: OTHER_NEEDED are needed after INSN, see whether INSN can take all the insns
1199: from SEQ's delay list, in addition to whatever insns it may execute
1200: (in DELAY_LIST). SETS and NEEDED are denote resources already set and
1201: needed while searching for delay slot insns. Return the concatenated
1202: delay list if possible, otherwise, return 0.
1203:
1204: SLOTS_TO_FILL is the total number of slots required by INSN, and
1205: PSLOTS_FILLED points to the number filled so far (also the number of
1206: insns in DELAY_LIST). It is updated with the number that have been
1207: filled from the SEQUENCE, if any.
1208:
1209: PANNUL_P points to a non-zero value if we already know that we need
1210: to annul INSN. If this routine determines that annulling is needed,
1211: it may set that value non-zero.
1212:
1213: PNEW_THREAD points to a location that is to receive the place at which
1214: execution should continue. */
1215:
1216: static rtx
1217: steal_delay_list_from_target (insn, condition, seq, delay_list,
1218: sets, needed, other_needed,
1219: slots_to_fill, pslots_filled, pannul_p,
1220: pnew_thread)
1221: rtx insn, condition;
1222: rtx seq;
1223: rtx delay_list;
1224: struct resources *sets, *needed, *other_needed;
1225: int slots_to_fill;
1226: int *pslots_filled;
1227: int *pannul_p;
1228: rtx *pnew_thread;
1229: {
1230: rtx temp;
1231: int slots_remaining = slots_to_fill - *pslots_filled;
1232: int total_slots_filled = *pslots_filled;
1233: rtx new_delay_list = 0;
1234: int must_annul = *pannul_p;
1235: int i;
1236:
1237: /* We can't do anything if there are more delay slots in SEQ than we
1238: can handle, or if we don't know that it will be a taken branch.
1239:
1240: We know that it will be a taken branch if it is either an unconditional
1241: branch or a conditional branch with a stricter branch condition. */
1242:
1243: if (XVECLEN (seq, 0) - 1 > slots_remaining
1244: || ! condition_dominates_p (condition, XVECEXP (seq, 0, 0)))
1245: return delay_list;
1246:
1247: for (i = 1; i < XVECLEN (seq, 0); i++)
1248: {
1249: rtx trial = XVECEXP (seq, 0, i);
1250:
1251: if (insn_references_resource_p (trial, sets, 0)
1252: || insn_sets_resource_p (trial, needed, 0)
1253: || insn_sets_resource_p (trial, sets, 0)
1254: #ifdef HAVE_cc0
1255: /* If TRIAL sets CC0, we can't copy it, so we can't steal this
1256: delay list. */
1.1.1.4 ! root 1257: || find_reg_note (trial, REG_CC_USER, NULL_RTX)
1.1 root 1258: #endif
1259: /* If TRIAL is from the fallthrough code of an annulled branch insn
1260: in SEQ, we cannot use it. */
1261: || (INSN_ANNULLED_BRANCH_P (XVECEXP (seq, 0, 0))
1262: && ! INSN_FROM_TARGET_P (trial)))
1263: return delay_list;
1264:
1265: /* If this insn was already done (usually in a previous delay slot),
1266: pretend we put it in our delay slot. */
1267: if (redundant_insn_p (trial, insn, new_delay_list))
1268: continue;
1269:
1270: if (! must_annul
1271: && ((condition == const_true_rtx
1272: || (! insn_sets_resource_p (trial, other_needed, 0)
1273: && ! may_trap_p (PATTERN (trial)))))
1274: ? eligible_for_delay (insn, total_slots_filled, trial)
1275: : (must_annul = 1,
1276: eligible_for_annul_false (insn, total_slots_filled, trial)))
1277: {
1278: temp = copy_rtx (trial);
1279: INSN_FROM_TARGET_P (temp) = 1;
1280: new_delay_list = add_to_delay_list (temp, new_delay_list);
1281: total_slots_filled++;
1282:
1283: if (--slots_remaining == 0)
1284: break;
1285: }
1286: else
1287: return delay_list;
1288: }
1289:
1290: /* Show the place to which we will be branching. */
1291: *pnew_thread = next_active_insn (JUMP_LABEL (XVECEXP (seq, 0, 0)));
1292:
1293: /* Add any new insns to the delay list and update the count of the
1294: number of slots filled. */
1295: *pslots_filled = total_slots_filled;
1296: *pannul_p = must_annul;
1297:
1298: if (delay_list == 0)
1299: return new_delay_list;
1300:
1301: for (temp = new_delay_list; temp; temp = XEXP (temp, 1))
1302: delay_list = add_to_delay_list (XEXP (temp, 0), delay_list);
1303:
1304: return delay_list;
1305: }
1306:
1307: /* Similar to steal_delay_list_from_target except that SEQ is on the
1308: fallthrough path of INSN. Here we only do something if the delay insn
1309: of SEQ is an unconditional branch. In that case we steal its delay slot
1310: for INSN since unconditional branches are much easier to fill. */
1311:
1312: static rtx
1313: steal_delay_list_from_fallthrough (insn, condition, seq,
1314: delay_list, sets, needed, other_needed,
1315: slots_to_fill, pslots_filled, pannul_p)
1316: rtx insn, condition;
1317: rtx seq;
1318: rtx delay_list;
1319: struct resources *sets, *needed, *other_needed;
1320: int slots_to_fill;
1321: int *pslots_filled;
1322: int *pannul_p;
1323: {
1324: int i;
1325:
1326: /* We can't do anything if SEQ's delay insn isn't an
1327: unconditional branch. */
1328:
1329: if (! simplejump_p (XVECEXP (seq, 0, 0))
1330: && GET_CODE (PATTERN (XVECEXP (seq, 0, 0))) != RETURN)
1331: return delay_list;
1332:
1333: for (i = 1; i < XVECLEN (seq, 0); i++)
1334: {
1335: rtx trial = XVECEXP (seq, 0, i);
1336:
1337: /* If TRIAL sets CC0, stealing it will move it too far from the use
1338: of CC0. */
1339: if (insn_references_resource_p (trial, sets, 0)
1340: || insn_sets_resource_p (trial, needed, 0)
1341: || insn_sets_resource_p (trial, sets, 0)
1342: #ifdef HAVE_cc0
1343: || sets_cc0_p (PATTERN (trial))
1344: #endif
1345: )
1346:
1347: break;
1348:
1349: /* If this insn was already done, we don't need it. */
1350: if (redundant_insn_p (trial, insn, delay_list))
1351: {
1352: delete_from_delay_slot (trial);
1353: continue;
1354: }
1355:
1356: if (! *pannul_p
1357: && ((condition == const_true_rtx
1358: || (! insn_sets_resource_p (trial, other_needed, 0)
1359: && ! may_trap_p (PATTERN (trial)))))
1360: ? eligible_for_delay (insn, *pslots_filled, trial)
1361: : (*pannul_p = 1,
1362: eligible_for_annul_true (insn, *pslots_filled, trial)))
1363: {
1364: delete_from_delay_slot (trial);
1365: delay_list = add_to_delay_list (trial, delay_list);
1366:
1367: if (++(*pslots_filled) == slots_to_fill)
1368: break;
1369: }
1370: else
1371: break;
1372: }
1373:
1374: return delay_list;
1375: }
1376:
1377: /* Try merging insns starting at THREAD which match exactly the insns in
1378: INSN's delay list.
1379:
1380: If all insns were matched and the insn was previously annulling, the
1381: annul bit will be cleared.
1382:
1383: For each insn that is merged, if the branch is or will be non-annulling,
1384: we delete the merged insn. */
1385:
1386: static void
1387: try_merge_delay_insns (insn, thread)
1388: rtx insn, thread;
1389: {
1390: rtx trial, next_trial;
1391: rtx delay_insn = XVECEXP (PATTERN (insn), 0, 0);
1392: int annul_p = INSN_ANNULLED_BRANCH_P (delay_insn);
1393: int slot_number = 1;
1394: int num_slots = XVECLEN (PATTERN (insn), 0);
1395: rtx next_to_match = XVECEXP (PATTERN (insn), 0, slot_number);
1396: struct resources set, needed;
1397: rtx merged_insns = 0;
1398: int i;
1399:
1400: CLEAR_RESOURCE (&needed);
1401: CLEAR_RESOURCE (&set);
1402:
1403: /* If this is not an annulling branch, take into account anything needed in
1404: NEXT_TO_MATCH. This prevents two increments from being incorrectly
1405: folded into one. If we are annulling, this would be the correct
1406: thing to do. (The alternative, looking at things set in NEXT_TO_MATCH
1407: will essentially disable this optimization. This method is somewhat of
1408: a kludge, but I don't see a better way.) */
1409: if (! annul_p)
1410: mark_referenced_resources (next_to_match, &needed, 1);
1411:
1412: for (trial = thread; !stop_search_p (trial, 1); trial = next_trial)
1413: {
1414: rtx pat = PATTERN (trial);
1415:
1416: next_trial = next_nonnote_insn (trial);
1417:
1418: /* TRIAL must be a CALL_INSN or INSN. Skip USE and CLOBBER. */
1419: if (GET_CODE (trial) == INSN
1420: && (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER))
1421: continue;
1422:
1423: if (GET_CODE (next_to_match) == GET_CODE (trial)
1424: #ifdef HAVE_cc0
1425: /* We can't share an insn that sets cc0. */
1426: && ! sets_cc0_p (pat)
1427: #endif
1428: && ! insn_references_resource_p (trial, &set, 1)
1429: && ! insn_sets_resource_p (trial, &set, 1)
1430: && ! insn_sets_resource_p (trial, &needed, 1)
1431: && (trial = try_split (pat, trial, 0)) != 0
1432: && rtx_equal_p (PATTERN (next_to_match), PATTERN (trial))
1433: /* Have to test this condition if annul condition is different
1434: from (and less restrictive than) non-annulling one. */
1435: && eligible_for_delay (delay_insn, slot_number - 1, trial))
1436: {
1437: next_trial = next_nonnote_insn (trial);
1438:
1439: if (! annul_p)
1440: {
1441: update_block (trial, thread);
1442: delete_insn (trial);
1443: INSN_FROM_TARGET_P (next_to_match) = 0;
1444: }
1445: else
1446: merged_insns = gen_rtx (INSN_LIST, VOIDmode, trial, merged_insns);
1447:
1448: if (++slot_number == num_slots)
1449: break;
1450:
1451: next_to_match = XVECEXP (PATTERN (insn), 0, slot_number);
1452: if (! annul_p)
1453: mark_referenced_resources (next_to_match, &needed, 1);
1454: }
1455:
1.1.1.4 ! root 1456: mark_set_resources (trial, &set, 0, 1);
1.1 root 1457: mark_referenced_resources (trial, &needed, 1);
1458: }
1459:
1460: /* See if we stopped on a filled insn. If we did, try to see if its
1461: delay slots match. */
1462: if (slot_number != num_slots
1463: && trial && GET_CODE (trial) == INSN
1464: && GET_CODE (PATTERN (trial)) == SEQUENCE
1465: && ! INSN_ANNULLED_BRANCH_P (XVECEXP (PATTERN (trial), 0, 0)))
1466: {
1467: rtx pat = PATTERN (trial);
1468:
1469: for (i = 1; i < XVECLEN (pat, 0); i++)
1470: {
1471: rtx dtrial = XVECEXP (pat, 0, i);
1472:
1473: if (! insn_references_resource_p (dtrial, &set, 1)
1474: && ! insn_sets_resource_p (dtrial, &set, 1)
1475: && ! insn_sets_resource_p (dtrial, &needed, 1)
1476: #ifdef HAVE_cc0
1477: && ! sets_cc0_p (PATTERN (dtrial))
1478: #endif
1479: && rtx_equal_p (PATTERN (next_to_match), PATTERN (dtrial))
1480: && eligible_for_delay (delay_insn, slot_number - 1, dtrial))
1481: {
1482: if (! annul_p)
1483: {
1484: update_block (dtrial, thread);
1485: delete_from_delay_slot (dtrial);
1486: INSN_FROM_TARGET_P (next_to_match) = 0;
1487: }
1488: else
1489: merged_insns = gen_rtx (INSN_LIST, SImode, dtrial,
1490: merged_insns);
1491:
1492: if (++slot_number == num_slots)
1493: break;
1494:
1495: next_to_match = XVECEXP (PATTERN (insn), 0, slot_number);
1496: }
1497: }
1498: }
1499:
1500: /* If all insns in the delay slot have been matched and we were previously
1501: annulling the branch, we need not any more. In that case delete all the
1502: merged insns. Also clear the INSN_FROM_TARGET_P bit of each insn the
1503: the delay list so that we know that it isn't only being used at the
1504: target. */
1505: if (next_to_match == 0 && annul_p)
1506: {
1507: for (; merged_insns; merged_insns = XEXP (merged_insns, 1))
1508: {
1509: if (GET_MODE (merged_insns) == SImode)
1510: {
1511: update_block (XEXP (merged_insns, 0), thread);
1512: delete_from_delay_slot (XEXP (merged_insns, 0));
1513: }
1514: else
1515: {
1516: update_block (XEXP (merged_insns, 0), thread);
1517: delete_insn (XEXP (merged_insns, 0));
1518: }
1519: }
1520:
1521: INSN_ANNULLED_BRANCH_P (delay_insn) = 0;
1522:
1523: for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
1524: INSN_FROM_TARGET_P (XVECEXP (PATTERN (insn), 0, i)) = 0;
1525: }
1526: }
1527:
1528: /* See if INSN is redundant with an insn in front of TARGET. Often this
1529: is called when INSN is a candidate for a delay slot of TARGET.
1530: DELAY_LIST are insns that will be placed in delay slots of TARGET in front
1531: of INSN. Often INSN will be redundant with an insn in a delay slot of
1532: some previous insn. This happens when we have a series of branches to the
1533: same label; in that case the first insn at the target might want to go
1534: into each of the delay slots.
1535:
1536: If we are not careful, this routine can take up a significant fraction
1537: of the total compilation time (4%), but only wins rarely. Hence we
1538: speed this routine up by making two passes. The first pass goes back
1539: until it hits a label and sees if it find an insn with an identical
1540: pattern. Only in this (relatively rare) event does it check for
1541: data conflicts.
1542:
1543: We do not split insns we encounter. This could cause us not to find a
1544: redundant insn, but the cost of splitting seems greater than the possible
1545: gain in rare cases. */
1546:
1547: static int
1548: redundant_insn_p (insn, target, delay_list)
1549: rtx insn;
1550: rtx target;
1551: rtx delay_list;
1552: {
1553: rtx target_main = target;
1554: rtx ipat = PATTERN (insn);
1555: rtx trial, pat;
1556: struct resources needed, set;
1557: int i;
1558:
1559: /* Scan backwards looking for a match. */
1560: for (trial = PREV_INSN (target); trial; trial = PREV_INSN (trial))
1561: {
1562: if (GET_CODE (trial) == CODE_LABEL)
1563: return 0;
1564:
1565: if (GET_CODE (trial) != INSN && GET_CODE (trial) != JUMP_INSN
1566: && GET_CODE (trial) != JUMP_INSN)
1567: continue;
1568:
1569: pat = PATTERN (trial);
1570: if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER)
1571: continue;
1572:
1573: if (GET_CODE (pat) == SEQUENCE)
1574: {
1575: /* Stop for a CALL and its delay slots because it difficult to track
1576: its resource needs correctly. */
1577: if (GET_CODE (XVECEXP (pat, 0, 0)) == CALL_INSN)
1578: return 0;
1579:
1580: for (i = XVECLEN (pat, 0) - 1; i > 0; i--)
1581: if (GET_CODE (XVECEXP (pat, 0, i)) == GET_CODE (insn)
1582: && rtx_equal_p (PATTERN (XVECEXP (pat, 0, i)), ipat))
1583: break;
1584:
1585: /* If found a match, exit this loop early. */
1586: if (i > 0)
1587: break;
1588: }
1589:
1590: else if (GET_CODE (trial) == GET_CODE (insn) && rtx_equal_p (pat, ipat))
1591: break;
1592: }
1593:
1594: /* If we didn't find an insn that matches, return 0. */
1595: if (trial == 0)
1596: return 0;
1597:
1598: /* See what resources this insn sets and needs. If they overlap, or
1599: if this insn references CC0, it can't be redundant. */
1600:
1601: CLEAR_RESOURCE (&needed);
1602: CLEAR_RESOURCE (&set);
1.1.1.4 ! root 1603: mark_set_resources (insn, &set, 0, 1);
1.1 root 1604: mark_referenced_resources (insn, &needed, 1);
1605:
1606: /* If TARGET is a SEQUENCE, get the main insn. */
1607: if (GET_CODE (target) == INSN && GET_CODE (PATTERN (target)) == SEQUENCE)
1608: target_main = XVECEXP (PATTERN (target), 0, 0);
1609:
1610: if (resource_conflicts_p (&needed, &set)
1611: #ifdef HAVE_cc0
1612: || reg_mentioned_p (cc0_rtx, ipat)
1613: #endif
1614: /* The insn requiring the delay may not set anything needed or set by
1615: INSN. */
1616: || insn_sets_resource_p (target_main, &needed, 1)
1617: || insn_sets_resource_p (target_main, &set, 1))
1618: return 0;
1619:
1620: /* Insns we pass may not set either NEEDED or SET, so merge them for
1621: simpler tests. */
1622: needed.memory |= set.memory;
1623: IOR_HARD_REG_SET (needed.regs, set.regs);
1624:
1625: /* This insn isn't redundant if it conflicts with an insn that either is
1626: or will be in a delay slot of TARGET. */
1627:
1628: while (delay_list)
1629: {
1630: if (insn_sets_resource_p (XEXP (delay_list, 0), &needed, 1))
1631: return 0;
1632: delay_list = XEXP (delay_list, 1);
1633: }
1634:
1635: if (GET_CODE (target) == INSN && GET_CODE (PATTERN (target)) == SEQUENCE)
1636: for (i = 1; i < XVECLEN (PATTERN (target), 0); i++)
1637: if (insn_sets_resource_p (XVECEXP (PATTERN (target), 0, i), &needed, 1))
1638: return 0;
1639:
1640: /* Scan backwards until we reach a label or an insn that uses something
1641: INSN sets or sets something insn uses or sets. */
1642:
1643: for (trial = PREV_INSN (target);
1644: trial && GET_CODE (trial) != CODE_LABEL;
1645: trial = PREV_INSN (trial))
1646: {
1647: if (GET_CODE (trial) != INSN && GET_CODE (trial) != CALL_INSN
1648: && GET_CODE (trial) != JUMP_INSN)
1649: continue;
1650:
1651: pat = PATTERN (trial);
1652: if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER)
1653: continue;
1654:
1655: if (GET_CODE (pat) == SEQUENCE)
1656: {
1657: /* If this is a CALL_INSN and its delay slots, it is hard to track
1658: the resource needs properly, so give up. */
1659: if (GET_CODE (XVECEXP (pat, 0, 0)) == CALL_INSN)
1660: return 0;
1661:
1662: /* See if any of the insns in the delay slot match, updating
1663: resource requirements as we go. */
1664: for (i = XVECLEN (pat, 0) - 1; i > 0; i--)
1665: {
1666: rtx candidate = XVECEXP (pat, 0, i);
1667:
1668: /* If an insn will be annulled if the branch is false, it isn't
1669: considered as a possible duplicate insn. */
1670: if (rtx_equal_p (PATTERN (candidate), ipat)
1671: && ! (INSN_ANNULLED_BRANCH_P (XVECEXP (pat, 0, 0))
1672: && INSN_FROM_TARGET_P (candidate)))
1673: {
1674: /* Show that this insn will be used in the sequel. */
1675: INSN_FROM_TARGET_P (candidate) = 0;
1676: return 1;
1677: }
1678:
1679: /* Unless this is an annulled insn from the target of a branch,
1680: we must stop if it sets anything needed or set by INSN. */
1681: if ((! INSN_ANNULLED_BRANCH_P (XVECEXP (pat, 0, 0))
1682: || ! INSN_FROM_TARGET_P (candidate))
1683: && insn_sets_resource_p (candidate, &needed, 1))
1684: return 0;
1685: }
1686:
1687:
1688: /* If the insn requiring the delay slot conflicts with INSN, we
1689: must stop. */
1690: if (insn_sets_resource_p (XVECEXP (pat, 0, 0), &needed, 1))
1691: return 0;
1692: }
1693: else
1694: {
1695: /* See if TRIAL is the same as INSN. */
1696: pat = PATTERN (trial);
1697: if (rtx_equal_p (pat, ipat))
1698: return 1;
1699:
1700: /* Can't go any further if TRIAL conflicts with INSN. */
1701: if (insn_sets_resource_p (trial, &needed, 1))
1702: return 0;
1703: }
1704: }
1705:
1706: return 0;
1707: }
1708:
1709: /* Return 1 if THREAD can only be executed in one way. If LABEL is non-zero,
1710: it is the target of the branch insn being scanned. If ALLOW_FALLTHROUGH
1711: is non-zero, we are allowed to fall into this thread; otherwise, we are
1712: not.
1713:
1714: If LABEL is used more than one or we pass a label other than LABEL before
1715: finding an active insn, we do not own this thread. */
1716:
1717: static int
1718: own_thread_p (thread, label, allow_fallthrough)
1719: rtx thread;
1720: rtx label;
1721: int allow_fallthrough;
1722: {
1723: rtx active_insn;
1724: rtx insn;
1725:
1726: /* We don't own the function end. */
1727: if (thread == 0)
1728: return 0;
1729:
1730: /* Get the first active insn, or THREAD, if it is an active insn. */
1731: active_insn = next_active_insn (PREV_INSN (thread));
1732:
1733: for (insn = thread; insn != active_insn; insn = NEXT_INSN (insn))
1734: if (GET_CODE (insn) == CODE_LABEL
1735: && (insn != label || LABEL_NUSES (insn) != 1))
1736: return 0;
1737:
1738: if (allow_fallthrough)
1739: return 1;
1740:
1741: /* Ensure that we reach a BARRIER before any insn or label. */
1742: for (insn = prev_nonnote_insn (thread);
1743: insn == 0 || GET_CODE (insn) != BARRIER;
1744: insn = prev_nonnote_insn (insn))
1745: if (insn == 0
1746: || GET_CODE (insn) == CODE_LABEL
1747: || (GET_CODE (insn) == INSN
1748: && GET_CODE (PATTERN (insn)) != USE
1749: && GET_CODE (PATTERN (insn)) != CLOBBER))
1750: return 0;
1751:
1752: return 1;
1753: }
1754:
1755: /* Find the number of the basic block that starts closest to INSN. Return -1
1756: if we couldn't find such a basic block. */
1757:
1758: static int
1759: find_basic_block (insn)
1760: rtx insn;
1761: {
1762: int i;
1763:
1764: /* Scan backwards to the previous BARRIER. Then see if we can find a
1765: label that starts a basic block. Return the basic block number. */
1766:
1767: for (insn = prev_nonnote_insn (insn);
1768: insn && GET_CODE (insn) != BARRIER;
1769: insn = prev_nonnote_insn (insn))
1770: ;
1771:
1772: /* The start of the function is basic block zero. */
1773: if (insn == 0)
1774: return 0;
1775:
1776: /* See if any of the upcoming CODE_LABELs start a basic block. If we reach
1777: anything other than a CODE_LABEL or note, we can't find this code. */
1778: for (insn = next_nonnote_insn (insn);
1779: insn && GET_CODE (insn) == CODE_LABEL;
1780: insn = next_nonnote_insn (insn))
1781: {
1782: for (i = 0; i < n_basic_blocks; i++)
1783: if (insn == basic_block_head[i])
1784: return i;
1785: }
1786:
1787: return -1;
1788: }
1789:
1790: /* Called when INSN is being moved from a location near the target of a jump.
1.1.1.2 root 1791: We leave a marker of the form (use (INSN)) immediately in front
1.1 root 1792: of WHERE for mark_target_live_regs. These markers will be deleted when
1.1.1.2 root 1793: reorg finishes.
1794:
1795: We used to try to update the live status of registers if WHERE is at
1796: the start of a basic block, but that can't work since we may remove a
1797: BARRIER in relax_delay_slots. */
1.1 root 1798:
1799: static void
1800: update_block (insn, where)
1801: rtx insn;
1802: rtx where;
1803: {
1.1.1.2 root 1804: int b;
1805:
1.1 root 1806: /* Ignore if this was in a delay slot and it came from the target of
1807: a branch. */
1808: if (INSN_FROM_TARGET_P (insn))
1809: return;
1810:
1.1.1.2 root 1811: emit_insn_before (gen_rtx (USE, VOIDmode, insn), where);
1.1 root 1812:
1813: /* INSN might be making a value live in a block where it didn't use to
1814: be. So recompute liveness information for this block. */
1.1.1.2 root 1815:
1816: b = find_basic_block (insn);
1817: if (b != -1)
1818: bb_ticks[b]++;
1.1 root 1819: }
1820:
1821: /* Marks registers possibly live at the current place being scanned by
1822: mark_target_live_regs. Used only by next two function. */
1823:
1824: static HARD_REG_SET current_live_regs;
1825:
1826: /* Marks registers for which we have seen a REG_DEAD note but no assignment.
1827: Also only used by the next two functions. */
1828:
1829: static HARD_REG_SET pending_dead_regs;
1830:
1831: /* Utility function called from mark_target_live_regs via note_stores.
1832: It deadens any CLOBBERed registers and livens any SET registers. */
1833:
1834: static void
1835: update_live_status (dest, x)
1836: rtx dest;
1837: rtx x;
1838: {
1839: int first_regno, last_regno;
1840: int i;
1841:
1842: if (GET_CODE (dest) != REG
1843: && (GET_CODE (dest) != SUBREG || GET_CODE (SUBREG_REG (dest)) != REG))
1844: return;
1845:
1846: if (GET_CODE (dest) == SUBREG)
1847: first_regno = REGNO (SUBREG_REG (dest)) + SUBREG_WORD (dest);
1848: else
1849: first_regno = REGNO (dest);
1850:
1851: last_regno = first_regno + HARD_REGNO_NREGS (first_regno, GET_MODE (dest));
1852:
1853: if (GET_CODE (x) == CLOBBER)
1854: for (i = first_regno; i < last_regno; i++)
1855: CLEAR_HARD_REG_BIT (current_live_regs, i);
1856: else
1857: for (i = first_regno; i < last_regno; i++)
1858: {
1859: SET_HARD_REG_BIT (current_live_regs, i);
1860: CLEAR_HARD_REG_BIT (pending_dead_regs, i);
1861: }
1862: }
1863:
1864: /* Similar to next_insn, but ignores insns in the delay slots of
1865: an annulled branch. */
1866:
1867: static rtx
1868: next_insn_no_annul (insn)
1869: rtx insn;
1870: {
1871: if (insn)
1872: {
1873: /* If INSN is an annulled branch, skip any insns from the target
1874: of the branch. */
1875: if (INSN_ANNULLED_BRANCH_P (insn)
1876: && NEXT_INSN (PREV_INSN (insn)) != insn)
1877: while (INSN_FROM_TARGET_P (NEXT_INSN (insn)))
1878: insn = NEXT_INSN (insn);
1879:
1880: insn = NEXT_INSN (insn);
1881: if (insn && GET_CODE (insn) == INSN
1882: && GET_CODE (PATTERN (insn)) == SEQUENCE)
1883: insn = XVECEXP (PATTERN (insn), 0, 0);
1884: }
1885:
1886: return insn;
1887: }
1888:
1889: /* Set the resources that are live at TARGET.
1890:
1891: If TARGET is zero, we refer to the end of the current function and can
1892: return our precomputed value.
1893:
1894: Otherwise, we try to find out what is live by consulting the basic block
1895: information. This is tricky, because we must consider the actions of
1896: reload and jump optimization, which occur after the basic block information
1897: has been computed.
1898:
1899: Accordingly, we proceed as follows::
1900:
1901: We find the previous BARRIER and look at all immediately following labels
1902: (with no intervening active insns) to see if any of them start a basic
1903: block. If we hit the start of the function first, we use block 0.
1904:
1905: Once we have found a basic block and a corresponding first insns, we can
1906: accurately compute the live status from basic_block_live_regs and
1907: reg_renumber. (By starting at a label following a BARRIER, we are immune
1908: to actions taken by reload and jump.) Then we scan all insns between
1909: that point and our target. For each CLOBBER (or for call-clobbered regs
1910: when we pass a CALL_INSN), mark the appropriate registers are dead. For
1911: a SET, mark them as live.
1912:
1913: We have to be careful when using REG_DEAD notes because they are not
1914: updated by such things as find_equiv_reg. So keep track of registers
1915: marked as dead that haven't been assigned to, and mark them dead at the
1916: next CODE_LABEL since reload and jump won't propagate values across labels.
1917:
1918: If we cannot find the start of a basic block (should be a very rare
1919: case, if it can happen at all), mark everything as potentially live.
1920:
1921: Next, scan forward from TARGET looking for things set or clobbered
1922: before they are used. These are not live.
1923:
1924: Because we can be called many times on the same target, save our results
1925: in a hash table indexed by INSN_UID. */
1926:
1927: static void
1928: mark_target_live_regs (target, res)
1929: rtx target;
1930: struct resources *res;
1931: {
1932: int b = -1;
1933: int i;
1934: struct target_info *tinfo;
1935: rtx insn, next;
1936: rtx jump_insn = 0;
1.1.1.4 ! root 1937: rtx jump_target;
1.1 root 1938: HARD_REG_SET scratch;
1939: struct resources set, needed;
1940: int jump_count = 0;
1941:
1942: /* Handle end of function. */
1943: if (target == 0)
1944: {
1945: *res = end_of_function_needs;
1946: return;
1947: }
1948:
1949: /* We have to assume memory is needed, but the CC isn't. */
1950: res->memory = 1;
1951: res->volatil = 0;
1952: res->cc = 0;
1953:
1954: /* See if we have computed this value already. */
1955: for (tinfo = target_hash_table[INSN_UID (target) % TARGET_HASH_PRIME];
1956: tinfo; tinfo = tinfo->next)
1957: if (tinfo->uid == INSN_UID (target))
1958: break;
1959:
1960: /* Start by getting the basic block number. If we have saved information,
1961: we can get it from there unless the insn at the start of the basic block
1962: has been deleted. */
1963: if (tinfo && tinfo->block != -1
1964: && ! INSN_DELETED_P (basic_block_head[tinfo->block]))
1965: b = tinfo->block;
1966:
1967: if (b == -1)
1968: b = find_basic_block (target);
1969:
1970: if (tinfo)
1971: {
1972: /* If the information is up-to-date, use it. Otherwise, we will
1973: update it below. */
1974: if (b == tinfo->block && b != -1 && tinfo->bb_tick == bb_ticks[b])
1975: {
1976: COPY_HARD_REG_SET (res->regs, tinfo->live_regs);
1977: return;
1978: }
1979: }
1980: else
1981: {
1982: /* Allocate a place to put our results and chain it into the
1983: hash table. */
1984: tinfo = (struct target_info *) oballoc (sizeof (struct target_info));
1985: tinfo->uid = INSN_UID (target);
1986: tinfo->block = b;
1987: tinfo->next = target_hash_table[INSN_UID (target) % TARGET_HASH_PRIME];
1988: target_hash_table[INSN_UID (target) % TARGET_HASH_PRIME] = tinfo;
1989: }
1990:
1991: CLEAR_HARD_REG_SET (pending_dead_regs);
1992:
1993: /* If we found a basic block, get the live registers from it and update
1994: them with anything set or killed between its start and the insn before
1995: TARGET. Otherwise, we must assume everything is live. */
1996: if (b != -1)
1997: {
1998: regset regs_live = basic_block_live_at_start[b];
1.1.1.4 ! root 1999: int offset, j;
! 2000: REGSET_ELT_TYPE bit;
1.1 root 2001: int regno;
2002: rtx start_insn, stop_insn;
2003:
2004: /* Compute hard regs live at start of block -- this is the real hard regs
2005: marked live, plus live pseudo regs that have been renumbered to
2006: hard regs. */
2007:
2008: #ifdef HARD_REG_SET
2009: current_live_regs = *regs_live;
2010: #else
2011: COPY_HARD_REG_SET (current_live_regs, regs_live);
2012: #endif
2013:
2014: for (offset = 0, i = 0; offset < regset_size; offset++)
2015: {
2016: if (regs_live[offset] == 0)
1.1.1.4 ! root 2017: i += REGSET_ELT_BITS;
1.1 root 2018: else
2019: for (bit = 1; bit && i < max_regno; bit <<= 1, i++)
2020: if ((regs_live[offset] & bit)
2021: && (regno = reg_renumber[i]) >= 0)
2022: for (j = regno;
2023: j < regno + HARD_REGNO_NREGS (regno,
2024: PSEUDO_REGNO_MODE (i));
2025: j++)
2026: SET_HARD_REG_BIT (current_live_regs, j);
2027: }
2028:
2029: /* Get starting and ending insn, handling the case where each might
2030: be a SEQUENCE. */
2031: start_insn = (b == 0 ? get_insns () : basic_block_head[b]);
2032: stop_insn = target;
2033:
2034: if (GET_CODE (start_insn) == INSN
2035: && GET_CODE (PATTERN (start_insn)) == SEQUENCE)
2036: start_insn = XVECEXP (PATTERN (start_insn), 0, 0);
2037:
2038: if (GET_CODE (stop_insn) == INSN
2039: && GET_CODE (PATTERN (stop_insn)) == SEQUENCE)
2040: stop_insn = next_insn (PREV_INSN (stop_insn));
2041:
2042: for (insn = start_insn; insn != stop_insn;
2043: insn = next_insn_no_annul (insn))
2044: {
2045: rtx link;
2046: rtx real_insn = insn;
2047:
2048: /* If this insn is from the target of a branch, it isn't going to
2049: be used in the sequel. If it is used in both cases, this
2050: test will not be true. */
2051: if (INSN_FROM_TARGET_P (insn))
2052: continue;
2053:
2054: /* If this insn is a USE made by update_block, we care about the
2055: underlying insn. */
2056: if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == USE
1.1.1.4 ! root 2057: && GET_RTX_CLASS (GET_CODE (XEXP (PATTERN (insn), 0))) == 'i')
1.1 root 2058: real_insn = XEXP (PATTERN (insn), 0);
2059:
2060: if (GET_CODE (real_insn) == CALL_INSN)
2061: {
2062: /* CALL clobbers all call-used regs that aren't fixed except
2063: sp, ap, and fp. Do this before setting the result of the
2064: call live. */
2065: for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
2066: if (call_used_regs[i]
2067: && i != STACK_POINTER_REGNUM && i != FRAME_POINTER_REGNUM
2068: && i != ARG_POINTER_REGNUM
2069: #if ARG_POINTER_REGNUM != FRAME_POINTER_REGNUM
2070: && ! (i == ARG_POINTER_REGNUM && fixed_regs[i])
2071: #endif
2072: #ifdef PIC_OFFSET_TABLE_REGNUM
2073: && ! (i == PIC_OFFSET_TABLE_REGNUM && flag_pic)
2074: #endif
2075: )
2076: CLEAR_HARD_REG_BIT (current_live_regs, i);
1.1.1.2 root 2077:
2078: /* A CALL_INSN sets any global register live, since it may
2079: have been modified by the call. */
2080: for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
2081: if (global_regs[i])
2082: SET_HARD_REG_BIT (current_live_regs, i);
1.1 root 2083: }
2084:
2085: /* Mark anything killed in an insn to be deadened at the next
2086: label. Ignore USE insns; the only REG_DEAD notes will be for
2087: parameters. But they might be early. A CALL_INSN will usually
2088: clobber registers used for parameters. It isn't worth bothering
2089: with the unlikely case when it won't. */
2090: if ((GET_CODE (real_insn) == INSN
2091: && GET_CODE (PATTERN (real_insn)) != USE)
2092: || GET_CODE (real_insn) == JUMP_INSN
2093: || GET_CODE (real_insn) == CALL_INSN)
2094: {
2095: for (link = REG_NOTES (real_insn); link; link = XEXP (link, 1))
2096: if (REG_NOTE_KIND (link) == REG_DEAD
2097: && GET_CODE (XEXP (link, 0)) == REG
2098: && REGNO (XEXP (link, 0)) < FIRST_PSEUDO_REGISTER)
2099: {
2100: int first_regno = REGNO (XEXP (link, 0));
2101: int last_regno
2102: = (first_regno
2103: + HARD_REGNO_NREGS (first_regno,
2104: GET_MODE (XEXP (link, 0))));
2105:
2106: for (i = first_regno; i < last_regno; i++)
2107: SET_HARD_REG_BIT (pending_dead_regs, i);
2108: }
2109:
2110: note_stores (PATTERN (real_insn), update_live_status);
2111:
2112: /* If any registers were unused after this insn, kill them.
2113: These notes will always be accurate. */
2114: for (link = REG_NOTES (real_insn); link; link = XEXP (link, 1))
2115: if (REG_NOTE_KIND (link) == REG_UNUSED
2116: && GET_CODE (XEXP (link, 0)) == REG
2117: && REGNO (XEXP (link, 0)) < FIRST_PSEUDO_REGISTER)
2118: {
2119: int first_regno = REGNO (XEXP (link, 0));
2120: int last_regno
2121: = (first_regno
2122: + HARD_REGNO_NREGS (first_regno,
2123: GET_MODE (XEXP (link, 0))));
2124:
2125: for (i = first_regno; i < last_regno; i++)
2126: CLEAR_HARD_REG_BIT (current_live_regs, i);
2127: }
2128: }
2129:
1.1.1.4 ! root 2130: else if (GET_CODE (real_insn) == CODE_LABEL)
1.1 root 2131: {
2132: /* A label clobbers the pending dead registers since neither
2133: reload nor jump will propagate a value across a label. */
2134: AND_COMPL_HARD_REG_SET (current_live_regs, pending_dead_regs);
2135: CLEAR_HARD_REG_SET (pending_dead_regs);
2136: }
1.1.1.4 ! root 2137:
! 2138: /* The beginning of the epilogue corresponds to the end of the
! 2139: RTL chain when there are no epilogue insns. Certain resources
! 2140: are implicitly required at that point. */
! 2141: else if (GET_CODE (real_insn) == NOTE
! 2142: && NOTE_LINE_NUMBER (real_insn) == NOTE_INSN_EPILOGUE_BEG)
! 2143: IOR_HARD_REG_SET (current_live_regs, start_of_epilogue_needs.regs);
1.1 root 2144: }
2145:
2146: COPY_HARD_REG_SET (res->regs, current_live_regs);
2147: tinfo->block = b;
2148: tinfo->bb_tick = bb_ticks[b];
2149: }
2150: else
2151: /* We didn't find the start of a basic block. Assume everything
2152: in use. This should happen only extremely rarely. */
2153: SET_HARD_REG_SET (res->regs);
2154:
2155: /* Now step forward from TARGET looking for registers that are set before
2156: they are used. These are dead. If we pass a label, any pending dead
2157: registers that weren't yet used can be made dead. Stop when we pass a
2158: conditional JUMP_INSN; follow the first few unconditional branches. */
2159:
2160: CLEAR_RESOURCE (&set);
2161: CLEAR_RESOURCE (&needed);
2162:
2163: for (insn = target; insn; insn = next)
2164: {
1.1.1.4 ! root 2165: rtx this_jump_insn = insn;
1.1 root 2166:
2167: next = NEXT_INSN (insn);
2168: switch (GET_CODE (insn))
2169: {
2170: case CODE_LABEL:
2171: AND_COMPL_HARD_REG_SET (pending_dead_regs, needed.regs);
2172: AND_COMPL_HARD_REG_SET (res->regs, pending_dead_regs);
2173: CLEAR_HARD_REG_SET (pending_dead_regs);
2174: continue;
2175:
2176: case BARRIER:
2177: case NOTE:
2178: continue;
2179:
2180: case INSN:
1.1.1.4 ! root 2181: if (GET_CODE (PATTERN (insn)) == USE)
! 2182: {
! 2183: /* If INSN is a USE made by update_block, we care about the
! 2184: underlying insn. Any registers set by the underlying insn
! 2185: are live since the insn is being done somewhere else. */
! 2186: if (GET_RTX_CLASS (GET_CODE (XEXP (PATTERN (insn), 0))) == 'i')
! 2187: mark_set_resources (XEXP (PATTERN (insn), 0), res, 0, 1);
! 2188:
! 2189: /* All other USE insns are to be ignored. */
! 2190: continue;
! 2191: }
! 2192: else if (GET_CODE (PATTERN (insn)) == CLOBBER)
1.1 root 2193: continue;
1.1.1.4 ! root 2194: else if (GET_CODE (PATTERN (insn)) == SEQUENCE)
! 2195: {
! 2196: /* An unconditional jump can be used to fill the delay slot
! 2197: of a call, so search for a JUMP_INSN in any position. */
! 2198: for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
! 2199: {
! 2200: this_jump_insn = XVECEXP (PATTERN (insn), 0, i);
! 2201: if (GET_CODE (this_jump_insn) == JUMP_INSN)
! 2202: break;
! 2203: }
! 2204: }
1.1 root 2205: }
2206:
1.1.1.4 ! root 2207: if (GET_CODE (this_jump_insn) == JUMP_INSN)
1.1 root 2208: {
2209: if (jump_count++ < 10
1.1.1.4 ! root 2210: && (simplejump_p (this_jump_insn)
! 2211: || GET_CODE (PATTERN (this_jump_insn)) == RETURN))
1.1 root 2212: {
1.1.1.4 ! root 2213: next = next_active_insn (JUMP_LABEL (this_jump_insn));
1.1 root 2214: if (jump_insn == 0)
1.1.1.4 ! root 2215: {
! 2216: jump_insn = insn;
! 2217: jump_target = JUMP_LABEL (this_jump_insn);
! 2218: }
1.1 root 2219: }
2220: else
2221: break;
2222: }
2223:
2224: mark_referenced_resources (insn, &needed, 1);
1.1.1.4 ! root 2225: mark_set_resources (insn, &set, 0, 1);
1.1 root 2226:
2227: COPY_HARD_REG_SET (scratch, set.regs);
2228: AND_COMPL_HARD_REG_SET (scratch, needed.regs);
2229: AND_COMPL_HARD_REG_SET (res->regs, scratch);
2230: }
2231:
2232: /* If we hit an unconditional branch, we have another way of finding out
2233: what is live: we can see what is live at the branch target and include
2234: anything used but not set before the branch. The only things that are
1.1.1.2 root 2235: live are those that are live using the above test and the test below.
2236:
2237: Don't try this if we expired our jump count above, since that would
2238: mean there may be an infinite loop in the function being compiled. */
2239:
2240: if (jump_insn && jump_count < 10)
1.1 root 2241: {
2242: struct resources new_resources;
2243: rtx stop_insn = next_active_insn (jump_insn);
2244:
2245: mark_target_live_regs (next_active_insn (jump_target), &new_resources);
2246: CLEAR_RESOURCE (&set);
2247: CLEAR_RESOURCE (&needed);
2248:
2249: /* Include JUMP_INSN in the needed registers. */
2250: for (insn = target; insn != stop_insn; insn = next_active_insn (insn))
2251: {
2252: mark_referenced_resources (insn, &needed, 1);
2253:
2254: COPY_HARD_REG_SET (scratch, needed.regs);
2255: AND_COMPL_HARD_REG_SET (scratch, set.regs);
2256: IOR_HARD_REG_SET (new_resources.regs, scratch);
2257:
1.1.1.4 ! root 2258: mark_set_resources (insn, &set, 0, 1);
1.1 root 2259: }
2260:
2261: AND_HARD_REG_SET (res->regs, new_resources.regs);
2262: }
2263:
2264: COPY_HARD_REG_SET (tinfo->live_regs, res->regs);
2265: }
2266:
2267: /* Scan a function looking for insns that need a delay slot and find insns to
2268: put into the delay slot.
2269:
2270: NON_JUMPS_P is non-zero if we are to only try to fill non-jump insns (such
2271: as calls). We do these first since we don't want jump insns (that are
2272: easier to fill) to get the only insns that could be used for non-jump insns.
2273: When it is zero, only try to fill JUMP_INSNs.
2274:
2275: When slots are filled in this manner, the insns (including the
2276: delay_insn) are put together in a SEQUENCE rtx. In this fashion,
2277: it is possible to tell whether a delay slot has really been filled
2278: or not. `final' knows how to deal with this, by communicating
2279: through FINAL_SEQUENCE. */
2280:
2281: static void
2282: fill_simple_delay_slots (first, non_jumps_p)
2283: rtx first;
2284: {
2285: register rtx insn, pat, trial, next_trial;
1.1.1.4 ! root 2286: register int i, j;
1.1 root 2287: int num_unfilled_slots = unfilled_slots_next - unfilled_slots_base;
2288: struct resources needed, set;
2289: register int slots_to_fill, slots_filled;
2290: rtx delay_list;
2291:
2292: for (i = 0; i < num_unfilled_slots; i++)
2293: {
2294: /* Get the next insn to fill. If it has already had any slots assigned,
2295: we can't do anything with it. Maybe we'll improve this later. */
2296:
2297: insn = unfilled_slots_base[i];
2298: if (insn == 0
2299: || INSN_DELETED_P (insn)
2300: || (GET_CODE (insn) == INSN
2301: && GET_CODE (PATTERN (insn)) == SEQUENCE)
2302: || (GET_CODE (insn) == JUMP_INSN && non_jumps_p)
2303: || (GET_CODE (insn) != JUMP_INSN && ! non_jumps_p))
2304: continue;
2305:
2306: slots_to_fill = num_delay_slots (insn);
2307: if (slots_to_fill == 0)
2308: abort ();
2309:
2310: /* This insn needs, or can use, some delay slots. SLOTS_TO_FILL
1.1.1.4 ! root 2311: says how many. After initialization, first try optimizing
! 2312:
! 2313: call _foo call _foo
! 2314: nop add %o7,.-L1,%o7
! 2315: b,a L1
! 2316: nop
! 2317:
! 2318: If this case applies, the delay slot of the call is filled with
! 2319: the unconditional jump. This is done first to avoid having the
! 2320: delay slot of the call filled in the backward scan. Also, since
! 2321: the unconditional jump is likely to also have a delay slot, that
! 2322: insn must exist when it is subsequently scanned. */
! 2323:
! 2324: slots_filled = 0;
! 2325: delay_list = 0;
! 2326:
! 2327: if (GET_CODE (insn) == CALL_INSN
! 2328: && (trial = next_active_insn (insn))
! 2329: && GET_CODE (trial) == JUMP_INSN
! 2330: && simplejump_p (trial)
! 2331: && eligible_for_delay (insn, slots_filled, trial)
! 2332: && no_labels_between_p (insn, trial))
! 2333: {
! 2334: slots_filled++;
! 2335: delay_list = add_to_delay_list (trial, delay_list);
! 2336: /* Remove the unconditional jump from consideration for delay slot
! 2337: filling and unthread it. */
! 2338: if (unfilled_slots_base[i + 1] == trial)
! 2339: unfilled_slots_base[i + 1] = 0;
! 2340: {
! 2341: rtx next = NEXT_INSN (trial);
! 2342: rtx prev = PREV_INSN (trial);
! 2343: if (prev)
! 2344: NEXT_INSN (prev) = next;
! 2345: if (next)
! 2346: PREV_INSN (next) = prev;
! 2347: }
! 2348: }
! 2349:
! 2350: /* Now, scan backwards from the insn to search for a potential
! 2351: delay-slot candidate. Stop searching when a label or jump is hit.
! 2352:
1.1 root 2353: For each candidate, if it is to go into the delay slot (moved
2354: forward in execution sequence), it must not need or set any resources
2355: that were set by later insns and must not set any resources that
2356: are needed for those insns.
2357:
2358: The delay slot insn itself sets resources unless it is a call
2359: (in which case the called routine, not the insn itself, is doing
2360: the setting). */
2361:
1.1.1.4 ! root 2362: if (slots_filled < slots_to_fill)
1.1 root 2363: {
1.1.1.4 ! root 2364: CLEAR_RESOURCE (&needed);
! 2365: CLEAR_RESOURCE (&set);
! 2366: mark_set_resources (insn, &set, 0, 0);
! 2367: mark_referenced_resources (insn, &needed, 0);
1.1 root 2368:
1.1.1.4 ! root 2369: for (trial = prev_nonnote_insn (insn); ! stop_search_p (trial, 1);
! 2370: trial = next_trial)
! 2371: {
! 2372: next_trial = prev_nonnote_insn (trial);
1.1 root 2373:
1.1.1.4 ! root 2374: /* This must be an INSN or CALL_INSN. */
! 2375: pat = PATTERN (trial);
! 2376:
! 2377: /* USE and CLOBBER at this level was just for flow; ignore it. */
! 2378: if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER)
! 2379: continue;
1.1 root 2380:
1.1.1.4 ! root 2381: /* Check for resource conflict first, to avoid unnecessary
! 2382: splitting. */
! 2383: if (! insn_references_resource_p (trial, &set, 1)
! 2384: && ! insn_sets_resource_p (trial, &set, 1)
! 2385: && ! insn_sets_resource_p (trial, &needed, 1)
1.1 root 2386: #ifdef HAVE_cc0
1.1.1.4 ! root 2387: /* Can't separate set of cc0 from its use. */
! 2388: && ! (reg_mentioned_p (cc0_rtx, pat)
! 2389: && ! sets_cc0_p (cc0_rtx, pat))
1.1 root 2390: #endif
1.1.1.4 ! root 2391: )
1.1 root 2392: {
1.1.1.4 ! root 2393: trial = try_split (pat, trial, 1);
! 2394: next_trial = prev_nonnote_insn (trial);
! 2395: if (eligible_for_delay (insn, slots_filled, trial))
! 2396: {
! 2397: /* In this case, we are searching backward, so if we
! 2398: find insns to put on the delay list, we want
! 2399: to put them at the head, rather than the
! 2400: tail, of the list. */
! 2401:
! 2402: delay_list = gen_rtx (INSN_LIST, VOIDmode,
! 2403: trial, delay_list);
! 2404: update_block (trial, trial);
! 2405: delete_insn (trial);
! 2406: if (slots_to_fill == ++slots_filled)
! 2407: break;
! 2408: continue;
! 2409: }
1.1 root 2410: }
2411:
1.1.1.4 ! root 2412: mark_set_resources (trial, &set, 0, 1);
! 2413: mark_referenced_resources (trial, &needed, 1);
! 2414: }
1.1 root 2415: }
2416:
2417: /* If all needed slots haven't been filled, we come here. */
2418:
2419: /* Try to optimize case of jumping around a single insn. */
2420: #if defined(ANNUL_IFFALSE_SLOTS) || defined(ANNUL_IFTRUE_SLOTS)
1.1.1.4 ! root 2421: if (slots_filled != slots_to_fill
! 2422: && delay_list == 0
! 2423: && GET_CODE (insn) == JUMP_INSN && condjump_p (insn))
1.1 root 2424: {
2425: delay_list = optimize_skip (insn);
2426: if (delay_list)
2427: slots_filled += 1;
2428: }
2429: #endif
2430:
2431: /* Try to get insns from beyond the insn needing the delay slot.
2432: These insns can neither set or reference resources set in insns being
2433: skipped, cannot set resources in the insn being skipped, and, if this
2434: is a CALL_INSN (or a CALL_INSN is passed), cannot trap (because the
2435: call might not return).
2436:
2437: If this is a conditional jump, see if it merges back to us early
2438: enough for us to pick up insns from the merge point. Don't do
2439: this if there is another branch to our label unless we pass all of
2440: them.
2441:
2442: Another similar merge is if we jump to the same place that a
2443: later unconditional jump branches to. In that case, we don't
2444: care about the number of uses of our label. */
2445:
1.1.1.4 ! root 2446: if (slots_filled != slots_to_fill
! 2447: && (GET_CODE (insn) != JUMP_INSN
! 2448: || (condjump_p (insn) && ! simplejump_p (insn)
! 2449: && JUMP_LABEL (insn) != 0)))
1.1 root 2450: {
2451: rtx target = 0;
2452: int maybe_never = 0;
2453: int passed_label = 0;
2454: int target_uses;
2455: struct resources needed_at_jump;
2456:
2457: CLEAR_RESOURCE (&needed);
2458: CLEAR_RESOURCE (&set);
2459:
2460: if (GET_CODE (insn) == CALL_INSN)
2461: {
1.1.1.4 ! root 2462: mark_set_resources (insn, &set, 0, 1);
1.1 root 2463: mark_referenced_resources (insn, &needed, 1);
2464: maybe_never = 1;
2465: }
1.1.1.4 ! root 2466: else
1.1 root 2467: {
1.1.1.4 ! root 2468: mark_set_resources (insn, &set, 0, 0);
! 2469: mark_referenced_resources (insn, &needed, 0);
! 2470: if (GET_CODE (insn) == JUMP_INSN)
! 2471: {
! 2472: /* Get our target and show how many more uses we want to
! 2473: see before we hit the label. */
! 2474: target = JUMP_LABEL (insn);
! 2475: target_uses = LABEL_NUSES (target) - 1;
! 2476: }
! 2477:
1.1 root 2478: }
2479:
2480: for (trial = next_nonnote_insn (insn); trial; trial = next_trial)
2481: {
2482: rtx pat, trial_delay;
2483:
2484: next_trial = next_nonnote_insn (trial);
2485:
2486: if (GET_CODE (trial) == CODE_LABEL)
2487: {
2488: passed_label = 1;
2489:
2490: /* If this is our target, see if we have seen all its uses.
2491: If so, indicate we have passed our target and ignore it.
2492: All other labels cause us to stop our search. */
2493: if (trial == target && target_uses == 0)
2494: {
2495: target = 0;
2496: continue;
2497: }
2498: else
2499: break;
2500: }
2501: else if (GET_CODE (trial) == BARRIER)
2502: break;
2503:
2504: /* We must have an INSN, JUMP_INSN, or CALL_INSN. */
2505: pat = PATTERN (trial);
2506:
2507: /* Stand-alone USE and CLOBBER are just for flow. */
2508: if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER)
2509: continue;
2510:
2511: /* If this already has filled delay slots, get the insn needing
2512: the delay slots. */
2513: if (GET_CODE (pat) == SEQUENCE)
2514: trial_delay = XVECEXP (pat, 0, 0);
2515: else
2516: trial_delay = trial;
2517:
2518: /* If this is a jump insn to our target, indicate that we have
2519: seen another jump to it. If we aren't handling a conditional
2520: jump, stop our search. Otherwise, compute the needs at its
2521: target and add them to NEEDED. */
2522: if (GET_CODE (trial_delay) == JUMP_INSN)
2523: {
2524: if (target == 0)
2525: break;
2526: else if (JUMP_LABEL (trial_delay) == target)
2527: target_uses--;
2528: else
2529: {
2530: mark_target_live_regs
2531: (next_active_insn (JUMP_LABEL (trial_delay)),
2532: &needed_at_jump);
2533: needed.memory |= needed_at_jump.memory;
2534: IOR_HARD_REG_SET (needed.regs, needed_at_jump.regs);
2535: }
2536: }
2537:
2538: /* See if we have a resource problem before we try to
2539: split. */
2540: if (target == 0
2541: && GET_CODE (pat) != SEQUENCE
2542: && ! insn_references_resource_p (trial, &set, 1)
2543: && ! insn_sets_resource_p (trial, &set, 1)
2544: && ! insn_sets_resource_p (trial, &needed, 1)
2545: #ifdef HAVE_cc0
2546: && ! (reg_mentioned_p (cc0_rtx, pat) && ! sets_cc0_p (pat))
2547: #endif
2548: && ! (maybe_never && may_trap_p (pat))
2549: && (trial = try_split (pat, trial, 0))
2550: && eligible_for_delay (insn, slots_filled, trial))
2551: {
2552: next_trial = next_nonnote_insn (trial);
2553: delay_list = add_to_delay_list (trial, delay_list);
2554:
2555: #ifdef HAVE_cc0
2556: if (reg_mentioned_p (cc0_rtx, pat))
2557: link_cc0_insns (trial);
2558: #endif
2559:
2560: if (passed_label)
2561: update_block (trial, trial);
2562: delete_insn (trial);
2563: if (slots_to_fill == ++slots_filled)
2564: break;
2565: continue;
2566: }
2567:
1.1.1.4 ! root 2568: mark_set_resources (trial, &set, 0, 1);
1.1 root 2569: mark_referenced_resources (trial, &needed, 1);
2570:
2571: /* Ensure we don't put insns between the setting of cc and the
2572: comparison by moving a setting of cc into an earlier delay
2573: slot since these insns could clobber the condition code. */
2574: set.cc = 1;
2575:
2576: /* If this is a call or jump, we might not get here. */
2577: if (GET_CODE (trial) == CALL_INSN
2578: || GET_CODE (trial) == JUMP_INSN)
2579: maybe_never = 1;
2580: }
2581:
2582: /* If there are slots left to fill and our search was stopped by an
2583: unconditional branch, try the insn at the branch target. We can
2584: redirect the branch if it works. */
2585: if (slots_to_fill != slots_filled
2586: && trial
2587: && GET_CODE (trial) == JUMP_INSN
2588: && simplejump_p (trial)
2589: && (target == 0 || JUMP_LABEL (trial) == target)
2590: && (next_trial = next_active_insn (JUMP_LABEL (trial))) != 0
2591: && ! (GET_CODE (next_trial) == INSN
2592: && GET_CODE (PATTERN (next_trial)) == SEQUENCE)
2593: && ! insn_references_resource_p (next_trial, &set, 1)
2594: && ! insn_sets_resource_p (next_trial, &set, 1)
2595: && ! insn_sets_resource_p (next_trial, &needed, 1)
2596: #ifdef HAVE_cc0
1.1.1.4 ! root 2597: && ! reg_mentioned_p (cc0_rtx, PATTERN (next_trial))
1.1 root 2598: #endif
2599: && ! (maybe_never && may_trap_p (PATTERN (next_trial)))
2600: && (next_trial = try_split (PATTERN (next_trial), next_trial, 0))
2601: && eligible_for_delay (insn, slots_filled, next_trial))
2602: {
2603: rtx new_label = next_active_insn (next_trial);
2604:
2605: if (new_label != 0)
2606: new_label = get_label_before (new_label);
2607:
2608: delay_list
2609: = add_to_delay_list (copy_rtx (next_trial), delay_list);
2610: slots_filled++;
2611: redirect_jump (trial, new_label);
2612:
2613: /* If we merged because we both jumped to the same place,
2614: redirect the original insn also. */
2615: if (target)
2616: redirect_jump (insn, new_label);
2617: }
2618: }
2619:
2620: if (delay_list)
2621: unfilled_slots_base[i]
2622: = emit_delay_sequence (insn, delay_list,
2623: slots_filled, slots_to_fill);
2624:
2625: if (slots_to_fill == slots_filled)
2626: unfilled_slots_base[i] = 0;
2627:
2628: note_delay_statistics (slots_filled, 0);
2629: }
2630:
2631: #ifdef DELAY_SLOTS_FOR_EPILOGUE
2632: /* See if the epilogue needs any delay slots. Try to fill them if so.
2633: The only thing we can do is scan backwards from the end of the
2634: function. If we did this in a previous pass, it is incorrect to do it
2635: again. */
2636: if (current_function_epilogue_delay_list)
2637: return;
2638:
2639: slots_to_fill = DELAY_SLOTS_FOR_EPILOGUE;
2640: if (slots_to_fill == 0)
2641: return;
2642:
2643: slots_filled = 0;
2644: CLEAR_RESOURCE (&needed);
2645: CLEAR_RESOURCE (&set);
2646:
2647: for (trial = get_last_insn (); ! stop_search_p (trial, 1);
2648: trial = PREV_INSN (trial))
2649: {
2650: if (GET_CODE (trial) == NOTE)
2651: continue;
2652: pat = PATTERN (trial);
2653: if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER)
2654: continue;
2655:
2656: if (! insn_references_resource_p (trial, &set, 1)
2657: && ! insn_sets_resource_p (trial, &needed, 1)
2658: #ifdef HAVE_cc0
2659: /* Don't want to mess with cc0 here. */
2660: && ! reg_mentioned_p (cc0_rtx, pat)
2661: #endif
2662: )
2663: {
2664: trial = try_split (pat, trial, 1);
2665: if (ELIGIBLE_FOR_EPILOGUE_DELAY (trial, slots_filled))
2666: {
2667: /* Here as well we are searching backward, so put the
2668: insns we find on the head of the list. */
2669:
2670: current_function_epilogue_delay_list
2671: = gen_rtx (INSN_LIST, VOIDmode, trial,
2672: current_function_epilogue_delay_list);
2673: mark_referenced_resources (trial, &end_of_function_needs, 1);
2674: update_block (trial, trial);
2675: delete_insn (trial);
2676:
2677: /* Clear deleted bit so final.c will output the insn. */
2678: INSN_DELETED_P (trial) = 0;
2679:
2680: if (slots_to_fill == ++slots_filled)
2681: break;
2682: continue;
2683: }
2684: }
2685:
1.1.1.4 ! root 2686: mark_set_resources (trial, &set, 0, 1);
1.1 root 2687: mark_referenced_resources (trial, &needed, 1);
2688: }
2689:
2690: note_delay_statistics (slots_filled, 0);
2691: #endif
2692: }
2693:
2694: /* Try to find insns to place in delay slots.
2695:
2696: INSN is the jump needing SLOTS_TO_FILL delay slots. It tests CONDITION
2697: or is an unconditional branch if CONDITION is const_true_rtx.
2698: *PSLOTS_FILLED is updated with the number of slots that we have filled.
2699:
2700: THREAD is a flow-of-control, either the insns to be executed if the
2701: branch is true or if the branch is false, THREAD_IF_TRUE says which.
2702:
2703: OPPOSITE_THREAD is the thread in the opposite direction. It is used
2704: to see if any potential delay slot insns set things needed there.
2705:
2706: LIKELY is non-zero if it is extremely likely that the branch will be
2707: taken and THREAD_IF_TRUE is set. This is used for the branch at the
2708: end of a loop back up to the top.
2709:
2710: OWN_THREAD and OWN_OPPOSITE_THREAD are true if we are the only user of the
2711: thread. I.e., it is the fallthrough code of our jump or the target of the
2712: jump when we are the only jump going there.
2713:
2714: If OWN_THREAD is false, it must be the "true" thread of a jump. In that
2715: case, we can only take insns from the head of the thread for our delay
2716: slot. We then adjust the jump to point after the insns we have taken. */
2717:
2718: static rtx
2719: fill_slots_from_thread (insn, condition, thread, opposite_thread, likely,
2720: thread_if_true, own_thread, own_opposite_thread,
2721: slots_to_fill, pslots_filled)
2722: rtx insn;
2723: rtx condition;
2724: rtx thread, opposite_thread;
2725: int likely;
2726: int thread_if_true;
2727: int own_thread, own_opposite_thread;
2728: int slots_to_fill, *pslots_filled;
2729: {
1.1.1.2 root 2730: rtx new_thread;
1.1 root 2731: rtx delay_list = 0;
2732: struct resources opposite_needed, set, needed;
2733: rtx trial;
2734: int lose = 0;
2735: int must_annul = 0;
2736:
2737: /* Validate our arguments. */
2738: if ((condition == const_true_rtx && ! thread_if_true)
2739: || (! own_thread && ! thread_if_true))
2740: abort ();
2741:
2742: /* If our thread is the end of subroutine, we can't get any delay
2743: insns from that. */
2744: if (thread == 0)
2745: return 0;
2746:
2747: /* If this is an unconditional branch, nothing is needed at the
2748: opposite thread. Otherwise, compute what is needed there. */
2749: if (condition == const_true_rtx)
2750: CLEAR_RESOURCE (&opposite_needed);
2751: else
2752: mark_target_live_regs (opposite_thread, &opposite_needed);
2753:
1.1.1.2 root 2754: /* If the insn at THREAD can be split, do it here to avoid having to
2755: update THREAD and NEW_THREAD if it is done in the loop below. Also
2756: initialize NEW_THREAD. */
2757:
2758: new_thread = thread = try_split (PATTERN (thread), thread, 0);
2759:
1.1 root 2760: /* Scan insns at THREAD. We are looking for an insn that can be removed
2761: from THREAD (it neither sets nor references resources that were set
2762: ahead of it and it doesn't set anything needs by the insns ahead of
2763: it) and that either can be placed in an annulling insn or aren't
2764: needed at OPPOSITE_THREAD. */
2765:
2766: CLEAR_RESOURCE (&needed);
2767: CLEAR_RESOURCE (&set);
2768:
2769: /* If we do not own this thread, we must stop as soon as we find
2770: something that we can't put in a delay slot, since all we can do
2771: is branch into THREAD at a later point. Therefore, labels stop
2772: the search if this is not the `true' thread. */
2773:
2774: for (trial = thread;
2775: ! stop_search_p (trial, ! thread_if_true) && (! lose || own_thread);
2776: trial = next_nonnote_insn (trial))
2777: {
2778: rtx pat;
2779:
2780: /* If we have passed a label, we no longer own this thread. */
2781: if (GET_CODE (trial) == CODE_LABEL)
2782: {
2783: own_thread = 0;
2784: continue;
2785: }
2786:
2787: pat = PATTERN (trial);
2788: if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER)
2789: continue;
2790:
2791: /* If TRIAL conflicts with the insns ahead of it, we lose. Also,
2792: don't separate or copy insns that set and use CC0. */
2793: if (! insn_references_resource_p (trial, &set, 1)
2794: && ! insn_sets_resource_p (trial, &set, 1)
2795: && ! insn_sets_resource_p (trial, &needed, 1)
2796: #ifdef HAVE_cc0
2797: && ! (reg_mentioned_p (cc0_rtx, pat)
2798: && (! own_thread || ! sets_cc0_p (pat)))
2799: #endif
2800: )
2801: {
2802: /* If TRIAL is redundant with some insn before INSN, we don't
2803: actually need to add it to the delay list; we can merely pretend
2804: we did. */
2805: if (redundant_insn_p (trial, insn, delay_list))
2806: {
2807: if (own_thread)
2808: {
2809: update_block (trial, thread);
2810: delete_insn (trial);
2811: }
2812: else
2813: new_thread = next_active_insn (trial);
2814:
2815: continue;
2816: }
2817:
2818: /* There are two ways we can win: If TRIAL doesn't set anything
2819: needed at the opposite thread and can't trap, or if it can
2820: go into an annulled delay slot. */
2821: if (condition == const_true_rtx
2822: || (! insn_sets_resource_p (trial, &opposite_needed, 1)
2823: && ! may_trap_p (pat)))
2824: {
2825: trial = try_split (pat, trial, 0);
2826: pat = PATTERN (trial);
2827: if (eligible_for_delay (insn, *pslots_filled, trial))
2828: goto winner;
2829: }
2830: else if (0
2831: #ifdef ANNUL_IFTRUE_SLOTS
2832: || ! thread_if_true
2833: #endif
2834: #ifdef ANNUL_IFFALSE_SLOTS
2835: || thread_if_true
2836: #endif
2837: )
2838: {
2839: trial = try_split (pat, trial, 0);
2840: pat = PATTERN (trial);
2841: if ((thread_if_true
2842: ? eligible_for_annul_false (insn, *pslots_filled, trial)
2843: : eligible_for_annul_true (insn, *pslots_filled, trial)))
2844: {
2845: rtx temp;
2846:
2847: must_annul = 1;
2848: winner:
2849:
2850: #ifdef HAVE_cc0
2851: if (reg_mentioned_p (cc0_rtx, pat))
2852: link_cc0_insns (trial);
2853: #endif
2854:
2855: /* If we own this thread, delete the insn. If this is the
2856: destination of a branch, show that a basic block status
2857: may have been updated. In any case, mark the new
2858: starting point of this thread. */
2859: if (own_thread)
2860: {
2861: update_block (trial, thread);
2862: delete_insn (trial);
2863: }
2864: else
2865: new_thread = next_active_insn (trial);
2866:
2867: temp = own_thread ? trial : copy_rtx (trial);
2868: if (thread_if_true)
2869: INSN_FROM_TARGET_P (temp) = 1;
2870:
2871: delay_list = add_to_delay_list (temp, delay_list);
2872:
2873: if (slots_to_fill == ++(*pslots_filled))
2874: {
2875: /* Even though we have filled all the slots, we
2876: may be branching to a location that has a
2877: redundant insn. Skip any if so. */
2878: while (new_thread && ! own_thread
2879: && ! insn_sets_resource_p (new_thread, &set, 1)
2880: && ! insn_sets_resource_p (new_thread, &needed, 1)
2881: && ! insn_references_resource_p (new_thread,
2882: &set, 1)
2883: && redundant_insn_p (new_thread, insn,
2884: delay_list))
2885: new_thread = next_active_insn (new_thread);
2886: break;
2887: }
2888:
2889: continue;
2890: }
2891: }
2892: }
2893:
2894: /* This insn can't go into a delay slot. */
2895: lose = 1;
1.1.1.4 ! root 2896: mark_set_resources (trial, &set, 0, 1);
1.1 root 2897: mark_referenced_resources (trial, &needed, 1);
2898:
2899: /* Ensure we don't put insns between the setting of cc and the comparison
2900: by moving a setting of cc into an earlier delay slot since these insns
2901: could clobber the condition code. */
2902: set.cc = 1;
2903:
2904: /* If this insn is a register-register copy and the next insn has
2905: a use of our destination, change it to use our source. That way,
2906: it will become a candidate for our delay slot the next time
2907: through this loop. This case occurs commonly in loops that
2908: scan a list.
2909:
2910: We could check for more complex cases than those tested below,
2911: but it doesn't seem worth it. It might also be a good idea to try
1.1.1.2 root 2912: to swap the two insns. That might do better.
2913:
2914: We can't do this if the next insn modifies our source, because that
2915: would make the replacement into the insn invalid. This also
2916: prevents updating the contents of a PRE_INC. */
1.1 root 2917:
2918: if (GET_CODE (trial) == INSN && GET_CODE (pat) == SET
2919: && GET_CODE (SET_SRC (pat)) == REG
2920: && GET_CODE (SET_DEST (pat)) == REG)
2921: {
2922: rtx next = next_nonnote_insn (trial);
2923:
2924: if (next && GET_CODE (next) == INSN
1.1.1.2 root 2925: && GET_CODE (PATTERN (next)) != USE
2926: && ! reg_set_p (SET_DEST (pat), next)
2927: && reg_referenced_p (SET_DEST (pat), PATTERN (next)))
1.1 root 2928: validate_replace_rtx (SET_DEST (pat), SET_SRC (pat), next);
2929: }
2930: }
2931:
2932: /* If we stopped on a branch insn that has delay slots, see if we can
2933: steal some of the insns in those slots. */
2934: if (trial && GET_CODE (trial) == INSN
2935: && GET_CODE (PATTERN (trial)) == SEQUENCE
2936: && GET_CODE (XVECEXP (PATTERN (trial), 0, 0)) == JUMP_INSN)
2937: {
2938: /* If this is the `true' thread, we will want to follow the jump,
2939: so we can only do this if we have taken everything up to here. */
2940: if (thread_if_true && trial == new_thread)
2941: delay_list
2942: = steal_delay_list_from_target (insn, condition, PATTERN (trial),
2943: delay_list, &set, &needed,
2944: &opposite_needed, slots_to_fill,
2945: pslots_filled, &must_annul,
2946: &new_thread);
2947: else if (! thread_if_true)
2948: delay_list
2949: = steal_delay_list_from_fallthrough (insn, condition,
2950: PATTERN (trial),
2951: delay_list, &set, &needed,
2952: &opposite_needed, slots_to_fill,
2953: pslots_filled, &must_annul);
2954: }
2955:
2956: /* If we haven't found anything for this delay slot and it is very
2957: likely that the branch will be taken, see if the insn at our target
1.1.1.2 root 2958: increments or decrements a register with an increment that does not
2959: depend on the destination register. If so, try to place the opposite
1.1 root 2960: arithmetic insn after the jump insn and put the arithmetic insn in the
2961: delay slot. If we can't do this, return. */
2962: if (delay_list == 0 && likely && new_thread && GET_CODE (new_thread) == INSN)
2963: {
2964: rtx pat = PATTERN (new_thread);
2965: rtx dest;
2966: rtx src;
2967:
1.1.1.2 root 2968: trial = new_thread;
1.1 root 2969: pat = PATTERN (trial);
2970:
2971: if (GET_CODE (trial) != INSN || GET_CODE (pat) != SET
2972: || ! eligible_for_delay (insn, 0, trial))
2973: return 0;
2974:
2975: dest = SET_DEST (pat), src = SET_SRC (pat);
2976: if ((GET_CODE (src) == PLUS || GET_CODE (src) == MINUS)
1.1.1.2 root 2977: && rtx_equal_p (XEXP (src, 0), dest)
2978: && ! reg_overlap_mentioned_p (dest, XEXP (src, 1)))
1.1 root 2979: {
2980: rtx other = XEXP (src, 1);
2981: rtx new_arith;
2982: rtx ninsn;
2983:
2984: /* If this is a constant adjustment, use the same code with
2985: the negated constant. Otherwise, reverse the sense of the
2986: arithmetic. */
2987: if (GET_CODE (other) == CONST_INT)
2988: new_arith = gen_rtx (GET_CODE (src), GET_MODE (src), dest,
2989: negate_rtx (GET_MODE (src), other));
2990: else
2991: new_arith = gen_rtx (GET_CODE (src) == PLUS ? MINUS : PLUS,
2992: GET_MODE (src), dest, other);
2993:
2994: ninsn = emit_insn_after (gen_rtx (SET, VOIDmode, dest, new_arith),
2995: insn);
2996:
2997: if (recog_memoized (ninsn) < 0
2998: || (insn_extract (ninsn),
2999: ! constrain_operands (INSN_CODE (ninsn), 1)))
3000: {
3001: delete_insn (ninsn);
3002: return 0;
3003: }
3004:
3005: if (own_thread)
3006: {
3007: update_block (trial, thread);
3008: delete_insn (trial);
3009: }
3010: else
3011: new_thread = next_active_insn (trial);
3012:
3013: ninsn = own_thread ? trial : copy_rtx (trial);
3014: if (thread_if_true)
3015: INSN_FROM_TARGET_P (ninsn) = 1;
3016:
1.1.1.4 ! root 3017: delay_list = add_to_delay_list (ninsn, NULL_RTX);
1.1 root 3018: (*pslots_filled)++;
3019: }
3020: }
3021:
3022: if (delay_list && must_annul)
3023: INSN_ANNULLED_BRANCH_P (insn) = 1;
3024:
3025: /* If we are to branch into the middle of this thread, find an appropriate
3026: label or make a new one if none, and redirect INSN to it. If we hit the
3027: end of the function, use the end-of-function label. */
3028: if (new_thread != thread)
3029: {
3030: rtx label;
3031:
3032: if (! thread_if_true)
3033: abort ();
3034:
3035: if (new_thread && GET_CODE (new_thread) == JUMP_INSN
3036: && (simplejump_p (new_thread)
3037: || GET_CODE (PATTERN (new_thread)) == RETURN))
1.1.1.4 ! root 3038: new_thread = follow_jumps (JUMP_LABEL (new_thread));
1.1 root 3039:
3040: if (new_thread == 0)
3041: label = find_end_label ();
3042: else if (GET_CODE (new_thread) == CODE_LABEL)
3043: label = new_thread;
3044: else
3045: label = get_label_before (new_thread);
3046:
3047: redirect_jump (insn, label);
3048: }
3049:
3050: return delay_list;
3051: }
3052:
3053: /* Make another attempt to find insns to place in delay slots.
3054:
3055: We previously looked for insns located in front of the delay insn
3056: and, for non-jump delay insns, located behind the delay insn.
3057:
3058: Here only try to schedule jump insns and try to move insns from either
3059: the target or the following insns into the delay slot. If annulling is
3060: supported, we will be likely to do this. Otherwise, we can do this only
3061: if safe. */
3062:
3063: static void
3064: fill_eager_delay_slots (first)
3065: rtx first;
3066: {
3067: register rtx insn;
3068: register int i;
3069: int num_unfilled_slots = unfilled_slots_next - unfilled_slots_base;
3070:
3071: for (i = 0; i < num_unfilled_slots; i++)
3072: {
3073: rtx condition;
3074: rtx target_label, insn_at_target, fallthrough_insn;
3075: rtx delay_list = 0;
3076: int own_target;
3077: int own_fallthrough;
3078: int prediction, slots_to_fill, slots_filled;
3079:
3080: insn = unfilled_slots_base[i];
3081: if (insn == 0
3082: || INSN_DELETED_P (insn)
3083: || GET_CODE (insn) != JUMP_INSN
3084: || ! condjump_p (insn))
3085: continue;
3086:
3087: slots_to_fill = num_delay_slots (insn);
3088: if (slots_to_fill == 0)
3089: abort ();
3090:
3091: slots_filled = 0;
3092: target_label = JUMP_LABEL (insn);
3093: condition = get_branch_condition (insn, target_label);
3094:
3095: if (condition == 0)
3096: continue;
3097:
3098: /* Get the next active fallthough and target insns and see if we own
3099: them. Then see whether the branch is likely true. We don't need
3100: to do a lot of this for unconditional branches. */
3101:
3102: insn_at_target = next_active_insn (target_label);
3103: own_target = own_thread_p (target_label, target_label, 0);
3104:
3105: if (condition == const_true_rtx)
3106: {
3107: own_fallthrough = 0;
3108: fallthrough_insn = 0;
3109: prediction = 2;
3110: }
3111: else
3112: {
3113: fallthrough_insn = next_active_insn (insn);
1.1.1.4 ! root 3114: own_fallthrough = own_thread_p (NEXT_INSN (insn), NULL_RTX, 1);
1.1 root 3115: prediction = mostly_true_jump (insn, condition);
3116: }
3117:
3118: /* If this insn is expected to branch, first try to get insns from our
3119: target, then our fallthrough insns. If it is not, expected to branch,
3120: try the other order. */
3121:
3122: if (prediction)
3123: {
3124: delay_list
3125: = fill_slots_from_thread (insn, condition, insn_at_target,
3126: fallthrough_insn, prediction == 2, 1,
3127: own_target, own_fallthrough,
3128: slots_to_fill, &slots_filled);
3129:
3130: if (delay_list == 0 && own_fallthrough)
3131: {
3132: /* Even though we didn't find anything for delay slots,
3133: we might have found a redundant insn which we deleted
3134: from the thread that was filled. So we have to recompute
3135: the next insn at the target. */
3136: target_label = JUMP_LABEL (insn);
3137: insn_at_target = next_active_insn (target_label);
3138:
3139: delay_list
3140: = fill_slots_from_thread (insn, condition, fallthrough_insn,
3141: insn_at_target, 0, 0,
3142: own_fallthrough, own_target,
3143: slots_to_fill, &slots_filled);
3144: }
3145: }
3146: else
3147: {
3148: if (own_fallthrough)
3149: delay_list
3150: = fill_slots_from_thread (insn, condition, fallthrough_insn,
3151: insn_at_target, 0, 0,
3152: own_fallthrough, own_target,
3153: slots_to_fill, &slots_filled);
3154:
3155: if (delay_list == 0)
3156: delay_list
3157: = fill_slots_from_thread (insn, condition, insn_at_target,
3158: next_active_insn (insn), 0, 1,
3159: own_target, own_fallthrough,
3160: slots_to_fill, &slots_filled);
3161: }
3162:
3163: if (delay_list)
3164: unfilled_slots_base[i]
3165: = emit_delay_sequence (insn, delay_list,
3166: slots_filled, slots_to_fill);
3167:
3168: if (slots_to_fill == slots_filled)
3169: unfilled_slots_base[i] = 0;
3170:
3171: note_delay_statistics (slots_filled, 1);
3172: }
3173: }
3174:
3175: /* Once we have tried two ways to fill a delay slot, make a pass over the
3176: code to try to improve the results and to do such things as more jump
3177: threading. */
3178:
3179: static void
3180: relax_delay_slots (first)
3181: rtx first;
3182: {
3183: register rtx insn, next, pat;
3184: register rtx trial, delay_insn, target_label;
3185:
3186: /* Look at every JUMP_INSN and see if we can improve it. */
3187: for (insn = first; insn; insn = next)
3188: {
3189: rtx other;
3190:
3191: next = next_active_insn (insn);
3192:
3193: /* If this is a jump insn, see if it now jumps to a jump, jumps to
3194: the next insn, or jumps to a label that is not the last of a
3195: group of consecutive labels. */
3196: if (GET_CODE (insn) == JUMP_INSN
3197: && (target_label = JUMP_LABEL (insn)) != 0)
3198: {
1.1.1.4 ! root 3199: target_label = follow_jumps (target_label);
1.1 root 3200: target_label = prev_label (next_active_insn (target_label));
3201:
1.1.1.3 root 3202: if (target_label == 0)
3203: target_label = find_end_label ();
3204:
1.1 root 3205: if (next_active_insn (target_label) == next)
3206: {
3207: delete_jump (insn);
3208: continue;
3209: }
3210:
3211: if (target_label != JUMP_LABEL (insn))
1.1.1.3 root 3212: redirect_jump (insn, target_label);
1.1 root 3213:
3214: /* See if this jump branches around a unconditional jump.
3215: If so, invert this jump and point it to the target of the
3216: second jump. */
3217: if (next && GET_CODE (next) == JUMP_INSN
3218: && (simplejump_p (next) || GET_CODE (PATTERN (next)) == RETURN)
3219: && next_active_insn (target_label) == next_active_insn (next)
3220: && no_labels_between_p (insn, next))
3221: {
3222: rtx label = JUMP_LABEL (next);
3223:
3224: /* Be careful how we do this to avoid deleting code or
3225: labels that are momentarily dead. See similar optimization
3226: in jump.c.
3227:
3228: We also need to ensure we properly handle the case when
3229: invert_jump fails. */
3230:
3231: ++LABEL_NUSES (target_label);
3232: if (label)
3233: ++LABEL_NUSES (label);
3234:
3235: if (invert_jump (insn, label))
3236: {
3237: delete_insn (next);
3238: next = insn;
3239: }
3240:
3241: if (label)
3242: --LABEL_NUSES (label);
3243:
3244: if (--LABEL_NUSES (target_label) == 0)
3245: delete_insn (target_label);
3246:
3247: continue;
3248: }
3249: }
3250:
3251: /* If this is an unconditional jump and the previous insn is a
3252: conditional jump, try reversing the condition of the previous
3253: insn and swapping our targets. The next pass might be able to
3254: fill the slots.
3255:
3256: Don't do this if we expect the conditional branch to be true, because
3257: we would then be making the more common case longer. */
3258:
3259: if (GET_CODE (insn) == JUMP_INSN
3260: && (simplejump_p (insn) || GET_CODE (PATTERN (insn)) == RETURN)
3261: && (other = prev_active_insn (insn)) != 0
3262: && condjump_p (other)
3263: && no_labels_between_p (other, insn)
3264: && ! mostly_true_jump (other,
3265: get_branch_condition (other,
3266: JUMP_LABEL (other))))
3267: {
3268: rtx other_target = JUMP_LABEL (other);
3269:
3270: /* Increment the count of OTHER_TARGET, so it doesn't get deleted
3271: as we move the label. */
3272: if (other_target)
3273: ++LABEL_NUSES (other_target);
3274:
3275: if (invert_jump (other, target_label))
3276: redirect_jump (insn, other_target);
3277:
3278: if (other_target)
3279: --LABEL_NUSES (other_target);
3280: }
3281:
3282: /* Now look only at cases where we have filled a delay slot. */
3283: if (GET_CODE (insn) != INSN
3284: || GET_CODE (PATTERN (insn)) != SEQUENCE)
3285: continue;
3286:
3287: pat = PATTERN (insn);
3288: delay_insn = XVECEXP (pat, 0, 0);
3289:
3290: /* See if the first insn in the delay slot is redundant with some
3291: previous insn. Remove it from the delay slot if so; then set up
3292: to reprocess this insn. */
3293: if (redundant_insn_p (XVECEXP (pat, 0, 1), delay_insn, 0))
3294: {
3295: delete_from_delay_slot (XVECEXP (pat, 0, 1));
3296: next = prev_active_insn (next);
3297: continue;
3298: }
3299:
3300: /* Now look only at the cases where we have a filled JUMP_INSN. */
3301: if (GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) != JUMP_INSN
3302: || ! condjump_p (XVECEXP (PATTERN (insn), 0, 0)))
3303: continue;
3304:
3305: target_label = JUMP_LABEL (delay_insn);
3306:
3307: if (target_label)
3308: {
3309: /* If this jump goes to another unconditional jump, thread it, but
3310: don't convert a jump into a RETURN here. */
1.1.1.4 ! root 3311: trial = follow_jumps (target_label);
1.1 root 3312: trial = prev_label (next_active_insn (trial));
3313: if (trial == 0 && target_label != 0)
3314: trial = find_end_label ();
3315:
3316: if (trial != target_label)
3317: {
3318: redirect_jump (delay_insn, trial);
3319: target_label = trial;
3320: }
3321:
3322: /* If the first insn at TARGET_LABEL is redundant with a previous
3323: insn, redirect the jump to the following insn process again. */
3324: trial = next_active_insn (target_label);
3325: if (trial && GET_CODE (PATTERN (trial)) != SEQUENCE
3326: && redundant_insn_p (trial, insn, 0))
3327: {
3328: trial = next_active_insn (trial);
3329: if (trial == 0)
3330: target_label = find_end_label ();
3331: else
3332: target_label = get_label_before (trial);
3333: redirect_jump (delay_insn, target_label);
3334: next = insn;
3335: continue;
3336: }
3337:
3338: /* Similarly, if it is an unconditional jump with one insn in its
3339: delay list and that insn is redundant, thread the jump. */
3340: if (trial && GET_CODE (PATTERN (trial)) == SEQUENCE
3341: && XVECLEN (PATTERN (trial), 0) == 2
3342: && GET_CODE (XVECEXP (PATTERN (trial), 0, 0)) == JUMP_INSN
3343: && (simplejump_p (XVECEXP (PATTERN (trial), 0, 0))
3344: || GET_CODE (PATTERN (XVECEXP (PATTERN (trial), 0, 0))) == RETURN)
3345: && redundant_insn_p (XVECEXP (PATTERN (trial), 0, 1), insn, 0))
3346: {
3347: target_label = JUMP_LABEL (XVECEXP (PATTERN (trial), 0, 0));
3348: if (target_label == 0)
3349: target_label = find_end_label ();
3350: redirect_jump (delay_insn, target_label);
3351: next = insn;
3352: continue;
3353: }
3354: }
3355:
3356: if (! INSN_ANNULLED_BRANCH_P (delay_insn)
3357: && prev_active_insn (target_label) == insn
3358: #ifdef HAVE_cc0
3359: /* If the last insn in the delay slot sets CC0 for some insn,
3360: various code assumes that it is in a delay slot. We could
3361: put it back where it belonged and delete the register notes,
1.1.1.3 root 3362: but it doesn't seem worthwhile in this uncommon case. */
1.1 root 3363: && ! find_reg_note (XVECEXP (pat, 0, XVECLEN (pat, 0) - 1),
1.1.1.4 ! root 3364: REG_CC_USER, NULL_RTX)
1.1 root 3365: #endif
3366: )
3367: {
1.1.1.3 root 3368: int i;
3369:
1.1 root 3370: /* All this insn does is execute its delay list and jump to the
3371: following insn. So delete the jump and just execute the delay
3372: list insns.
3373:
3374: We do this by deleting the INSN containing the SEQUENCE, then
3375: re-emitting the insns separately, and then deleting the jump.
3376: This allows the count of the jump target to be properly
3377: decremented. */
3378:
1.1.1.3 root 3379: /* Clear the from target bit, since these insns are no longer
3380: in delay slots. */
3381: for (i = 0; i < XVECLEN (pat, 0); i++)
3382: INSN_FROM_TARGET_P (XVECEXP (pat, 0, i)) = 0;
3383:
1.1 root 3384: trial = PREV_INSN (insn);
3385: delete_insn (insn);
3386: emit_insn_after (pat, trial);
3387: delete_scheduled_jump (delay_insn);
3388: continue;
3389: }
3390:
3391: /* See if this jump (with its delay slots) branches around another
3392: jump (without delay slots). If so, invert this jump and point
3393: it to the target of the second jump. We cannot do this for
3394: annulled jumps, though. Again, don't convert a jump to a RETURN
3395: here. */
3396: if (! INSN_ANNULLED_BRANCH_P (delay_insn)
3397: && next && GET_CODE (next) == JUMP_INSN
3398: && (simplejump_p (next) || GET_CODE (PATTERN (next)) == RETURN)
3399: && next_active_insn (target_label) == next_active_insn (next)
3400: && no_labels_between_p (insn, next))
3401: {
3402: rtx label = JUMP_LABEL (next);
3403: rtx old_label = JUMP_LABEL (delay_insn);
3404:
3405: if (label == 0)
3406: label = find_end_label ();
3407:
3408: /* Be careful how we do this to avoid deleting code or labels
3409: that are momentarily dead. See similar optimization in jump.c */
3410: if (old_label)
3411: ++LABEL_NUSES (old_label);
3412:
3413: if (invert_jump (delay_insn, label))
3414: {
3415: delete_insn (next);
3416: next = insn;
3417: }
3418:
3419: if (old_label && --LABEL_NUSES (old_label) == 0)
3420: delete_insn (old_label);
3421: continue;
3422: }
3423:
3424: /* If we own the thread opposite the way this insn branches, see if we
3425: can merge its delay slots with following insns. */
3426: if (INSN_FROM_TARGET_P (XVECEXP (pat, 0, 1))
3427: && own_thread_p (NEXT_INSN (insn), 0, 1))
3428: try_merge_delay_insns (insn, next);
3429: else if (! INSN_FROM_TARGET_P (XVECEXP (pat, 0, 1))
3430: && own_thread_p (target_label, target_label, 0))
3431: try_merge_delay_insns (insn, next_active_insn (target_label));
3432:
3433: /* If we get here, we haven't deleted INSN. But we may have deleted
3434: NEXT, so recompute it. */
3435: next = next_active_insn (insn);
3436: }
3437: }
3438:
3439: #ifdef HAVE_return
3440:
3441: /* Look for filled jumps to the end of function label. We can try to convert
3442: them into RETURN insns if the insns in the delay slot are valid for the
3443: RETURN as well. */
3444:
3445: static void
3446: make_return_insns (first)
3447: rtx first;
3448: {
3449: rtx insn, jump_insn, pat;
3450: rtx real_return_label = end_of_function_label;
3451: int slots, i;
3452:
3453: /* See if there is a RETURN insn in the function other than the one we
3454: made for END_OF_FUNCTION_LABEL. If so, set up anything we can't change
3455: into a RETURN to jump to it. */
3456: for (insn = first; insn; insn = NEXT_INSN (insn))
3457: if (GET_CODE (insn) == JUMP_INSN && GET_CODE (PATTERN (insn)) == RETURN)
3458: {
3459: real_return_label = get_label_before (insn);
3460: break;
3461: }
3462:
3463: /* Show an extra usage of REAL_RETURN_LABEL so it won't go away if it
3464: was equal to END_OF_FUNCTION_LABEL. */
3465: LABEL_NUSES (real_return_label)++;
3466:
3467: /* Clear the list of insns to fill so we can use it. */
3468: obstack_free (&unfilled_slots_obstack, unfilled_firstobj);
3469:
3470: for (insn = first; insn; insn = NEXT_INSN (insn))
3471: {
3472: /* Only look at filled JUMP_INSNs that go to the end of function
3473: label. */
3474: if (GET_CODE (insn) != INSN
3475: || GET_CODE (PATTERN (insn)) != SEQUENCE
3476: || GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) != JUMP_INSN
3477: || JUMP_LABEL (XVECEXP (PATTERN (insn), 0, 0)) != end_of_function_label)
3478: continue;
3479:
3480: pat = PATTERN (insn);
3481: jump_insn = XVECEXP (pat, 0, 0);
3482:
3483: /* If we can't make the jump into a RETURN, redirect it to the best
3484: RETURN and go on to the next insn. */
1.1.1.4 ! root 3485: if (! redirect_jump (jump_insn, NULL_RTX))
1.1 root 3486: {
3487: redirect_jump (jump_insn, real_return_label);
3488: continue;
3489: }
3490:
3491: /* See if this RETURN can accept the insns current in its delay slot.
3492: It can if it has more or an equal number of slots and the contents
3493: of each is valid. */
3494:
3495: slots = num_delay_slots (jump_insn);
3496: if (slots >= XVECLEN (pat, 0) - 1)
3497: {
3498: for (i = 1; i < XVECLEN (pat, 0); i++)
3499: if (! (
3500: #ifdef ANNUL_IFFALSE_SLOTS
3501: (INSN_ANNULLED_BRANCH_P (jump_insn)
3502: && INSN_FROM_TARGET_P (XVECEXP (pat, 0, i)))
3503: ? eligible_for_annul_false (jump_insn, i - 1,
3504: XVECEXP (pat, 0, i)) :
3505: #endif
3506: #ifdef ANNUL_IFTRUE_SLOTS
3507: (INSN_ANNULLED_BRANCH_P (jump_insn)
3508: && ! INSN_FROM_TARGET_P (XVECEXP (pat, 0, i)))
3509: ? eligible_for_annul_true (jump_insn, i - 1,
3510: XVECEXP (pat, 0, i)) :
3511: #endif
3512: eligible_for_delay (jump_insn, i -1, XVECEXP (pat, 0, i))))
3513: break;
3514: }
3515: else
3516: i = 0;
3517:
3518: if (i == XVECLEN (pat, 0))
3519: continue;
3520:
3521: /* We have to do something with this insn. If it is an unconditional
3522: RETURN, delete the SEQUENCE and output the individual insns,
3523: followed by the RETURN. Then set things up so we try to find
3524: insns for its delay slots, if it needs some. */
3525: if (GET_CODE (PATTERN (jump_insn)) == RETURN)
3526: {
3527: rtx prev = PREV_INSN (insn);
3528:
3529: delete_insn (insn);
3530: for (i = 1; i < XVECLEN (pat, 0); i++)
3531: prev = emit_insn_after (PATTERN (XVECEXP (pat, 0, i)), prev);
3532:
3533: insn = emit_jump_insn_after (PATTERN (jump_insn), prev);
3534: emit_barrier_after (insn);
3535:
3536: if (slots)
3537: obstack_ptr_grow (&unfilled_slots_obstack, insn);
3538: }
3539: else
3540: /* It is probably more efficient to keep this with its current
3541: delay slot as a branch to a RETURN. */
3542: redirect_jump (jump_insn, real_return_label);
3543: }
3544:
3545: /* Now delete REAL_RETURN_LABEL if we never used it. Then try to fill any
3546: new delay slots we have created. */
3547: if (--LABEL_NUSES (real_return_label) == 0)
3548: delete_insn (real_return_label);
3549:
3550: fill_simple_delay_slots (first, 1);
3551: fill_simple_delay_slots (first, 0);
3552: }
3553: #endif
3554:
3555: /* Try to find insns to place in delay slots. */
3556:
3557: void
3558: dbr_schedule (first, file)
3559: rtx first;
3560: FILE *file;
3561: {
1.1.1.4 ! root 3562: rtx insn, next, epilogue_insn = 0;
1.1 root 3563: int i;
3564: #if 0
3565: int old_flag_no_peephole = flag_no_peephole;
3566:
3567: /* Execute `final' once in prescan mode to delete any insns that won't be
3568: used. Don't let final try to do any peephole optimization--it will
3569: ruin dataflow information for this pass. */
3570:
3571: flag_no_peephole = 1;
3572: final (first, 0, NO_DEBUG, 1, 1);
3573: flag_no_peephole = old_flag_no_peephole;
3574: #endif
3575:
3576: /* Find the highest INSN_UID and allocate and initialize our map from
3577: INSN_UID's to position in code. */
3578: for (max_uid = 0, insn = first; insn; insn = NEXT_INSN (insn))
1.1.1.4 ! root 3579: {
! 3580: if (INSN_UID (insn) > max_uid)
! 3581: max_uid = INSN_UID (insn);
! 3582: if (GET_CODE (insn) == NOTE
! 3583: && NOTE_LINE_NUMBER (insn) == NOTE_INSN_EPILOGUE_BEG)
! 3584: epilogue_insn = insn;
! 3585: }
1.1 root 3586:
3587: uid_to_ruid = (int *) alloca ((max_uid + 1) * sizeof (int *));
3588: for (i = 0, insn = first; insn; i++, insn = NEXT_INSN (insn))
3589: uid_to_ruid[INSN_UID (insn)] = i;
3590:
3591: /* Initialize the list of insns that need filling. */
3592: if (unfilled_firstobj == 0)
3593: {
3594: gcc_obstack_init (&unfilled_slots_obstack);
3595: unfilled_firstobj = (rtx *) obstack_alloc (&unfilled_slots_obstack, 0);
3596: }
3597:
3598: for (insn = next_active_insn (first); insn; insn = next_active_insn (insn))
3599: {
3600: rtx target;
3601:
3602: INSN_ANNULLED_BRANCH_P (insn) = 0;
3603: INSN_FROM_TARGET_P (insn) = 0;
3604:
3605: /* Skip vector tables. We can't get attributes for them. */
3606: if (GET_CODE (insn) == JUMP_INSN
3607: && (GET_CODE (PATTERN (insn)) == ADDR_VEC
3608: || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC))
3609: continue;
3610:
3611: if (num_delay_slots (insn) > 0)
3612: obstack_ptr_grow (&unfilled_slots_obstack, insn);
3613:
3614: /* Ensure all jumps go to the last of a set of consecutive labels. */
3615: if (GET_CODE (insn) == JUMP_INSN && condjump_p (insn)
3616: && JUMP_LABEL (insn) != 0
3617: && ((target = prev_label (next_active_insn (JUMP_LABEL (insn))))
3618: != JUMP_LABEL (insn)))
3619: redirect_jump (insn, target);
3620: }
3621:
3622: /* Indicate what resources are required to be valid at the end of the current
3623: function. The condition code never is and memory always is. If the
3624: frame pointer is needed, it is and so is the stack pointer unless
3625: EXIT_IGNORE_STACK is non-zero. If the frame pointer is not needed, the
1.1.1.3 root 3626: stack pointer is. Registers used to return the function value are
3627: needed. Registers holding global variables are needed. */
1.1 root 3628:
3629: end_of_function_needs.cc = 0;
3630: end_of_function_needs.memory = 1;
3631: CLEAR_HARD_REG_SET (end_of_function_needs.regs);
3632:
3633: if (frame_pointer_needed)
3634: {
3635: SET_HARD_REG_BIT (end_of_function_needs.regs, FRAME_POINTER_REGNUM);
3636: #ifdef EXIT_IGNORE_STACK
3637: if (! EXIT_IGNORE_STACK)
3638: #endif
3639: SET_HARD_REG_BIT (end_of_function_needs.regs, STACK_POINTER_REGNUM);
3640: }
3641: else
3642: SET_HARD_REG_BIT (end_of_function_needs.regs, STACK_POINTER_REGNUM);
3643:
3644: if (current_function_return_rtx != 0
3645: && GET_CODE (current_function_return_rtx) == REG)
3646: mark_referenced_resources (current_function_return_rtx,
3647: &end_of_function_needs, 0);
3648:
1.1.1.3 root 3649: for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3650: if (global_regs[i])
3651: SET_HARD_REG_BIT (end_of_function_needs.regs, i);
3652:
1.1.1.4 ! root 3653: /* The registers required to be live at the end of the function are
! 3654: represented in the flow information as being dead just prior to
! 3655: reaching the end of the function. For example, the return of a value
! 3656: might be represented by a USE of the return register immediately
! 3657: followed by an unconditional jump to the return label where the
! 3658: return label is the end of the RTL chain. The end of the RTL chain
! 3659: is then taken to mean that the return register is live.
! 3660:
! 3661: This sequence is no longer maintained when epilogue instructions are
! 3662: added to the RTL chain. To reconstruct the original meaning, the
! 3663: start of the epilogue (NOTE_INSN_EPILOGUE_BEG) is regarded as the
! 3664: point where these registers become live (start_of_epilogue_needs).
! 3665: If epilogue instructions are present, the registers set by those
! 3666: instructions won't have been processed by flow. Thus, those
! 3667: registers are additionally required at the end of the RTL chain
! 3668: (end_of_function_needs). */
! 3669:
! 3670: start_of_epilogue_needs = end_of_function_needs;
! 3671:
! 3672: while (epilogue_insn = next_nonnote_insn (epilogue_insn))
! 3673: mark_set_resources (epilogue_insn, &end_of_function_needs, 0, 0);
! 3674:
1.1 root 3675: /* Show we haven't computed an end-of-function label yet. */
3676: end_of_function_label = 0;
3677:
3678: /* Allocate and initialize the tables used by mark_target_live_regs. */
3679: target_hash_table
3680: = (struct target_info **) alloca ((TARGET_HASH_PRIME
3681: * sizeof (struct target_info *)));
3682: bzero (target_hash_table, TARGET_HASH_PRIME * sizeof (struct target_info *));
3683:
3684: bb_ticks = (int *) alloca (n_basic_blocks * sizeof (int));
3685: bzero (bb_ticks, n_basic_blocks * sizeof (int));
3686:
3687: /* Initialize the statistics for this function. */
3688: bzero (num_insns_needing_delays, sizeof num_insns_needing_delays);
3689: bzero (num_filled_delays, sizeof num_filled_delays);
3690:
3691: /* Now do the delay slot filling. Try everything twice in case earlier
3692: changes make more slots fillable. */
3693:
3694: for (reorg_pass_number = 0;
3695: reorg_pass_number < MAX_REORG_PASSES;
3696: reorg_pass_number++)
3697: {
3698: fill_simple_delay_slots (first, 1);
3699: fill_simple_delay_slots (first, 0);
3700: fill_eager_delay_slots (first);
3701: relax_delay_slots (first);
3702: }
3703:
3704: /* Delete any USE insns made by update_block; subsequent passes don't need
3705: them or know how to deal with them. */
3706: for (insn = first; insn; insn = next)
3707: {
3708: next = NEXT_INSN (insn);
3709:
3710: if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == USE
1.1.1.4 ! root 3711: && GET_RTX_CLASS (GET_CODE (XEXP (PATTERN (insn), 0))) == 'i')
1.1 root 3712: next = delete_insn (insn);
3713: }
3714:
3715: /* If we made an end of function label, indicate that it is now
3716: safe to delete it by undoing our prior adjustment to LABEL_NUSES.
3717: If it is now unused, delete it. */
3718: if (end_of_function_label && --LABEL_NUSES (end_of_function_label) == 0)
3719: delete_insn (end_of_function_label);
3720:
3721: #ifdef HAVE_return
3722: if (HAVE_return && end_of_function_label != 0)
3723: make_return_insns (first);
3724: #endif
3725:
3726: obstack_free (&unfilled_slots_obstack, unfilled_firstobj);
3727:
3728: /* It is not clear why the line below is needed, but it does seem to be. */
3729: unfilled_firstobj = (rtx *) obstack_alloc (&unfilled_slots_obstack, 0);
3730:
1.1.1.4 ! root 3731: /* Reposition the prologue and epilogue notes in case we moved the
! 3732: prologue/epilogue insns. */
! 3733: reposition_prologue_and_epilogue_notes (first);
! 3734:
1.1 root 3735: if (file)
3736: {
3737: register int i, j, need_comma;
3738:
3739: for (reorg_pass_number = 0;
3740: reorg_pass_number < MAX_REORG_PASSES;
3741: reorg_pass_number++)
3742: {
3743: fprintf (file, ";; Reorg pass #%d:\n", reorg_pass_number + 1);
3744: for (i = 0; i < NUM_REORG_FUNCTIONS; i++)
3745: {
3746: need_comma = 0;
3747: fprintf (file, ";; Reorg function #%d\n", i);
3748:
3749: fprintf (file, ";; %d insns needing delay slots\n;; ",
3750: num_insns_needing_delays[i][reorg_pass_number]);
3751:
3752: for (j = 0; j < MAX_DELAY_HISTOGRAM; j++)
3753: if (num_filled_delays[i][j][reorg_pass_number])
3754: {
3755: if (need_comma)
3756: fprintf (file, ", ");
3757: need_comma = 1;
3758: fprintf (file, "%d got %d delays",
3759: num_filled_delays[i][j][reorg_pass_number], j);
3760: }
3761: fprintf (file, "\n");
3762: }
3763: }
3764: }
3765: }
3766: #endif /* DELAY_SLOTS */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.