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