Mercurial > hg > CbC > CbC_gcc
annotate gcc/cfgcleanup.c @ 129:002ebcbc1eb4
remove test_env
author | mir3636 |
---|---|
date | Tue, 15 May 2018 18:45:25 +0900 |
parents | f6334be47118 |
children | 04ced10e8804 |
rev | line source |
---|---|
0 | 1 /* Control flow optimization code for GNU compiler. |
2 Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
3 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010 |
0 | 4 Free Software Foundation, Inc. |
5 | |
6 This file is part of GCC. | |
7 | |
8 GCC is free software; you can redistribute it and/or modify it under | |
9 the terms of the GNU General Public License as published by the Free | |
10 Software Foundation; either version 3, or (at your option) any later | |
11 version. | |
12 | |
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
16 for more details. | |
17 | |
18 You should have received a copy of the GNU General Public License | |
19 along with GCC; see the file COPYING3. If not see | |
20 <http://www.gnu.org/licenses/>. */ | |
21 | |
22 /* This file contains optimizer of the control flow. The main entry point is | |
23 cleanup_cfg. Following optimizations are performed: | |
24 | |
25 - Unreachable blocks removal | |
26 - Edge forwarding (edge to the forwarder block is forwarded to its | |
27 successor. Simplification of the branch instruction is performed by | |
28 underlying infrastructure so branch can be converted to simplejump or | |
29 eliminated). | |
30 - Cross jumping (tail merging) | |
31 - Conditional jump-around-simplejump simplification | |
32 - Basic block merging. */ | |
33 | |
34 #include "config.h" | |
35 #include "system.h" | |
36 #include "coretypes.h" | |
37 #include "tm.h" | |
38 #include "rtl.h" | |
39 #include "hard-reg-set.h" | |
40 #include "regs.h" | |
41 #include "timevar.h" | |
42 #include "output.h" | |
43 #include "insn-config.h" | |
44 #include "flags.h" | |
45 #include "recog.h" | |
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
|
46 #include "diagnostic-core.h" |
0 | 47 #include "cselib.h" |
48 #include "params.h" | |
49 #include "tm_p.h" | |
50 #include "target.h" | |
51 #include "cfglayout.h" | |
52 #include "emit-rtl.h" | |
53 #include "tree-pass.h" | |
54 #include "cfgloop.h" | |
55 #include "expr.h" | |
56 #include "df.h" | |
57 #include "dce.h" | |
58 #include "dbgcnt.h" | |
59 | |
60 #define FORWARDER_BLOCK_P(BB) ((BB)->flags & BB_FORWARDER_BLOCK) | |
61 | |
62 /* Set to true when we are running first pass of try_optimize_cfg loop. */ | |
63 static bool first_pass; | |
64 | |
65 /* Set to true if crossjumps occured in the latest run of try_optimize_cfg. */ | |
66 static bool crossjumps_occured; | |
67 | |
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
|
68 /* 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
|
69 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
|
70 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
|
71 |
0 | 72 static bool try_crossjump_to_edge (int, edge, edge); |
73 static bool try_crossjump_bb (int, basic_block); | |
74 static bool outgoing_edges_match (int, basic_block, basic_block); | |
75 static bool old_insns_match_p (int, rtx, rtx); | |
76 | |
77 static void merge_blocks_move_predecessor_nojumps (basic_block, basic_block); | |
78 static void merge_blocks_move_successor_nojumps (basic_block, basic_block); | |
79 static bool try_optimize_cfg (int); | |
80 static bool try_simplify_condjump (basic_block); | |
81 static bool try_forward_edges (int, basic_block); | |
82 static edge thread_jump (edge, basic_block); | |
83 static bool mark_effect (rtx, bitmap); | |
84 static void notice_new_block (basic_block); | |
85 static void update_forwarder_flag (basic_block); | |
86 static int mentions_nonequal_regs (rtx *, void *); | |
87 static void merge_memattrs (rtx, rtx); | |
88 | |
89 /* Set flags for newly created block. */ | |
90 | |
91 static void | |
92 notice_new_block (basic_block bb) | |
93 { | |
94 if (!bb) | |
95 return; | |
96 | |
97 if (forwarder_block_p (bb)) | |
98 bb->flags |= BB_FORWARDER_BLOCK; | |
99 } | |
100 | |
101 /* Recompute forwarder flag after block has been modified. */ | |
102 | |
103 static void | |
104 update_forwarder_flag (basic_block bb) | |
105 { | |
106 if (forwarder_block_p (bb)) | |
107 bb->flags |= BB_FORWARDER_BLOCK; | |
108 else | |
109 bb->flags &= ~BB_FORWARDER_BLOCK; | |
110 } | |
111 | |
112 /* Simplify a conditional jump around an unconditional jump. | |
113 Return true if something changed. */ | |
114 | |
115 static bool | |
116 try_simplify_condjump (basic_block cbranch_block) | |
117 { | |
118 basic_block jump_block, jump_dest_block, cbranch_dest_block; | |
119 edge cbranch_jump_edge, cbranch_fallthru_edge; | |
120 rtx cbranch_insn; | |
121 | |
122 /* Verify that there are exactly two successors. */ | |
123 if (EDGE_COUNT (cbranch_block->succs) != 2) | |
124 return false; | |
125 | |
126 /* Verify that we've got a normal conditional branch at the end | |
127 of the block. */ | |
128 cbranch_insn = BB_END (cbranch_block); | |
129 if (!any_condjump_p (cbranch_insn)) | |
130 return false; | |
131 | |
132 cbranch_fallthru_edge = FALLTHRU_EDGE (cbranch_block); | |
133 cbranch_jump_edge = BRANCH_EDGE (cbranch_block); | |
134 | |
135 /* The next block must not have multiple predecessors, must not | |
136 be the last block in the function, and must contain just the | |
137 unconditional jump. */ | |
138 jump_block = cbranch_fallthru_edge->dest; | |
139 if (!single_pred_p (jump_block) | |
140 || jump_block->next_bb == EXIT_BLOCK_PTR | |
141 || !FORWARDER_BLOCK_P (jump_block)) | |
142 return false; | |
143 jump_dest_block = single_succ (jump_block); | |
144 | |
145 /* If we are partitioning hot/cold basic blocks, we don't want to | |
146 mess up unconditional or indirect jumps that cross between hot | |
147 and cold sections. | |
148 | |
149 Basic block partitioning may result in some jumps that appear to | |
150 be optimizable (or blocks that appear to be mergeable), but which really | |
151 must be left untouched (they are required to make it safely across | |
152 partition boundaries). See the comments at the top of | |
153 bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */ | |
154 | |
155 if (BB_PARTITION (jump_block) != BB_PARTITION (jump_dest_block) | |
156 || (cbranch_jump_edge->flags & EDGE_CROSSING)) | |
157 return false; | |
158 | |
159 /* The conditional branch must target the block after the | |
160 unconditional branch. */ | |
161 cbranch_dest_block = cbranch_jump_edge->dest; | |
162 | |
163 if (cbranch_dest_block == EXIT_BLOCK_PTR | |
164 || !can_fallthru (jump_block, cbranch_dest_block)) | |
165 return false; | |
166 | |
167 /* Invert the conditional branch. */ | |
168 if (!invert_jump (cbranch_insn, block_label (jump_dest_block), 0)) | |
169 return false; | |
170 | |
171 if (dump_file) | |
172 fprintf (dump_file, "Simplifying condjump %i around jump %i\n", | |
173 INSN_UID (cbranch_insn), INSN_UID (BB_END (jump_block))); | |
174 | |
175 /* Success. Update the CFG to match. Note that after this point | |
176 the edge variable names appear backwards; the redirection is done | |
177 this way to preserve edge profile data. */ | |
178 cbranch_jump_edge = redirect_edge_succ_nodup (cbranch_jump_edge, | |
179 cbranch_dest_block); | |
180 cbranch_fallthru_edge = redirect_edge_succ_nodup (cbranch_fallthru_edge, | |
181 jump_dest_block); | |
182 cbranch_jump_edge->flags |= EDGE_FALLTHRU; | |
183 cbranch_fallthru_edge->flags &= ~EDGE_FALLTHRU; | |
184 update_br_prob_note (cbranch_block); | |
185 | |
186 /* Delete the block with the unconditional jump, and clean up the mess. */ | |
187 delete_basic_block (jump_block); | |
188 tidy_fallthru_edge (cbranch_jump_edge); | |
189 update_forwarder_flag (cbranch_block); | |
190 | |
191 return true; | |
192 } | |
193 | |
194 /* Attempt to prove that operation is NOOP using CSElib or mark the effect | |
195 on register. Used by jump threading. */ | |
196 | |
197 static bool | |
198 mark_effect (rtx exp, regset nonequal) | |
199 { | |
200 int regno; | |
201 rtx dest; | |
202 switch (GET_CODE (exp)) | |
203 { | |
204 /* In case we do clobber the register, mark it as equal, as we know the | |
205 value is dead so it don't have to match. */ | |
206 case CLOBBER: | |
207 if (REG_P (XEXP (exp, 0))) | |
208 { | |
209 dest = XEXP (exp, 0); | |
210 regno = REGNO (dest); | |
211 CLEAR_REGNO_REG_SET (nonequal, regno); | |
212 if (regno < FIRST_PSEUDO_REGISTER) | |
213 { | |
214 int n = hard_regno_nregs[regno][GET_MODE (dest)]; | |
215 while (--n > 0) | |
216 CLEAR_REGNO_REG_SET (nonequal, regno + n); | |
217 } | |
218 } | |
219 return false; | |
220 | |
221 case SET: | |
222 if (rtx_equal_for_cselib_p (SET_DEST (exp), SET_SRC (exp))) | |
223 return false; | |
224 dest = SET_DEST (exp); | |
225 if (dest == pc_rtx) | |
226 return false; | |
227 if (!REG_P (dest)) | |
228 return true; | |
229 regno = REGNO (dest); | |
230 SET_REGNO_REG_SET (nonequal, regno); | |
231 if (regno < FIRST_PSEUDO_REGISTER) | |
232 { | |
233 int n = hard_regno_nregs[regno][GET_MODE (dest)]; | |
234 while (--n > 0) | |
235 SET_REGNO_REG_SET (nonequal, regno + n); | |
236 } | |
237 return false; | |
238 | |
239 default: | |
240 return false; | |
241 } | |
242 } | |
243 | |
244 /* Return nonzero if X is a register set in regset DATA. | |
245 Called via for_each_rtx. */ | |
246 static int | |
247 mentions_nonequal_regs (rtx *x, void *data) | |
248 { | |
249 regset nonequal = (regset) data; | |
250 if (REG_P (*x)) | |
251 { | |
252 int regno; | |
253 | |
254 regno = REGNO (*x); | |
255 if (REGNO_REG_SET_P (nonequal, regno)) | |
256 return 1; | |
257 if (regno < FIRST_PSEUDO_REGISTER) | |
258 { | |
259 int n = hard_regno_nregs[regno][GET_MODE (*x)]; | |
260 while (--n > 0) | |
261 if (REGNO_REG_SET_P (nonequal, regno + n)) | |
262 return 1; | |
263 } | |
264 } | |
265 return 0; | |
266 } | |
267 /* Attempt to prove that the basic block B will have no side effects and | |
268 always continues in the same edge if reached via E. Return the edge | |
269 if exist, NULL otherwise. */ | |
270 | |
271 static edge | |
272 thread_jump (edge e, basic_block b) | |
273 { | |
274 rtx set1, set2, cond1, cond2, insn; | |
275 enum rtx_code code1, code2, reversed_code2; | |
276 bool reverse1 = false; | |
277 unsigned i; | |
278 regset nonequal; | |
279 bool failed = false; | |
280 reg_set_iterator rsi; | |
281 | |
282 if (b->flags & BB_NONTHREADABLE_BLOCK) | |
283 return NULL; | |
284 | |
285 /* At the moment, we do handle only conditional jumps, but later we may | |
286 want to extend this code to tablejumps and others. */ | |
287 if (EDGE_COUNT (e->src->succs) != 2) | |
288 return NULL; | |
289 if (EDGE_COUNT (b->succs) != 2) | |
290 { | |
291 b->flags |= BB_NONTHREADABLE_BLOCK; | |
292 return NULL; | |
293 } | |
294 | |
295 /* Second branch must end with onlyjump, as we will eliminate the jump. */ | |
296 if (!any_condjump_p (BB_END (e->src))) | |
297 return NULL; | |
298 | |
299 if (!any_condjump_p (BB_END (b)) || !onlyjump_p (BB_END (b))) | |
300 { | |
301 b->flags |= BB_NONTHREADABLE_BLOCK; | |
302 return NULL; | |
303 } | |
304 | |
305 set1 = pc_set (BB_END (e->src)); | |
306 set2 = pc_set (BB_END (b)); | |
307 if (((e->flags & EDGE_FALLTHRU) != 0) | |
308 != (XEXP (SET_SRC (set1), 1) == pc_rtx)) | |
309 reverse1 = true; | |
310 | |
311 cond1 = XEXP (SET_SRC (set1), 0); | |
312 cond2 = XEXP (SET_SRC (set2), 0); | |
313 if (reverse1) | |
314 code1 = reversed_comparison_code (cond1, BB_END (e->src)); | |
315 else | |
316 code1 = GET_CODE (cond1); | |
317 | |
318 code2 = GET_CODE (cond2); | |
319 reversed_code2 = reversed_comparison_code (cond2, BB_END (b)); | |
320 | |
321 if (!comparison_dominates_p (code1, code2) | |
322 && !comparison_dominates_p (code1, reversed_code2)) | |
323 return NULL; | |
324 | |
325 /* Ensure that the comparison operators are equivalent. | |
326 ??? This is far too pessimistic. We should allow swapped operands, | |
327 different CCmodes, or for example comparisons for interval, that | |
328 dominate even when operands are not equivalent. */ | |
329 if (!rtx_equal_p (XEXP (cond1, 0), XEXP (cond2, 0)) | |
330 || !rtx_equal_p (XEXP (cond1, 1), XEXP (cond2, 1))) | |
331 return NULL; | |
332 | |
333 /* Short circuit cases where block B contains some side effects, as we can't | |
334 safely bypass it. */ | |
335 for (insn = NEXT_INSN (BB_HEAD (b)); insn != NEXT_INSN (BB_END (b)); | |
336 insn = NEXT_INSN (insn)) | |
337 if (INSN_P (insn) && side_effects_p (PATTERN (insn))) | |
338 { | |
339 b->flags |= BB_NONTHREADABLE_BLOCK; | |
340 return NULL; | |
341 } | |
342 | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
343 cselib_init (0); |
0 | 344 |
345 /* First process all values computed in the source basic block. */ | |
346 for (insn = NEXT_INSN (BB_HEAD (e->src)); | |
347 insn != NEXT_INSN (BB_END (e->src)); | |
348 insn = NEXT_INSN (insn)) | |
349 if (INSN_P (insn)) | |
350 cselib_process_insn (insn); | |
351 | |
352 nonequal = BITMAP_ALLOC (NULL); | |
353 CLEAR_REG_SET (nonequal); | |
354 | |
355 /* Now assume that we've continued by the edge E to B and continue | |
356 processing as if it were same basic block. | |
357 Our goal is to prove that whole block is an NOOP. */ | |
358 | |
359 for (insn = NEXT_INSN (BB_HEAD (b)); | |
360 insn != NEXT_INSN (BB_END (b)) && !failed; | |
361 insn = NEXT_INSN (insn)) | |
362 { | |
363 if (INSN_P (insn)) | |
364 { | |
365 rtx pat = PATTERN (insn); | |
366 | |
367 if (GET_CODE (pat) == PARALLEL) | |
368 { | |
369 for (i = 0; i < (unsigned)XVECLEN (pat, 0); i++) | |
370 failed |= mark_effect (XVECEXP (pat, 0, i), nonequal); | |
371 } | |
372 else | |
373 failed |= mark_effect (pat, nonequal); | |
374 } | |
375 | |
376 cselib_process_insn (insn); | |
377 } | |
378 | |
379 /* Later we should clear nonequal of dead registers. So far we don't | |
380 have life information in cfg_cleanup. */ | |
381 if (failed) | |
382 { | |
383 b->flags |= BB_NONTHREADABLE_BLOCK; | |
384 goto failed_exit; | |
385 } | |
386 | |
387 /* cond2 must not mention any register that is not equal to the | |
388 former block. */ | |
389 if (for_each_rtx (&cond2, mentions_nonequal_regs, nonequal)) | |
390 goto failed_exit; | |
391 | |
392 EXECUTE_IF_SET_IN_REG_SET (nonequal, 0, i, rsi) | |
393 goto failed_exit; | |
394 | |
395 BITMAP_FREE (nonequal); | |
396 cselib_finish (); | |
397 if ((comparison_dominates_p (code1, code2) != 0) | |
398 != (XEXP (SET_SRC (set2), 1) == pc_rtx)) | |
399 return BRANCH_EDGE (b); | |
400 else | |
401 return FALLTHRU_EDGE (b); | |
402 | |
403 failed_exit: | |
404 BITMAP_FREE (nonequal); | |
405 cselib_finish (); | |
406 return NULL; | |
407 } | |
408 | |
409 /* Attempt to forward edges leaving basic block B. | |
410 Return true if successful. */ | |
411 | |
412 static bool | |
413 try_forward_edges (int mode, basic_block b) | |
414 { | |
415 bool changed = false; | |
416 edge_iterator ei; | |
417 edge e, *threaded_edges = NULL; | |
418 | |
419 /* If we are partitioning hot/cold basic blocks, we don't want to | |
420 mess up unconditional or indirect jumps that cross between hot | |
421 and cold sections. | |
422 | |
423 Basic block partitioning may result in some jumps that appear to | |
424 be optimizable (or blocks that appear to be mergeable), but which really | |
425 must be left untouched (they are required to make it safely across | |
426 partition boundaries). See the comments at the top of | |
427 bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */ | |
428 | |
429 if (find_reg_note (BB_END (b), REG_CROSSING_JUMP, NULL_RTX)) | |
430 return false; | |
431 | |
432 for (ei = ei_start (b->succs); (e = ei_safe_edge (ei)); ) | |
433 { | |
434 basic_block target, first; | |
435 int counter, goto_locus; | |
436 bool threaded = false; | |
437 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
|
438 bool may_thread = first_pass || (b->flags & BB_MODIFIED) != 0; |
0 | 439 |
440 /* Skip complex edges because we don't know how to update them. | |
441 | |
442 Still handle fallthru edges, as we can succeed to forward fallthru | |
443 edge to the same place as the branch edge of conditional branch | |
444 and turn conditional branch to an unconditional branch. */ | |
445 if (e->flags & EDGE_COMPLEX) | |
446 { | |
447 ei_next (&ei); | |
448 continue; | |
449 } | |
450 | |
451 target = first = e->dest; | |
452 counter = NUM_FIXED_BLOCKS; | |
453 goto_locus = e->goto_locus; | |
454 | |
455 /* If we are partitioning hot/cold basic_blocks, we don't want to mess | |
456 up jumps that cross between hot/cold sections. | |
457 | |
458 Basic block partitioning may result in some jumps that appear | |
459 to be optimizable (or blocks that appear to be mergeable), but which | |
460 really must be left untouched (they are required to make it safely | |
461 across partition boundaries). See the comments at the top of | |
462 bb-reorder.c:partition_hot_cold_basic_blocks for complete | |
463 details. */ | |
464 | |
465 if (first != EXIT_BLOCK_PTR | |
466 && find_reg_note (BB_END (first), REG_CROSSING_JUMP, NULL_RTX)) | |
467 return false; | |
468 | |
469 while (counter < n_basic_blocks) | |
470 { | |
471 basic_block new_target = NULL; | |
472 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
|
473 may_thread |= (target->flags & BB_MODIFIED) != 0; |
0 | 474 |
475 if (FORWARDER_BLOCK_P (target) | |
476 && !(single_succ_edge (target)->flags & EDGE_CROSSING) | |
477 && single_succ (target) != EXIT_BLOCK_PTR) | |
478 { | |
479 /* Bypass trivial infinite loops. */ | |
480 new_target = single_succ (target); | |
481 if (target == new_target) | |
482 counter = n_basic_blocks; | |
483 else if (!optimize) | |
484 { | |
485 /* When not optimizing, ensure that edges or forwarder | |
486 blocks with different locus are not optimized out. */ | |
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
|
487 int new_locus = single_succ_edge (target)->goto_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
|
488 int locus = goto_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
|
489 |
f6334be47118
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 if (new_locus && locus && !locator_eq (new_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
|
491 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
|
492 else |
0 | 493 { |
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 rtx 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
|
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 if (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
|
497 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
|
498 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
499 last = BB_END (target); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
500 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
|
501 last = prev_nondebug_insn (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
|
502 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
503 new_locus = last && 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
|
504 ? INSN_LOCATOR (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
|
505 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
506 if (new_locus && locus && !locator_eq (new_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
|
507 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
|
508 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
|
509 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
510 if (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
|
511 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
|
512 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
513 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
|
514 } |
0 | 515 } |
516 } | |
517 } | |
518 | |
519 /* Allow to thread only over one edge at time to simplify updating | |
520 of probabilities. */ | |
521 else if ((mode & CLEANUP_THREADING) && may_thread) | |
522 { | |
523 edge t = thread_jump (e, target); | |
524 if (t) | |
525 { | |
526 if (!threaded_edges) | |
527 threaded_edges = XNEWVEC (edge, n_basic_blocks); | |
528 else | |
529 { | |
530 int i; | |
531 | |
532 /* Detect an infinite loop across blocks not | |
533 including the start block. */ | |
534 for (i = 0; i < nthreaded_edges; ++i) | |
535 if (threaded_edges[i] == t) | |
536 break; | |
537 if (i < nthreaded_edges) | |
538 { | |
539 counter = n_basic_blocks; | |
540 break; | |
541 } | |
542 } | |
543 | |
544 /* Detect an infinite loop across the start block. */ | |
545 if (t->dest == b) | |
546 break; | |
547 | |
548 gcc_assert (nthreaded_edges < n_basic_blocks - NUM_FIXED_BLOCKS); | |
549 threaded_edges[nthreaded_edges++] = t; | |
550 | |
551 new_target = t->dest; | |
552 new_target_threaded = true; | |
553 } | |
554 } | |
555 | |
556 if (!new_target) | |
557 break; | |
558 | |
559 counter++; | |
560 target = new_target; | |
561 threaded |= new_target_threaded; | |
562 } | |
563 | |
564 if (counter >= n_basic_blocks) | |
565 { | |
566 if (dump_file) | |
567 fprintf (dump_file, "Infinite loop in BB %i.\n", | |
568 target->index); | |
569 } | |
570 else if (target == first) | |
571 ; /* We didn't do anything. */ | |
572 else | |
573 { | |
574 /* Save the values now, as the edge may get removed. */ | |
575 gcov_type edge_count = e->count; | |
576 int edge_probability = e->probability; | |
577 int edge_frequency; | |
578 int n = 0; | |
579 | |
580 e->goto_locus = goto_locus; | |
581 | |
582 /* Don't force if target is exit block. */ | |
583 if (threaded && target != EXIT_BLOCK_PTR) | |
584 { | |
585 notice_new_block (redirect_edge_and_branch_force (e, target)); | |
586 if (dump_file) | |
587 fprintf (dump_file, "Conditionals threaded.\n"); | |
588 } | |
589 else if (!redirect_edge_and_branch (e, target)) | |
590 { | |
591 if (dump_file) | |
592 fprintf (dump_file, | |
593 "Forwarding edge %i->%i to %i failed.\n", | |
594 b->index, e->dest->index, target->index); | |
595 ei_next (&ei); | |
596 continue; | |
597 } | |
598 | |
599 /* We successfully forwarded the edge. Now update profile | |
600 data: for each edge we traversed in the chain, remove | |
601 the original edge's execution count. */ | |
602 edge_frequency = ((edge_probability * b->frequency | |
603 + REG_BR_PROB_BASE / 2) | |
604 / REG_BR_PROB_BASE); | |
605 | |
606 if (!FORWARDER_BLOCK_P (b) && forwarder_block_p (b)) | |
607 b->flags |= BB_FORWARDER_BLOCK; | |
608 | |
609 do | |
610 { | |
611 edge t; | |
612 | |
613 if (!single_succ_p (first)) | |
614 { | |
615 gcc_assert (n < nthreaded_edges); | |
616 t = threaded_edges [n++]; | |
617 gcc_assert (t->src == first); | |
618 update_bb_profile_for_threading (first, edge_frequency, | |
619 edge_count, t); | |
620 update_br_prob_note (first); | |
621 } | |
622 else | |
623 { | |
624 first->count -= edge_count; | |
625 if (first->count < 0) | |
626 first->count = 0; | |
627 first->frequency -= edge_frequency; | |
628 if (first->frequency < 0) | |
629 first->frequency = 0; | |
630 /* It is possible that as the result of | |
631 threading we've removed edge as it is | |
632 threaded to the fallthru edge. Avoid | |
633 getting out of sync. */ | |
634 if (n < nthreaded_edges | |
635 && first == threaded_edges [n]->src) | |
636 n++; | |
637 t = single_succ_edge (first); | |
638 } | |
639 | |
640 t->count -= edge_count; | |
641 if (t->count < 0) | |
642 t->count = 0; | |
643 first = t->dest; | |
644 } | |
645 while (first != target); | |
646 | |
647 changed = true; | |
648 continue; | |
649 } | |
650 ei_next (&ei); | |
651 } | |
652 | |
653 if (threaded_edges) | |
654 free (threaded_edges); | |
655 return changed; | |
656 } | |
657 | |
658 | |
659 /* Blocks A and B are to be merged into a single block. A has no incoming | |
660 fallthru edge, so it can be moved before B without adding or modifying | |
661 any jumps (aside from the jump from A to B). */ | |
662 | |
663 static void | |
664 merge_blocks_move_predecessor_nojumps (basic_block a, basic_block b) | |
665 { | |
666 rtx barrier; | |
667 | |
668 /* If we are partitioning hot/cold basic blocks, we don't want to | |
669 mess up unconditional or indirect jumps that cross between hot | |
670 and cold sections. | |
671 | |
672 Basic block partitioning may result in some jumps that appear to | |
673 be optimizable (or blocks that appear to be mergeable), but which really | |
674 must be left untouched (they are required to make it safely across | |
675 partition boundaries). See the comments at the top of | |
676 bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */ | |
677 | |
678 if (BB_PARTITION (a) != BB_PARTITION (b)) | |
679 return; | |
680 | |
681 barrier = next_nonnote_insn (BB_END (a)); | |
682 gcc_assert (BARRIER_P (barrier)); | |
683 delete_insn (barrier); | |
684 | |
685 /* Scramble the insn chain. */ | |
686 if (BB_END (a) != PREV_INSN (BB_HEAD (b))) | |
687 reorder_insns_nobb (BB_HEAD (a), BB_END (a), PREV_INSN (BB_HEAD (b))); | |
688 df_set_bb_dirty (a); | |
689 | |
690 if (dump_file) | |
691 fprintf (dump_file, "Moved block %d before %d and merged.\n", | |
692 a->index, b->index); | |
693 | |
694 /* Swap the records for the two blocks around. */ | |
695 | |
696 unlink_block (a); | |
697 link_block (a, b->prev_bb); | |
698 | |
699 /* Now blocks A and B are contiguous. Merge them. */ | |
700 merge_blocks (a, b); | |
701 } | |
702 | |
703 /* Blocks A and B are to be merged into a single block. B has no outgoing | |
704 fallthru edge, so it can be moved after A without adding or modifying | |
705 any jumps (aside from the jump from A to B). */ | |
706 | |
707 static void | |
708 merge_blocks_move_successor_nojumps (basic_block a, basic_block b) | |
709 { | |
710 rtx barrier, real_b_end; | |
711 rtx label, table; | |
712 | |
713 /* If we are partitioning hot/cold basic blocks, we don't want to | |
714 mess up unconditional or indirect jumps that cross between hot | |
715 and cold sections. | |
716 | |
717 Basic block partitioning may result in some jumps that appear to | |
718 be optimizable (or blocks that appear to be mergeable), but which really | |
719 must be left untouched (they are required to make it safely across | |
720 partition boundaries). See the comments at the top of | |
721 bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */ | |
722 | |
723 if (BB_PARTITION (a) != BB_PARTITION (b)) | |
724 return; | |
725 | |
726 real_b_end = BB_END (b); | |
727 | |
728 /* If there is a jump table following block B temporarily add the jump table | |
729 to block B so that it will also be moved to the correct location. */ | |
730 if (tablejump_p (BB_END (b), &label, &table) | |
731 && prev_active_insn (label) == BB_END (b)) | |
732 { | |
733 BB_END (b) = table; | |
734 } | |
735 | |
736 /* There had better have been a barrier there. Delete it. */ | |
737 barrier = NEXT_INSN (BB_END (b)); | |
738 if (barrier && BARRIER_P (barrier)) | |
739 delete_insn (barrier); | |
740 | |
741 | |
742 /* Scramble the insn chain. */ | |
743 reorder_insns_nobb (BB_HEAD (b), BB_END (b), BB_END (a)); | |
744 | |
745 /* Restore the real end of b. */ | |
746 BB_END (b) = real_b_end; | |
747 | |
748 if (dump_file) | |
749 fprintf (dump_file, "Moved block %d after %d and merged.\n", | |
750 b->index, a->index); | |
751 | |
752 /* Now blocks A and B are contiguous. Merge them. */ | |
753 merge_blocks (a, b); | |
754 } | |
755 | |
756 /* Attempt to merge basic blocks that are potentially non-adjacent. | |
757 Return NULL iff the attempt failed, otherwise return basic block | |
758 where cleanup_cfg should continue. Because the merging commonly | |
759 moves basic block away or introduces another optimization | |
760 possibility, return basic block just before B so cleanup_cfg don't | |
761 need to iterate. | |
762 | |
763 It may be good idea to return basic block before C in the case | |
764 C has been moved after B and originally appeared earlier in the | |
765 insn sequence, but we have no information available about the | |
766 relative ordering of these two. Hopefully it is not too common. */ | |
767 | |
768 static basic_block | |
769 merge_blocks_move (edge e, basic_block b, basic_block c, int mode) | |
770 { | |
771 basic_block next; | |
772 | |
773 /* If we are partitioning hot/cold basic blocks, we don't want to | |
774 mess up unconditional or indirect jumps that cross between hot | |
775 and cold sections. | |
776 | |
777 Basic block partitioning may result in some jumps that appear to | |
778 be optimizable (or blocks that appear to be mergeable), but which really | |
779 must be left untouched (they are required to make it safely across | |
780 partition boundaries). See the comments at the top of | |
781 bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */ | |
782 | |
783 if (BB_PARTITION (b) != BB_PARTITION (c)) | |
784 return NULL; | |
785 | |
786 /* If B has a fallthru edge to C, no need to move anything. */ | |
787 if (e->flags & EDGE_FALLTHRU) | |
788 { | |
789 int b_index = b->index, c_index = c->index; | |
790 merge_blocks (b, c); | |
791 update_forwarder_flag (b); | |
792 | |
793 if (dump_file) | |
794 fprintf (dump_file, "Merged %d and %d without moving.\n", | |
795 b_index, c_index); | |
796 | |
797 return b->prev_bb == ENTRY_BLOCK_PTR ? b : b->prev_bb; | |
798 } | |
799 | |
800 /* Otherwise we will need to move code around. Do that only if expensive | |
801 transformations are allowed. */ | |
802 else if (mode & CLEANUP_EXPENSIVE) | |
803 { | |
804 edge tmp_edge, b_fallthru_edge; | |
805 bool c_has_outgoing_fallthru; | |
806 bool b_has_incoming_fallthru; | |
807 | |
808 /* Avoid overactive code motion, as the forwarder blocks should be | |
809 eliminated by edge redirection instead. One exception might have | |
810 been if B is a forwarder block and C has no fallthru edge, but | |
811 that should be cleaned up by bb-reorder instead. */ | |
812 if (FORWARDER_BLOCK_P (b) || FORWARDER_BLOCK_P (c)) | |
813 return NULL; | |
814 | |
815 /* We must make sure to not munge nesting of lexical blocks, | |
816 and loop notes. This is done by squeezing out all the notes | |
817 and leaving them there to lie. Not ideal, but functional. */ | |
818 | |
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
|
819 tmp_edge = find_fallthru_edge (c->succs); |
0 | 820 c_has_outgoing_fallthru = (tmp_edge != NULL); |
821 | |
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
|
822 tmp_edge = find_fallthru_edge (b->preds); |
0 | 823 b_has_incoming_fallthru = (tmp_edge != NULL); |
824 b_fallthru_edge = tmp_edge; | |
825 next = b->prev_bb; | |
826 if (next == c) | |
827 next = next->prev_bb; | |
828 | |
829 /* Otherwise, we're going to try to move C after B. If C does | |
830 not have an outgoing fallthru, then it can be moved | |
831 immediately after B without introducing or modifying jumps. */ | |
832 if (! c_has_outgoing_fallthru) | |
833 { | |
834 merge_blocks_move_successor_nojumps (b, c); | |
835 return next == ENTRY_BLOCK_PTR ? next->next_bb : next; | |
836 } | |
837 | |
838 /* If B does not have an incoming fallthru, then it can be moved | |
839 immediately before C without introducing or modifying jumps. | |
840 C cannot be the first block, so we do not have to worry about | |
841 accessing a non-existent block. */ | |
842 | |
843 if (b_has_incoming_fallthru) | |
844 { | |
845 basic_block bb; | |
846 | |
847 if (b_fallthru_edge->src == ENTRY_BLOCK_PTR) | |
848 return NULL; | |
849 bb = force_nonfallthru (b_fallthru_edge); | |
850 if (bb) | |
851 notice_new_block (bb); | |
852 } | |
853 | |
854 merge_blocks_move_predecessor_nojumps (b, c); | |
855 return next == ENTRY_BLOCK_PTR ? next->next_bb : next; | |
856 } | |
857 | |
858 return NULL; | |
859 } | |
860 | |
861 | |
862 /* Removes the memory attributes of MEM expression | |
863 if they are not equal. */ | |
864 | |
865 void | |
866 merge_memattrs (rtx x, rtx y) | |
867 { | |
868 int i; | |
869 int j; | |
870 enum rtx_code code; | |
871 const char *fmt; | |
872 | |
873 if (x == y) | |
874 return; | |
875 if (x == 0 || y == 0) | |
876 return; | |
877 | |
878 code = GET_CODE (x); | |
879 | |
880 if (code != GET_CODE (y)) | |
881 return; | |
882 | |
883 if (GET_MODE (x) != GET_MODE (y)) | |
884 return; | |
885 | |
886 if (code == MEM && MEM_ATTRS (x) != MEM_ATTRS (y)) | |
887 { | |
888 if (! MEM_ATTRS (x)) | |
889 MEM_ATTRS (y) = 0; | |
890 else if (! MEM_ATTRS (y)) | |
891 MEM_ATTRS (x) = 0; | |
892 else | |
893 { | |
894 rtx mem_size; | |
895 | |
896 if (MEM_ALIAS_SET (x) != MEM_ALIAS_SET (y)) | |
897 { | |
898 set_mem_alias_set (x, 0); | |
899 set_mem_alias_set (y, 0); | |
900 } | |
901 | |
902 if (! mem_expr_equal_p (MEM_EXPR (x), MEM_EXPR (y))) | |
903 { | |
904 set_mem_expr (x, 0); | |
905 set_mem_expr (y, 0); | |
906 set_mem_offset (x, 0); | |
907 set_mem_offset (y, 0); | |
908 } | |
909 else if (MEM_OFFSET (x) != MEM_OFFSET (y)) | |
910 { | |
911 set_mem_offset (x, 0); | |
912 set_mem_offset (y, 0); | |
913 } | |
914 | |
915 if (!MEM_SIZE (x)) | |
916 mem_size = NULL_RTX; | |
917 else if (!MEM_SIZE (y)) | |
918 mem_size = NULL_RTX; | |
919 else | |
920 mem_size = GEN_INT (MAX (INTVAL (MEM_SIZE (x)), | |
921 INTVAL (MEM_SIZE (y)))); | |
922 set_mem_size (x, mem_size); | |
923 set_mem_size (y, mem_size); | |
924 | |
925 set_mem_align (x, MIN (MEM_ALIGN (x), MEM_ALIGN (y))); | |
926 set_mem_align (y, MEM_ALIGN (x)); | |
927 } | |
928 } | |
929 | |
930 fmt = GET_RTX_FORMAT (code); | |
931 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) | |
932 { | |
933 switch (fmt[i]) | |
934 { | |
935 case 'E': | |
936 /* Two vectors must have the same length. */ | |
937 if (XVECLEN (x, i) != XVECLEN (y, i)) | |
938 return; | |
939 | |
940 for (j = 0; j < XVECLEN (x, i); j++) | |
941 merge_memattrs (XVECEXP (x, i, j), XVECEXP (y, i, j)); | |
942 | |
943 break; | |
944 | |
945 case 'e': | |
946 merge_memattrs (XEXP (x, i), XEXP (y, i)); | |
947 } | |
948 } | |
949 return; | |
950 } | |
951 | |
952 | |
953 /* Return true if I1 and I2 are equivalent and thus can be crossjumped. */ | |
954 | |
955 static bool | |
956 old_insns_match_p (int mode ATTRIBUTE_UNUSED, rtx i1, rtx i2) | |
957 { | |
958 rtx p1, p2; | |
959 | |
960 /* Verify that I1 and I2 are equivalent. */ | |
961 if (GET_CODE (i1) != GET_CODE (i2)) | |
962 return false; | |
963 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
964 /* __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
|
965 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
|
966 if (NOTE_INSN_BASIC_BLOCK_P (i1) && NOTE_INSN_BASIC_BLOCK_P (i2)) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
967 return true; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
968 |
0 | 969 p1 = PATTERN (i1); |
970 p2 = PATTERN (i2); | |
971 | |
972 if (GET_CODE (p1) != GET_CODE (p2)) | |
973 return false; | |
974 | |
975 /* If this is a CALL_INSN, compare register usage information. | |
976 If we don't check this on stack register machines, the two | |
977 CALL_INSNs might be merged leaving reg-stack.c with mismatching | |
978 numbers of stack registers in the same basic block. | |
979 If we don't check this on machines with delay slots, a delay slot may | |
980 be filled that clobbers a parameter expected by the subroutine. | |
981 | |
982 ??? 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
|
983 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
|
984 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
985 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
|
986 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
987 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
|
988 { |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
989 /* 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
|
990 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
|
991 rtx n2 = find_reg_note (i2, REG_EH_REGION, 0); |
0 | 992 |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
993 if (!n1 && n2) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
994 return false; |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
995 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
996 if (n1 && (!n2 || XEXP (n1, 0) != XEXP (n2, 0))) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
997 return false; |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
998 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
999 if (!rtx_equal_p (CALL_INSN_FUNCTION_USAGE (i1), |
0 | 1000 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
|
1001 || SIBLING_CALL_P (i1) != SIBLING_CALL_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
|
1002 return false; |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1003 } |
0 | 1004 |
1005 #ifdef STACK_REGS | |
1006 /* If cross_jump_death_matters is not 0, the insn's mode | |
1007 indicates whether or not the insn contains any stack-like | |
1008 regs. */ | |
1009 | |
1010 if ((mode & CLEANUP_POST_REGSTACK) && stack_regs_mentioned (i1)) | |
1011 { | |
1012 /* If register stack conversion has already been done, then | |
1013 death notes must also be compared before it is certain that | |
1014 the two instruction streams match. */ | |
1015 | |
1016 rtx note; | |
1017 HARD_REG_SET i1_regset, i2_regset; | |
1018 | |
1019 CLEAR_HARD_REG_SET (i1_regset); | |
1020 CLEAR_HARD_REG_SET (i2_regset); | |
1021 | |
1022 for (note = REG_NOTES (i1); note; note = XEXP (note, 1)) | |
1023 if (REG_NOTE_KIND (note) == REG_DEAD && STACK_REG_P (XEXP (note, 0))) | |
1024 SET_HARD_REG_BIT (i1_regset, REGNO (XEXP (note, 0))); | |
1025 | |
1026 for (note = REG_NOTES (i2); note; note = XEXP (note, 1)) | |
1027 if (REG_NOTE_KIND (note) == REG_DEAD && STACK_REG_P (XEXP (note, 0))) | |
1028 SET_HARD_REG_BIT (i2_regset, REGNO (XEXP (note, 0))); | |
1029 | |
1030 if (!hard_reg_set_equal_p (i1_regset, i2_regset)) | |
1031 return false; | |
1032 } | |
1033 #endif | |
1034 | |
1035 if (reload_completed | |
1036 ? rtx_renumbered_equal_p (p1, p2) : rtx_equal_p (p1, p2)) | |
1037 return true; | |
1038 | |
1039 return false; | |
1040 } | |
1041 | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1042 /* 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
|
1043 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
|
1044 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1045 static void |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1046 merge_notes (rtx i1, rtx i2) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1047 { |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1048 /* 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
|
1049 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
|
1050 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
|
1051 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
|
1052 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1053 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
|
1054 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
|
1055 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
|
1056 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
|
1057 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
|
1058 && !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
|
1059 { |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1060 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
|
1061 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
|
1062 } |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1063 } |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1064 |
0 | 1065 /* Look through the insns at the end of BB1 and BB2 and find the longest |
1066 sequence that are equivalent. Store the first insns for that sequence | |
1067 in *F1 and *F2 and return the sequence length. | |
1068 | |
1069 To simplify callers of this function, if the blocks match exactly, | |
1070 store the head of the blocks in *F1 and *F2. */ | |
1071 | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1072 int |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1073 flow_find_cross_jump (basic_block bb1, basic_block bb2, rtx *f1, rtx *f2) |
0 | 1074 { |
1075 rtx i1, i2, last1, last2, afterlast1, afterlast2; | |
1076 int ninsns = 0; | |
1077 | |
1078 /* Skip simple jumps at the end of the blocks. Complex jumps still | |
1079 need to be compared for equivalence, which we'll do below. */ | |
1080 | |
1081 i1 = BB_END (bb1); | |
1082 last1 = afterlast1 = last2 = afterlast2 = NULL_RTX; | |
1083 if (onlyjump_p (i1) | |
1084 || (returnjump_p (i1) && !side_effects_p (PATTERN (i1)))) | |
1085 { | |
1086 last1 = i1; | |
1087 i1 = PREV_INSN (i1); | |
1088 } | |
1089 | |
1090 i2 = BB_END (bb2); | |
1091 if (onlyjump_p (i2) | |
1092 || (returnjump_p (i2) && !side_effects_p (PATTERN (i2)))) | |
1093 { | |
1094 last2 = i2; | |
1095 /* Count everything except for unconditional jump as insn. */ | |
1096 if (!simplejump_p (i2) && !returnjump_p (i2) && last1) | |
1097 ninsns++; | |
1098 i2 = PREV_INSN (i2); | |
1099 } | |
1100 | |
1101 while (true) | |
1102 { | |
1103 /* Ignore notes. */ | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1104 while (!NONDEBUG_INSN_P (i1) && i1 != BB_HEAD (bb1)) |
0 | 1105 i1 = PREV_INSN (i1); |
1106 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1107 while (!NONDEBUG_INSN_P (i2) && i2 != BB_HEAD (bb2)) |
0 | 1108 i2 = PREV_INSN (i2); |
1109 | |
1110 if (i1 == BB_HEAD (bb1) || i2 == BB_HEAD (bb2)) | |
1111 break; | |
1112 | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1113 if (!old_insns_match_p (0, i1, i2)) |
0 | 1114 break; |
1115 | |
1116 merge_memattrs (i1, i2); | |
1117 | |
1118 /* Don't begin a cross-jump with a NOTE insn. */ | |
1119 if (INSN_P (i1)) | |
1120 { | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1121 merge_notes (i1, i2); |
0 | 1122 |
1123 afterlast1 = last1, afterlast2 = last2; | |
1124 last1 = i1, last2 = i2; | |
1125 ninsns++; | |
1126 } | |
1127 | |
1128 i1 = PREV_INSN (i1); | |
1129 i2 = PREV_INSN (i2); | |
1130 } | |
1131 | |
1132 #ifdef HAVE_cc0 | |
1133 /* Don't allow the insn after a compare to be shared by | |
1134 cross-jumping unless the compare is also shared. */ | |
1135 if (ninsns && reg_mentioned_p (cc0_rtx, last1) && ! sets_cc0_p (last1)) | |
1136 last1 = afterlast1, last2 = afterlast2, ninsns--; | |
1137 #endif | |
1138 | |
1139 /* Include preceding notes and labels in the cross-jump. One, | |
1140 this may bring us to the head of the blocks as requested above. | |
1141 Two, it keeps line number notes as matched as may be. */ | |
1142 if (ninsns) | |
1143 { | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1144 while (last1 != BB_HEAD (bb1) && !NONDEBUG_INSN_P (PREV_INSN (last1))) |
0 | 1145 last1 = PREV_INSN (last1); |
1146 | |
1147 if (last1 != BB_HEAD (bb1) && LABEL_P (PREV_INSN (last1))) | |
1148 last1 = PREV_INSN (last1); | |
1149 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1150 while (last2 != BB_HEAD (bb2) && !NONDEBUG_INSN_P (PREV_INSN (last2))) |
0 | 1151 last2 = PREV_INSN (last2); |
1152 | |
1153 if (last2 != BB_HEAD (bb2) && LABEL_P (PREV_INSN (last2))) | |
1154 last2 = PREV_INSN (last2); | |
1155 | |
1156 *f1 = last1; | |
1157 *f2 = last2; | |
1158 } | |
1159 | |
1160 return ninsns; | |
1161 } | |
1162 | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1163 /* 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
|
1164 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
|
1165 If STOP_AFTER is nonzero, stop after finding that many matching |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1166 instructions. */ |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1167 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1168 int |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1169 flow_find_head_matching_sequence (basic_block bb1, basic_block bb2, rtx *f1, |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1170 rtx *f2, int 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
|
1171 { |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1172 rtx i1, i2, last1, last2, beforelast1, beforelast2; |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1173 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
|
1174 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
|
1175 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
|
1176 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
|
1177 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1178 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
|
1179 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
|
1180 nehedges1++; |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1181 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
|
1182 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
|
1183 nehedges2++; |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1184 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1185 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
|
1186 i2 = BB_HEAD (bb2); |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1187 last1 = beforelast1 = last2 = beforelast2 = NULL_RTX; |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1188 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1189 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
|
1190 { |
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
|
1191 /* 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
|
1192 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
|
1193 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1194 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
|
1195 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
|
1196 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
|
1197 } |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1198 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1199 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
|
1200 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1201 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
|
1202 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
|
1203 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
|
1204 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1205 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1206 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
|
1207 || (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
|
1208 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
|
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 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
|
1211 || 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
|
1212 break; |
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 /* 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
|
1215 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
|
1216 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
|
1217 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
|
1218 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
|
1219 && 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
|
1220 || (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
|
1221 && 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
|
1222 || (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
|
1223 && 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
|
1224 break; |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1225 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1226 if (!old_insns_match_p (0, 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
|
1227 break; |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1228 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1229 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
|
1230 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1231 /* 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
|
1232 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
|
1233 { |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1234 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
|
1235 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1236 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
|
1237 last1 = i1, last2 = i2; |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1238 ninsns++; |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1239 } |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1240 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1241 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
|
1242 || (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
|
1243 break; |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1244 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1245 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
|
1246 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
|
1247 } |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1248 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1249 #ifdef HAVE_cc0 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1250 /* 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
|
1251 after the compare is also shared. */ |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1252 if (ninsns && reg_mentioned_p (cc0_rtx, last1) && sets_cc0_p (last1)) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1253 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
|
1254 #endif |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1255 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1256 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
|
1257 { |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1258 *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
|
1259 *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
|
1260 } |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1261 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1262 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
|
1263 } |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1264 |
0 | 1265 /* Return true iff outgoing edges of BB1 and BB2 match, together with |
1266 the branch instruction. This means that if we commonize the control | |
1267 flow before end of the basic block, the semantic remains unchanged. | |
1268 | |
1269 We may assume that there exists one edge with a common destination. */ | |
1270 | |
1271 static bool | |
1272 outgoing_edges_match (int mode, basic_block bb1, basic_block bb2) | |
1273 { | |
1274 int nehedges1 = 0, nehedges2 = 0; | |
1275 edge fallthru1 = 0, fallthru2 = 0; | |
1276 edge e1, e2; | |
1277 edge_iterator ei; | |
1278 | |
1279 /* If BB1 has only one successor, we may be looking at either an | |
1280 unconditional jump, or a fake edge to exit. */ | |
1281 if (single_succ_p (bb1) | |
1282 && (single_succ_edge (bb1)->flags & (EDGE_COMPLEX | EDGE_FAKE)) == 0 | |
1283 && (!JUMP_P (BB_END (bb1)) || simplejump_p (BB_END (bb1)))) | |
1284 return (single_succ_p (bb2) | |
1285 && (single_succ_edge (bb2)->flags | |
1286 & (EDGE_COMPLEX | EDGE_FAKE)) == 0 | |
1287 && (!JUMP_P (BB_END (bb2)) || simplejump_p (BB_END (bb2)))); | |
1288 | |
1289 /* Match conditional jumps - this may get tricky when fallthru and branch | |
1290 edges are crossed. */ | |
1291 if (EDGE_COUNT (bb1->succs) == 2 | |
1292 && any_condjump_p (BB_END (bb1)) | |
1293 && onlyjump_p (BB_END (bb1))) | |
1294 { | |
1295 edge b1, f1, b2, f2; | |
1296 bool reverse, match; | |
1297 rtx set1, set2, cond1, cond2; | |
1298 enum rtx_code code1, code2; | |
1299 | |
1300 if (EDGE_COUNT (bb2->succs) != 2 | |
1301 || !any_condjump_p (BB_END (bb2)) | |
1302 || !onlyjump_p (BB_END (bb2))) | |
1303 return false; | |
1304 | |
1305 b1 = BRANCH_EDGE (bb1); | |
1306 b2 = BRANCH_EDGE (bb2); | |
1307 f1 = FALLTHRU_EDGE (bb1); | |
1308 f2 = FALLTHRU_EDGE (bb2); | |
1309 | |
1310 /* Get around possible forwarders on fallthru edges. Other cases | |
1311 should be optimized out already. */ | |
1312 if (FORWARDER_BLOCK_P (f1->dest)) | |
1313 f1 = single_succ_edge (f1->dest); | |
1314 | |
1315 if (FORWARDER_BLOCK_P (f2->dest)) | |
1316 f2 = single_succ_edge (f2->dest); | |
1317 | |
1318 /* To simplify use of this function, return false if there are | |
1319 unneeded forwarder blocks. These will get eliminated later | |
1320 during cleanup_cfg. */ | |
1321 if (FORWARDER_BLOCK_P (f1->dest) | |
1322 || FORWARDER_BLOCK_P (f2->dest) | |
1323 || FORWARDER_BLOCK_P (b1->dest) | |
1324 || FORWARDER_BLOCK_P (b2->dest)) | |
1325 return false; | |
1326 | |
1327 if (f1->dest == f2->dest && b1->dest == b2->dest) | |
1328 reverse = false; | |
1329 else if (f1->dest == b2->dest && b1->dest == f2->dest) | |
1330 reverse = true; | |
1331 else | |
1332 return false; | |
1333 | |
1334 set1 = pc_set (BB_END (bb1)); | |
1335 set2 = pc_set (BB_END (bb2)); | |
1336 if ((XEXP (SET_SRC (set1), 1) == pc_rtx) | |
1337 != (XEXP (SET_SRC (set2), 1) == pc_rtx)) | |
1338 reverse = !reverse; | |
1339 | |
1340 cond1 = XEXP (SET_SRC (set1), 0); | |
1341 cond2 = XEXP (SET_SRC (set2), 0); | |
1342 code1 = GET_CODE (cond1); | |
1343 if (reverse) | |
1344 code2 = reversed_comparison_code (cond2, BB_END (bb2)); | |
1345 else | |
1346 code2 = GET_CODE (cond2); | |
1347 | |
1348 if (code2 == UNKNOWN) | |
1349 return false; | |
1350 | |
1351 /* Verify codes and operands match. */ | |
1352 match = ((code1 == code2 | |
1353 && rtx_renumbered_equal_p (XEXP (cond1, 0), XEXP (cond2, 0)) | |
1354 && rtx_renumbered_equal_p (XEXP (cond1, 1), XEXP (cond2, 1))) | |
1355 || (code1 == swap_condition (code2) | |
1356 && rtx_renumbered_equal_p (XEXP (cond1, 1), | |
1357 XEXP (cond2, 0)) | |
1358 && rtx_renumbered_equal_p (XEXP (cond1, 0), | |
1359 XEXP (cond2, 1)))); | |
1360 | |
1361 /* If we return true, we will join the blocks. Which means that | |
1362 we will only have one branch prediction bit to work with. Thus | |
1363 we require the existing branches to have probabilities that are | |
1364 roughly similar. */ | |
1365 if (match | |
1366 && optimize_bb_for_speed_p (bb1) | |
1367 && optimize_bb_for_speed_p (bb2)) | |
1368 { | |
1369 int prob2; | |
1370 | |
1371 if (b1->dest == b2->dest) | |
1372 prob2 = b2->probability; | |
1373 else | |
1374 /* Do not use f2 probability as f2 may be forwarded. */ | |
1375 prob2 = REG_BR_PROB_BASE - b2->probability; | |
1376 | |
1377 /* Fail if the difference in probabilities is greater than 50%. | |
1378 This rules out two well-predicted branches with opposite | |
1379 outcomes. */ | |
1380 if (abs (b1->probability - prob2) > REG_BR_PROB_BASE / 2) | |
1381 { | |
1382 if (dump_file) | |
1383 fprintf (dump_file, | |
1384 "Outcomes of branch in bb %i and %i differ too much (%i %i)\n", | |
1385 bb1->index, bb2->index, b1->probability, prob2); | |
1386 | |
1387 return false; | |
1388 } | |
1389 } | |
1390 | |
1391 if (dump_file && match) | |
1392 fprintf (dump_file, "Conditionals in bb %i and %i match.\n", | |
1393 bb1->index, bb2->index); | |
1394 | |
1395 return match; | |
1396 } | |
1397 | |
1398 /* Generic case - we are seeing a computed jump, table jump or trapping | |
1399 instruction. */ | |
1400 | |
1401 /* Check whether there are tablejumps in the end of BB1 and BB2. | |
1402 Return true if they are identical. */ | |
1403 { | |
1404 rtx label1, label2; | |
1405 rtx table1, table2; | |
1406 | |
1407 if (tablejump_p (BB_END (bb1), &label1, &table1) | |
1408 && tablejump_p (BB_END (bb2), &label2, &table2) | |
1409 && GET_CODE (PATTERN (table1)) == GET_CODE (PATTERN (table2))) | |
1410 { | |
1411 /* The labels should never be the same rtx. If they really are same | |
1412 the jump tables are same too. So disable crossjumping of blocks BB1 | |
1413 and BB2 because when deleting the common insns in the end of BB1 | |
1414 by delete_basic_block () the jump table would be deleted too. */ | |
1415 /* If LABEL2 is referenced in BB1->END do not do anything | |
1416 because we would loose information when replacing | |
1417 LABEL1 by LABEL2 and then LABEL2 by LABEL1 in BB1->END. */ | |
1418 if (label1 != label2 && !rtx_referenced_p (label2, BB_END (bb1))) | |
1419 { | |
1420 /* Set IDENTICAL to true when the tables are identical. */ | |
1421 bool identical = false; | |
1422 rtx p1, p2; | |
1423 | |
1424 p1 = PATTERN (table1); | |
1425 p2 = PATTERN (table2); | |
1426 if (GET_CODE (p1) == ADDR_VEC && rtx_equal_p (p1, p2)) | |
1427 { | |
1428 identical = true; | |
1429 } | |
1430 else if (GET_CODE (p1) == ADDR_DIFF_VEC | |
1431 && (XVECLEN (p1, 1) == XVECLEN (p2, 1)) | |
1432 && rtx_equal_p (XEXP (p1, 2), XEXP (p2, 2)) | |
1433 && rtx_equal_p (XEXP (p1, 3), XEXP (p2, 3))) | |
1434 { | |
1435 int i; | |
1436 | |
1437 identical = true; | |
1438 for (i = XVECLEN (p1, 1) - 1; i >= 0 && identical; i--) | |
1439 if (!rtx_equal_p (XVECEXP (p1, 1, i), XVECEXP (p2, 1, i))) | |
1440 identical = false; | |
1441 } | |
1442 | |
1443 if (identical) | |
1444 { | |
1445 replace_label_data rr; | |
1446 bool match; | |
1447 | |
1448 /* Temporarily replace references to LABEL1 with LABEL2 | |
1449 in BB1->END so that we could compare the instructions. */ | |
1450 rr.r1 = label1; | |
1451 rr.r2 = label2; | |
1452 rr.update_label_nuses = false; | |
1453 for_each_rtx (&BB_END (bb1), replace_label, &rr); | |
1454 | |
1455 match = old_insns_match_p (mode, BB_END (bb1), BB_END (bb2)); | |
1456 if (dump_file && match) | |
1457 fprintf (dump_file, | |
1458 "Tablejumps in bb %i and %i match.\n", | |
1459 bb1->index, bb2->index); | |
1460 | |
1461 /* Set the original label in BB1->END because when deleting | |
1462 a block whose end is a tablejump, the tablejump referenced | |
1463 from the instruction is deleted too. */ | |
1464 rr.r1 = label2; | |
1465 rr.r2 = label1; | |
1466 for_each_rtx (&BB_END (bb1), replace_label, &rr); | |
1467 | |
1468 return match; | |
1469 } | |
1470 } | |
1471 return false; | |
1472 } | |
1473 } | |
1474 | |
1475 /* First ensure that the instructions match. There may be many outgoing | |
1476 edges so this test is generally cheaper. */ | |
1477 if (!old_insns_match_p (mode, BB_END (bb1), BB_END (bb2))) | |
1478 return false; | |
1479 | |
1480 /* Search the outgoing edges, ensure that the counts do match, find possible | |
1481 fallthru and exception handling edges since these needs more | |
1482 validation. */ | |
1483 if (EDGE_COUNT (bb1->succs) != EDGE_COUNT (bb2->succs)) | |
1484 return false; | |
1485 | |
1486 FOR_EACH_EDGE (e1, ei, bb1->succs) | |
1487 { | |
1488 e2 = EDGE_SUCC (bb2, ei.index); | |
1489 | |
1490 if (e1->flags & EDGE_EH) | |
1491 nehedges1++; | |
1492 | |
1493 if (e2->flags & EDGE_EH) | |
1494 nehedges2++; | |
1495 | |
1496 if (e1->flags & EDGE_FALLTHRU) | |
1497 fallthru1 = e1; | |
1498 if (e2->flags & EDGE_FALLTHRU) | |
1499 fallthru2 = e2; | |
1500 } | |
1501 | |
1502 /* If number of edges of various types does not match, fail. */ | |
1503 if (nehedges1 != nehedges2 | |
1504 || (fallthru1 != 0) != (fallthru2 != 0)) | |
1505 return false; | |
1506 | |
1507 /* fallthru edges must be forwarded to the same destination. */ | |
1508 if (fallthru1) | |
1509 { | |
1510 basic_block d1 = (forwarder_block_p (fallthru1->dest) | |
1511 ? single_succ (fallthru1->dest): fallthru1->dest); | |
1512 basic_block d2 = (forwarder_block_p (fallthru2->dest) | |
1513 ? single_succ (fallthru2->dest): fallthru2->dest); | |
1514 | |
1515 if (d1 != d2) | |
1516 return false; | |
1517 } | |
1518 | |
1519 /* Ensure the same EH region. */ | |
1520 { | |
1521 rtx n1 = find_reg_note (BB_END (bb1), REG_EH_REGION, 0); | |
1522 rtx n2 = find_reg_note (BB_END (bb2), REG_EH_REGION, 0); | |
1523 | |
1524 if (!n1 && n2) | |
1525 return false; | |
1526 | |
1527 if (n1 && (!n2 || XEXP (n1, 0) != XEXP (n2, 0))) | |
1528 return false; | |
1529 } | |
1530 | |
1531 /* The same checks as in try_crossjump_to_edge. It is required for RTL | |
1532 version of sequence abstraction. */ | |
1533 FOR_EACH_EDGE (e1, ei, bb2->succs) | |
1534 { | |
1535 edge e2; | |
1536 edge_iterator ei; | |
1537 basic_block d1 = e1->dest; | |
1538 | |
1539 if (FORWARDER_BLOCK_P (d1)) | |
1540 d1 = EDGE_SUCC (d1, 0)->dest; | |
1541 | |
1542 FOR_EACH_EDGE (e2, ei, bb1->succs) | |
1543 { | |
1544 basic_block d2 = e2->dest; | |
1545 if (FORWARDER_BLOCK_P (d2)) | |
1546 d2 = EDGE_SUCC (d2, 0)->dest; | |
1547 if (d1 == d2) | |
1548 break; | |
1549 } | |
1550 | |
1551 if (!e2) | |
1552 return false; | |
1553 } | |
1554 | |
1555 return true; | |
1556 } | |
1557 | |
1558 /* Returns true if BB basic block has a preserve label. */ | |
1559 | |
1560 static bool | |
1561 block_has_preserve_label (basic_block bb) | |
1562 { | |
1563 return (bb | |
1564 && block_label (bb) | |
1565 && LABEL_PRESERVE_P (block_label (bb))); | |
1566 } | |
1567 | |
1568 /* E1 and E2 are edges with the same destination block. Search their | |
1569 predecessors for common code. If found, redirect control flow from | |
1570 (maybe the middle of) E1->SRC to (maybe the middle of) E2->SRC. */ | |
1571 | |
1572 static bool | |
1573 try_crossjump_to_edge (int mode, edge e1, edge e2) | |
1574 { | |
1575 int nmatch; | |
1576 basic_block src1 = e1->src, src2 = e2->src; | |
1577 basic_block redirect_to, redirect_from, to_remove; | |
1578 rtx newpos1, newpos2; | |
1579 edge s; | |
1580 edge_iterator ei; | |
1581 | |
1582 newpos1 = newpos2 = NULL_RTX; | |
1583 | |
1584 /* If we have partitioned hot/cold basic blocks, it is a bad idea | |
1585 to try this optimization. | |
1586 | |
1587 Basic block partitioning may result in some jumps that appear to | |
1588 be optimizable (or blocks that appear to be mergeable), but which really | |
1589 must be left untouched (they are required to make it safely across | |
1590 partition boundaries). See the comments at the top of | |
1591 bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */ | |
1592 | |
1593 if (flag_reorder_blocks_and_partition && reload_completed) | |
1594 return false; | |
1595 | |
1596 /* Search backward through forwarder blocks. We don't need to worry | |
1597 about multiple entry or chained forwarders, as they will be optimized | |
1598 away. We do this to look past the unconditional jump following a | |
1599 conditional jump that is required due to the current CFG shape. */ | |
1600 if (single_pred_p (src1) | |
1601 && FORWARDER_BLOCK_P (src1)) | |
1602 e1 = single_pred_edge (src1), src1 = e1->src; | |
1603 | |
1604 if (single_pred_p (src2) | |
1605 && FORWARDER_BLOCK_P (src2)) | |
1606 e2 = single_pred_edge (src2), src2 = e2->src; | |
1607 | |
1608 /* Nothing to do if we reach ENTRY, or a common source block. */ | |
1609 if (src1 == ENTRY_BLOCK_PTR || src2 == ENTRY_BLOCK_PTR) | |
1610 return false; | |
1611 if (src1 == src2) | |
1612 return false; | |
1613 | |
1614 /* Seeing more than 1 forwarder blocks would confuse us later... */ | |
1615 if (FORWARDER_BLOCK_P (e1->dest) | |
1616 && FORWARDER_BLOCK_P (single_succ (e1->dest))) | |
1617 return false; | |
1618 | |
1619 if (FORWARDER_BLOCK_P (e2->dest) | |
1620 && FORWARDER_BLOCK_P (single_succ (e2->dest))) | |
1621 return false; | |
1622 | |
1623 /* Likewise with dead code (possibly newly created by the other optimizations | |
1624 of cfg_cleanup). */ | |
1625 if (EDGE_COUNT (src1->preds) == 0 || EDGE_COUNT (src2->preds) == 0) | |
1626 return false; | |
1627 | |
1628 /* Look for the common insn sequence, part the first ... */ | |
1629 if (!outgoing_edges_match (mode, src1, src2)) | |
1630 return false; | |
1631 | |
1632 /* ... and part the second. */ | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
1633 nmatch = flow_find_cross_jump (src1, src2, &newpos1, &newpos2); |
0 | 1634 |
1635 /* Don't proceed with the crossjump unless we found a sufficient number | |
1636 of matching instructions or the 'from' block was totally matched | |
1637 (such that its predecessors will hopefully be redirected and the | |
1638 block removed). */ | |
1639 if ((nmatch < PARAM_VALUE (PARAM_MIN_CROSSJUMP_INSNS)) | |
1640 && (newpos1 != BB_HEAD (src1))) | |
1641 return false; | |
1642 | |
1643 /* Avoid deleting preserve label when redirecting ABNORMAL edges. */ | |
1644 if (block_has_preserve_label (e1->dest) | |
1645 && (e1->flags & EDGE_ABNORMAL)) | |
1646 return false; | |
1647 | |
1648 /* Here we know that the insns in the end of SRC1 which are common with SRC2 | |
1649 will be deleted. | |
1650 If we have tablejumps in the end of SRC1 and SRC2 | |
1651 they have been already compared for equivalence in outgoing_edges_match () | |
1652 so replace the references to TABLE1 by references to TABLE2. */ | |
1653 { | |
1654 rtx label1, label2; | |
1655 rtx table1, table2; | |
1656 | |
1657 if (tablejump_p (BB_END (src1), &label1, &table1) | |
1658 && tablejump_p (BB_END (src2), &label2, &table2) | |
1659 && label1 != label2) | |
1660 { | |
1661 replace_label_data rr; | |
1662 rtx insn; | |
1663 | |
1664 /* Replace references to LABEL1 with LABEL2. */ | |
1665 rr.r1 = label1; | |
1666 rr.r2 = label2; | |
1667 rr.update_label_nuses = true; | |
1668 for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) | |
1669 { | |
1670 /* Do not replace the label in SRC1->END because when deleting | |
1671 a block whose end is a tablejump, the tablejump referenced | |
1672 from the instruction is deleted too. */ | |
1673 if (insn != BB_END (src1)) | |
1674 for_each_rtx (&insn, replace_label, &rr); | |
1675 } | |
1676 } | |
1677 } | |
1678 | |
1679 /* Avoid splitting if possible. We must always split when SRC2 has | |
1680 EH predecessor edges, or we may end up with basic blocks with both | |
1681 normal and EH predecessor edges. */ | |
1682 if (newpos2 == BB_HEAD (src2) | |
1683 && !(EDGE_PRED (src2, 0)->flags & EDGE_EH)) | |
1684 redirect_to = src2; | |
1685 else | |
1686 { | |
1687 if (newpos2 == BB_HEAD (src2)) | |
1688 { | |
1689 /* Skip possible basic block header. */ | |
1690 if (LABEL_P (newpos2)) | |
1691 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
|
1692 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
|
1693 newpos2 = NEXT_INSN (newpos2); |
0 | 1694 if (NOTE_P (newpos2)) |
1695 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
|
1696 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
|
1697 newpos2 = NEXT_INSN (newpos2); |
0 | 1698 } |
1699 | |
1700 if (dump_file) | |
1701 fprintf (dump_file, "Splitting bb %i before %i insns\n", | |
1702 src2->index, nmatch); | |
1703 redirect_to = split_block (src2, PREV_INSN (newpos2))->dest; | |
1704 } | |
1705 | |
1706 if (dump_file) | |
1707 fprintf (dump_file, | |
1708 "Cross jumping from bb %i to bb %i; %i common insns\n", | |
1709 src1->index, src2->index, nmatch); | |
1710 | |
1711 /* We may have some registers visible through the block. */ | |
1712 df_set_bb_dirty (redirect_to); | |
1713 | |
1714 /* Recompute the frequencies and counts of outgoing edges. */ | |
1715 FOR_EACH_EDGE (s, ei, redirect_to->succs) | |
1716 { | |
1717 edge s2; | |
1718 edge_iterator ei; | |
1719 basic_block d = s->dest; | |
1720 | |
1721 if (FORWARDER_BLOCK_P (d)) | |
1722 d = single_succ (d); | |
1723 | |
1724 FOR_EACH_EDGE (s2, ei, src1->succs) | |
1725 { | |
1726 basic_block d2 = s2->dest; | |
1727 if (FORWARDER_BLOCK_P (d2)) | |
1728 d2 = single_succ (d2); | |
1729 if (d == d2) | |
1730 break; | |
1731 } | |
1732 | |
1733 s->count += s2->count; | |
1734 | |
1735 /* Take care to update possible forwarder blocks. We verified | |
1736 that there is no more than one in the chain, so we can't run | |
1737 into infinite loop. */ | |
1738 if (FORWARDER_BLOCK_P (s->dest)) | |
1739 { | |
1740 single_succ_edge (s->dest)->count += s2->count; | |
1741 s->dest->count += s2->count; | |
1742 s->dest->frequency += EDGE_FREQUENCY (s); | |
1743 } | |
1744 | |
1745 if (FORWARDER_BLOCK_P (s2->dest)) | |
1746 { | |
1747 single_succ_edge (s2->dest)->count -= s2->count; | |
1748 if (single_succ_edge (s2->dest)->count < 0) | |
1749 single_succ_edge (s2->dest)->count = 0; | |
1750 s2->dest->count -= s2->count; | |
1751 s2->dest->frequency -= EDGE_FREQUENCY (s); | |
1752 if (s2->dest->frequency < 0) | |
1753 s2->dest->frequency = 0; | |
1754 if (s2->dest->count < 0) | |
1755 s2->dest->count = 0; | |
1756 } | |
1757 | |
1758 if (!redirect_to->frequency && !src1->frequency) | |
1759 s->probability = (s->probability + s2->probability) / 2; | |
1760 else | |
1761 s->probability | |
1762 = ((s->probability * redirect_to->frequency + | |
1763 s2->probability * src1->frequency) | |
1764 / (redirect_to->frequency + src1->frequency)); | |
1765 } | |
1766 | |
1767 /* Adjust count and frequency for the block. An earlier jump | |
1768 threading pass may have left the profile in an inconsistent | |
1769 state (see update_bb_profile_for_threading) so we must be | |
1770 prepared for overflows. */ | |
1771 redirect_to->count += src1->count; | |
1772 redirect_to->frequency += src1->frequency; | |
1773 if (redirect_to->frequency > BB_FREQ_MAX) | |
1774 redirect_to->frequency = BB_FREQ_MAX; | |
1775 update_br_prob_note (redirect_to); | |
1776 | |
1777 /* Edit SRC1 to go to REDIRECT_TO at NEWPOS1. */ | |
1778 | |
1779 /* Skip possible basic block header. */ | |
1780 if (LABEL_P (newpos1)) | |
1781 newpos1 = NEXT_INSN (newpos1); | |
1782 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1783 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
|
1784 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
|
1785 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1786 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
|
1787 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
|
1788 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1789 while (DEBUG_INSN_P (newpos1)) |
0 | 1790 newpos1 = NEXT_INSN (newpos1); |
1791 | |
1792 redirect_from = split_block (src1, PREV_INSN (newpos1))->src; | |
1793 to_remove = single_succ (redirect_from); | |
1794 | |
1795 redirect_edge_and_branch_force (single_succ_edge (redirect_from), redirect_to); | |
1796 delete_basic_block (to_remove); | |
1797 | |
1798 update_forwarder_flag (redirect_from); | |
1799 if (redirect_to != src2) | |
1800 update_forwarder_flag (src2); | |
1801 | |
1802 return true; | |
1803 } | |
1804 | |
1805 /* Search the predecessors of BB for common insn sequences. When found, | |
1806 share code between them by redirecting control flow. Return true if | |
1807 any changes made. */ | |
1808 | |
1809 static bool | |
1810 try_crossjump_bb (int mode, basic_block bb) | |
1811 { | |
1812 edge e, e2, fallthru; | |
1813 bool changed; | |
1814 unsigned max, ix, ix2; | |
1815 basic_block ev, ev2; | |
1816 | |
1817 /* Nothing to do if there is not at least two incoming edges. */ | |
1818 if (EDGE_COUNT (bb->preds) < 2) | |
1819 return false; | |
1820 | |
1821 /* Don't crossjump if this block ends in a computed jump, | |
1822 unless we are optimizing for size. */ | |
1823 if (optimize_bb_for_size_p (bb) | |
1824 && bb != EXIT_BLOCK_PTR | |
1825 && computed_jump_p (BB_END (bb))) | |
1826 return false; | |
1827 | |
1828 /* If we are partitioning hot/cold basic blocks, we don't want to | |
1829 mess up unconditional or indirect jumps that cross between hot | |
1830 and cold sections. | |
1831 | |
1832 Basic block partitioning may result in some jumps that appear to | |
1833 be optimizable (or blocks that appear to be mergeable), but which really | |
1834 must be left untouched (they are required to make it safely across | |
1835 partition boundaries). See the comments at the top of | |
1836 bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */ | |
1837 | |
1838 if (BB_PARTITION (EDGE_PRED (bb, 0)->src) != | |
1839 BB_PARTITION (EDGE_PRED (bb, 1)->src) | |
1840 || (EDGE_PRED (bb, 0)->flags & EDGE_CROSSING)) | |
1841 return false; | |
1842 | |
1843 /* It is always cheapest to redirect a block that ends in a branch to | |
1844 a block that falls through into BB, as that adds no branches to the | |
1845 program. We'll try that combination first. */ | |
1846 fallthru = NULL; | |
1847 max = PARAM_VALUE (PARAM_MAX_CROSSJUMP_EDGES); | |
1848 | |
1849 if (EDGE_COUNT (bb->preds) > max) | |
1850 return false; | |
1851 | |
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
|
1852 fallthru = find_fallthru_edge (bb->preds); |
0 | 1853 |
1854 changed = false; | |
1855 for (ix = 0, ev = bb; ix < EDGE_COUNT (ev->preds); ) | |
1856 { | |
1857 e = EDGE_PRED (ev, ix); | |
1858 ix++; | |
1859 | |
1860 /* As noted above, first try with the fallthru predecessor (or, a | |
1861 fallthru predecessor if we are in cfglayout mode). */ | |
1862 if (fallthru) | |
1863 { | |
1864 /* Don't combine the fallthru edge into anything else. | |
1865 If there is a match, we'll do it the other way around. */ | |
1866 if (e == fallthru) | |
1867 continue; | |
1868 /* If nothing changed since the last attempt, there is nothing | |
1869 we can do. */ | |
1870 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
|
1871 && !((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
|
1872 || (fallthru->src->flags & BB_MODIFIED))) |
0 | 1873 continue; |
1874 | |
1875 if (try_crossjump_to_edge (mode, e, fallthru)) | |
1876 { | |
1877 changed = true; | |
1878 ix = 0; | |
1879 ev = bb; | |
1880 continue; | |
1881 } | |
1882 } | |
1883 | |
1884 /* Non-obvious work limiting check: Recognize that we're going | |
1885 to call try_crossjump_bb on every basic block. So if we have | |
1886 two blocks with lots of outgoing edges (a switch) and they | |
1887 share lots of common destinations, then we would do the | |
1888 cross-jump check once for each common destination. | |
1889 | |
1890 Now, if the blocks actually are cross-jump candidates, then | |
1891 all of their destinations will be shared. Which means that | |
1892 we only need check them for cross-jump candidacy once. We | |
1893 can eliminate redundant checks of crossjump(A,B) by arbitrarily | |
1894 choosing to do the check from the block for which the edge | |
1895 in question is the first successor of A. */ | |
1896 if (EDGE_SUCC (e->src, 0) != e) | |
1897 continue; | |
1898 | |
1899 for (ix2 = 0, ev2 = bb; ix2 < EDGE_COUNT (ev2->preds); ) | |
1900 { | |
1901 e2 = EDGE_PRED (ev2, ix2); | |
1902 ix2++; | |
1903 | |
1904 if (e2 == e) | |
1905 continue; | |
1906 | |
1907 /* We've already checked the fallthru edge above. */ | |
1908 if (e2 == fallthru) | |
1909 continue; | |
1910 | |
1911 /* The "first successor" check above only prevents multiple | |
1912 checks of crossjump(A,B). In order to prevent redundant | |
1913 checks of crossjump(B,A), require that A be the block | |
1914 with the lowest index. */ | |
1915 if (e->src->index > e2->src->index) | |
1916 continue; | |
1917 | |
1918 /* If nothing changed since the last attempt, there is nothing | |
1919 we can do. */ | |
1920 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
|
1921 && !((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
|
1922 || (e2->src->flags & BB_MODIFIED))) |
0 | 1923 continue; |
1924 | |
1925 if (try_crossjump_to_edge (mode, e, e2)) | |
1926 { | |
1927 changed = true; | |
1928 ev2 = bb; | |
1929 ix = 0; | |
1930 break; | |
1931 } | |
1932 } | |
1933 } | |
1934 | |
1935 if (changed) | |
1936 crossjumps_occured = true; | |
1937 | |
1938 return changed; | |
1939 } | |
1940 | |
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
|
1941 /* 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
|
1942 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
|
1943 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
|
1944 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1945 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
|
1946 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
|
1947 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1948 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
|
1949 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
|
1950 edge e0; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1951 rtx *headptr, *currptr, *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
|
1952 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
|
1953 unsigned 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
|
1954 rtx e0_last_head, cond, 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
|
1955 unsigned nedges = EDGE_COUNT (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
|
1956 rtx jump = 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
|
1957 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
|
1958 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1959 /* 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
|
1960 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
|
1961 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
|
1962 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1963 /* 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
|
1964 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
|
1965 if (optimize_bb_for_size_p (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
|
1966 && bb != EXIT_BLOCK_PTR |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1967 && 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
|
1968 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
|
1969 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1970 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
|
1971 if (cond == 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
|
1972 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
|
1973 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1974 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
|
1975 if (EDGE_SUCC (bb, ix)->dest == EXIT_BLOCK_PTR) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1976 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
|
1977 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1978 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
|
1979 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1980 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
|
1981 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
|
1982 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1983 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
|
1984 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1985 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
|
1986 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
|
1987 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1988 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1989 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
|
1990 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
|
1991 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1992 /* 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
|
1993 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
|
1994 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
1995 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
|
1996 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
|
1997 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
|
1998 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
|
1999 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
|
2000 .... |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2001 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
|
2002 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
|
2003 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
|
2004 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
|
2005 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
|
2006 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
|
2007 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2008 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
|
2009 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
|
2010 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
|
2011 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2012 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
|
2013 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
|
2014 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2015 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
|
2016 || 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
|
2017 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
|
2018 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2019 /* 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
|
2020 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
|
2021 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
|
2022 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
|
2023 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2024 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
|
2025 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
|
2026 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
|
2027 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
|
2028 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
|
2029 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
|
2030 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
|
2031 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
|
2032 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
|
2033 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
|
2034 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
|
2035 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2036 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2037 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2038 e0 = EDGE_SUCC (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
|
2039 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
|
2040 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
|
2041 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2042 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
|
2043 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2044 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
|
2045 rtx e0_last, e_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
|
2046 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
|
2047 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2048 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
|
2049 &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
|
2050 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
|
2051 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
|
2052 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2053 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
|
2054 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2055 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
|
2056 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
|
2057 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2058 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2059 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2060 /* 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
|
2061 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
|
2062 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
|
2063 && 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
|
2064 && (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
|
2065 || 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
|
2066 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2067 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
|
2068 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
|
2069 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
|
2070 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
|
2071 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
|
2072 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
|
2073 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2074 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2075 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
|
2076 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
|
2077 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2078 /* 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
|
2079 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
|
2080 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
|
2081 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2082 currptr = XNEWVEC (rtx, nedges); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2083 headptr = XNEWVEC (rtx, nedges); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2084 nextptr = XNEWVEC (rtx, nedges); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2085 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2086 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
|
2087 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2088 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
|
2089 basic_block merge_bb = 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
|
2090 rtx head = BB_HEAD (merge_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
|
2091 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2092 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
|
2093 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
|
2094 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
|
2095 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
|
2096 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2097 /* 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
|
2098 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
|
2099 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
|
2100 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
|
2101 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
|
2102 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
|
2103 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
|
2104 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2105 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2106 /* 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
|
2107 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
|
2108 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
|
2109 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
|
2110 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2111 rtx 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
|
2112 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2113 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
|
2114 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
|
2115 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
|
2116 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
|
2117 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2118 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
|
2119 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
|
2120 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2121 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
|
2122 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2123 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
|
2124 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
|
2125 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
|
2126 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2127 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2128 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
|
2129 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
|
2130 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2131 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
|
2132 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
|
2133 if (cond == 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
|
2134 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
|
2135 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2136 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2137 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
|
2138 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2139 rtx 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
|
2140 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
|
2141 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
|
2142 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
|
2143 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
|
2144 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2145 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
|
2146 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
|
2147 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2148 /* 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
|
2149 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
|
2150 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2151 #ifdef HAVE_cc0 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2152 /* 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
|
2153 the cc0. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2154 if (reg_mentioned_p (cc0_rtx, 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
|
2155 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
|
2156 #endif |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2157 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2158 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
|
2159 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2160 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2161 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
|
2162 /* 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
|
2163 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
|
2164 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
|
2165 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2166 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
|
2167 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
|
2168 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2169 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
|
2170 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
|
2171 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
|
2172 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2173 rtx curr = currptr[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
|
2174 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
|
2175 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
|
2176 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
|
2177 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
|
2178 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2179 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2180 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2181 /* 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
|
2182 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
|
2183 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
|
2184 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
|
2185 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2186 rtx curr = currptr[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
|
2187 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
|
2188 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
|
2189 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
|
2190 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
|
2191 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2192 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2193 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
|
2194 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
|
2195 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
|
2196 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
|
2197 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
|
2198 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
|
2199 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2200 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
|
2201 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
|
2202 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2203 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
|
2204 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2205 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
|
2206 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
|
2207 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2208 /* 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
|
2209 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
|
2210 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2211 #ifdef HAVE_cc0 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2212 /* 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
|
2213 the cc0. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2214 if (reg_mentioned_p (cc0_rtx, 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
|
2215 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
|
2216 #endif |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2217 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2218 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
|
2219 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
|
2220 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2221 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2222 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
|
2223 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2224 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
|
2225 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
|
2226 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
|
2227 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
|
2228 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2229 crossjumps_occured |= 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
|
2230 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2231 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
|
2232 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
63
diff
changeset
|
2233 |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2234 /* 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
|
2235 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
|
2236 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2237 static bool |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2238 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
|
2239 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2240 rtx insn = BB_END (bb); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2241 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2242 while (1) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2243 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2244 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
|
2245 return true; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2246 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
|
2247 return false; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2248 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
|
2249 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2250 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2251 |
0 | 2252 /* Do simple CFG optimizations - basic block merging, simplifying of jump |
2253 instructions etc. Return nonzero if changes were made. */ | |
2254 | |
2255 static bool | |
2256 try_optimize_cfg (int mode) | |
2257 { | |
2258 bool changed_overall = false; | |
2259 bool changed; | |
2260 int iterations = 0; | |
2261 basic_block bb, b, next; | |
2262 | |
2263 if (mode & (CLEANUP_CROSSJUMP | CLEANUP_THREADING)) | |
2264 clear_bb_flags (); | |
2265 | |
2266 crossjumps_occured = false; | |
2267 | |
2268 FOR_EACH_BB (bb) | |
2269 update_forwarder_flag (bb); | |
2270 | |
2271 if (! targetm.cannot_modify_jumps_p ()) | |
2272 { | |
2273 first_pass = true; | |
2274 /* Attempt to merge blocks as made possible by edge removal. If | |
2275 a block has only one successor, and the successor has only | |
2276 one predecessor, they may be combined. */ | |
2277 do | |
2278 { | |
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
|
2279 block_was_dirty = false; |
0 | 2280 changed = false; |
2281 iterations++; | |
2282 | |
2283 if (dump_file) | |
2284 fprintf (dump_file, | |
2285 "\n\ntry_optimize_cfg iteration %i\n\n", | |
2286 iterations); | |
2287 | |
2288 for (b = ENTRY_BLOCK_PTR->next_bb; b != EXIT_BLOCK_PTR;) | |
2289 { | |
2290 basic_block c; | |
2291 edge s; | |
2292 bool changed_here = false; | |
2293 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2294 /* 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
|
2295 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
|
2296 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
|
2297 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
|
2298 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
|
2299 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
|
2300 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
|
2301 __builtin_unreachable (). */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2302 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
|
2303 || (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
|
2304 && trivially_empty_bb_p (b) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2305 && single_succ_edge (ENTRY_BLOCK_PTR)->dest != b)) |
0 | 2306 { |
2307 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
|
2308 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
|
2309 { |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2310 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
|
2311 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
|
2312 |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2313 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
|
2314 { |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2315 if (b->il.rtl->footer |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2316 && BARRIER_P (b->il.rtl->footer)) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2317 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
|
2318 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
|
2319 && e->src->il.rtl->footer == NULL) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2320 { |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2321 if (b->il.rtl->footer) |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2322 { |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2323 e->src->il.rtl->footer = b->il.rtl->footer; |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2324 b->il.rtl->footer = NULL; |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2325 } |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2326 else |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2327 { |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2328 start_sequence (); |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2329 e->src->il.rtl->footer = emit_barrier (); |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2330 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
|
2331 } |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2332 } |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2333 } |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2334 else |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2335 { |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2336 rtx last = get_last_bb_insn (b); |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2337 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
|
2338 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
|
2339 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
|
2340 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
|
2341 } |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
2342 } |
0 | 2343 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
|
2344 changed = true; |
0 | 2345 /* Avoid trying to remove ENTRY_BLOCK_PTR. */ |
2346 b = (c == ENTRY_BLOCK_PTR ? c->next_bb : c); | |
2347 continue; | |
2348 } | |
2349 | |
2350 /* Remove code labels no longer used. */ | |
2351 if (single_pred_p (b) | |
2352 && (single_pred_edge (b)->flags & EDGE_FALLTHRU) | |
2353 && !(single_pred_edge (b)->flags & EDGE_COMPLEX) | |
2354 && LABEL_P (BB_HEAD (b)) | |
2355 /* If the previous block ends with a branch to this | |
2356 block, we can't delete the label. Normally this | |
2357 is a condjump that is yet to be simplified, but | |
2358 if CASE_DROPS_THRU, this can be a tablejump with | |
2359 some element going to the same place as the | |
2360 default (fallthru). */ | |
2361 && (single_pred (b) == ENTRY_BLOCK_PTR | |
2362 || !JUMP_P (BB_END (single_pred (b))) | |
2363 || ! label_is_jump_target_p (BB_HEAD (b), | |
2364 BB_END (single_pred (b))))) | |
2365 { | |
2366 rtx label = BB_HEAD (b); | |
2367 | |
2368 delete_insn_chain (label, label, false); | |
2369 /* If the case label is undeletable, move it after the | |
2370 BASIC_BLOCK note. */ | |
2371 if (NOTE_KIND (BB_HEAD (b)) == NOTE_INSN_DELETED_LABEL) | |
2372 { | |
2373 rtx bb_note = NEXT_INSN (BB_HEAD (b)); | |
2374 | |
2375 reorder_insns_nobb (label, label, bb_note); | |
2376 BB_HEAD (b) = bb_note; | |
2377 if (BB_END (b) == bb_note) | |
2378 BB_END (b) = label; | |
2379 } | |
2380 if (dump_file) | |
2381 fprintf (dump_file, "Deleted label in block %i.\n", | |
2382 b->index); | |
2383 } | |
2384 | |
2385 /* If we fall through an empty block, we can remove it. */ | |
2386 if (!(mode & CLEANUP_CFGLAYOUT) | |
2387 && single_pred_p (b) | |
2388 && (single_pred_edge (b)->flags & EDGE_FALLTHRU) | |
2389 && !LABEL_P (BB_HEAD (b)) | |
2390 && FORWARDER_BLOCK_P (b) | |
2391 /* Note that forwarder_block_p true ensures that | |
2392 there is a successor for this block. */ | |
2393 && (single_succ_edge (b)->flags & EDGE_FALLTHRU) | |
2394 && n_basic_blocks > NUM_FIXED_BLOCKS + 1) | |
2395 { | |
2396 if (dump_file) | |
2397 fprintf (dump_file, | |
2398 "Deleting fallthru block %i.\n", | |
2399 b->index); | |
2400 | |
2401 c = b->prev_bb == ENTRY_BLOCK_PTR ? b->next_bb : b->prev_bb; | |
2402 redirect_edge_succ_nodup (single_pred_edge (b), | |
2403 single_succ (b)); | |
2404 delete_basic_block (b); | |
2405 changed = true; | |
2406 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
|
2407 continue; |
0 | 2408 } |
2409 | |
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
|
2410 /* Merge B with its single successor, if any. */ |
0 | 2411 if (single_succ_p (b) |
2412 && (s = single_succ_edge (b)) | |
2413 && !(s->flags & EDGE_COMPLEX) | |
2414 && (c = s->dest) != EXIT_BLOCK_PTR | |
2415 && single_pred_p (c) | |
2416 && b != c) | |
2417 { | |
2418 /* When not in cfg_layout mode use code aware of reordering | |
2419 INSN. This code possibly creates new basic blocks so it | |
2420 does not fit merge_blocks interface and is kept here in | |
2421 hope that it will become useless once more of compiler | |
2422 is transformed to use cfg_layout mode. */ | |
2423 | |
2424 if ((mode & CLEANUP_CFGLAYOUT) | |
2425 && can_merge_blocks_p (b, c)) | |
2426 { | |
2427 merge_blocks (b, c); | |
2428 update_forwarder_flag (b); | |
2429 changed_here = true; | |
2430 } | |
2431 else if (!(mode & CLEANUP_CFGLAYOUT) | |
2432 /* If the jump insn has side effects, | |
2433 we can't kill the edge. */ | |
2434 && (!JUMP_P (BB_END (b)) | |
2435 || (reload_completed | |
2436 ? simplejump_p (BB_END (b)) | |
2437 : (onlyjump_p (BB_END (b)) | |
2438 && !tablejump_p (BB_END (b), | |
2439 NULL, NULL)))) | |
2440 && (next = merge_blocks_move (s, b, c, mode))) | |
2441 { | |
2442 b = next; | |
2443 changed_here = true; | |
2444 } | |
2445 } | |
2446 | |
2447 /* Simplify branch over branch. */ | |
2448 if ((mode & CLEANUP_EXPENSIVE) | |
2449 && !(mode & CLEANUP_CFGLAYOUT) | |
2450 && try_simplify_condjump (b)) | |
2451 changed_here = true; | |
2452 | |
2453 /* If B has a single outgoing edge, but uses a | |
2454 non-trivial jump instruction without side-effects, we | |
2455 can either delete the jump entirely, or replace it | |
2456 with a simple unconditional jump. */ | |
2457 if (single_succ_p (b) | |
2458 && single_succ (b) != EXIT_BLOCK_PTR | |
2459 && onlyjump_p (BB_END (b)) | |
2460 && !find_reg_note (BB_END (b), REG_CROSSING_JUMP, NULL_RTX) | |
2461 && try_redirect_by_replacing_jump (single_succ_edge (b), | |
2462 single_succ (b), | |
2463 (mode & CLEANUP_CFGLAYOUT) != 0)) | |
2464 { | |
2465 update_forwarder_flag (b); | |
2466 changed_here = true; | |
2467 } | |
2468 | |
2469 /* Simplify branch to branch. */ | |
2470 if (try_forward_edges (mode, b)) | |
2471 changed_here = true; | |
2472 | |
2473 /* Look for shared code between blocks. */ | |
2474 if ((mode & CLEANUP_CROSSJUMP) | |
2475 && try_crossjump_bb (mode, b)) | |
2476 changed_here = true; | |
2477 | |
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
|
2478 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
|
2479 /* 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
|
2480 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
|
2481 && 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
|
2482 && 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
|
2483 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
|
2484 |
0 | 2485 /* Don't get confused by the index shift caused by |
2486 deleting blocks. */ | |
2487 if (!changed_here) | |
2488 b = b->next_bb; | |
2489 else | |
2490 changed = true; | |
2491 } | |
2492 | |
2493 if ((mode & CLEANUP_CROSSJUMP) | |
2494 && try_crossjump_bb (mode, EXIT_BLOCK_PTR)) | |
2495 changed = true; | |
2496 | |
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
|
2497 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
|
2498 { |
f6334be47118
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 /* 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
|
2500 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
|
2501 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
|
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 |
0 | 2504 #ifdef ENABLE_CHECKING |
2505 if (changed) | |
2506 verify_flow_info (); | |
2507 #endif | |
2508 | |
2509 changed_overall |= changed; | |
2510 first_pass = false; | |
2511 } | |
2512 while (changed); | |
2513 } | |
2514 | |
2515 FOR_ALL_BB (b) | |
2516 b->flags &= ~(BB_FORWARDER_BLOCK | BB_NONTHREADABLE_BLOCK); | |
2517 | |
2518 return changed_overall; | |
2519 } | |
2520 | |
2521 /* Delete all unreachable basic blocks. */ | |
2522 | |
2523 bool | |
2524 delete_unreachable_blocks (void) | |
2525 { | |
2526 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
|
2527 basic_block b, prev_bb; |
0 | 2528 |
2529 find_unreachable_blocks (); | |
2530 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2531 /* 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
|
2532 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
|
2533 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
|
2534 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
|
2535 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
|
2536 otherwise. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2537 if (MAY_HAVE_DEBUG_STMTS && current_ir_type () == IR_GIMPLE |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2538 && dom_info_available_p (CDI_DOMINATORS)) |
0 | 2539 { |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2540 for (b = EXIT_BLOCK_PTR->prev_bb; b != ENTRY_BLOCK_PTR; 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
|
2541 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2542 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
|
2543 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2544 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
|
2545 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2546 /* 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
|
2547 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
|
2548 case. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2549 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
|
2550 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
|
2551 else |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2552 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2553 VEC (basic_block, heap) *h |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2554 = 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
|
2555 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2556 while (VEC_length (basic_block, h)) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2557 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2558 b = VEC_pop (basic_block, h); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2559 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2560 prev_bb = b->prev_bb; |
0 | 2561 |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2562 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
|
2563 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2564 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
|
2565 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2566 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2567 VEC_free (basic_block, heap, h); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2568 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2569 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2570 changed = true; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2571 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2572 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2573 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2574 else |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2575 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2576 for (b = EXIT_BLOCK_PTR->prev_bb; b != ENTRY_BLOCK_PTR; b = prev_bb) |
0 | 2577 { |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2578 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
|
2579 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2580 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
|
2581 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2582 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
|
2583 changed = true; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2584 } |
0 | 2585 } |
2586 } | |
2587 | |
2588 if (changed) | |
2589 tidy_fallthru_edges (); | |
2590 return changed; | |
2591 } | |
2592 | |
2593 /* Delete any jump tables never referenced. We can't delete them at the | |
2594 time of removing tablejump insn as they are referenced by the preceding | |
2595 insns computing the destination, so we delay deleting and garbagecollect | |
2596 them once life information is computed. */ | |
2597 void | |
2598 delete_dead_jumptables (void) | |
2599 { | |
2600 basic_block bb; | |
2601 | |
2602 /* A dead jump table does not belong to any basic block. Scan insns | |
2603 between two adjacent basic blocks. */ | |
2604 FOR_EACH_BB (bb) | |
2605 { | |
2606 rtx insn, next; | |
2607 | |
2608 for (insn = NEXT_INSN (BB_END (bb)); | |
2609 insn && !NOTE_INSN_BASIC_BLOCK_P (insn); | |
2610 insn = next) | |
2611 { | |
2612 next = NEXT_INSN (insn); | |
2613 if (LABEL_P (insn) | |
2614 && 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
|
2615 && JUMP_TABLE_DATA_P (next)) |
0 | 2616 { |
2617 rtx label = insn, jump = next; | |
2618 | |
2619 if (dump_file) | |
2620 fprintf (dump_file, "Dead jumptable %i removed\n", | |
2621 INSN_UID (insn)); | |
2622 | |
2623 next = NEXT_INSN (next); | |
2624 delete_insn (jump); | |
2625 delete_insn (label); | |
2626 } | |
2627 } | |
2628 } | |
2629 } | |
2630 | |
2631 | |
2632 /* Tidy the CFG by deleting unreachable code and whatnot. */ | |
2633 | |
2634 bool | |
2635 cleanup_cfg (int mode) | |
2636 { | |
2637 bool changed = false; | |
2638 | |
2639 /* Set the cfglayout mode flag here. We could update all the callers | |
2640 but that is just inconvenient, especially given that we eventually | |
2641 want to have cfglayout mode as the default. */ | |
2642 if (current_ir_type () == IR_RTL_CFGLAYOUT) | |
2643 mode |= CLEANUP_CFGLAYOUT; | |
2644 | |
2645 timevar_push (TV_CLEANUP_CFG); | |
2646 if (delete_unreachable_blocks ()) | |
2647 { | |
2648 changed = true; | |
2649 /* We've possibly created trivially dead code. Cleanup it right | |
2650 now to introduce more opportunities for try_optimize_cfg. */ | |
2651 if (!(mode & (CLEANUP_NO_INSN_DEL)) | |
2652 && !reload_completed) | |
2653 delete_trivially_dead_insns (get_insns (), max_reg_num ()); | |
2654 } | |
2655 | |
2656 compact_blocks (); | |
2657 | |
2658 /* To tail-merge blocks ending in the same noreturn function (e.g. | |
2659 a call to abort) we have to insert fake edges to exit. Do this | |
2660 here once. The fake edges do not interfere with any other CFG | |
2661 cleanups. */ | |
2662 if (mode & CLEANUP_CROSSJUMP) | |
2663 add_noreturn_fake_exit_edges (); | |
2664 | |
2665 if (!dbg_cnt (cfg_cleanup)) | |
2666 return changed; | |
2667 | |
2668 while (try_optimize_cfg (mode)) | |
2669 { | |
2670 delete_unreachable_blocks (), changed = true; | |
2671 if (!(mode & CLEANUP_NO_INSN_DEL)) | |
2672 { | |
2673 /* Try to remove some trivially dead insns when doing an expensive | |
2674 cleanup. But delete_trivially_dead_insns doesn't work after | |
2675 reload (it only handles pseudos) and run_fast_dce is too costly | |
2676 to run in every iteration. | |
2677 | |
2678 For effective cross jumping, we really want to run a fast DCE to | |
2679 clean up any dead conditions, or they get in the way of performing | |
2680 useful tail merges. | |
2681 | |
2682 Other transformations in cleanup_cfg are not so sensitive to dead | |
2683 code, so delete_trivially_dead_insns or even doing nothing at all | |
2684 is good enough. */ | |
2685 if ((mode & CLEANUP_EXPENSIVE) && !reload_completed | |
2686 && !delete_trivially_dead_insns (get_insns (), max_reg_num ())) | |
2687 break; | |
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
|
2688 if ((mode & CLEANUP_CROSSJUMP) && crossjumps_occured) |
0 | 2689 run_fast_dce (); |
2690 } | |
2691 else | |
2692 break; | |
2693 } | |
2694 | |
2695 if (mode & CLEANUP_CROSSJUMP) | |
2696 remove_fake_exit_edges (); | |
2697 | |
2698 /* Don't call delete_dead_jumptables in cfglayout mode, because | |
2699 that function assumes that jump tables are in the insns stream. | |
2700 But we also don't _have_ to delete dead jumptables in cfglayout | |
2701 mode because we shouldn't even be looking at things that are | |
2702 not in a basic block. Dead jumptables are cleaned up when | |
2703 going out of cfglayout mode. */ | |
2704 if (!(mode & CLEANUP_CFGLAYOUT)) | |
2705 delete_dead_jumptables (); | |
2706 | |
2707 timevar_pop (TV_CLEANUP_CFG); | |
2708 | |
2709 return changed; | |
2710 } | |
2711 | |
2712 static unsigned int | |
2713 rest_of_handle_jump (void) | |
2714 { | |
2715 if (crtl->tail_call_emit) | |
2716 fixup_tail_calls (); | |
2717 return 0; | |
2718 } | |
2719 | |
2720 struct rtl_opt_pass pass_jump = | |
2721 { | |
2722 { | |
2723 RTL_PASS, | |
2724 "sibling", /* name */ | |
2725 NULL, /* gate */ | |
2726 rest_of_handle_jump, /* execute */ | |
2727 NULL, /* sub */ | |
2728 NULL, /* next */ | |
2729 0, /* static_pass_number */ | |
2730 TV_JUMP, /* tv_id */ | |
2731 0, /* properties_required */ | |
2732 0, /* properties_provided */ | |
2733 0, /* properties_destroyed */ | |
2734 TODO_ggc_collect, /* todo_flags_start */ | |
2735 TODO_verify_flow, /* todo_flags_finish */ | |
2736 } | |
2737 }; | |
2738 | |
2739 | |
2740 static unsigned int | |
2741 rest_of_handle_jump2 (void) | |
2742 { | |
2743 delete_trivially_dead_insns (get_insns (), max_reg_num ()); | |
2744 if (dump_file) | |
2745 dump_flow_info (dump_file, dump_flags); | |
2746 cleanup_cfg ((optimize ? CLEANUP_EXPENSIVE : 0) | |
2747 | (flag_thread_jumps ? CLEANUP_THREADING : 0)); | |
2748 return 0; | |
2749 } | |
2750 | |
2751 | |
2752 struct rtl_opt_pass pass_jump2 = | |
2753 { | |
2754 { | |
2755 RTL_PASS, | |
2756 "jump", /* name */ | |
2757 NULL, /* gate */ | |
2758 rest_of_handle_jump2, /* execute */ | |
2759 NULL, /* sub */ | |
2760 NULL, /* next */ | |
2761 0, /* static_pass_number */ | |
2762 TV_JUMP, /* tv_id */ | |
2763 0, /* properties_required */ | |
2764 0, /* properties_provided */ | |
2765 0, /* properties_destroyed */ | |
2766 TODO_ggc_collect, /* todo_flags_start */ | |
2767 TODO_dump_func | TODO_verify_rtl_sharing,/* todo_flags_finish */ | |
2768 } | |
2769 }; | |
2770 | |
2771 |