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