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