Mercurial > hg > CbC > CbC_gcc
annotate gcc/cfgcleanup.c @ 128:fe568345ddd5
fix CbC-example
author | mir3636 |
---|---|
date | Wed, 11 Apr 2018 19:32:28 +0900 |
parents | 04ced10e8804 |
children | 84e7813d76e9 |
rev | line source |
---|---|
0 | 1 /* Control flow optimization code for GNU compiler. |
111 | 2 Copyright (C) 1987-2017 Free Software Foundation, Inc. |
0 | 3 |
4 This file is part of GCC. | |
5 | |
6 GCC is free software; you can redistribute it and/or modify it under | |
7 the terms of the GNU General Public License as published by the Free | |
8 Software Foundation; either version 3, or (at your option) any later | |
9 version. | |
10 | |
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
14 for more details. | |
15 | |
16 You should have received a copy of the GNU General Public License | |
17 along with GCC; see the file COPYING3. If not see | |
18 <http://www.gnu.org/licenses/>. */ | |
19 | |
20 /* This file contains optimizer of the control flow. The main entry point is | |
21 cleanup_cfg. Following optimizations are performed: | |
22 | |
23 - Unreachable blocks removal | |
24 - Edge forwarding (edge to the forwarder block is forwarded to its | |
25 successor. Simplification of the branch instruction is performed by | |
26 underlying infrastructure so branch can be converted to simplejump or | |
27 eliminated). | |
28 - Cross jumping (tail merging) | |
29 - Conditional jump-around-simplejump simplification | |
30 - Basic block merging. */ | |
31 | |
32 #include "config.h" | |
33 #include "system.h" | |
34 #include "coretypes.h" | |
111 | 35 #include "backend.h" |
36 #include "target.h" | |
0 | 37 #include "rtl.h" |
111 | 38 #include "tree.h" |
39 #include "cfghooks.h" | |
40 #include "df.h" | |
41 #include "memmodel.h" | |
42 #include "tm_p.h" | |
0 | 43 #include "insn-config.h" |
111 | 44 #include "emit-rtl.h" |
0 | 45 #include "cselib.h" |
46 #include "params.h" | |
47 #include "tree-pass.h" | |
48 #include "cfgloop.h" | |
111 | 49 #include "cfgrtl.h" |
50 #include "cfganal.h" | |
51 #include "cfgbuild.h" | |
52 #include "cfgcleanup.h" | |
0 | 53 #include "dce.h" |
54 #include "dbgcnt.h" | |
111 | 55 #include "rtl-iter.h" |
0 | 56 |
57 #define FORWARDER_BLOCK_P(BB) ((BB)->flags & BB_FORWARDER_BLOCK) | |
58 | |
59 /* Set to true when we are running first pass of try_optimize_cfg loop. */ | |
60 static bool first_pass; | |
61 | |
111 | 62 /* Set to true if crossjumps occurred in the latest run of try_optimize_cfg. */ |
63 static bool crossjumps_occurred; | |
0 | 64 |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
65 /* Set to true if we couldn't run an optimization due to stale liveness |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
66 information; we should run df_analyze to enable more opportunities. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
67 static bool block_was_dirty; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
68 |
111 | 69 static bool try_crossjump_to_edge (int, edge, edge, enum replace_direction); |
0 | 70 static bool try_crossjump_bb (int, basic_block); |
71 static bool outgoing_edges_match (int, basic_block, basic_block); | |
111 | 72 static enum replace_direction old_insns_match_p (int, rtx_insn *, rtx_insn *); |
0 | 73 |
74 static void merge_blocks_move_predecessor_nojumps (basic_block, basic_block); | |
75 static void merge_blocks_move_successor_nojumps (basic_block, basic_block); | |
76 static bool try_optimize_cfg (int); | |
77 static bool try_simplify_condjump (basic_block); | |
78 static bool try_forward_edges (int, basic_block); | |
79 static edge thread_jump (edge, basic_block); | |
80 static bool mark_effect (rtx, bitmap); | |
81 static void notice_new_block (basic_block); | |
82 static void update_forwarder_flag (basic_block); | |
83 static void merge_memattrs (rtx, rtx); | |
84 | |
85 /* Set flags for newly created block. */ | |
86 | |
87 static void | |
88 notice_new_block (basic_block bb) | |
89 { | |
90 if (!bb) | |
91 return; | |
92 | |
93 if (forwarder_block_p (bb)) | |
94 bb->flags |= BB_FORWARDER_BLOCK; | |
95 } | |
96 | |
97 /* Recompute forwarder flag after block has been modified. */ | |
98 | |
99 static void | |
100 update_forwarder_flag (basic_block bb) | |
101 { | |
102 if (forwarder_block_p (bb)) | |
103 bb->flags |= BB_FORWARDER_BLOCK; | |
104 else | |
105 bb->flags &= ~BB_FORWARDER_BLOCK; | |
106 } | |
107 | |
108 /* Simplify a conditional jump around an unconditional jump. | |
109 Return true if something changed. */ | |
110 | |
111 static bool | |
112 try_simplify_condjump (basic_block cbranch_block) | |
113 { | |
114 basic_block jump_block, jump_dest_block, cbranch_dest_block; | |
115 edge cbranch_jump_edge, cbranch_fallthru_edge; | |
111 | 116 rtx_insn *cbranch_insn; |
0 | 117 |
118 /* Verify that there are exactly two successors. */ | |
119 if (EDGE_COUNT (cbranch_block->succs) != 2) | |
120 return false; | |
121 | |
122 /* Verify that we've got a normal conditional branch at the end | |
123 of the block. */ | |
124 cbranch_insn = BB_END (cbranch_block); | |
125 if (!any_condjump_p (cbranch_insn)) | |
126 return false; | |
127 | |
128 cbranch_fallthru_edge = FALLTHRU_EDGE (cbranch_block); | |
129 cbranch_jump_edge = BRANCH_EDGE (cbranch_block); | |
130 | |
131 /* The next block must not have multiple predecessors, must not | |
132 be the last block in the function, and must contain just the | |
133 unconditional jump. */ | |
134 jump_block = cbranch_fallthru_edge->dest; | |
135 if (!single_pred_p (jump_block) | |
111 | 136 || jump_block->next_bb == EXIT_BLOCK_PTR_FOR_FN (cfun) |
0 | 137 || !FORWARDER_BLOCK_P (jump_block)) |
138 return false; | |
139 jump_dest_block = single_succ (jump_block); | |
140 | |
141 /* If we are partitioning hot/cold basic blocks, we don't want to | |
142 mess up unconditional or indirect jumps that cross between hot | |
143 and cold sections. | |
144 | |
145 Basic block partitioning may result in some jumps that appear to | |
146 be optimizable (or blocks that appear to be mergeable), but which really | |
147 must be left untouched (they are required to make it safely across | |
148 partition boundaries). See the comments at the top of | |
149 bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */ | |
150 | |
151 if (BB_PARTITION (jump_block) != BB_PARTITION (jump_dest_block) | |
152 || (cbranch_jump_edge->flags & EDGE_CROSSING)) | |
153 return false; | |
154 | |
155 /* The conditional branch must target the block after the | |
156 unconditional branch. */ | |
157 cbranch_dest_block = cbranch_jump_edge->dest; | |
158 | |
111 | 159 if (cbranch_dest_block == EXIT_BLOCK_PTR_FOR_FN (cfun) |
160 || jump_dest_block == EXIT_BLOCK_PTR_FOR_FN (cfun) | |
0 | 161 || !can_fallthru (jump_block, cbranch_dest_block)) |
162 return false; | |
163 | |
164 /* Invert the conditional branch. */ | |
111 | 165 if (!invert_jump (as_a <rtx_jump_insn *> (cbranch_insn), |
166 block_label (jump_dest_block), 0)) | |
0 | 167 return false; |
168 | |
169 if (dump_file) | |
170 fprintf (dump_file, "Simplifying condjump %i around jump %i\n", | |
171 INSN_UID (cbranch_insn), INSN_UID (BB_END (jump_block))); | |
172 | |
173 /* Success. Update the CFG to match. Note that after this point | |
174 the edge variable names appear backwards; the redirection is done | |
175 this way to preserve edge profile data. */ | |
176 cbranch_jump_edge = redirect_edge_succ_nodup (cbranch_jump_edge, | |
177 cbranch_dest_block); | |
178 cbranch_fallthru_edge = redirect_edge_succ_nodup (cbranch_fallthru_edge, | |
179 jump_dest_block); | |
180 cbranch_jump_edge->flags |= EDGE_FALLTHRU; | |
181 cbranch_fallthru_edge->flags &= ~EDGE_FALLTHRU; | |
182 update_br_prob_note (cbranch_block); | |
183 | |
184 /* Delete the block with the unconditional jump, and clean up the mess. */ | |
185 delete_basic_block (jump_block); | |
186 tidy_fallthru_edge (cbranch_jump_edge); | |
187 update_forwarder_flag (cbranch_block); | |
188 | |
189 return true; | |
190 } | |
191 | |
192 /* Attempt to prove that operation is NOOP using CSElib or mark the effect | |
193 on register. Used by jump threading. */ | |
194 | |
195 static bool | |
196 mark_effect (rtx exp, regset nonequal) | |
197 { | |
198 rtx dest; | |
199 switch (GET_CODE (exp)) | |
200 { | |
201 /* In case we do clobber the register, mark it as equal, as we know the | |
202 value is dead so it don't have to match. */ | |
203 case CLOBBER: | |
111 | 204 dest = XEXP (exp, 0); |
205 if (REG_P (dest)) | |
206 bitmap_clear_range (nonequal, REGNO (dest), REG_NREGS (dest)); | |
0 | 207 return false; |
208 | |
209 case SET: | |
210 if (rtx_equal_for_cselib_p (SET_DEST (exp), SET_SRC (exp))) | |
211 return false; | |
212 dest = SET_DEST (exp); | |
213 if (dest == pc_rtx) | |
214 return false; | |
215 if (!REG_P (dest)) | |
216 return true; | |
111 | 217 bitmap_set_range (nonequal, REGNO (dest), REG_NREGS (dest)); |
0 | 218 return false; |
219 | |
220 default: | |
221 return false; | |
222 } | |
223 } | |
224 | |
111 | 225 /* Return true if X contains a register in NONEQUAL. */ |
226 static bool | |
227 mentions_nonequal_regs (const_rtx x, regset nonequal) | |
0 | 228 { |
111 | 229 subrtx_iterator::array_type array; |
230 FOR_EACH_SUBRTX (iter, array, x, NONCONST) | |
0 | 231 { |
111 | 232 const_rtx x = *iter; |
233 if (REG_P (x)) | |
0 | 234 { |
111 | 235 unsigned int end_regno = END_REGNO (x); |
236 for (unsigned int regno = REGNO (x); regno < end_regno; ++regno) | |
237 if (REGNO_REG_SET_P (nonequal, regno)) | |
238 return true; | |
0 | 239 } |
240 } | |
111 | 241 return false; |
0 | 242 } |
111 | 243 |
0 | 244 /* Attempt to prove that the basic block B will have no side effects and |
245 always continues in the same edge if reached via E. Return the edge | |
246 if exist, NULL otherwise. */ | |
247 | |
248 static edge | |
249 thread_jump (edge e, basic_block b) | |
250 { | |
111 | 251 rtx set1, set2, cond1, cond2; |
252 rtx_insn *insn; | |
0 | 253 enum rtx_code code1, code2, reversed_code2; |
254 bool reverse1 = false; | |
255 unsigned i; | |
256 regset nonequal; | |
257 bool failed = false; | |
258 reg_set_iterator rsi; | |
259 | |
260 if (b->flags & BB_NONTHREADABLE_BLOCK) | |
261 return NULL; | |
262 | |
263 /* At the moment, we do handle only conditional jumps, but later we may | |
264 want to extend this code to tablejumps and others. */ | |
265 if (EDGE_COUNT (e->src->succs) != 2) | |
266 return NULL; | |
267 if (EDGE_COUNT (b->succs) != 2) | |
268 { | |
269 b->flags |= BB_NONTHREADABLE_BLOCK; | |
270 return NULL; | |
271 } | |
272 | |
273 /* Second branch must end with onlyjump, as we will eliminate the jump. */ | |
274 if (!any_condjump_p (BB_END (e->src))) | |
275 return NULL; | |
276 | |
277 if (!any_condjump_p (BB_END (b)) || !onlyjump_p (BB_END (b))) | |
278 { | |
279 b->flags |= BB_NONTHREADABLE_BLOCK; | |
280 return NULL; | |
281 } | |
282 | |
283 set1 = pc_set (BB_END (e->src)); | |
284 set2 = pc_set (BB_END (b)); | |
285 if (((e->flags & EDGE_FALLTHRU) != 0) | |
286 != (XEXP (SET_SRC (set1), 1) == pc_rtx)) | |
287 reverse1 = true; | |
288 | |
289 cond1 = XEXP (SET_SRC (set1), 0); | |
290 cond2 = XEXP (SET_SRC (set2), 0); | |
291 if (reverse1) | |
292 code1 = reversed_comparison_code (cond1, BB_END (e->src)); | |
293 else | |
294 code1 = GET_CODE (cond1); | |
295 | |
296 code2 = GET_CODE (cond2); | |
297 reversed_code2 = reversed_comparison_code (cond2, BB_END (b)); | |
298 | |
299 if (!comparison_dominates_p (code1, code2) | |
300 && !comparison_dominates_p (code1, reversed_code2)) | |
301 return NULL; | |
302 | |
303 /* Ensure that the comparison operators are equivalent. | |
304 ??? This is far too pessimistic. We should allow swapped operands, | |
305 different CCmodes, or for example comparisons for interval, that | |
306 dominate even when operands are not equivalent. */ | |
307 if (!rtx_equal_p (XEXP (cond1, 0), XEXP (cond2, 0)) | |
308 || !rtx_equal_p (XEXP (cond1, 1), XEXP (cond2, 1))) | |
309 return NULL; | |
310 | |
311 /* Short circuit cases where block B contains some side effects, as we can't | |
312 safely bypass it. */ | |
313 for (insn = NEXT_INSN (BB_HEAD (b)); insn != NEXT_INSN (BB_END (b)); | |
314 insn = NEXT_INSN (insn)) | |
315 if (INSN_P (insn) && side_effects_p (PATTERN (insn))) | |
316 { | |
317 b->flags |= BB_NONTHREADABLE_BLOCK; | |
318 return NULL; | |
319 } | |
320 | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
321 cselib_init (0); |
0 | 322 |
323 /* First process all values computed in the source basic block. */ | |
324 for (insn = NEXT_INSN (BB_HEAD (e->src)); | |
325 insn != NEXT_INSN (BB_END (e->src)); | |
326 insn = NEXT_INSN (insn)) | |
327 if (INSN_P (insn)) | |
328 cselib_process_insn (insn); | |
329 | |
330 nonequal = BITMAP_ALLOC (NULL); | |
331 CLEAR_REG_SET (nonequal); | |
332 | |
333 /* Now assume that we've continued by the edge E to B and continue | |
334 processing as if it were same basic block. | |
335 Our goal is to prove that whole block is an NOOP. */ | |
336 | |
337 for (insn = NEXT_INSN (BB_HEAD (b)); | |
338 insn != NEXT_INSN (BB_END (b)) && !failed; | |
339 insn = NEXT_INSN (insn)) | |
340 { | |
341 if (INSN_P (insn)) | |
342 { | |
343 rtx pat = PATTERN (insn); | |
344 | |
345 if (GET_CODE (pat) == PARALLEL) | |
346 { | |
347 for (i = 0; i < (unsigned)XVECLEN (pat, 0); i++) | |
348 failed |= mark_effect (XVECEXP (pat, 0, i), nonequal); | |
349 } | |
350 else | |
351 failed |= mark_effect (pat, nonequal); | |
352 } | |
353 | |
354 cselib_process_insn (insn); | |
355 } | |
356 | |
357 /* Later we should clear nonequal of dead registers. So far we don't | |
358 have life information in cfg_cleanup. */ | |
359 if (failed) | |
360 { | |
361 b->flags |= BB_NONTHREADABLE_BLOCK; | |
362 goto failed_exit; | |
363 } | |
364 | |
365 /* cond2 must not mention any register that is not equal to the | |
366 former block. */ | |
111 | 367 if (mentions_nonequal_regs (cond2, nonequal)) |
0 | 368 goto failed_exit; |
369 | |
370 EXECUTE_IF_SET_IN_REG_SET (nonequal, 0, i, rsi) | |
371 goto failed_exit; | |
372 | |
373 BITMAP_FREE (nonequal); | |
374 cselib_finish (); | |
375 if ((comparison_dominates_p (code1, code2) != 0) | |
376 != (XEXP (SET_SRC (set2), 1) == pc_rtx)) | |
377 return BRANCH_EDGE (b); | |
378 else | |
379 return FALLTHRU_EDGE (b); | |
380 | |
381 failed_exit: | |
382 BITMAP_FREE (nonequal); | |
383 cselib_finish (); | |
384 return NULL; | |
385 } | |
386 | |
387 /* Attempt to forward edges leaving basic block B. | |
388 Return true if successful. */ | |
389 | |
390 static bool | |
391 try_forward_edges (int mode, basic_block b) | |
392 { | |
393 bool changed = false; | |
394 edge_iterator ei; | |
395 edge e, *threaded_edges = NULL; | |
396 | |
397 /* If we are partitioning hot/cold basic blocks, we don't want to | |
398 mess up unconditional or indirect jumps that cross between hot | |
399 and cold sections. | |
400 | |
401 Basic block partitioning may result in some jumps that appear to | |
402 be optimizable (or blocks that appear to be mergeable), but which really | |
403 must be left untouched (they are required to make it safely across | |
404 partition boundaries). See the comments at the top of | |
405 bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */ | |
406 | |
111 | 407 if (JUMP_P (BB_END (b)) && CROSSING_JUMP_P (BB_END (b))) |
0 | 408 return false; |
409 | |
410 for (ei = ei_start (b->succs); (e = ei_safe_edge (ei)); ) | |
411 { | |
412 basic_block target, first; | |
111 | 413 location_t goto_locus; |
414 int counter; | |
0 | 415 bool threaded = false; |
416 int nthreaded_edges = 0; | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
417 bool may_thread = first_pass || (b->flags & BB_MODIFIED) != 0; |
0 | 418 |
419 /* Skip complex edges because we don't know how to update them. | |
420 | |
421 Still handle fallthru edges, as we can succeed to forward fallthru | |
422 edge to the same place as the branch edge of conditional branch | |
423 and turn conditional branch to an unconditional branch. */ | |
424 if (e->flags & EDGE_COMPLEX) | |
425 { | |
426 ei_next (&ei); | |
427 continue; | |
428 } | |
429 | |
430 target = first = e->dest; | |
431 counter = NUM_FIXED_BLOCKS; | |
432 goto_locus = e->goto_locus; | |
433 | |
434 /* If we are partitioning hot/cold basic_blocks, we don't want to mess | |
435 up jumps that cross between hot/cold sections. | |
436 | |
437 Basic block partitioning may result in some jumps that appear | |
438 to be optimizable (or blocks that appear to be mergeable), but which | |
439 really must be left untouched (they are required to make it safely | |
440 across partition boundaries). See the comments at the top of | |
441 bb-reorder.c:partition_hot_cold_basic_blocks for complete | |
442 details. */ | |
443 | |
111 | 444 if (first != EXIT_BLOCK_PTR_FOR_FN (cfun) |
445 && JUMP_P (BB_END (first)) | |
446 && CROSSING_JUMP_P (BB_END (first))) | |
447 return changed; | |
448 | |
449 while (counter < n_basic_blocks_for_fn (cfun)) | |
0 | 450 { |
451 basic_block new_target = NULL; | |
452 bool new_target_threaded = false; | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
453 may_thread |= (target->flags & BB_MODIFIED) != 0; |
0 | 454 |
455 if (FORWARDER_BLOCK_P (target) | |
456 && !(single_succ_edge (target)->flags & EDGE_CROSSING) | |
111 | 457 && single_succ (target) != EXIT_BLOCK_PTR_FOR_FN (cfun)) |
0 | 458 { |
459 /* Bypass trivial infinite loops. */ | |
460 new_target = single_succ (target); | |
461 if (target == new_target) | |
111 | 462 counter = n_basic_blocks_for_fn (cfun); |
0 | 463 else if (!optimize) |
464 { | |
465 /* When not optimizing, ensure that edges or forwarder | |
466 blocks with different locus are not optimized out. */ | |
111 | 467 location_t new_locus = single_succ_edge (target)->goto_locus; |
468 location_t locus = goto_locus; | |
469 | |
470 if (LOCATION_LOCUS (new_locus) != UNKNOWN_LOCATION | |
471 && LOCATION_LOCUS (locus) != UNKNOWN_LOCATION | |
472 && new_locus != locus) | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
473 new_target = NULL; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
474 else |
0 | 475 { |
111 | 476 if (LOCATION_LOCUS (new_locus) != UNKNOWN_LOCATION) |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
477 locus = new_locus; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
478 |
111 | 479 rtx_insn *last = BB_END (target); |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
480 if (DEBUG_INSN_P (last)) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
481 last = prev_nondebug_insn (last); |
111 | 482 if (last && INSN_P (last)) |
483 new_locus = INSN_LOCATION (last); | |
484 else | |
485 new_locus = UNKNOWN_LOCATION; | |
486 | |
487 if (LOCATION_LOCUS (new_locus) != UNKNOWN_LOCATION | |
488 && LOCATION_LOCUS (locus) != UNKNOWN_LOCATION | |
489 && new_locus != locus) | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
490 new_target = NULL; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
491 else |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
492 { |
111 | 493 if (LOCATION_LOCUS (new_locus) != UNKNOWN_LOCATION) |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
494 locus = new_locus; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
495 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
496 goto_locus = locus; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
497 } |
0 | 498 } |
499 } | |
500 } | |
501 | |
502 /* Allow to thread only over one edge at time to simplify updating | |
503 of probabilities. */ | |
504 else if ((mode & CLEANUP_THREADING) && may_thread) | |
505 { | |
506 edge t = thread_jump (e, target); | |
507 if (t) | |
508 { | |
509 if (!threaded_edges) | |
111 | 510 threaded_edges = XNEWVEC (edge, |
511 n_basic_blocks_for_fn (cfun)); | |
0 | 512 else |
513 { | |
514 int i; | |
515 | |
516 /* Detect an infinite loop across blocks not | |
517 including the start block. */ | |
518 for (i = 0; i < nthreaded_edges; ++i) | |
519 if (threaded_edges[i] == t) | |
520 break; | |
521 if (i < nthreaded_edges) | |
522 { | |
111 | 523 counter = n_basic_blocks_for_fn (cfun); |
0 | 524 break; |
525 } | |
526 } | |
527 | |
528 /* Detect an infinite loop across the start block. */ | |
529 if (t->dest == b) | |
530 break; | |
531 | |
111 | 532 gcc_assert (nthreaded_edges |
533 < (n_basic_blocks_for_fn (cfun) | |
534 - NUM_FIXED_BLOCKS)); | |
0 | 535 threaded_edges[nthreaded_edges++] = t; |
536 | |
537 new_target = t->dest; | |
538 new_target_threaded = true; | |
539 } | |
540 } | |
541 | |
542 if (!new_target) | |
543 break; | |
544 | |
545 counter++; | |
546 target = new_target; | |
547 threaded |= new_target_threaded; | |
548 } | |
549 | |
111 | 550 if (counter >= n_basic_blocks_for_fn (cfun)) |
0 | 551 { |
552 if (dump_file) | |
553 fprintf (dump_file, "Infinite loop in BB %i.\n", | |
554 target->index); | |
555 } | |
556 else if (target == first) | |
557 ; /* We didn't do anything. */ | |
558 else | |
559 { | |
560 /* Save the values now, as the edge may get removed. */ | |
111 | 561 profile_count edge_count = e->count (); |
562 profile_probability edge_probability = e->probability; | |
0 | 563 int edge_frequency; |
564 int n = 0; | |
565 | |
566 e->goto_locus = goto_locus; | |
567 | |
568 /* Don't force if target is exit block. */ | |
111 | 569 if (threaded && target != EXIT_BLOCK_PTR_FOR_FN (cfun)) |
0 | 570 { |
571 notice_new_block (redirect_edge_and_branch_force (e, target)); | |
572 if (dump_file) | |
573 fprintf (dump_file, "Conditionals threaded.\n"); | |
574 } | |
575 else if (!redirect_edge_and_branch (e, target)) | |
576 { | |
577 if (dump_file) | |
578 fprintf (dump_file, | |
579 "Forwarding edge %i->%i to %i failed.\n", | |
580 b->index, e->dest->index, target->index); | |
581 ei_next (&ei); | |
582 continue; | |
583 } | |
584 | |
585 /* We successfully forwarded the edge. Now update profile | |
586 data: for each edge we traversed in the chain, remove | |
587 the original edge's execution count. */ | |
111 | 588 edge_frequency = edge_probability.apply (b->frequency); |
0 | 589 |
590 do | |
591 { | |
592 edge t; | |
593 | |
594 if (!single_succ_p (first)) | |
595 { | |
596 gcc_assert (n < nthreaded_edges); | |
597 t = threaded_edges [n++]; | |
598 gcc_assert (t->src == first); | |
599 update_bb_profile_for_threading (first, edge_frequency, | |
600 edge_count, t); | |
601 update_br_prob_note (first); | |
602 } | |
603 else | |
604 { | |
605 first->count -= edge_count; | |
606 first->frequency -= edge_frequency; | |
607 if (first->frequency < 0) | |
608 first->frequency = 0; | |
609 /* It is possible that as the result of | |
610 threading we've removed edge as it is | |
611 threaded to the fallthru edge. Avoid | |
612 getting out of sync. */ | |
613 if (n < nthreaded_edges | |
614 && first == threaded_edges [n]->src) | |
615 n++; | |
616 t = single_succ_edge (first); | |
617 } | |
618 | |
619 first = t->dest; | |
620 } | |
621 while (first != target); | |
622 | |
623 changed = true; | |
624 continue; | |
625 } | |
626 ei_next (&ei); | |
627 } | |
628 | |
111 | 629 free (threaded_edges); |
0 | 630 return changed; |
631 } | |
632 | |
633 | |
634 /* Blocks A and B are to be merged into a single block. A has no incoming | |
635 fallthru edge, so it can be moved before B without adding or modifying | |
636 any jumps (aside from the jump from A to B). */ | |
637 | |
638 static void | |
639 merge_blocks_move_predecessor_nojumps (basic_block a, basic_block b) | |
640 { | |
111 | 641 rtx_insn *barrier; |
0 | 642 |
643 /* If we are partitioning hot/cold basic blocks, we don't want to | |
644 mess up unconditional or indirect jumps that cross between hot | |
645 and cold sections. | |
646 | |
647 Basic block partitioning may result in some jumps that appear to | |
648 be optimizable (or blocks that appear to be mergeable), but which really | |
649 must be left untouched (they are required to make it safely across | |
650 partition boundaries). See the comments at the top of | |
651 bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */ | |
652 | |
653 if (BB_PARTITION (a) != BB_PARTITION (b)) | |
654 return; | |
655 | |
656 barrier = next_nonnote_insn (BB_END (a)); | |
657 gcc_assert (BARRIER_P (barrier)); | |
658 delete_insn (barrier); | |
659 | |
660 /* Scramble the insn chain. */ | |
661 if (BB_END (a) != PREV_INSN (BB_HEAD (b))) | |
662 reorder_insns_nobb (BB_HEAD (a), BB_END (a), PREV_INSN (BB_HEAD (b))); | |
663 df_set_bb_dirty (a); | |
664 | |
665 if (dump_file) | |
666 fprintf (dump_file, "Moved block %d before %d and merged.\n", | |
667 a->index, b->index); | |
668 | |
669 /* Swap the records for the two blocks around. */ | |
670 | |
671 unlink_block (a); | |
672 link_block (a, b->prev_bb); | |
673 | |
674 /* Now blocks A and B are contiguous. Merge them. */ | |
675 merge_blocks (a, b); | |
676 } | |
677 | |
678 /* Blocks A and B are to be merged into a single block. B has no outgoing | |
679 fallthru edge, so it can be moved after A without adding or modifying | |
680 any jumps (aside from the jump from A to B). */ | |
681 | |
682 static void | |
683 merge_blocks_move_successor_nojumps (basic_block a, basic_block b) | |
684 { | |
111 | 685 rtx_insn *barrier, *real_b_end; |
686 rtx_insn *label; | |
687 rtx_jump_table_data *table; | |
0 | 688 |
689 /* If we are partitioning hot/cold basic blocks, we don't want to | |
690 mess up unconditional or indirect jumps that cross between hot | |
691 and cold sections. | |
692 | |
693 Basic block partitioning may result in some jumps that appear to | |
694 be optimizable (or blocks that appear to be mergeable), but which really | |
695 must be left untouched (they are required to make it safely across | |
696 partition boundaries). See the comments at the top of | |
697 bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */ | |
698 | |
699 if (BB_PARTITION (a) != BB_PARTITION (b)) | |
700 return; | |
701 | |
702 real_b_end = BB_END (b); | |
703 | |
704 /* If there is a jump table following block B temporarily add the jump table | |
705 to block B so that it will also be moved to the correct location. */ | |
706 if (tablejump_p (BB_END (b), &label, &table) | |
707 && prev_active_insn (label) == BB_END (b)) | |
708 { | |
709 BB_END (b) = table; | |
710 } | |
711 | |
712 /* There had better have been a barrier there. Delete it. */ | |
713 barrier = NEXT_INSN (BB_END (b)); | |
714 if (barrier && BARRIER_P (barrier)) | |
715 delete_insn (barrier); | |
716 | |
717 | |
718 /* Scramble the insn chain. */ | |
719 reorder_insns_nobb (BB_HEAD (b), BB_END (b), BB_END (a)); | |
720 | |
721 /* Restore the real end of b. */ | |
722 BB_END (b) = real_b_end; | |
723 | |
724 if (dump_file) | |
725 fprintf (dump_file, "Moved block %d after %d and merged.\n", | |
726 b->index, a->index); | |
727 | |
728 /* Now blocks A and B are contiguous. Merge them. */ | |
729 merge_blocks (a, b); | |
730 } | |
731 | |
732 /* Attempt to merge basic blocks that are potentially non-adjacent. | |
733 Return NULL iff the attempt failed, otherwise return basic block | |
734 where cleanup_cfg should continue. Because the merging commonly | |
735 moves basic block away or introduces another optimization | |
736 possibility, return basic block just before B so cleanup_cfg don't | |
737 need to iterate. | |
738 | |
739 It may be good idea to return basic block before C in the case | |
740 C has been moved after B and originally appeared earlier in the | |
741 insn sequence, but we have no information available about the | |
742 relative ordering of these two. Hopefully it is not too common. */ | |
743 | |
744 static basic_block | |
745 merge_blocks_move (edge e, basic_block b, basic_block c, int mode) | |
746 { | |
747 basic_block next; | |
748 | |
749 /* If we are partitioning hot/cold basic blocks, we don't want to | |
750 mess up unconditional or indirect jumps that cross between hot | |
751 and cold sections. | |
752 | |
753 Basic block partitioning may result in some jumps that appear to | |
754 be optimizable (or blocks that appear to be mergeable), but which really | |
755 must be left untouched (they are required to make it safely across | |
756 partition boundaries). See the comments at the top of | |
757 bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */ | |
758 | |
759 if (BB_PARTITION (b) != BB_PARTITION (c)) | |
760 return NULL; | |
761 | |
762 /* If B has a fallthru edge to C, no need to move anything. */ | |
763 if (e->flags & EDGE_FALLTHRU) | |
764 { | |
765 int b_index = b->index, c_index = c->index; | |
111 | 766 |
767 /* Protect the loop latches. */ | |
768 if (current_loops && c->loop_father->latch == c) | |
769 return NULL; | |
770 | |
0 | 771 merge_blocks (b, c); |
772 update_forwarder_flag (b); | |
773 | |
774 if (dump_file) | |
775 fprintf (dump_file, "Merged %d and %d without moving.\n", | |
776 b_index, c_index); | |
777 | |
111 | 778 return b->prev_bb == ENTRY_BLOCK_PTR_FOR_FN (cfun) ? b : b->prev_bb; |
0 | 779 } |
780 | |
781 /* Otherwise we will need to move code around. Do that only if expensive | |
782 transformations are allowed. */ | |
783 else if (mode & CLEANUP_EXPENSIVE) | |
784 { | |
785 edge tmp_edge, b_fallthru_edge; | |
786 bool c_has_outgoing_fallthru; | |
787 bool b_has_incoming_fallthru; | |
788 | |
789 /* Avoid overactive code motion, as the forwarder blocks should be | |
790 eliminated by edge redirection instead. One exception might have | |
791 been if B is a forwarder block and C has no fallthru edge, but | |
792 that should be cleaned up by bb-reorder instead. */ | |
793 if (FORWARDER_BLOCK_P (b) || FORWARDER_BLOCK_P (c)) | |
794 return NULL; | |
795 | |
796 /* We must make sure to not munge nesting of lexical blocks, | |
797 and loop notes. This is done by squeezing out all the notes | |
798 and leaving them there to lie. Not ideal, but functional. */ | |
799 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
800 tmp_edge = find_fallthru_edge (c->succs); |
0 | 801 c_has_outgoing_fallthru = (tmp_edge != NULL); |
802 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
803 tmp_edge = find_fallthru_edge (b->preds); |
0 | 804 b_has_incoming_fallthru = (tmp_edge != NULL); |
805 b_fallthru_edge = tmp_edge; | |
806 next = b->prev_bb; | |
807 if (next == c) | |
808 next = next->prev_bb; | |
809 | |
810 /* Otherwise, we're going to try to move C after B. If C does | |
811 not have an outgoing fallthru, then it can be moved | |
812 immediately after B without introducing or modifying jumps. */ | |
813 if (! c_has_outgoing_fallthru) | |
814 { | |
815 merge_blocks_move_successor_nojumps (b, c); | |
111 | 816 return next == ENTRY_BLOCK_PTR_FOR_FN (cfun) ? next->next_bb : next; |
0 | 817 } |
818 | |
819 /* If B does not have an incoming fallthru, then it can be moved | |
820 immediately before C without introducing or modifying jumps. | |
821 C cannot be the first block, so we do not have to worry about | |
822 accessing a non-existent block. */ | |
823 | |
824 if (b_has_incoming_fallthru) | |
825 { | |
826 basic_block bb; | |
827 | |
111 | 828 if (b_fallthru_edge->src == ENTRY_BLOCK_PTR_FOR_FN (cfun)) |
0 | 829 return NULL; |
830 bb = force_nonfallthru (b_fallthru_edge); | |
831 if (bb) | |
832 notice_new_block (bb); | |
833 } | |
834 | |
835 merge_blocks_move_predecessor_nojumps (b, c); | |
111 | 836 return next == ENTRY_BLOCK_PTR_FOR_FN (cfun) ? next->next_bb : next; |
0 | 837 } |
838 | |
839 return NULL; | |
840 } | |
841 | |
842 | |
843 /* Removes the memory attributes of MEM expression | |
844 if they are not equal. */ | |
845 | |
111 | 846 static void |
0 | 847 merge_memattrs (rtx x, rtx y) |
848 { | |
849 int i; | |
850 int j; | |
851 enum rtx_code code; | |
852 const char *fmt; | |
853 | |
854 if (x == y) | |
855 return; | |
856 if (x == 0 || y == 0) | |
857 return; | |
858 | |
859 code = GET_CODE (x); | |
860 | |
861 if (code != GET_CODE (y)) | |
862 return; | |
863 | |
864 if (GET_MODE (x) != GET_MODE (y)) | |
865 return; | |
866 | |
111 | 867 if (code == MEM && !mem_attrs_eq_p (MEM_ATTRS (x), MEM_ATTRS (y))) |
0 | 868 { |
869 if (! MEM_ATTRS (x)) | |
870 MEM_ATTRS (y) = 0; | |
871 else if (! MEM_ATTRS (y)) | |
872 MEM_ATTRS (x) = 0; | |
873 else | |
874 { | |
111 | 875 HOST_WIDE_INT mem_size; |
0 | 876 |
877 if (MEM_ALIAS_SET (x) != MEM_ALIAS_SET (y)) | |
878 { | |
879 set_mem_alias_set (x, 0); | |
880 set_mem_alias_set (y, 0); | |
881 } | |
882 | |
883 if (! mem_expr_equal_p (MEM_EXPR (x), MEM_EXPR (y))) | |
884 { | |
885 set_mem_expr (x, 0); | |
886 set_mem_expr (y, 0); | |
111 | 887 clear_mem_offset (x); |
888 clear_mem_offset (y); | |
0 | 889 } |
111 | 890 else if (MEM_OFFSET_KNOWN_P (x) != MEM_OFFSET_KNOWN_P (y) |
891 || (MEM_OFFSET_KNOWN_P (x) | |
892 && MEM_OFFSET (x) != MEM_OFFSET (y))) | |
0 | 893 { |
111 | 894 clear_mem_offset (x); |
895 clear_mem_offset (y); | |
0 | 896 } |
897 | |
111 | 898 if (MEM_SIZE_KNOWN_P (x) && MEM_SIZE_KNOWN_P (y)) |
899 { | |
900 mem_size = MAX (MEM_SIZE (x), MEM_SIZE (y)); | |
901 set_mem_size (x, mem_size); | |
902 set_mem_size (y, mem_size); | |
903 } | |
0 | 904 else |
111 | 905 { |
906 clear_mem_size (x); | |
907 clear_mem_size (y); | |
908 } | |
0 | 909 |
910 set_mem_align (x, MIN (MEM_ALIGN (x), MEM_ALIGN (y))); | |
911 set_mem_align (y, MEM_ALIGN (x)); | |
912 } | |
913 } | |
111 | 914 if (code == MEM) |
915 { | |
916 if (MEM_READONLY_P (x) != MEM_READONLY_P (y)) | |
917 { | |
918 MEM_READONLY_P (x) = 0; | |
919 MEM_READONLY_P (y) = 0; | |
920 } | |
921 if (MEM_NOTRAP_P (x) != MEM_NOTRAP_P (y)) | |
922 { | |
923 MEM_NOTRAP_P (x) = 0; | |
924 MEM_NOTRAP_P (y) = 0; | |
925 } | |
926 if (MEM_VOLATILE_P (x) != MEM_VOLATILE_P (y)) | |
927 { | |
928 MEM_VOLATILE_P (x) = 1; | |
929 MEM_VOLATILE_P (y) = 1; | |
930 } | |
931 } | |
0 | 932 |
933 fmt = GET_RTX_FORMAT (code); | |
934 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) | |
935 { | |
936 switch (fmt[i]) | |
937 { | |
938 case 'E': | |
939 /* Two vectors must have the same length. */ | |
940 if (XVECLEN (x, i) != XVECLEN (y, i)) | |
941 return; | |
942 | |
943 for (j = 0; j < XVECLEN (x, i); j++) | |
944 merge_memattrs (XVECEXP (x, i, j), XVECEXP (y, i, j)); | |
945 | |
946 break; | |
947 | |
948 case 'e': | |
949 merge_memattrs (XEXP (x, i), XEXP (y, i)); | |
950 } | |
951 } | |
952 return; | |
953 } | |
954 | |
955 | |
111 | 956 /* Checks if patterns P1 and P2 are equivalent, apart from the possibly |
957 different single sets S1 and S2. */ | |
0 | 958 |
959 static bool | |
111 | 960 equal_different_set_p (rtx p1, rtx s1, rtx p2, rtx s2) |
961 { | |
962 int i; | |
963 rtx e1, e2; | |
964 | |
965 if (p1 == s1 && p2 == s2) | |
966 return true; | |
967 | |
968 if (GET_CODE (p1) != PARALLEL || GET_CODE (p2) != PARALLEL) | |
969 return false; | |
970 | |
971 if (XVECLEN (p1, 0) != XVECLEN (p2, 0)) | |
972 return false; | |
973 | |
974 for (i = 0; i < XVECLEN (p1, 0); i++) | |
975 { | |
976 e1 = XVECEXP (p1, 0, i); | |
977 e2 = XVECEXP (p2, 0, i); | |
978 if (e1 == s1 && e2 == s2) | |
979 continue; | |
980 if (reload_completed | |
981 ? rtx_renumbered_equal_p (e1, e2) : rtx_equal_p (e1, e2)) | |
982 continue; | |
983 | |
984 return false; | |
985 } | |
986 | |
987 return true; | |
988 } | |
989 | |
990 | |
991 /* NOTE1 is the REG_EQUAL note, if any, attached to an insn | |
992 that is a single_set with a SET_SRC of SRC1. Similarly | |
993 for NOTE2/SRC2. | |
994 | |
995 So effectively NOTE1/NOTE2 are an alternate form of | |
996 SRC1/SRC2 respectively. | |
997 | |
998 Return nonzero if SRC1 or NOTE1 has the same constant | |
999 integer value as SRC2 or NOTE2. Else return zero. */ | |
1000 static int | |
1001 values_equal_p (rtx note1, rtx note2, rtx src1, rtx src2) | |
1002 { | |
1003 if (note1 | |
1004 && note2 | |
1005 && CONST_INT_P (XEXP (note1, 0)) | |
1006 && rtx_equal_p (XEXP (note1, 0), XEXP (note2, 0))) | |
1007 return 1; | |
1008 | |
1009 if (!note1 | |
1010 && !note2 | |
1011 && CONST_INT_P (src1) | |
1012 && CONST_INT_P (src2) | |
1013 && rtx_equal_p (src1, src2)) | |
1014 return 1; | |
1015 | |
1016 if (note1 | |
1017 && CONST_INT_P (src2) | |
1018 && rtx_equal_p (XEXP (note1, 0), src2)) | |
1019 return 1; | |
1020 | |
1021 if (note2 | |
1022 && CONST_INT_P (src1) | |
1023 && rtx_equal_p (XEXP (note2, 0), src1)) | |
1024 return 1; | |
1025 | |
1026 return 0; | |
1027 } | |
1028 | |
1029 /* Examine register notes on I1 and I2 and return: | |
1030 - dir_forward if I1 can be replaced by I2, or | |
1031 - dir_backward if I2 can be replaced by I1, or | |
1032 - dir_both if both are the case. */ | |
1033 | |
1034 static enum replace_direction | |
1035 can_replace_by (rtx_insn *i1, rtx_insn *i2) | |
1036 { | |
1037 rtx s1, s2, d1, d2, src1, src2, note1, note2; | |
1038 bool c1, c2; | |
1039 | |
1040 /* Check for 2 sets. */ | |
1041 s1 = single_set (i1); | |
1042 s2 = single_set (i2); | |
1043 if (s1 == NULL_RTX || s2 == NULL_RTX) | |
1044 return dir_none; | |
1045 | |
1046 /* Check that the 2 sets set the same dest. */ | |
1047 d1 = SET_DEST (s1); | |
1048 d2 = SET_DEST (s2); | |
1049 if (!(reload_completed | |
1050 ? rtx_renumbered_equal_p (d1, d2) : rtx_equal_p (d1, d2))) | |
1051 return dir_none; | |
1052 | |
1053 /* Find identical req_equiv or reg_equal note, which implies that the 2 sets | |
1054 set dest to the same value. */ | |
1055 note1 = find_reg_equal_equiv_note (i1); | |
1056 note2 = find_reg_equal_equiv_note (i2); | |
1057 | |
1058 src1 = SET_SRC (s1); | |
1059 src2 = SET_SRC (s2); | |
1060 | |
1061 if (!values_equal_p (note1, note2, src1, src2)) | |
1062 return dir_none; | |
1063 | |
1064 if (!equal_different_set_p (PATTERN (i1), s1, PATTERN (i2), s2)) | |
1065 return dir_none; | |
1066 | |
1067 /* Although the 2 sets set dest to the same value, we cannot replace | |
1068 (set (dest) (const_int)) | |
1069 by | |
1070 (set (dest) (reg)) | |
1071 because we don't know if the reg is live and has the same value at the | |
1072 location of replacement. */ | |
1073 c1 = CONST_INT_P (src1); | |
1074 c2 = CONST_INT_P (src2); | |
1075 if (c1 && c2) | |
1076 return dir_both; | |
1077 else if (c2) | |
1078 return dir_forward; | |
1079 else if (c1) | |
1080 return dir_backward; | |
1081 | |
1082 return dir_none; | |
1083 } | |
1084 | |
1085 /* Merges directions A and B. */ | |
1086 | |
1087 static enum replace_direction | |
1088 merge_dir (enum replace_direction a, enum replace_direction b) | |
1089 { | |
1090 /* Implements the following table: | |
1091 |bo fw bw no | |
1092 ---+----------- | |
1093 bo |bo fw bw no | |
1094 fw |-- fw no no | |
1095 bw |-- -- bw no | |
1096 no |-- -- -- no. */ | |
1097 | |
1098 if (a == b) | |
1099 return a; | |
1100 | |
1101 if (a == dir_both) | |
1102 return b; | |
1103 if (b == dir_both) | |
1104 return a; | |
1105 | |
1106 return dir_none; | |
1107 } | |
1108 | |
1109 /* Array of flags indexed by reg note kind, true if the given | |
1110 reg note is CFA related. */ | |
1111 static const bool reg_note_cfa_p[] = { | |
1112 #undef REG_CFA_NOTE | |
1113 #define DEF_REG_NOTE(NAME) false, | |
1114 #define REG_CFA_NOTE(NAME) true, | |
1115 #include "reg-notes.def" | |
1116 #undef REG_CFA_NOTE | |
1117 #undef DEF_REG_NOTE | |
1118 false | |
1119 }; | |
1120 | |
1121 /* Return true if I1 and I2 have identical CFA notes (the same order | |
1122 and equivalent content). */ | |
1123 | |
1124 static bool | |
1125 insns_have_identical_cfa_notes (rtx_insn *i1, rtx_insn *i2) | |
1126 { | |
1127 rtx n1, n2; | |
1128 for (n1 = REG_NOTES (i1), n2 = REG_NOTES (i2); ; | |
1129 n1 = XEXP (n1, 1), n2 = XEXP (n2, 1)) | |
1130 { | |
1131 /* Skip over reg notes not related to CFI information. */ | |
1132 while (n1 && !reg_note_cfa_p[REG_NOTE_KIND (n1)]) | |
1133 n1 = XEXP (n1, 1); | |
1134 while (n2 && !reg_note_cfa_p[REG_NOTE_KIND (n2)]) | |
1135 n2 = XEXP (n2, 1); | |
1136 if (n1 == NULL_RTX && n2 == NULL_RTX) | |
1137 return true; | |
1138 if (n1 == NULL_RTX || n2 == NULL_RTX) | |
1139 return false; | |
1140 if (XEXP (n1, 0) == XEXP (n2, 0)) | |
1141 ; | |
1142 else if (XEXP (n1, 0) == NULL_RTX || XEXP (n2, 0) == NULL_RTX) | |
1143 return false; | |
1144 else if (!(reload_completed | |
1145 ? rtx_renumbered_equal_p (XEXP (n1, 0), XEXP (n2, 0)) | |
1146 : rtx_equal_p (XEXP (n1, 0), XEXP (n2, 0)))) | |
1147 return false; | |
1148 } | |
1149 } | |
1150 | |
1151 /* Examine I1 and I2 and return: | |
1152 - dir_forward if I1 can be replaced by I2, or | |
1153 - dir_backward if I2 can be replaced by I1, or | |
1154 - dir_both if both are the case. */ | |
1155 | |
1156 static enum replace_direction | |
1157 old_insns_match_p (int mode ATTRIBUTE_UNUSED, rtx_insn *i1, rtx_insn *i2) | |
0 | 1158 { |
1159 rtx p1, p2; | |
1160 | |
1161 /* Verify that I1 and I2 are equivalent. */ | |
1162 if (GET_CODE (i1) != GET_CODE (i2)) | |
111 | 1163 return dir_none; |
0 | 1164 |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1165 /* __builtin_unreachable() may lead to empty blocks (ending with |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1166 NOTE_INSN_BASIC_BLOCK). They may be crossjumped. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1167 if (NOTE_INSN_BASIC_BLOCK_P (i1) && NOTE_INSN_BASIC_BLOCK_P (i2)) |
111 | 1168 return dir_both; |
1169 | |
1170 /* ??? Do not allow cross-jumping between different stack levels. */ | |
1171 p1 = find_reg_note (i1, REG_ARGS_SIZE, NULL); | |
1172 p2 = find_reg_note (i2, REG_ARGS_SIZE, NULL); | |
1173 if (p1 && p2) | |
1174 { | |
1175 p1 = XEXP (p1, 0); | |
1176 p2 = XEXP (p2, 0); | |
1177 if (!rtx_equal_p (p1, p2)) | |
1178 return dir_none; | |
1179 | |
1180 /* ??? Worse, this adjustment had better be constant lest we | |
1181 have differing incoming stack levels. */ | |
1182 if (!frame_pointer_needed | |
1183 && find_args_size_adjust (i1) == HOST_WIDE_INT_MIN) | |
1184 return dir_none; | |
1185 } | |
1186 else if (p1 || p2) | |
1187 return dir_none; | |
1188 | |
1189 /* Do not allow cross-jumping between frame related insns and other | |
1190 insns. */ | |
1191 if (RTX_FRAME_RELATED_P (i1) != RTX_FRAME_RELATED_P (i2)) | |
1192 return dir_none; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1193 |
0 | 1194 p1 = PATTERN (i1); |
1195 p2 = PATTERN (i2); | |
1196 | |
1197 if (GET_CODE (p1) != GET_CODE (p2)) | |
111 | 1198 return dir_none; |
0 | 1199 |
1200 /* If this is a CALL_INSN, compare register usage information. | |
1201 If we don't check this on stack register machines, the two | |
1202 CALL_INSNs might be merged leaving reg-stack.c with mismatching | |
1203 numbers of stack registers in the same basic block. | |
1204 If we don't check this on machines with delay slots, a delay slot may | |
1205 be filled that clobbers a parameter expected by the subroutine. | |
1206 | |
1207 ??? We take the simple route for now and assume that if they're | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1208 equal, they were constructed identically. |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1209 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1210 Also check for identical exception regions. */ |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1211 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1212 if (CALL_P (i1)) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1213 { |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1214 /* Ensure the same EH region. */ |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1215 rtx n1 = find_reg_note (i1, REG_EH_REGION, 0); |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1216 rtx n2 = find_reg_note (i2, REG_EH_REGION, 0); |
0 | 1217 |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1218 if (!n1 && n2) |
111 | 1219 return dir_none; |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1220 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1221 if (n1 && (!n2 || XEXP (n1, 0) != XEXP (n2, 0))) |
111 | 1222 return dir_none; |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1223 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1224 if (!rtx_equal_p (CALL_INSN_FUNCTION_USAGE (i1), |
0 | 1225 CALL_INSN_FUNCTION_USAGE (i2)) |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1226 || SIBLING_CALL_P (i1) != SIBLING_CALL_P (i2)) |
111 | 1227 return dir_none; |
1228 | |
1229 /* For address sanitizer, never crossjump __asan_report_* builtins, | |
1230 otherwise errors might be reported on incorrect lines. */ | |
1231 if (flag_sanitize & SANITIZE_ADDRESS) | |
1232 { | |
1233 rtx call = get_call_rtx_from (i1); | |
1234 if (call && GET_CODE (XEXP (XEXP (call, 0), 0)) == SYMBOL_REF) | |
1235 { | |
1236 rtx symbol = XEXP (XEXP (call, 0), 0); | |
1237 if (SYMBOL_REF_DECL (symbol) | |
1238 && TREE_CODE (SYMBOL_REF_DECL (symbol)) == FUNCTION_DECL) | |
1239 { | |
1240 if ((DECL_BUILT_IN_CLASS (SYMBOL_REF_DECL (symbol)) | |
1241 == BUILT_IN_NORMAL) | |
1242 && DECL_FUNCTION_CODE (SYMBOL_REF_DECL (symbol)) | |
1243 >= BUILT_IN_ASAN_REPORT_LOAD1 | |
1244 && DECL_FUNCTION_CODE (SYMBOL_REF_DECL (symbol)) | |
1245 <= BUILT_IN_ASAN_STOREN) | |
1246 return dir_none; | |
1247 } | |
1248 } | |
1249 } | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1250 } |
0 | 1251 |
111 | 1252 /* If both i1 and i2 are frame related, verify all the CFA notes |
1253 in the same order and with the same content. */ | |
1254 if (RTX_FRAME_RELATED_P (i1) && !insns_have_identical_cfa_notes (i1, i2)) | |
1255 return dir_none; | |
1256 | |
0 | 1257 #ifdef STACK_REGS |
1258 /* If cross_jump_death_matters is not 0, the insn's mode | |
1259 indicates whether or not the insn contains any stack-like | |
1260 regs. */ | |
1261 | |
1262 if ((mode & CLEANUP_POST_REGSTACK) && stack_regs_mentioned (i1)) | |
1263 { | |
1264 /* If register stack conversion has already been done, then | |
1265 death notes must also be compared before it is certain that | |
1266 the two instruction streams match. */ | |
1267 | |
1268 rtx note; | |
1269 HARD_REG_SET i1_regset, i2_regset; | |
1270 | |
1271 CLEAR_HARD_REG_SET (i1_regset); | |
1272 CLEAR_HARD_REG_SET (i2_regset); | |
1273 | |
1274 for (note = REG_NOTES (i1); note; note = XEXP (note, 1)) | |
1275 if (REG_NOTE_KIND (note) == REG_DEAD && STACK_REG_P (XEXP (note, 0))) | |
1276 SET_HARD_REG_BIT (i1_regset, REGNO (XEXP (note, 0))); | |
1277 | |
1278 for (note = REG_NOTES (i2); note; note = XEXP (note, 1)) | |
1279 if (REG_NOTE_KIND (note) == REG_DEAD && STACK_REG_P (XEXP (note, 0))) | |
1280 SET_HARD_REG_BIT (i2_regset, REGNO (XEXP (note, 0))); | |
1281 | |
1282 if (!hard_reg_set_equal_p (i1_regset, i2_regset)) | |
111 | 1283 return dir_none; |
0 | 1284 } |
1285 #endif | |
1286 | |
1287 if (reload_completed | |
1288 ? rtx_renumbered_equal_p (p1, p2) : rtx_equal_p (p1, p2)) | |
111 | 1289 return dir_both; |
1290 | |
1291 return can_replace_by (i1, i2); | |
0 | 1292 } |
1293 | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1294 /* When comparing insns I1 and I2 in flow_find_cross_jump or |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1295 flow_find_head_matching_sequence, ensure the notes match. */ |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1296 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1297 static void |
111 | 1298 merge_notes (rtx_insn *i1, rtx_insn *i2) |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1299 { |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1300 /* If the merged insns have different REG_EQUAL notes, then |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1301 remove them. */ |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1302 rtx equiv1 = find_reg_equal_equiv_note (i1); |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1303 rtx equiv2 = find_reg_equal_equiv_note (i2); |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1304 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1305 if (equiv1 && !equiv2) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1306 remove_note (i1, equiv1); |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1307 else if (!equiv1 && equiv2) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1308 remove_note (i2, equiv2); |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1309 else if (equiv1 && equiv2 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1310 && !rtx_equal_p (XEXP (equiv1, 0), XEXP (equiv2, 0))) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1311 { |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1312 remove_note (i1, equiv1); |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1313 remove_note (i2, equiv2); |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1314 } |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1315 } |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1316 |
111 | 1317 /* Walks from I1 in BB1 backward till the next non-debug insn, and returns the |
1318 resulting insn in I1, and the corresponding bb in BB1. At the head of a | |
1319 bb, if there is a predecessor bb that reaches this bb via fallthru, and | |
1320 FOLLOW_FALLTHRU, walks further in the predecessor bb and registers this in | |
1321 DID_FALLTHRU. Otherwise, stops at the head of the bb. */ | |
1322 | |
1323 static void | |
1324 walk_to_nondebug_insn (rtx_insn **i1, basic_block *bb1, bool follow_fallthru, | |
1325 bool *did_fallthru) | |
1326 { | |
1327 edge fallthru; | |
1328 | |
1329 *did_fallthru = false; | |
1330 | |
1331 /* Ignore notes. */ | |
1332 while (!NONDEBUG_INSN_P (*i1)) | |
1333 { | |
1334 if (*i1 != BB_HEAD (*bb1)) | |
1335 { | |
1336 *i1 = PREV_INSN (*i1); | |
1337 continue; | |
1338 } | |
1339 | |
1340 if (!follow_fallthru) | |
1341 return; | |
1342 | |
1343 fallthru = find_fallthru_edge ((*bb1)->preds); | |
1344 if (!fallthru || fallthru->src == ENTRY_BLOCK_PTR_FOR_FN (cfun) | |
1345 || !single_succ_p (fallthru->src)) | |
1346 return; | |
1347 | |
1348 *bb1 = fallthru->src; | |
1349 *i1 = BB_END (*bb1); | |
1350 *did_fallthru = true; | |
1351 } | |
1352 } | |
1353 | |
0 | 1354 /* Look through the insns at the end of BB1 and BB2 and find the longest |
111 | 1355 sequence that are either equivalent, or allow forward or backward |
1356 replacement. Store the first insns for that sequence in *F1 and *F2 and | |
1357 return the sequence length. | |
1358 | |
1359 DIR_P indicates the allowed replacement direction on function entry, and | |
1360 the actual replacement direction on function exit. If NULL, only equivalent | |
1361 sequences are allowed. | |
0 | 1362 |
1363 To simplify callers of this function, if the blocks match exactly, | |
1364 store the head of the blocks in *F1 and *F2. */ | |
1365 | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1366 int |
111 | 1367 flow_find_cross_jump (basic_block bb1, basic_block bb2, rtx_insn **f1, |
1368 rtx_insn **f2, enum replace_direction *dir_p) | |
0 | 1369 { |
111 | 1370 rtx_insn *i1, *i2, *last1, *last2, *afterlast1, *afterlast2; |
0 | 1371 int ninsns = 0; |
111 | 1372 enum replace_direction dir, last_dir, afterlast_dir; |
1373 bool follow_fallthru, did_fallthru; | |
1374 | |
1375 if (dir_p) | |
1376 dir = *dir_p; | |
1377 else | |
1378 dir = dir_both; | |
1379 afterlast_dir = dir; | |
1380 last_dir = afterlast_dir; | |
0 | 1381 |
1382 /* Skip simple jumps at the end of the blocks. Complex jumps still | |
1383 need to be compared for equivalence, which we'll do below. */ | |
1384 | |
1385 i1 = BB_END (bb1); | |
111 | 1386 last1 = afterlast1 = last2 = afterlast2 = NULL; |
0 | 1387 if (onlyjump_p (i1) |
1388 || (returnjump_p (i1) && !side_effects_p (PATTERN (i1)))) | |
1389 { | |
1390 last1 = i1; | |
1391 i1 = PREV_INSN (i1); | |
1392 } | |
1393 | |
1394 i2 = BB_END (bb2); | |
1395 if (onlyjump_p (i2) | |
1396 || (returnjump_p (i2) && !side_effects_p (PATTERN (i2)))) | |
1397 { | |
1398 last2 = i2; | |
111 | 1399 /* Count everything except for unconditional jump as insn. |
1400 Don't count any jumps if dir_p is NULL. */ | |
1401 if (!simplejump_p (i2) && !returnjump_p (i2) && last1 && dir_p) | |
0 | 1402 ninsns++; |
1403 i2 = PREV_INSN (i2); | |
1404 } | |
1405 | |
1406 while (true) | |
1407 { | |
111 | 1408 /* In the following example, we can replace all jumps to C by jumps to A. |
1409 | |
1410 This removes 4 duplicate insns. | |
1411 [bb A] insn1 [bb C] insn1 | |
1412 insn2 insn2 | |
1413 [bb B] insn3 insn3 | |
1414 insn4 insn4 | |
1415 jump_insn jump_insn | |
1416 | |
1417 We could also replace all jumps to A by jumps to C, but that leaves B | |
1418 alive, and removes only 2 duplicate insns. In a subsequent crossjump | |
1419 step, all jumps to B would be replaced with jumps to the middle of C, | |
1420 achieving the same result with more effort. | |
1421 So we allow only the first possibility, which means that we don't allow | |
1422 fallthru in the block that's being replaced. */ | |
1423 | |
1424 follow_fallthru = dir_p && dir != dir_forward; | |
1425 walk_to_nondebug_insn (&i1, &bb1, follow_fallthru, &did_fallthru); | |
1426 if (did_fallthru) | |
1427 dir = dir_backward; | |
1428 | |
1429 follow_fallthru = dir_p && dir != dir_backward; | |
1430 walk_to_nondebug_insn (&i2, &bb2, follow_fallthru, &did_fallthru); | |
1431 if (did_fallthru) | |
1432 dir = dir_forward; | |
0 | 1433 |
1434 if (i1 == BB_HEAD (bb1) || i2 == BB_HEAD (bb2)) | |
1435 break; | |
1436 | |
111 | 1437 /* Do not turn corssing edge to non-crossing or vice versa after |
1438 reload. */ | |
1439 if (BB_PARTITION (BLOCK_FOR_INSN (i1)) | |
1440 != BB_PARTITION (BLOCK_FOR_INSN (i2)) | |
1441 && reload_completed) | |
1442 break; | |
1443 | |
1444 dir = merge_dir (dir, old_insns_match_p (0, i1, i2)); | |
1445 if (dir == dir_none || (!dir_p && dir != dir_both)) | |
0 | 1446 break; |
1447 | |
1448 merge_memattrs (i1, i2); | |
1449 | |
1450 /* Don't begin a cross-jump with a NOTE insn. */ | |
1451 if (INSN_P (i1)) | |
1452 { | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1453 merge_notes (i1, i2); |
0 | 1454 |
1455 afterlast1 = last1, afterlast2 = last2; | |
1456 last1 = i1, last2 = i2; | |
111 | 1457 afterlast_dir = last_dir; |
1458 last_dir = dir; | |
1459 if (active_insn_p (i1)) | |
1460 ninsns++; | |
0 | 1461 } |
1462 | |
1463 i1 = PREV_INSN (i1); | |
1464 i2 = PREV_INSN (i2); | |
1465 } | |
1466 | |
1467 /* Don't allow the insn after a compare to be shared by | |
1468 cross-jumping unless the compare is also shared. */ | |
111 | 1469 if (HAVE_cc0 && ninsns && reg_mentioned_p (cc0_rtx, last1) |
1470 && ! sets_cc0_p (last1)) | |
1471 last1 = afterlast1, last2 = afterlast2, last_dir = afterlast_dir, ninsns--; | |
0 | 1472 |
1473 /* Include preceding notes and labels in the cross-jump. One, | |
1474 this may bring us to the head of the blocks as requested above. | |
1475 Two, it keeps line number notes as matched as may be. */ | |
1476 if (ninsns) | |
1477 { | |
111 | 1478 bb1 = BLOCK_FOR_INSN (last1); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1479 while (last1 != BB_HEAD (bb1) && !NONDEBUG_INSN_P (PREV_INSN (last1))) |
0 | 1480 last1 = PREV_INSN (last1); |
1481 | |
1482 if (last1 != BB_HEAD (bb1) && LABEL_P (PREV_INSN (last1))) | |
1483 last1 = PREV_INSN (last1); | |
1484 | |
111 | 1485 bb2 = BLOCK_FOR_INSN (last2); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1486 while (last2 != BB_HEAD (bb2) && !NONDEBUG_INSN_P (PREV_INSN (last2))) |
0 | 1487 last2 = PREV_INSN (last2); |
1488 | |
1489 if (last2 != BB_HEAD (bb2) && LABEL_P (PREV_INSN (last2))) | |
1490 last2 = PREV_INSN (last2); | |
1491 | |
1492 *f1 = last1; | |
1493 *f2 = last2; | |
1494 } | |
1495 | |
111 | 1496 if (dir_p) |
1497 *dir_p = last_dir; | |
0 | 1498 return ninsns; |
1499 } | |
1500 | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1501 /* Like flow_find_cross_jump, except start looking for a matching sequence from |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1502 the head of the two blocks. Do not include jumps at the end. |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1503 If STOP_AFTER is nonzero, stop after finding that many matching |
111 | 1504 instructions. If STOP_AFTER is zero, count all INSN_P insns, if it is |
1505 non-zero, only count active insns. */ | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1506 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1507 int |
111 | 1508 flow_find_head_matching_sequence (basic_block bb1, basic_block bb2, rtx_insn **f1, |
1509 rtx_insn **f2, int stop_after) | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1510 { |
111 | 1511 rtx_insn *i1, *i2, *last1, *last2, *beforelast1, *beforelast2; |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1512 int ninsns = 0; |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1513 edge e; |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1514 edge_iterator ei; |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1515 int nehedges1 = 0, nehedges2 = 0; |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1516 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1517 FOR_EACH_EDGE (e, ei, bb1->succs) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1518 if (e->flags & EDGE_EH) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1519 nehedges1++; |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1520 FOR_EACH_EDGE (e, ei, bb2->succs) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1521 if (e->flags & EDGE_EH) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1522 nehedges2++; |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1523 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1524 i1 = BB_HEAD (bb1); |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1525 i2 = BB_HEAD (bb2); |
111 | 1526 last1 = beforelast1 = last2 = beforelast2 = NULL; |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1527 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1528 while (true) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1529 { |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1530 /* Ignore notes, except NOTE_INSN_EPILOGUE_BEG. */ |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1531 while (!NONDEBUG_INSN_P (i1) && i1 != BB_END (bb1)) |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1532 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1533 if (NOTE_P (i1) && NOTE_KIND (i1) == NOTE_INSN_EPILOGUE_BEG) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1534 break; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1535 i1 = NEXT_INSN (i1); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1536 } |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1537 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1538 while (!NONDEBUG_INSN_P (i2) && i2 != BB_END (bb2)) |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1539 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1540 if (NOTE_P (i2) && NOTE_KIND (i2) == NOTE_INSN_EPILOGUE_BEG) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1541 break; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1542 i2 = NEXT_INSN (i2); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1543 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1544 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1545 if ((i1 == BB_END (bb1) && !NONDEBUG_INSN_P (i1)) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1546 || (i2 == BB_END (bb2) && !NONDEBUG_INSN_P (i2))) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1547 break; |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1548 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1549 if (NOTE_P (i1) || NOTE_P (i2) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1550 || JUMP_P (i1) || JUMP_P (i2)) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1551 break; |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1552 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1553 /* A sanity check to make sure we're not merging insns with different |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1554 effects on EH. If only one of them ends a basic block, it shouldn't |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1555 have an EH edge; if both end a basic block, there should be the same |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1556 number of EH edges. */ |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1557 if ((i1 == BB_END (bb1) && i2 != BB_END (bb2) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1558 && nehedges1 > 0) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1559 || (i2 == BB_END (bb2) && i1 != BB_END (bb1) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1560 && nehedges2 > 0) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1561 || (i1 == BB_END (bb1) && i2 == BB_END (bb2) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1562 && nehedges1 != nehedges2)) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1563 break; |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1564 |
111 | 1565 if (old_insns_match_p (0, i1, i2) != dir_both) |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1566 break; |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1567 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1568 merge_memattrs (i1, i2); |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1569 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1570 /* Don't begin a cross-jump with a NOTE insn. */ |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1571 if (INSN_P (i1)) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1572 { |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1573 merge_notes (i1, i2); |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1574 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1575 beforelast1 = last1, beforelast2 = last2; |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1576 last1 = i1, last2 = i2; |
111 | 1577 if (!stop_after || active_insn_p (i1)) |
1578 ninsns++; | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1579 } |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1580 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1581 if (i1 == BB_END (bb1) || i2 == BB_END (bb2) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1582 || (stop_after > 0 && ninsns == stop_after)) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1583 break; |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1584 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1585 i1 = NEXT_INSN (i1); |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1586 i2 = NEXT_INSN (i2); |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1587 } |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1588 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1589 /* Don't allow a compare to be shared by cross-jumping unless the insn |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1590 after the compare is also shared. */ |
111 | 1591 if (HAVE_cc0 && ninsns && reg_mentioned_p (cc0_rtx, last1) |
1592 && sets_cc0_p (last1)) | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1593 last1 = beforelast1, last2 = beforelast2, ninsns--; |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1594 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1595 if (ninsns) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1596 { |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1597 *f1 = last1; |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1598 *f2 = last2; |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1599 } |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1600 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1601 return ninsns; |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1602 } |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1603 |
0 | 1604 /* Return true iff outgoing edges of BB1 and BB2 match, together with |
1605 the branch instruction. This means that if we commonize the control | |
1606 flow before end of the basic block, the semantic remains unchanged. | |
1607 | |
1608 We may assume that there exists one edge with a common destination. */ | |
1609 | |
1610 static bool | |
1611 outgoing_edges_match (int mode, basic_block bb1, basic_block bb2) | |
1612 { | |
1613 int nehedges1 = 0, nehedges2 = 0; | |
1614 edge fallthru1 = 0, fallthru2 = 0; | |
1615 edge e1, e2; | |
1616 edge_iterator ei; | |
1617 | |
111 | 1618 /* If we performed shrink-wrapping, edges to the exit block can |
1619 only be distinguished for JUMP_INSNs. The two paths may differ in | |
1620 whether they went through the prologue. Sibcalls are fine, we know | |
1621 that we either didn't need or inserted an epilogue before them. */ | |
1622 if (crtl->shrink_wrapped | |
1623 && single_succ_p (bb1) | |
1624 && single_succ (bb1) == EXIT_BLOCK_PTR_FOR_FN (cfun) | |
1625 && !JUMP_P (BB_END (bb1)) | |
1626 && !(CALL_P (BB_END (bb1)) && SIBLING_CALL_P (BB_END (bb1)))) | |
1627 return false; | |
1628 | |
0 | 1629 /* If BB1 has only one successor, we may be looking at either an |
1630 unconditional jump, or a fake edge to exit. */ | |
1631 if (single_succ_p (bb1) | |
1632 && (single_succ_edge (bb1)->flags & (EDGE_COMPLEX | EDGE_FAKE)) == 0 | |
1633 && (!JUMP_P (BB_END (bb1)) || simplejump_p (BB_END (bb1)))) | |
1634 return (single_succ_p (bb2) | |
1635 && (single_succ_edge (bb2)->flags | |
1636 & (EDGE_COMPLEX | EDGE_FAKE)) == 0 | |
1637 && (!JUMP_P (BB_END (bb2)) || simplejump_p (BB_END (bb2)))); | |
1638 | |
1639 /* Match conditional jumps - this may get tricky when fallthru and branch | |
1640 edges are crossed. */ | |
1641 if (EDGE_COUNT (bb1->succs) == 2 | |
1642 && any_condjump_p (BB_END (bb1)) | |
1643 && onlyjump_p (BB_END (bb1))) | |
1644 { | |
1645 edge b1, f1, b2, f2; | |
1646 bool reverse, match; | |
1647 rtx set1, set2, cond1, cond2; | |
1648 enum rtx_code code1, code2; | |
1649 | |
1650 if (EDGE_COUNT (bb2->succs) != 2 | |
1651 || !any_condjump_p (BB_END (bb2)) | |
1652 || !onlyjump_p (BB_END (bb2))) | |
1653 return false; | |
1654 | |
1655 b1 = BRANCH_EDGE (bb1); | |
1656 b2 = BRANCH_EDGE (bb2); | |
1657 f1 = FALLTHRU_EDGE (bb1); | |
1658 f2 = FALLTHRU_EDGE (bb2); | |
1659 | |
1660 /* Get around possible forwarders on fallthru edges. Other cases | |
1661 should be optimized out already. */ | |
1662 if (FORWARDER_BLOCK_P (f1->dest)) | |
1663 f1 = single_succ_edge (f1->dest); | |
1664 | |
1665 if (FORWARDER_BLOCK_P (f2->dest)) | |
1666 f2 = single_succ_edge (f2->dest); | |
1667 | |
1668 /* To simplify use of this function, return false if there are | |
1669 unneeded forwarder blocks. These will get eliminated later | |
1670 during cleanup_cfg. */ | |
1671 if (FORWARDER_BLOCK_P (f1->dest) | |
1672 || FORWARDER_BLOCK_P (f2->dest) | |
1673 || FORWARDER_BLOCK_P (b1->dest) | |
1674 || FORWARDER_BLOCK_P (b2->dest)) | |
1675 return false; | |
1676 | |
1677 if (f1->dest == f2->dest && b1->dest == b2->dest) | |
1678 reverse = false; | |
1679 else if (f1->dest == b2->dest && b1->dest == f2->dest) | |
1680 reverse = true; | |
1681 else | |
1682 return false; | |
1683 | |
1684 set1 = pc_set (BB_END (bb1)); | |
1685 set2 = pc_set (BB_END (bb2)); | |
1686 if ((XEXP (SET_SRC (set1), 1) == pc_rtx) | |
1687 != (XEXP (SET_SRC (set2), 1) == pc_rtx)) | |
1688 reverse = !reverse; | |
1689 | |
1690 cond1 = XEXP (SET_SRC (set1), 0); | |
1691 cond2 = XEXP (SET_SRC (set2), 0); | |
1692 code1 = GET_CODE (cond1); | |
1693 if (reverse) | |
1694 code2 = reversed_comparison_code (cond2, BB_END (bb2)); | |
1695 else | |
1696 code2 = GET_CODE (cond2); | |
1697 | |
1698 if (code2 == UNKNOWN) | |
1699 return false; | |
1700 | |
1701 /* Verify codes and operands match. */ | |
1702 match = ((code1 == code2 | |
1703 && rtx_renumbered_equal_p (XEXP (cond1, 0), XEXP (cond2, 0)) | |
1704 && rtx_renumbered_equal_p (XEXP (cond1, 1), XEXP (cond2, 1))) | |
1705 || (code1 == swap_condition (code2) | |
1706 && rtx_renumbered_equal_p (XEXP (cond1, 1), | |
1707 XEXP (cond2, 0)) | |
1708 && rtx_renumbered_equal_p (XEXP (cond1, 0), | |
1709 XEXP (cond2, 1)))); | |
1710 | |
1711 /* If we return true, we will join the blocks. Which means that | |
1712 we will only have one branch prediction bit to work with. Thus | |
1713 we require the existing branches to have probabilities that are | |
1714 roughly similar. */ | |
1715 if (match | |
1716 && optimize_bb_for_speed_p (bb1) | |
1717 && optimize_bb_for_speed_p (bb2)) | |
1718 { | |
111 | 1719 profile_probability prob2; |
0 | 1720 |
1721 if (b1->dest == b2->dest) | |
1722 prob2 = b2->probability; | |
1723 else | |
1724 /* Do not use f2 probability as f2 may be forwarded. */ | |
111 | 1725 prob2 = b2->probability.invert (); |
0 | 1726 |
1727 /* Fail if the difference in probabilities is greater than 50%. | |
1728 This rules out two well-predicted branches with opposite | |
1729 outcomes. */ | |
111 | 1730 if (b1->probability.differs_lot_from_p (prob2)) |
0 | 1731 { |
1732 if (dump_file) | |
111 | 1733 { |
1734 fprintf (dump_file, | |
1735 "Outcomes of branch in bb %i and %i differ too" | |
1736 " much (", bb1->index, bb2->index); | |
1737 b1->probability.dump (dump_file); | |
1738 prob2.dump (dump_file); | |
1739 fprintf (dump_file, ")\n"); | |
1740 } | |
0 | 1741 return false; |
1742 } | |
1743 } | |
1744 | |
1745 if (dump_file && match) | |
1746 fprintf (dump_file, "Conditionals in bb %i and %i match.\n", | |
1747 bb1->index, bb2->index); | |
1748 | |
1749 return match; | |
1750 } | |
1751 | |
1752 /* Generic case - we are seeing a computed jump, table jump or trapping | |
1753 instruction. */ | |
1754 | |
1755 /* Check whether there are tablejumps in the end of BB1 and BB2. | |
1756 Return true if they are identical. */ | |
1757 { | |
111 | 1758 rtx_insn *label1, *label2; |
1759 rtx_jump_table_data *table1, *table2; | |
0 | 1760 |
1761 if (tablejump_p (BB_END (bb1), &label1, &table1) | |
1762 && tablejump_p (BB_END (bb2), &label2, &table2) | |
1763 && GET_CODE (PATTERN (table1)) == GET_CODE (PATTERN (table2))) | |
1764 { | |
1765 /* The labels should never be the same rtx. If they really are same | |
1766 the jump tables are same too. So disable crossjumping of blocks BB1 | |
1767 and BB2 because when deleting the common insns in the end of BB1 | |
1768 by delete_basic_block () the jump table would be deleted too. */ | |
1769 /* If LABEL2 is referenced in BB1->END do not do anything | |
1770 because we would loose information when replacing | |
1771 LABEL1 by LABEL2 and then LABEL2 by LABEL1 in BB1->END. */ | |
1772 if (label1 != label2 && !rtx_referenced_p (label2, BB_END (bb1))) | |
1773 { | |
1774 /* Set IDENTICAL to true when the tables are identical. */ | |
1775 bool identical = false; | |
1776 rtx p1, p2; | |
1777 | |
1778 p1 = PATTERN (table1); | |
1779 p2 = PATTERN (table2); | |
1780 if (GET_CODE (p1) == ADDR_VEC && rtx_equal_p (p1, p2)) | |
1781 { | |
1782 identical = true; | |
1783 } | |
1784 else if (GET_CODE (p1) == ADDR_DIFF_VEC | |
1785 && (XVECLEN (p1, 1) == XVECLEN (p2, 1)) | |
1786 && rtx_equal_p (XEXP (p1, 2), XEXP (p2, 2)) | |
1787 && rtx_equal_p (XEXP (p1, 3), XEXP (p2, 3))) | |
1788 { | |
1789 int i; | |
1790 | |
1791 identical = true; | |
1792 for (i = XVECLEN (p1, 1) - 1; i >= 0 && identical; i--) | |
1793 if (!rtx_equal_p (XVECEXP (p1, 1, i), XVECEXP (p2, 1, i))) | |
1794 identical = false; | |
1795 } | |
1796 | |
1797 if (identical) | |
1798 { | |
1799 bool match; | |
1800 | |
1801 /* Temporarily replace references to LABEL1 with LABEL2 | |
1802 in BB1->END so that we could compare the instructions. */ | |
111 | 1803 replace_label_in_insn (BB_END (bb1), label1, label2, false); |
1804 | |
1805 match = (old_insns_match_p (mode, BB_END (bb1), BB_END (bb2)) | |
1806 == dir_both); | |
0 | 1807 if (dump_file && match) |
1808 fprintf (dump_file, | |
1809 "Tablejumps in bb %i and %i match.\n", | |
1810 bb1->index, bb2->index); | |
1811 | |
1812 /* Set the original label in BB1->END because when deleting | |
1813 a block whose end is a tablejump, the tablejump referenced | |
1814 from the instruction is deleted too. */ | |
111 | 1815 replace_label_in_insn (BB_END (bb1), label2, label1, false); |
0 | 1816 |
1817 return match; | |
1818 } | |
1819 } | |
1820 return false; | |
1821 } | |
1822 } | |
1823 | |
111 | 1824 /* Find the last non-debug non-note instruction in each bb, except |
1825 stop when we see the NOTE_INSN_BASIC_BLOCK, as old_insns_match_p | |
1826 handles that case specially. old_insns_match_p does not handle | |
1827 other types of instruction notes. */ | |
1828 rtx_insn *last1 = BB_END (bb1); | |
1829 rtx_insn *last2 = BB_END (bb2); | |
1830 while (!NOTE_INSN_BASIC_BLOCK_P (last1) && | |
1831 (DEBUG_INSN_P (last1) || NOTE_P (last1))) | |
1832 last1 = PREV_INSN (last1); | |
1833 while (!NOTE_INSN_BASIC_BLOCK_P (last2) && | |
1834 (DEBUG_INSN_P (last2) || NOTE_P (last2))) | |
1835 last2 = PREV_INSN (last2); | |
1836 gcc_assert (last1 && last2); | |
1837 | |
0 | 1838 /* First ensure that the instructions match. There may be many outgoing |
1839 edges so this test is generally cheaper. */ | |
111 | 1840 if (old_insns_match_p (mode, last1, last2) != dir_both) |
0 | 1841 return false; |
1842 | |
1843 /* Search the outgoing edges, ensure that the counts do match, find possible | |
1844 fallthru and exception handling edges since these needs more | |
1845 validation. */ | |
1846 if (EDGE_COUNT (bb1->succs) != EDGE_COUNT (bb2->succs)) | |
1847 return false; | |
1848 | |
111 | 1849 bool nonfakeedges = false; |
0 | 1850 FOR_EACH_EDGE (e1, ei, bb1->succs) |
1851 { | |
1852 e2 = EDGE_SUCC (bb2, ei.index); | |
1853 | |
111 | 1854 if ((e1->flags & EDGE_FAKE) == 0) |
1855 nonfakeedges = true; | |
1856 | |
0 | 1857 if (e1->flags & EDGE_EH) |
1858 nehedges1++; | |
1859 | |
1860 if (e2->flags & EDGE_EH) | |
1861 nehedges2++; | |
1862 | |
1863 if (e1->flags & EDGE_FALLTHRU) | |
1864 fallthru1 = e1; | |
1865 if (e2->flags & EDGE_FALLTHRU) | |
1866 fallthru2 = e2; | |
1867 } | |
1868 | |
1869 /* If number of edges of various types does not match, fail. */ | |
1870 if (nehedges1 != nehedges2 | |
1871 || (fallthru1 != 0) != (fallthru2 != 0)) | |
1872 return false; | |
1873 | |
111 | 1874 /* If !ACCUMULATE_OUTGOING_ARGS, bb1 (and bb2) have no successors |
1875 and the last real insn doesn't have REG_ARGS_SIZE note, don't | |
1876 attempt to optimize, as the two basic blocks might have different | |
1877 REG_ARGS_SIZE depths. For noreturn calls and unconditional | |
1878 traps there should be REG_ARG_SIZE notes, they could be missing | |
1879 for __builtin_unreachable () uses though. */ | |
1880 if (!nonfakeedges | |
1881 && !ACCUMULATE_OUTGOING_ARGS | |
1882 && (!INSN_P (last1) | |
1883 || !find_reg_note (last1, REG_ARGS_SIZE, NULL))) | |
1884 return false; | |
1885 | |
0 | 1886 /* fallthru edges must be forwarded to the same destination. */ |
1887 if (fallthru1) | |
1888 { | |
1889 basic_block d1 = (forwarder_block_p (fallthru1->dest) | |
1890 ? single_succ (fallthru1->dest): fallthru1->dest); | |
1891 basic_block d2 = (forwarder_block_p (fallthru2->dest) | |
1892 ? single_succ (fallthru2->dest): fallthru2->dest); | |
1893 | |
1894 if (d1 != d2) | |
1895 return false; | |
1896 } | |
1897 | |
1898 /* Ensure the same EH region. */ | |
1899 { | |
1900 rtx n1 = find_reg_note (BB_END (bb1), REG_EH_REGION, 0); | |
1901 rtx n2 = find_reg_note (BB_END (bb2), REG_EH_REGION, 0); | |
1902 | |
1903 if (!n1 && n2) | |
1904 return false; | |
1905 | |
1906 if (n1 && (!n2 || XEXP (n1, 0) != XEXP (n2, 0))) | |
1907 return false; | |
1908 } | |
1909 | |
1910 /* The same checks as in try_crossjump_to_edge. It is required for RTL | |
1911 version of sequence abstraction. */ | |
1912 FOR_EACH_EDGE (e1, ei, bb2->succs) | |
1913 { | |
1914 edge e2; | |
1915 edge_iterator ei; | |
1916 basic_block d1 = e1->dest; | |
1917 | |
1918 if (FORWARDER_BLOCK_P (d1)) | |
1919 d1 = EDGE_SUCC (d1, 0)->dest; | |
1920 | |
1921 FOR_EACH_EDGE (e2, ei, bb1->succs) | |
1922 { | |
1923 basic_block d2 = e2->dest; | |
1924 if (FORWARDER_BLOCK_P (d2)) | |
1925 d2 = EDGE_SUCC (d2, 0)->dest; | |
1926 if (d1 == d2) | |
1927 break; | |
1928 } | |
1929 | |
1930 if (!e2) | |
1931 return false; | |
1932 } | |
1933 | |
1934 return true; | |
1935 } | |
1936 | |
1937 /* Returns true if BB basic block has a preserve label. */ | |
1938 | |
1939 static bool | |
1940 block_has_preserve_label (basic_block bb) | |
1941 { | |
1942 return (bb | |
1943 && block_label (bb) | |
1944 && LABEL_PRESERVE_P (block_label (bb))); | |
1945 } | |
1946 | |
1947 /* E1 and E2 are edges with the same destination block. Search their | |
1948 predecessors for common code. If found, redirect control flow from | |
111 | 1949 (maybe the middle of) E1->SRC to (maybe the middle of) E2->SRC (dir_forward), |
1950 or the other way around (dir_backward). DIR specifies the allowed | |
1951 replacement direction. */ | |
0 | 1952 |
1953 static bool | |
111 | 1954 try_crossjump_to_edge (int mode, edge e1, edge e2, |
1955 enum replace_direction dir) | |
0 | 1956 { |
1957 int nmatch; | |
1958 basic_block src1 = e1->src, src2 = e2->src; | |
1959 basic_block redirect_to, redirect_from, to_remove; | |
111 | 1960 basic_block osrc1, osrc2, redirect_edges_to, tmp; |
1961 rtx_insn *newpos1, *newpos2; | |
0 | 1962 edge s; |
1963 edge_iterator ei; | |
1964 | |
111 | 1965 newpos1 = newpos2 = NULL; |
0 | 1966 |
1967 /* Search backward through forwarder blocks. We don't need to worry | |
1968 about multiple entry or chained forwarders, as they will be optimized | |
1969 away. We do this to look past the unconditional jump following a | |
1970 conditional jump that is required due to the current CFG shape. */ | |
1971 if (single_pred_p (src1) | |
1972 && FORWARDER_BLOCK_P (src1)) | |
1973 e1 = single_pred_edge (src1), src1 = e1->src; | |
1974 | |
1975 if (single_pred_p (src2) | |
1976 && FORWARDER_BLOCK_P (src2)) | |
1977 e2 = single_pred_edge (src2), src2 = e2->src; | |
1978 | |
1979 /* Nothing to do if we reach ENTRY, or a common source block. */ | |
111 | 1980 if (src1 == ENTRY_BLOCK_PTR_FOR_FN (cfun) || src2 |
1981 == ENTRY_BLOCK_PTR_FOR_FN (cfun)) | |
0 | 1982 return false; |
1983 if (src1 == src2) | |
1984 return false; | |
1985 | |
1986 /* Seeing more than 1 forwarder blocks would confuse us later... */ | |
1987 if (FORWARDER_BLOCK_P (e1->dest) | |
1988 && FORWARDER_BLOCK_P (single_succ (e1->dest))) | |
1989 return false; | |
1990 | |
1991 if (FORWARDER_BLOCK_P (e2->dest) | |
1992 && FORWARDER_BLOCK_P (single_succ (e2->dest))) | |
1993 return false; | |
1994 | |
1995 /* Likewise with dead code (possibly newly created by the other optimizations | |
1996 of cfg_cleanup). */ | |
1997 if (EDGE_COUNT (src1->preds) == 0 || EDGE_COUNT (src2->preds) == 0) | |
1998 return false; | |
1999 | |
111 | 2000 /* Do not turn corssing edge to non-crossing or vice versa after reload. */ |
2001 if (BB_PARTITION (src1) != BB_PARTITION (src2) | |
2002 && reload_completed) | |
2003 return false; | |
2004 | |
0 | 2005 /* Look for the common insn sequence, part the first ... */ |
2006 if (!outgoing_edges_match (mode, src1, src2)) | |
2007 return false; | |
2008 | |
2009 /* ... and part the second. */ | |
111 | 2010 nmatch = flow_find_cross_jump (src1, src2, &newpos1, &newpos2, &dir); |
2011 | |
2012 osrc1 = src1; | |
2013 osrc2 = src2; | |
2014 if (newpos1 != NULL_RTX) | |
2015 src1 = BLOCK_FOR_INSN (newpos1); | |
2016 if (newpos2 != NULL_RTX) | |
2017 src2 = BLOCK_FOR_INSN (newpos2); | |
2018 | |
2019 /* Check that SRC1 and SRC2 have preds again. They may have changed | |
2020 above due to the call to flow_find_cross_jump. */ | |
2021 if (EDGE_COUNT (src1->preds) == 0 || EDGE_COUNT (src2->preds) == 0) | |
2022 return false; | |
2023 | |
2024 if (dir == dir_backward) | |
2025 { | |
2026 std::swap (osrc1, osrc2); | |
2027 std::swap (src1, src2); | |
2028 std::swap (e1, e2); | |
2029 std::swap (newpos1, newpos2); | |
2030 } | |
0 | 2031 |
2032 /* Don't proceed with the crossjump unless we found a sufficient number | |
2033 of matching instructions or the 'from' block was totally matched | |
2034 (such that its predecessors will hopefully be redirected and the | |
2035 block removed). */ | |
2036 if ((nmatch < PARAM_VALUE (PARAM_MIN_CROSSJUMP_INSNS)) | |
2037 && (newpos1 != BB_HEAD (src1))) | |
2038 return false; | |
2039 | |
2040 /* Avoid deleting preserve label when redirecting ABNORMAL edges. */ | |
2041 if (block_has_preserve_label (e1->dest) | |
2042 && (e1->flags & EDGE_ABNORMAL)) | |
2043 return false; | |
2044 | |
2045 /* Here we know that the insns in the end of SRC1 which are common with SRC2 | |
2046 will be deleted. | |
2047 If we have tablejumps in the end of SRC1 and SRC2 | |
2048 they have been already compared for equivalence in outgoing_edges_match () | |
2049 so replace the references to TABLE1 by references to TABLE2. */ | |
111 | 2050 { |
2051 rtx_insn *label1, *label2; | |
2052 rtx_jump_table_data *table1, *table2; | |
2053 | |
2054 if (tablejump_p (BB_END (osrc1), &label1, &table1) | |
2055 && tablejump_p (BB_END (osrc2), &label2, &table2) | |
0 | 2056 && label1 != label2) |
2057 { | |
111 | 2058 rtx_insn *insn; |
0 | 2059 |
2060 /* Replace references to LABEL1 with LABEL2. */ | |
2061 for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) | |
2062 { | |
2063 /* Do not replace the label in SRC1->END because when deleting | |
2064 a block whose end is a tablejump, the tablejump referenced | |
2065 from the instruction is deleted too. */ | |
111 | 2066 if (insn != BB_END (osrc1)) |
2067 replace_label_in_insn (insn, label1, label2, true); | |
0 | 2068 } |
2069 } | |
111 | 2070 } |
0 | 2071 |
2072 /* Avoid splitting if possible. We must always split when SRC2 has | |
2073 EH predecessor edges, or we may end up with basic blocks with both | |
2074 normal and EH predecessor edges. */ | |
2075 if (newpos2 == BB_HEAD (src2) | |
2076 && !(EDGE_PRED (src2, 0)->flags & EDGE_EH)) | |
2077 redirect_to = src2; | |
2078 else | |
2079 { | |
2080 if (newpos2 == BB_HEAD (src2)) | |
2081 { | |
2082 /* Skip possible basic block header. */ | |
2083 if (LABEL_P (newpos2)) | |
2084 newpos2 = NEXT_INSN (newpos2); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2085 while (DEBUG_INSN_P (newpos2)) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2086 newpos2 = NEXT_INSN (newpos2); |
0 | 2087 if (NOTE_P (newpos2)) |
2088 newpos2 = NEXT_INSN (newpos2); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2089 while (DEBUG_INSN_P (newpos2)) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2090 newpos2 = NEXT_INSN (newpos2); |
0 | 2091 } |
2092 | |
2093 if (dump_file) | |
2094 fprintf (dump_file, "Splitting bb %i before %i insns\n", | |
2095 src2->index, nmatch); | |
2096 redirect_to = split_block (src2, PREV_INSN (newpos2))->dest; | |
2097 } | |
2098 | |
2099 if (dump_file) | |
2100 fprintf (dump_file, | |
2101 "Cross jumping from bb %i to bb %i; %i common insns\n", | |
2102 src1->index, src2->index, nmatch); | |
2103 | |
2104 /* We may have some registers visible through the block. */ | |
2105 df_set_bb_dirty (redirect_to); | |
2106 | |
111 | 2107 if (osrc2 == src2) |
2108 redirect_edges_to = redirect_to; | |
2109 else | |
2110 redirect_edges_to = osrc2; | |
2111 | |
0 | 2112 /* Recompute the frequencies and counts of outgoing edges. */ |
111 | 2113 FOR_EACH_EDGE (s, ei, redirect_edges_to->succs) |
0 | 2114 { |
2115 edge s2; | |
2116 edge_iterator ei; | |
2117 basic_block d = s->dest; | |
2118 | |
2119 if (FORWARDER_BLOCK_P (d)) | |
2120 d = single_succ (d); | |
2121 | |
2122 FOR_EACH_EDGE (s2, ei, src1->succs) | |
2123 { | |
2124 basic_block d2 = s2->dest; | |
2125 if (FORWARDER_BLOCK_P (d2)) | |
2126 d2 = single_succ (d2); | |
2127 if (d == d2) | |
2128 break; | |
2129 } | |
2130 | |
2131 /* Take care to update possible forwarder blocks. We verified | |
2132 that there is no more than one in the chain, so we can't run | |
2133 into infinite loop. */ | |
2134 if (FORWARDER_BLOCK_P (s->dest)) | |
2135 { | |
2136 s->dest->frequency += EDGE_FREQUENCY (s); | |
2137 } | |
2138 | |
2139 if (FORWARDER_BLOCK_P (s2->dest)) | |
2140 { | |
2141 s2->dest->frequency -= EDGE_FREQUENCY (s); | |
2142 if (s2->dest->frequency < 0) | |
2143 s2->dest->frequency = 0; | |
2144 } | |
2145 | |
111 | 2146 if (!redirect_edges_to->frequency && !src1->frequency) |
2147 s->probability = s->probability.combine_with_freq | |
2148 (redirect_edges_to->frequency, | |
2149 s2->probability, src1->frequency); | |
0 | 2150 } |
2151 | |
2152 /* Adjust count and frequency for the block. An earlier jump | |
2153 threading pass may have left the profile in an inconsistent | |
2154 state (see update_bb_profile_for_threading) so we must be | |
2155 prepared for overflows. */ | |
111 | 2156 tmp = redirect_to; |
2157 do | |
2158 { | |
2159 tmp->count += src1->count; | |
2160 tmp->frequency += src1->frequency; | |
2161 if (tmp->frequency > BB_FREQ_MAX) | |
2162 tmp->frequency = BB_FREQ_MAX; | |
2163 if (tmp == redirect_edges_to) | |
2164 break; | |
2165 tmp = find_fallthru_edge (tmp->succs)->dest; | |
2166 } | |
2167 while (true); | |
2168 update_br_prob_note (redirect_edges_to); | |
0 | 2169 |
2170 /* Edit SRC1 to go to REDIRECT_TO at NEWPOS1. */ | |
2171 | |
2172 /* Skip possible basic block header. */ | |
2173 if (LABEL_P (newpos1)) | |
2174 newpos1 = NEXT_INSN (newpos1); | |
2175 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2176 while (DEBUG_INSN_P (newpos1)) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2177 newpos1 = NEXT_INSN (newpos1); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2178 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2179 if (NOTE_INSN_BASIC_BLOCK_P (newpos1)) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2180 newpos1 = NEXT_INSN (newpos1); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2181 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2182 while (DEBUG_INSN_P (newpos1)) |
0 | 2183 newpos1 = NEXT_INSN (newpos1); |
2184 | |
2185 redirect_from = split_block (src1, PREV_INSN (newpos1))->src; | |
2186 to_remove = single_succ (redirect_from); | |
2187 | |
2188 redirect_edge_and_branch_force (single_succ_edge (redirect_from), redirect_to); | |
2189 delete_basic_block (to_remove); | |
2190 | |
2191 update_forwarder_flag (redirect_from); | |
2192 if (redirect_to != src2) | |
2193 update_forwarder_flag (src2); | |
2194 | |
2195 return true; | |
2196 } | |
2197 | |
2198 /* Search the predecessors of BB for common insn sequences. When found, | |
2199 share code between them by redirecting control flow. Return true if | |
2200 any changes made. */ | |
2201 | |
2202 static bool | |
2203 try_crossjump_bb (int mode, basic_block bb) | |
2204 { | |
2205 edge e, e2, fallthru; | |
2206 bool changed; | |
2207 unsigned max, ix, ix2; | |
2208 | |
2209 /* Nothing to do if there is not at least two incoming edges. */ | |
2210 if (EDGE_COUNT (bb->preds) < 2) | |
2211 return false; | |
2212 | |
2213 /* Don't crossjump if this block ends in a computed jump, | |
2214 unless we are optimizing for size. */ | |
2215 if (optimize_bb_for_size_p (bb) | |
111 | 2216 && bb != EXIT_BLOCK_PTR_FOR_FN (cfun) |
0 | 2217 && computed_jump_p (BB_END (bb))) |
2218 return false; | |
2219 | |
2220 /* If we are partitioning hot/cold basic blocks, we don't want to | |
2221 mess up unconditional or indirect jumps that cross between hot | |
2222 and cold sections. | |
2223 | |
2224 Basic block partitioning may result in some jumps that appear to | |
2225 be optimizable (or blocks that appear to be mergeable), but which really | |
2226 must be left untouched (they are required to make it safely across | |
2227 partition boundaries). See the comments at the top of | |
2228 bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */ | |
2229 | |
2230 if (BB_PARTITION (EDGE_PRED (bb, 0)->src) != | |
2231 BB_PARTITION (EDGE_PRED (bb, 1)->src) | |
2232 || (EDGE_PRED (bb, 0)->flags & EDGE_CROSSING)) | |
2233 return false; | |
2234 | |
2235 /* It is always cheapest to redirect a block that ends in a branch to | |
2236 a block that falls through into BB, as that adds no branches to the | |
2237 program. We'll try that combination first. */ | |
2238 fallthru = NULL; | |
2239 max = PARAM_VALUE (PARAM_MAX_CROSSJUMP_EDGES); | |
2240 | |
2241 if (EDGE_COUNT (bb->preds) > max) | |
2242 return false; | |
2243 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2244 fallthru = find_fallthru_edge (bb->preds); |
0 | 2245 |
2246 changed = false; | |
111 | 2247 for (ix = 0; ix < EDGE_COUNT (bb->preds);) |
0 | 2248 { |
111 | 2249 e = EDGE_PRED (bb, ix); |
0 | 2250 ix++; |
2251 | |
2252 /* As noted above, first try with the fallthru predecessor (or, a | |
2253 fallthru predecessor if we are in cfglayout mode). */ | |
2254 if (fallthru) | |
2255 { | |
2256 /* Don't combine the fallthru edge into anything else. | |
2257 If there is a match, we'll do it the other way around. */ | |
2258 if (e == fallthru) | |
2259 continue; | |
2260 /* If nothing changed since the last attempt, there is nothing | |
2261 we can do. */ | |
2262 if (!first_pass | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2263 && !((e->src->flags & BB_MODIFIED) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2264 || (fallthru->src->flags & BB_MODIFIED))) |
0 | 2265 continue; |
2266 | |
111 | 2267 if (try_crossjump_to_edge (mode, e, fallthru, dir_forward)) |
0 | 2268 { |
2269 changed = true; | |
2270 ix = 0; | |
2271 continue; | |
2272 } | |
2273 } | |
2274 | |
2275 /* Non-obvious work limiting check: Recognize that we're going | |
2276 to call try_crossjump_bb on every basic block. So if we have | |
2277 two blocks with lots of outgoing edges (a switch) and they | |
2278 share lots of common destinations, then we would do the | |
2279 cross-jump check once for each common destination. | |
2280 | |
2281 Now, if the blocks actually are cross-jump candidates, then | |
2282 all of their destinations will be shared. Which means that | |
2283 we only need check them for cross-jump candidacy once. We | |
2284 can eliminate redundant checks of crossjump(A,B) by arbitrarily | |
2285 choosing to do the check from the block for which the edge | |
2286 in question is the first successor of A. */ | |
2287 if (EDGE_SUCC (e->src, 0) != e) | |
2288 continue; | |
2289 | |
111 | 2290 for (ix2 = 0; ix2 < EDGE_COUNT (bb->preds); ix2++) |
0 | 2291 { |
111 | 2292 e2 = EDGE_PRED (bb, ix2); |
0 | 2293 |
2294 if (e2 == e) | |
2295 continue; | |
2296 | |
2297 /* We've already checked the fallthru edge above. */ | |
2298 if (e2 == fallthru) | |
2299 continue; | |
2300 | |
2301 /* The "first successor" check above only prevents multiple | |
2302 checks of crossjump(A,B). In order to prevent redundant | |
2303 checks of crossjump(B,A), require that A be the block | |
2304 with the lowest index. */ | |
2305 if (e->src->index > e2->src->index) | |
2306 continue; | |
2307 | |
2308 /* If nothing changed since the last attempt, there is nothing | |
2309 we can do. */ | |
2310 if (!first_pass | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2311 && !((e->src->flags & BB_MODIFIED) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2312 || (e2->src->flags & BB_MODIFIED))) |
0 | 2313 continue; |
2314 | |
111 | 2315 /* Both e and e2 are not fallthru edges, so we can crossjump in either |
2316 direction. */ | |
2317 if (try_crossjump_to_edge (mode, e, e2, dir_both)) | |
0 | 2318 { |
2319 changed = true; | |
2320 ix = 0; | |
2321 break; | |
2322 } | |
2323 } | |
2324 } | |
2325 | |
2326 if (changed) | |
111 | 2327 crossjumps_occurred = true; |
0 | 2328 |
2329 return changed; | |
2330 } | |
2331 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2332 /* Search the successors of BB for common insn sequences. When found, |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2333 share code between them by moving it across the basic block |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2334 boundary. Return true if any changes made. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2335 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2336 static bool |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2337 try_head_merge_bb (basic_block bb) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2338 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2339 basic_block final_dest_bb = NULL; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2340 int max_match = INT_MAX; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2341 edge e0; |
111 | 2342 rtx_insn **headptr, **currptr, **nextptr; |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2343 bool changed, moveall; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2344 unsigned ix; |
111 | 2345 rtx_insn *e0_last_head; |
2346 rtx cond; | |
2347 rtx_insn *move_before; | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2348 unsigned nedges = EDGE_COUNT (bb->succs); |
111 | 2349 rtx_insn *jump = BB_END (bb); |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2350 regset live, live_union; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2351 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2352 /* Nothing to do if there is not at least two outgoing edges. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2353 if (nedges < 2) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2354 return false; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2355 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2356 /* Don't crossjump if this block ends in a computed jump, |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2357 unless we are optimizing for size. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2358 if (optimize_bb_for_size_p (bb) |
111 | 2359 && bb != EXIT_BLOCK_PTR_FOR_FN (cfun) |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2360 && computed_jump_p (BB_END (bb))) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2361 return false; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2362 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2363 cond = get_condition (jump, &move_before, true, false); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2364 if (cond == NULL_RTX) |
111 | 2365 { |
2366 if (HAVE_cc0 && reg_mentioned_p (cc0_rtx, jump)) | |
2367 move_before = prev_nonnote_nondebug_insn (jump); | |
2368 else | |
2369 move_before = jump; | |
2370 } | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2371 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2372 for (ix = 0; ix < nedges; ix++) |
111 | 2373 if (EDGE_SUCC (bb, ix)->dest == EXIT_BLOCK_PTR_FOR_FN (cfun)) |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2374 return false; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2375 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2376 for (ix = 0; ix < nedges; ix++) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2377 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2378 edge e = EDGE_SUCC (bb, ix); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2379 basic_block other_bb = e->dest; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2380 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2381 if (df_get_bb_dirty (other_bb)) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2382 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2383 block_was_dirty = true; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2384 return false; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2385 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2386 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2387 if (e->flags & EDGE_ABNORMAL) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2388 return false; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2389 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2390 /* Normally, all destination blocks must only be reachable from this |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2391 block, i.e. they must have one incoming edge. |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2392 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2393 There is one special case we can handle, that of multiple consecutive |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2394 jumps where the first jumps to one of the targets of the second jump. |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2395 This happens frequently in switch statements for default labels. |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2396 The structure is as follows: |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2397 FINAL_DEST_BB |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2398 .... |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2399 if (cond) jump A; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2400 fall through |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2401 BB |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2402 jump with targets A, B, C, D... |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2403 A |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2404 has two incoming edges, from FINAL_DEST_BB and BB |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2405 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2406 In this case, we can try to move the insns through BB and into |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2407 FINAL_DEST_BB. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2408 if (EDGE_COUNT (other_bb->preds) != 1) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2409 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2410 edge incoming_edge, incoming_bb_other_edge; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2411 edge_iterator ei; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2412 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2413 if (final_dest_bb != NULL |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2414 || EDGE_COUNT (other_bb->preds) != 2) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2415 return false; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2416 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2417 /* We must be able to move the insns across the whole block. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2418 move_before = BB_HEAD (bb); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2419 while (!NONDEBUG_INSN_P (move_before)) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2420 move_before = NEXT_INSN (move_before); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2421 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2422 if (EDGE_COUNT (bb->preds) != 1) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2423 return false; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2424 incoming_edge = EDGE_PRED (bb, 0); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2425 final_dest_bb = incoming_edge->src; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2426 if (EDGE_COUNT (final_dest_bb->succs) != 2) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2427 return false; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2428 FOR_EACH_EDGE (incoming_bb_other_edge, ei, final_dest_bb->succs) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2429 if (incoming_bb_other_edge != incoming_edge) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2430 break; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2431 if (incoming_bb_other_edge->dest != other_bb) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2432 return false; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2433 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2434 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2435 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2436 e0 = EDGE_SUCC (bb, 0); |
111 | 2437 e0_last_head = NULL; |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2438 changed = false; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2439 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2440 for (ix = 1; ix < nedges; ix++) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2441 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2442 edge e = EDGE_SUCC (bb, ix); |
111 | 2443 rtx_insn *e0_last, *e_last; |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2444 int nmatch; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2445 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2446 nmatch = flow_find_head_matching_sequence (e0->dest, e->dest, |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2447 &e0_last, &e_last, 0); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2448 if (nmatch == 0) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2449 return false; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2450 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2451 if (nmatch < max_match) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2452 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2453 max_match = nmatch; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2454 e0_last_head = e0_last; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2455 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2456 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2457 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2458 /* If we matched an entire block, we probably have to avoid moving the |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2459 last insn. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2460 if (max_match > 0 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2461 && e0_last_head == BB_END (e0->dest) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2462 && (find_reg_note (e0_last_head, REG_EH_REGION, 0) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2463 || control_flow_insn_p (e0_last_head))) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2464 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2465 max_match--; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2466 if (max_match == 0) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2467 return false; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2468 do |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2469 e0_last_head = prev_real_insn (e0_last_head); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2470 while (DEBUG_INSN_P (e0_last_head)); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2471 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2472 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2473 if (max_match == 0) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2474 return false; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2475 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2476 /* We must find a union of the live registers at each of the end points. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2477 live = BITMAP_ALLOC (NULL); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2478 live_union = BITMAP_ALLOC (NULL); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2479 |
111 | 2480 currptr = XNEWVEC (rtx_insn *, nedges); |
2481 headptr = XNEWVEC (rtx_insn *, nedges); | |
2482 nextptr = XNEWVEC (rtx_insn *, nedges); | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2483 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2484 for (ix = 0; ix < nedges; ix++) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2485 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2486 int j; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2487 basic_block merge_bb = EDGE_SUCC (bb, ix)->dest; |
111 | 2488 rtx_insn *head = BB_HEAD (merge_bb); |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2489 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2490 while (!NONDEBUG_INSN_P (head)) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2491 head = NEXT_INSN (head); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2492 headptr[ix] = head; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2493 currptr[ix] = head; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2494 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2495 /* Compute the end point and live information */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2496 for (j = 1; j < max_match; j++) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2497 do |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2498 head = NEXT_INSN (head); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2499 while (!NONDEBUG_INSN_P (head)); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2500 simulate_backwards_to_point (merge_bb, live, head); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2501 IOR_REG_SET (live_union, live); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2502 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2503 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2504 /* If we're moving across two blocks, verify the validity of the |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2505 first move, then adjust the target and let the loop below deal |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2506 with the final move. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2507 if (final_dest_bb != NULL) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2508 { |
111 | 2509 rtx_insn *move_upto; |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2510 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2511 moveall = can_move_insns_across (currptr[0], e0_last_head, move_before, |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2512 jump, e0->dest, live_union, |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2513 NULL, &move_upto); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2514 if (!moveall) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2515 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2516 if (move_upto == NULL_RTX) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2517 goto out; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2518 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2519 while (e0_last_head != move_upto) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2520 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2521 df_simulate_one_insn_backwards (e0->dest, e0_last_head, |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2522 live_union); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2523 e0_last_head = PREV_INSN (e0_last_head); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2524 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2525 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2526 if (e0_last_head == NULL_RTX) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2527 goto out; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2528 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2529 jump = BB_END (final_dest_bb); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2530 cond = get_condition (jump, &move_before, true, false); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2531 if (cond == NULL_RTX) |
111 | 2532 { |
2533 if (HAVE_cc0 && reg_mentioned_p (cc0_rtx, jump)) | |
2534 move_before = prev_nonnote_nondebug_insn (jump); | |
2535 else | |
2536 move_before = jump; | |
2537 } | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2538 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2539 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2540 do |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2541 { |
111 | 2542 rtx_insn *move_upto; |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2543 moveall = can_move_insns_across (currptr[0], e0_last_head, |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2544 move_before, jump, e0->dest, live_union, |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2545 NULL, &move_upto); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2546 if (!moveall && move_upto == NULL_RTX) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2547 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2548 if (jump == move_before) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2549 break; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2550 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2551 /* Try again, using a different insertion point. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2552 move_before = jump; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2553 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2554 /* Don't try moving before a cc0 user, as that may invalidate |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2555 the cc0. */ |
111 | 2556 if (HAVE_cc0 && reg_mentioned_p (cc0_rtx, jump)) |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2557 break; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2558 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2559 continue; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2560 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2561 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2562 if (final_dest_bb && !moveall) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2563 /* We haven't checked whether a partial move would be OK for the first |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2564 move, so we have to fail this case. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2565 break; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2566 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2567 changed = true; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2568 for (;;) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2569 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2570 if (currptr[0] == move_upto) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2571 break; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2572 for (ix = 0; ix < nedges; ix++) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2573 { |
111 | 2574 rtx_insn *curr = currptr[ix]; |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2575 do |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2576 curr = NEXT_INSN (curr); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2577 while (!NONDEBUG_INSN_P (curr)); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2578 currptr[ix] = curr; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2579 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2580 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2581 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2582 /* If we can't currently move all of the identical insns, remember |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2583 each insn after the range that we'll merge. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2584 if (!moveall) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2585 for (ix = 0; ix < nedges; ix++) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2586 { |
111 | 2587 rtx_insn *curr = currptr[ix]; |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2588 do |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2589 curr = NEXT_INSN (curr); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2590 while (!NONDEBUG_INSN_P (curr)); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2591 nextptr[ix] = curr; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2592 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2593 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2594 reorder_insns (headptr[0], currptr[0], PREV_INSN (move_before)); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2595 df_set_bb_dirty (EDGE_SUCC (bb, 0)->dest); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2596 if (final_dest_bb != NULL) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2597 df_set_bb_dirty (final_dest_bb); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2598 df_set_bb_dirty (bb); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2599 for (ix = 1; ix < nedges; ix++) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2600 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2601 df_set_bb_dirty (EDGE_SUCC (bb, ix)->dest); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2602 delete_insn_chain (headptr[ix], currptr[ix], false); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2603 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2604 if (!moveall) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2605 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2606 if (jump == move_before) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2607 break; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2608 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2609 /* For the unmerged insns, try a different insertion point. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2610 move_before = jump; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2611 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2612 /* Don't try moving before a cc0 user, as that may invalidate |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2613 the cc0. */ |
111 | 2614 if (HAVE_cc0 && reg_mentioned_p (cc0_rtx, jump)) |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2615 break; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2616 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2617 for (ix = 0; ix < nedges; ix++) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2618 currptr[ix] = headptr[ix] = nextptr[ix]; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2619 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2620 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2621 while (!moveall); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2622 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2623 out: |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2624 free (currptr); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2625 free (headptr); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2626 free (nextptr); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2627 |
111 | 2628 crossjumps_occurred |= changed; |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2629 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2630 return changed; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2631 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2632 |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2633 /* Return true if BB contains just bb note, or bb note followed |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2634 by only DEBUG_INSNs. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2635 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2636 static bool |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2637 trivially_empty_bb_p (basic_block bb) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2638 { |
111 | 2639 rtx_insn *insn = BB_END (bb); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2640 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2641 while (1) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2642 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2643 if (insn == BB_HEAD (bb)) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2644 return true; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2645 if (!DEBUG_INSN_P (insn)) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2646 return false; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2647 insn = PREV_INSN (insn); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2648 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2649 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2650 |
111 | 2651 /* Return true if BB contains just a return and possibly a USE of the |
2652 return value. Fill in *RET and *USE with the return and use insns | |
2653 if any found, otherwise NULL. All CLOBBERs are ignored. */ | |
2654 | |
2655 static bool | |
2656 bb_is_just_return (basic_block bb, rtx_insn **ret, rtx_insn **use) | |
2657 { | |
2658 *ret = *use = NULL; | |
2659 rtx_insn *insn; | |
2660 | |
2661 if (bb == EXIT_BLOCK_PTR_FOR_FN (cfun)) | |
2662 return false; | |
2663 | |
2664 FOR_BB_INSNS (bb, insn) | |
2665 if (NONDEBUG_INSN_P (insn)) | |
2666 { | |
2667 rtx pat = PATTERN (insn); | |
2668 | |
2669 if (!*ret && ANY_RETURN_P (pat)) | |
2670 *ret = insn; | |
2671 else if (!*ret && !*use && GET_CODE (pat) == USE | |
2672 && REG_P (XEXP (pat, 0)) | |
2673 && REG_FUNCTION_VALUE_P (XEXP (pat, 0))) | |
2674 *use = insn; | |
2675 else if (GET_CODE (pat) != CLOBBER) | |
2676 return false; | |
2677 } | |
2678 | |
2679 return !!*ret; | |
2680 } | |
2681 | |
0 | 2682 /* Do simple CFG optimizations - basic block merging, simplifying of jump |
2683 instructions etc. Return nonzero if changes were made. */ | |
2684 | |
2685 static bool | |
2686 try_optimize_cfg (int mode) | |
2687 { | |
2688 bool changed_overall = false; | |
2689 bool changed; | |
2690 int iterations = 0; | |
2691 basic_block bb, b, next; | |
2692 | |
2693 if (mode & (CLEANUP_CROSSJUMP | CLEANUP_THREADING)) | |
2694 clear_bb_flags (); | |
2695 | |
111 | 2696 crossjumps_occurred = false; |
2697 | |
2698 FOR_EACH_BB_FN (bb, cfun) | |
0 | 2699 update_forwarder_flag (bb); |
2700 | |
2701 if (! targetm.cannot_modify_jumps_p ()) | |
2702 { | |
2703 first_pass = true; | |
2704 /* Attempt to merge blocks as made possible by edge removal. If | |
2705 a block has only one successor, and the successor has only | |
2706 one predecessor, they may be combined. */ | |
2707 do | |
2708 { | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2709 block_was_dirty = false; |
0 | 2710 changed = false; |
2711 iterations++; | |
2712 | |
2713 if (dump_file) | |
2714 fprintf (dump_file, | |
2715 "\n\ntry_optimize_cfg iteration %i\n\n", | |
2716 iterations); | |
2717 | |
111 | 2718 for (b = ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb; b |
2719 != EXIT_BLOCK_PTR_FOR_FN (cfun);) | |
0 | 2720 { |
2721 basic_block c; | |
2722 edge s; | |
2723 bool changed_here = false; | |
2724 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2725 /* Delete trivially dead basic blocks. This is either |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2726 blocks with no predecessors, or empty blocks with no |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2727 successors. However if the empty block with no |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2728 successors is the successor of the ENTRY_BLOCK, it is |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2729 kept. This ensures that the ENTRY_BLOCK will have a |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2730 successor which is a precondition for many RTL |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2731 passes. Empty blocks may result from expanding |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2732 __builtin_unreachable (). */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2733 if (EDGE_COUNT (b->preds) == 0 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2734 || (EDGE_COUNT (b->succs) == 0 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2735 && trivially_empty_bb_p (b) |
111 | 2736 && single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun))->dest |
2737 != b)) | |
0 | 2738 { |
2739 c = b->prev_bb; | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2740 if (EDGE_COUNT (b->preds) > 0) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2741 { |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2742 edge e; |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2743 edge_iterator ei; |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2744 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2745 if (current_ir_type () == IR_RTL_CFGLAYOUT) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2746 { |
111 | 2747 if (BB_FOOTER (b) |
2748 && BARRIER_P (BB_FOOTER (b))) | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2749 FOR_EACH_EDGE (e, ei, b->preds) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2750 if ((e->flags & EDGE_FALLTHRU) |
111 | 2751 && BB_FOOTER (e->src) == NULL) |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2752 { |
111 | 2753 if (BB_FOOTER (b)) |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2754 { |
111 | 2755 BB_FOOTER (e->src) = BB_FOOTER (b); |
2756 BB_FOOTER (b) = NULL; | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2757 } |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2758 else |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2759 { |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2760 start_sequence (); |
111 | 2761 BB_FOOTER (e->src) = emit_barrier (); |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2762 end_sequence (); |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2763 } |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2764 } |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2765 } |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2766 else |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2767 { |
111 | 2768 rtx_insn *last = get_last_bb_insn (b); |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2769 if (last && BARRIER_P (last)) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2770 FOR_EACH_EDGE (e, ei, b->preds) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2771 if ((e->flags & EDGE_FALLTHRU)) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2772 emit_barrier_after (BB_END (e->src)); |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2773 } |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2774 } |
0 | 2775 delete_basic_block (b); |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2776 changed = true; |
111 | 2777 /* Avoid trying to remove the exit block. */ |
2778 b = (c == ENTRY_BLOCK_PTR_FOR_FN (cfun) ? c->next_bb : c); | |
0 | 2779 continue; |
2780 } | |
2781 | |
2782 /* Remove code labels no longer used. */ | |
2783 if (single_pred_p (b) | |
2784 && (single_pred_edge (b)->flags & EDGE_FALLTHRU) | |
2785 && !(single_pred_edge (b)->flags & EDGE_COMPLEX) | |
2786 && LABEL_P (BB_HEAD (b)) | |
111 | 2787 && !LABEL_PRESERVE_P (BB_HEAD (b)) |
0 | 2788 /* If the previous block ends with a branch to this |
2789 block, we can't delete the label. Normally this | |
2790 is a condjump that is yet to be simplified, but | |
2791 if CASE_DROPS_THRU, this can be a tablejump with | |
2792 some element going to the same place as the | |
2793 default (fallthru). */ | |
111 | 2794 && (single_pred (b) == ENTRY_BLOCK_PTR_FOR_FN (cfun) |
0 | 2795 || !JUMP_P (BB_END (single_pred (b))) |
2796 || ! label_is_jump_target_p (BB_HEAD (b), | |
2797 BB_END (single_pred (b))))) | |
2798 { | |
111 | 2799 delete_insn (BB_HEAD (b)); |
0 | 2800 if (dump_file) |
2801 fprintf (dump_file, "Deleted label in block %i.\n", | |
2802 b->index); | |
2803 } | |
2804 | |
2805 /* If we fall through an empty block, we can remove it. */ | |
111 | 2806 if (!(mode & (CLEANUP_CFGLAYOUT | CLEANUP_NO_INSN_DEL)) |
0 | 2807 && single_pred_p (b) |
2808 && (single_pred_edge (b)->flags & EDGE_FALLTHRU) | |
2809 && !LABEL_P (BB_HEAD (b)) | |
2810 && FORWARDER_BLOCK_P (b) | |
2811 /* Note that forwarder_block_p true ensures that | |
2812 there is a successor for this block. */ | |
2813 && (single_succ_edge (b)->flags & EDGE_FALLTHRU) | |
111 | 2814 && n_basic_blocks_for_fn (cfun) > NUM_FIXED_BLOCKS + 1) |
0 | 2815 { |
2816 if (dump_file) | |
2817 fprintf (dump_file, | |
2818 "Deleting fallthru block %i.\n", | |
2819 b->index); | |
2820 | |
111 | 2821 c = ((b->prev_bb == ENTRY_BLOCK_PTR_FOR_FN (cfun)) |
2822 ? b->next_bb : b->prev_bb); | |
0 | 2823 redirect_edge_succ_nodup (single_pred_edge (b), |
2824 single_succ (b)); | |
2825 delete_basic_block (b); | |
2826 changed = true; | |
2827 b = c; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2828 continue; |
0 | 2829 } |
2830 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2831 /* Merge B with its single successor, if any. */ |
0 | 2832 if (single_succ_p (b) |
2833 && (s = single_succ_edge (b)) | |
2834 && !(s->flags & EDGE_COMPLEX) | |
111 | 2835 && (c = s->dest) != EXIT_BLOCK_PTR_FOR_FN (cfun) |
0 | 2836 && single_pred_p (c) |
2837 && b != c) | |
2838 { | |
2839 /* When not in cfg_layout mode use code aware of reordering | |
2840 INSN. This code possibly creates new basic blocks so it | |
2841 does not fit merge_blocks interface and is kept here in | |
2842 hope that it will become useless once more of compiler | |
2843 is transformed to use cfg_layout mode. */ | |
2844 | |
2845 if ((mode & CLEANUP_CFGLAYOUT) | |
2846 && can_merge_blocks_p (b, c)) | |
2847 { | |
2848 merge_blocks (b, c); | |
2849 update_forwarder_flag (b); | |
2850 changed_here = true; | |
2851 } | |
2852 else if (!(mode & CLEANUP_CFGLAYOUT) | |
2853 /* If the jump insn has side effects, | |
2854 we can't kill the edge. */ | |
2855 && (!JUMP_P (BB_END (b)) | |
2856 || (reload_completed | |
2857 ? simplejump_p (BB_END (b)) | |
2858 : (onlyjump_p (BB_END (b)) | |
2859 && !tablejump_p (BB_END (b), | |
2860 NULL, NULL)))) | |
2861 && (next = merge_blocks_move (s, b, c, mode))) | |
2862 { | |
2863 b = next; | |
2864 changed_here = true; | |
2865 } | |
2866 } | |
2867 | |
111 | 2868 /* Try to change a branch to a return to just that return. */ |
2869 rtx_insn *ret, *use; | |
2870 if (single_succ_p (b) | |
2871 && onlyjump_p (BB_END (b)) | |
2872 && bb_is_just_return (single_succ (b), &ret, &use)) | |
2873 { | |
2874 if (redirect_jump (as_a <rtx_jump_insn *> (BB_END (b)), | |
2875 PATTERN (ret), 0)) | |
2876 { | |
2877 if (use) | |
2878 emit_insn_before (copy_insn (PATTERN (use)), | |
2879 BB_END (b)); | |
2880 if (dump_file) | |
2881 fprintf (dump_file, "Changed jump %d->%d to return.\n", | |
2882 b->index, single_succ (b)->index); | |
2883 redirect_edge_succ (single_succ_edge (b), | |
2884 EXIT_BLOCK_PTR_FOR_FN (cfun)); | |
2885 single_succ_edge (b)->flags &= ~EDGE_CROSSING; | |
2886 changed_here = true; | |
2887 } | |
2888 } | |
2889 | |
2890 /* Try to change a conditional branch to a return to the | |
2891 respective conditional return. */ | |
2892 if (EDGE_COUNT (b->succs) == 2 | |
2893 && any_condjump_p (BB_END (b)) | |
2894 && bb_is_just_return (BRANCH_EDGE (b)->dest, &ret, &use)) | |
2895 { | |
2896 if (redirect_jump (as_a <rtx_jump_insn *> (BB_END (b)), | |
2897 PATTERN (ret), 0)) | |
2898 { | |
2899 if (use) | |
2900 emit_insn_before (copy_insn (PATTERN (use)), | |
2901 BB_END (b)); | |
2902 if (dump_file) | |
2903 fprintf (dump_file, "Changed conditional jump %d->%d " | |
2904 "to conditional return.\n", | |
2905 b->index, BRANCH_EDGE (b)->dest->index); | |
2906 redirect_edge_succ (BRANCH_EDGE (b), | |
2907 EXIT_BLOCK_PTR_FOR_FN (cfun)); | |
2908 BRANCH_EDGE (b)->flags &= ~EDGE_CROSSING; | |
2909 changed_here = true; | |
2910 } | |
2911 } | |
2912 | |
2913 /* Try to flip a conditional branch that falls through to | |
2914 a return so that it becomes a conditional return and a | |
2915 new jump to the original branch target. */ | |
2916 if (EDGE_COUNT (b->succs) == 2 | |
2917 && BRANCH_EDGE (b)->dest != EXIT_BLOCK_PTR_FOR_FN (cfun) | |
2918 && any_condjump_p (BB_END (b)) | |
2919 && bb_is_just_return (FALLTHRU_EDGE (b)->dest, &ret, &use)) | |
2920 { | |
2921 if (invert_jump (as_a <rtx_jump_insn *> (BB_END (b)), | |
2922 JUMP_LABEL (BB_END (b)), 0)) | |
2923 { | |
2924 basic_block new_ft = BRANCH_EDGE (b)->dest; | |
2925 if (redirect_jump (as_a <rtx_jump_insn *> (BB_END (b)), | |
2926 PATTERN (ret), 0)) | |
2927 { | |
2928 if (use) | |
2929 emit_insn_before (copy_insn (PATTERN (use)), | |
2930 BB_END (b)); | |
2931 if (dump_file) | |
2932 fprintf (dump_file, "Changed conditional jump " | |
2933 "%d->%d to conditional return, adding " | |
2934 "fall-through jump.\n", | |
2935 b->index, BRANCH_EDGE (b)->dest->index); | |
2936 redirect_edge_succ (BRANCH_EDGE (b), | |
2937 EXIT_BLOCK_PTR_FOR_FN (cfun)); | |
2938 BRANCH_EDGE (b)->flags &= ~EDGE_CROSSING; | |
2939 std::swap (BRANCH_EDGE (b)->probability, | |
2940 FALLTHRU_EDGE (b)->probability); | |
2941 update_br_prob_note (b); | |
2942 basic_block jb = force_nonfallthru (FALLTHRU_EDGE (b)); | |
2943 notice_new_block (jb); | |
2944 if (!redirect_jump (as_a <rtx_jump_insn *> (BB_END (jb)), | |
2945 block_label (new_ft), 0)) | |
2946 gcc_unreachable (); | |
2947 redirect_edge_succ (single_succ_edge (jb), new_ft); | |
2948 changed_here = true; | |
2949 } | |
2950 else | |
2951 { | |
2952 /* Invert the jump back to what it was. This should | |
2953 never fail. */ | |
2954 if (!invert_jump (as_a <rtx_jump_insn *> (BB_END (b)), | |
2955 JUMP_LABEL (BB_END (b)), 0)) | |
2956 gcc_unreachable (); | |
2957 } | |
2958 } | |
2959 } | |
2960 | |
0 | 2961 /* Simplify branch over branch. */ |
2962 if ((mode & CLEANUP_EXPENSIVE) | |
2963 && !(mode & CLEANUP_CFGLAYOUT) | |
2964 && try_simplify_condjump (b)) | |
2965 changed_here = true; | |
2966 | |
2967 /* If B has a single outgoing edge, but uses a | |
2968 non-trivial jump instruction without side-effects, we | |
2969 can either delete the jump entirely, or replace it | |
2970 with a simple unconditional jump. */ | |
2971 if (single_succ_p (b) | |
111 | 2972 && single_succ (b) != EXIT_BLOCK_PTR_FOR_FN (cfun) |
0 | 2973 && onlyjump_p (BB_END (b)) |
111 | 2974 && !CROSSING_JUMP_P (BB_END (b)) |
0 | 2975 && try_redirect_by_replacing_jump (single_succ_edge (b), |
2976 single_succ (b), | |
2977 (mode & CLEANUP_CFGLAYOUT) != 0)) | |
2978 { | |
2979 update_forwarder_flag (b); | |
2980 changed_here = true; | |
2981 } | |
2982 | |
2983 /* Simplify branch to branch. */ | |
2984 if (try_forward_edges (mode, b)) | |
111 | 2985 { |
2986 update_forwarder_flag (b); | |
2987 changed_here = true; | |
2988 } | |
0 | 2989 |
2990 /* Look for shared code between blocks. */ | |
2991 if ((mode & CLEANUP_CROSSJUMP) | |
2992 && try_crossjump_bb (mode, b)) | |
2993 changed_here = true; | |
2994 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2995 if ((mode & CLEANUP_CROSSJUMP) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2996 /* This can lengthen register lifetimes. Do it only after |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2997 reload. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2998 && reload_completed |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2999 && try_head_merge_bb (b)) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
3000 changed_here = true; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
3001 |
0 | 3002 /* Don't get confused by the index shift caused by |
3003 deleting blocks. */ | |
3004 if (!changed_here) | |
3005 b = b->next_bb; | |
3006 else | |
3007 changed = true; | |
3008 } | |
3009 | |
3010 if ((mode & CLEANUP_CROSSJUMP) | |
111 | 3011 && try_crossjump_bb (mode, EXIT_BLOCK_PTR_FOR_FN (cfun))) |
0 | 3012 changed = true; |
3013 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
3014 if (block_was_dirty) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
3015 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
3016 /* This should only be set by head-merging. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
3017 gcc_assert (mode & CLEANUP_CROSSJUMP); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
3018 df_analyze (); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
3019 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
3020 |
0 | 3021 if (changed) |
111 | 3022 { |
3023 /* Edge forwarding in particular can cause hot blocks previously | |
3024 reached by both hot and cold blocks to become dominated only | |
3025 by cold blocks. This will cause the verification below to fail, | |
3026 and lead to now cold code in the hot section. This is not easy | |
3027 to detect and fix during edge forwarding, and in some cases | |
3028 is only visible after newly unreachable blocks are deleted, | |
3029 which will be done in fixup_partitions. */ | |
3030 fixup_partitions (); | |
3031 checking_verify_flow_info (); | |
3032 } | |
0 | 3033 |
3034 changed_overall |= changed; | |
3035 first_pass = false; | |
3036 } | |
3037 while (changed); | |
3038 } | |
3039 | |
111 | 3040 FOR_ALL_BB_FN (b, cfun) |
0 | 3041 b->flags &= ~(BB_FORWARDER_BLOCK | BB_NONTHREADABLE_BLOCK); |
3042 | |
3043 return changed_overall; | |
3044 } | |
3045 | |
3046 /* Delete all unreachable basic blocks. */ | |
3047 | |
3048 bool | |
3049 delete_unreachable_blocks (void) | |
3050 { | |
3051 bool changed = false; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
3052 basic_block b, prev_bb; |
0 | 3053 |
3054 find_unreachable_blocks (); | |
3055 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
3056 /* When we're in GIMPLE mode and there may be debug insns, we should |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
3057 delete blocks in reverse dominator order, so as to get a chance |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
3058 to substitute all released DEFs into debug stmts. If we don't |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
3059 have dominators information, walking blocks backward gets us a |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
3060 better chance of retaining most debug information than |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
3061 otherwise. */ |
111 | 3062 if (MAY_HAVE_DEBUG_INSNS && current_ir_type () == IR_GIMPLE |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
3063 && dom_info_available_p (CDI_DOMINATORS)) |
0 | 3064 { |
111 | 3065 for (b = EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb; |
3066 b != ENTRY_BLOCK_PTR_FOR_FN (cfun); b = prev_bb) | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
3067 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
3068 prev_bb = b->prev_bb; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
3069 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
3070 if (!(b->flags & BB_REACHABLE)) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
3071 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
3072 /* Speed up the removal of blocks that don't dominate |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
3073 others. Walking backwards, this should be the common |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
3074 case. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
3075 if (!first_dom_son (CDI_DOMINATORS, b)) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
3076 delete_basic_block (b); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
3077 else |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
3078 { |
111 | 3079 vec<basic_block> h |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
3080 = get_all_dominated_blocks (CDI_DOMINATORS, b); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
3081 |
111 | 3082 while (h.length ()) |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
3083 { |
111 | 3084 b = h.pop (); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
3085 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
3086 prev_bb = b->prev_bb; |
0 | 3087 |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
3088 gcc_assert (!(b->flags & BB_REACHABLE)); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
3089 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
3090 delete_basic_block (b); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
3091 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
3092 |
111 | 3093 h.release (); |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
3094 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
3095 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
3096 changed = true; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
3097 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
3098 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
3099 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
3100 else |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
3101 { |
111 | 3102 for (b = EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb; |
3103 b != ENTRY_BLOCK_PTR_FOR_FN (cfun); b = prev_bb) | |
0 | 3104 { |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
3105 prev_bb = b->prev_bb; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
3106 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
3107 if (!(b->flags & BB_REACHABLE)) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
3108 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
3109 delete_basic_block (b); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
3110 changed = true; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
3111 } |
0 | 3112 } |
3113 } | |
3114 | |
3115 if (changed) | |
3116 tidy_fallthru_edges (); | |
3117 return changed; | |
3118 } | |
3119 | |
3120 /* Delete any jump tables never referenced. We can't delete them at the | |
3121 time of removing tablejump insn as they are referenced by the preceding | |
3122 insns computing the destination, so we delay deleting and garbagecollect | |
3123 them once life information is computed. */ | |
3124 void | |
3125 delete_dead_jumptables (void) | |
3126 { | |
3127 basic_block bb; | |
3128 | |
3129 /* A dead jump table does not belong to any basic block. Scan insns | |
3130 between two adjacent basic blocks. */ | |
111 | 3131 FOR_EACH_BB_FN (bb, cfun) |
0 | 3132 { |
111 | 3133 rtx_insn *insn, *next; |
0 | 3134 |
3135 for (insn = NEXT_INSN (BB_END (bb)); | |
3136 insn && !NOTE_INSN_BASIC_BLOCK_P (insn); | |
3137 insn = next) | |
3138 { | |
3139 next = NEXT_INSN (insn); | |
3140 if (LABEL_P (insn) | |
3141 && LABEL_NUSES (insn) == LABEL_PRESERVE_P (insn) | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
3142 && JUMP_TABLE_DATA_P (next)) |
0 | 3143 { |
111 | 3144 rtx_insn *label = insn, *jump = next; |
0 | 3145 |
3146 if (dump_file) | |
3147 fprintf (dump_file, "Dead jumptable %i removed\n", | |
3148 INSN_UID (insn)); | |
3149 | |
3150 next = NEXT_INSN (next); | |
3151 delete_insn (jump); | |
3152 delete_insn (label); | |
3153 } | |
3154 } | |
3155 } | |
3156 } | |
3157 | |
3158 | |
3159 /* Tidy the CFG by deleting unreachable code and whatnot. */ | |
3160 | |
3161 bool | |
3162 cleanup_cfg (int mode) | |
3163 { | |
3164 bool changed = false; | |
3165 | |
3166 /* Set the cfglayout mode flag here. We could update all the callers | |
3167 but that is just inconvenient, especially given that we eventually | |
3168 want to have cfglayout mode as the default. */ | |
3169 if (current_ir_type () == IR_RTL_CFGLAYOUT) | |
3170 mode |= CLEANUP_CFGLAYOUT; | |
3171 | |
3172 timevar_push (TV_CLEANUP_CFG); | |
3173 if (delete_unreachable_blocks ()) | |
3174 { | |
3175 changed = true; | |
3176 /* We've possibly created trivially dead code. Cleanup it right | |
3177 now to introduce more opportunities for try_optimize_cfg. */ | |
3178 if (!(mode & (CLEANUP_NO_INSN_DEL)) | |
3179 && !reload_completed) | |
3180 delete_trivially_dead_insns (get_insns (), max_reg_num ()); | |
3181 } | |
3182 | |
3183 compact_blocks (); | |
3184 | |
3185 /* To tail-merge blocks ending in the same noreturn function (e.g. | |
3186 a call to abort) we have to insert fake edges to exit. Do this | |
3187 here once. The fake edges do not interfere with any other CFG | |
3188 cleanups. */ | |
3189 if (mode & CLEANUP_CROSSJUMP) | |
3190 add_noreturn_fake_exit_edges (); | |
3191 | |
3192 if (!dbg_cnt (cfg_cleanup)) | |
3193 return changed; | |
3194 | |
3195 while (try_optimize_cfg (mode)) | |
3196 { | |
3197 delete_unreachable_blocks (), changed = true; | |
3198 if (!(mode & CLEANUP_NO_INSN_DEL)) | |
3199 { | |
3200 /* Try to remove some trivially dead insns when doing an expensive | |
3201 cleanup. But delete_trivially_dead_insns doesn't work after | |
3202 reload (it only handles pseudos) and run_fast_dce is too costly | |
3203 to run in every iteration. | |
3204 | |
3205 For effective cross jumping, we really want to run a fast DCE to | |
3206 clean up any dead conditions, or they get in the way of performing | |
3207 useful tail merges. | |
3208 | |
3209 Other transformations in cleanup_cfg are not so sensitive to dead | |
3210 code, so delete_trivially_dead_insns or even doing nothing at all | |
3211 is good enough. */ | |
3212 if ((mode & CLEANUP_EXPENSIVE) && !reload_completed | |
3213 && !delete_trivially_dead_insns (get_insns (), max_reg_num ())) | |
3214 break; | |
111 | 3215 if ((mode & CLEANUP_CROSSJUMP) && crossjumps_occurred) |
0 | 3216 run_fast_dce (); |
3217 } | |
3218 else | |
3219 break; | |
3220 } | |
3221 | |
3222 if (mode & CLEANUP_CROSSJUMP) | |
3223 remove_fake_exit_edges (); | |
3224 | |
3225 /* Don't call delete_dead_jumptables in cfglayout mode, because | |
3226 that function assumes that jump tables are in the insns stream. | |
3227 But we also don't _have_ to delete dead jumptables in cfglayout | |
3228 mode because we shouldn't even be looking at things that are | |
3229 not in a basic block. Dead jumptables are cleaned up when | |
3230 going out of cfglayout mode. */ | |
3231 if (!(mode & CLEANUP_CFGLAYOUT)) | |
3232 delete_dead_jumptables (); | |
3233 | |
111 | 3234 /* ??? We probably do this way too often. */ |
3235 if (current_loops | |
3236 && (changed | |
3237 || (mode & CLEANUP_CFG_CHANGED))) | |
3238 { | |
3239 timevar_push (TV_REPAIR_LOOPS); | |
3240 /* The above doesn't preserve dominance info if available. */ | |
3241 gcc_assert (!dom_info_available_p (CDI_DOMINATORS)); | |
3242 calculate_dominance_info (CDI_DOMINATORS); | |
3243 fix_loop_structure (NULL); | |
3244 free_dominance_info (CDI_DOMINATORS); | |
3245 timevar_pop (TV_REPAIR_LOOPS); | |
3246 } | |
3247 | |
0 | 3248 timevar_pop (TV_CLEANUP_CFG); |
3249 | |
3250 return changed; | |
3251 } | |
3252 | |
111 | 3253 namespace { |
3254 | |
3255 const pass_data pass_data_jump = | |
0 | 3256 { |
111 | 3257 RTL_PASS, /* type */ |
3258 "jump", /* name */ | |
3259 OPTGROUP_NONE, /* optinfo_flags */ | |
3260 TV_JUMP, /* tv_id */ | |
3261 0, /* properties_required */ | |
3262 0, /* properties_provided */ | |
3263 0, /* properties_destroyed */ | |
3264 0, /* todo_flags_start */ | |
3265 0, /* todo_flags_finish */ | |
0 | 3266 }; |
3267 | |
111 | 3268 class pass_jump : public rtl_opt_pass |
3269 { | |
3270 public: | |
3271 pass_jump (gcc::context *ctxt) | |
3272 : rtl_opt_pass (pass_data_jump, ctxt) | |
3273 {} | |
3274 | |
3275 /* opt_pass methods: */ | |
3276 virtual unsigned int execute (function *); | |
3277 | |
3278 }; // class pass_jump | |
3279 | |
3280 unsigned int | |
3281 pass_jump::execute (function *) | |
0 | 3282 { |
3283 delete_trivially_dead_insns (get_insns (), max_reg_num ()); | |
3284 if (dump_file) | |
3285 dump_flow_info (dump_file, dump_flags); | |
3286 cleanup_cfg ((optimize ? CLEANUP_EXPENSIVE : 0) | |
3287 | (flag_thread_jumps ? CLEANUP_THREADING : 0)); | |
3288 return 0; | |
3289 } | |
3290 | |
111 | 3291 } // anon namespace |
3292 | |
3293 rtl_opt_pass * | |
3294 make_pass_jump (gcc::context *ctxt) | |
3295 { | |
3296 return new pass_jump (ctxt); | |
3297 } | |
3298 | |
3299 namespace { | |
3300 | |
3301 const pass_data pass_data_jump2 = | |
0 | 3302 { |
111 | 3303 RTL_PASS, /* type */ |
3304 "jump2", /* name */ | |
3305 OPTGROUP_NONE, /* optinfo_flags */ | |
3306 TV_JUMP, /* tv_id */ | |
3307 0, /* properties_required */ | |
3308 0, /* properties_provided */ | |
3309 0, /* properties_destroyed */ | |
3310 0, /* todo_flags_start */ | |
3311 0, /* todo_flags_finish */ | |
0 | 3312 }; |
3313 | |
111 | 3314 class pass_jump2 : public rtl_opt_pass |
3315 { | |
3316 public: | |
3317 pass_jump2 (gcc::context *ctxt) | |
3318 : rtl_opt_pass (pass_data_jump2, ctxt) | |
3319 {} | |
3320 | |
3321 /* opt_pass methods: */ | |
3322 virtual unsigned int execute (function *) | |
3323 { | |
3324 cleanup_cfg (flag_crossjumping ? CLEANUP_CROSSJUMP : 0); | |
3325 return 0; | |
3326 } | |
3327 | |
3328 }; // class pass_jump2 | |
3329 | |
3330 } // anon namespace | |
3331 | |
3332 rtl_opt_pass * | |
3333 make_pass_jump2 (gcc::context *ctxt) | |
3334 { | |
3335 return new pass_jump2 (ctxt); | |
3336 } |