Mercurial > hg > CbC > CbC_gcc
comparison gcc/ifcvt.c @ 0:a06113de4d67
first commit
author | kent <kent@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 17 Jul 2009 14:47:48 +0900 |
parents | |
children | 3bfb6c00c1e0 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:a06113de4d67 |
---|---|
1 /* If-conversion support. | |
2 Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 | |
3 Free Software Foundation, Inc. | |
4 | |
5 This file is part of GCC. | |
6 | |
7 GCC is free software; you can redistribute it and/or modify it | |
8 under the terms of the GNU General Public License as published by | |
9 the Free Software Foundation; either version 3, or (at your option) | |
10 any later version. | |
11 | |
12 GCC is distributed in the hope that it will be useful, but WITHOUT | |
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public | |
15 License for more details. | |
16 | |
17 You should have received a copy of the GNU General Public License | |
18 along with GCC; see the file COPYING3. If not see | |
19 <http://www.gnu.org/licenses/>. */ | |
20 | |
21 #include "config.h" | |
22 #include "system.h" | |
23 #include "coretypes.h" | |
24 #include "tm.h" | |
25 | |
26 #include "rtl.h" | |
27 #include "regs.h" | |
28 #include "function.h" | |
29 #include "flags.h" | |
30 #include "insn-config.h" | |
31 #include "recog.h" | |
32 #include "except.h" | |
33 #include "hard-reg-set.h" | |
34 #include "basic-block.h" | |
35 #include "expr.h" | |
36 #include "real.h" | |
37 #include "output.h" | |
38 #include "optabs.h" | |
39 #include "toplev.h" | |
40 #include "tm_p.h" | |
41 #include "cfgloop.h" | |
42 #include "target.h" | |
43 #include "timevar.h" | |
44 #include "tree-pass.h" | |
45 #include "df.h" | |
46 #include "vec.h" | |
47 #include "vecprim.h" | |
48 #include "dbgcnt.h" | |
49 | |
50 #ifndef HAVE_conditional_execution | |
51 #define HAVE_conditional_execution 0 | |
52 #endif | |
53 #ifndef HAVE_conditional_move | |
54 #define HAVE_conditional_move 0 | |
55 #endif | |
56 #ifndef HAVE_incscc | |
57 #define HAVE_incscc 0 | |
58 #endif | |
59 #ifndef HAVE_decscc | |
60 #define HAVE_decscc 0 | |
61 #endif | |
62 #ifndef HAVE_trap | |
63 #define HAVE_trap 0 | |
64 #endif | |
65 #ifndef HAVE_conditional_trap | |
66 #define HAVE_conditional_trap 0 | |
67 #endif | |
68 | |
69 #ifndef MAX_CONDITIONAL_EXECUTE | |
70 #define MAX_CONDITIONAL_EXECUTE \ | |
71 (BRANCH_COST (optimize_function_for_speed_p (cfun), false) \ | |
72 + 1) | |
73 #endif | |
74 | |
75 #define IFCVT_MULTIPLE_DUMPS 1 | |
76 | |
77 #define NULL_BLOCK ((basic_block) NULL) | |
78 | |
79 /* # of IF-THEN or IF-THEN-ELSE blocks we looked at */ | |
80 static int num_possible_if_blocks; | |
81 | |
82 /* # of IF-THEN or IF-THEN-ELSE blocks were converted to conditional | |
83 execution. */ | |
84 static int num_updated_if_blocks; | |
85 | |
86 /* # of changes made. */ | |
87 static int num_true_changes; | |
88 | |
89 /* Whether conditional execution changes were made. */ | |
90 static int cond_exec_changed_p; | |
91 | |
92 /* Forward references. */ | |
93 static int count_bb_insns (const_basic_block); | |
94 static bool cheap_bb_rtx_cost_p (const_basic_block, int); | |
95 static rtx first_active_insn (basic_block); | |
96 static rtx last_active_insn (basic_block, int); | |
97 static basic_block block_fallthru (basic_block); | |
98 static int cond_exec_process_insns (ce_if_block_t *, rtx, rtx, rtx, rtx, int); | |
99 static rtx cond_exec_get_condition (rtx); | |
100 static rtx noce_get_condition (rtx, rtx *, bool); | |
101 static int noce_operand_ok (const_rtx); | |
102 static void merge_if_block (ce_if_block_t *); | |
103 static int find_cond_trap (basic_block, edge, edge); | |
104 static basic_block find_if_header (basic_block, int); | |
105 static int block_jumps_and_fallthru_p (basic_block, basic_block); | |
106 static int noce_find_if_block (basic_block, edge, edge, int); | |
107 static int cond_exec_find_if_block (ce_if_block_t *); | |
108 static int find_if_case_1 (basic_block, edge, edge); | |
109 static int find_if_case_2 (basic_block, edge, edge); | |
110 static int find_memory (rtx *, void *); | |
111 static int dead_or_predicable (basic_block, basic_block, basic_block, | |
112 basic_block, int); | |
113 static void noce_emit_move_insn (rtx, rtx); | |
114 static rtx block_has_only_trap (basic_block); | |
115 | |
116 /* Count the number of non-jump active insns in BB. */ | |
117 | |
118 static int | |
119 count_bb_insns (const_basic_block bb) | |
120 { | |
121 int count = 0; | |
122 rtx insn = BB_HEAD (bb); | |
123 | |
124 while (1) | |
125 { | |
126 if (CALL_P (insn) || NONJUMP_INSN_P (insn)) | |
127 count++; | |
128 | |
129 if (insn == BB_END (bb)) | |
130 break; | |
131 insn = NEXT_INSN (insn); | |
132 } | |
133 | |
134 return count; | |
135 } | |
136 | |
137 /* Determine whether the total insn_rtx_cost on non-jump insns in | |
138 basic block BB is less than MAX_COST. This function returns | |
139 false if the cost of any instruction could not be estimated. */ | |
140 | |
141 static bool | |
142 cheap_bb_rtx_cost_p (const_basic_block bb, int max_cost) | |
143 { | |
144 int count = 0; | |
145 rtx insn = BB_HEAD (bb); | |
146 bool speed = optimize_bb_for_speed_p (bb); | |
147 | |
148 while (1) | |
149 { | |
150 if (NONJUMP_INSN_P (insn)) | |
151 { | |
152 int cost = insn_rtx_cost (PATTERN (insn), speed); | |
153 if (cost == 0) | |
154 return false; | |
155 | |
156 /* If this instruction is the load or set of a "stack" register, | |
157 such as a floating point register on x87, then the cost of | |
158 speculatively executing this insn may need to include | |
159 the additional cost of popping its result off of the | |
160 register stack. Unfortunately, correctly recognizing and | |
161 accounting for this additional overhead is tricky, so for | |
162 now we simply prohibit such speculative execution. */ | |
163 #ifdef STACK_REGS | |
164 { | |
165 rtx set = single_set (insn); | |
166 if (set && STACK_REG_P (SET_DEST (set))) | |
167 return false; | |
168 } | |
169 #endif | |
170 | |
171 count += cost; | |
172 if (count >= max_cost) | |
173 return false; | |
174 } | |
175 else if (CALL_P (insn)) | |
176 return false; | |
177 | |
178 if (insn == BB_END (bb)) | |
179 break; | |
180 insn = NEXT_INSN (insn); | |
181 } | |
182 | |
183 return true; | |
184 } | |
185 | |
186 /* Return the first non-jump active insn in the basic block. */ | |
187 | |
188 static rtx | |
189 first_active_insn (basic_block bb) | |
190 { | |
191 rtx insn = BB_HEAD (bb); | |
192 | |
193 if (LABEL_P (insn)) | |
194 { | |
195 if (insn == BB_END (bb)) | |
196 return NULL_RTX; | |
197 insn = NEXT_INSN (insn); | |
198 } | |
199 | |
200 while (NOTE_P (insn)) | |
201 { | |
202 if (insn == BB_END (bb)) | |
203 return NULL_RTX; | |
204 insn = NEXT_INSN (insn); | |
205 } | |
206 | |
207 if (JUMP_P (insn)) | |
208 return NULL_RTX; | |
209 | |
210 return insn; | |
211 } | |
212 | |
213 /* Return the last non-jump active (non-jump) insn in the basic block. */ | |
214 | |
215 static rtx | |
216 last_active_insn (basic_block bb, int skip_use_p) | |
217 { | |
218 rtx insn = BB_END (bb); | |
219 rtx head = BB_HEAD (bb); | |
220 | |
221 while (NOTE_P (insn) | |
222 || JUMP_P (insn) | |
223 || (skip_use_p | |
224 && NONJUMP_INSN_P (insn) | |
225 && GET_CODE (PATTERN (insn)) == USE)) | |
226 { | |
227 if (insn == head) | |
228 return NULL_RTX; | |
229 insn = PREV_INSN (insn); | |
230 } | |
231 | |
232 if (LABEL_P (insn)) | |
233 return NULL_RTX; | |
234 | |
235 return insn; | |
236 } | |
237 | |
238 /* Return the basic block reached by falling though the basic block BB. */ | |
239 | |
240 static basic_block | |
241 block_fallthru (basic_block bb) | |
242 { | |
243 edge e; | |
244 edge_iterator ei; | |
245 | |
246 FOR_EACH_EDGE (e, ei, bb->succs) | |
247 if (e->flags & EDGE_FALLTHRU) | |
248 break; | |
249 | |
250 return (e) ? e->dest : NULL_BLOCK; | |
251 } | |
252 | |
253 /* Go through a bunch of insns, converting them to conditional | |
254 execution format if possible. Return TRUE if all of the non-note | |
255 insns were processed. */ | |
256 | |
257 static int | |
258 cond_exec_process_insns (ce_if_block_t *ce_info ATTRIBUTE_UNUSED, | |
259 /* if block information */rtx start, | |
260 /* first insn to look at */rtx end, | |
261 /* last insn to look at */rtx test, | |
262 /* conditional execution test */rtx prob_val, | |
263 /* probability of branch taken. */int mod_ok) | |
264 { | |
265 int must_be_last = FALSE; | |
266 rtx insn; | |
267 rtx xtest; | |
268 rtx pattern; | |
269 | |
270 if (!start || !end) | |
271 return FALSE; | |
272 | |
273 for (insn = start; ; insn = NEXT_INSN (insn)) | |
274 { | |
275 if (NOTE_P (insn)) | |
276 goto insn_done; | |
277 | |
278 gcc_assert(NONJUMP_INSN_P (insn) || CALL_P (insn)); | |
279 | |
280 /* Remove USE insns that get in the way. */ | |
281 if (reload_completed && GET_CODE (PATTERN (insn)) == USE) | |
282 { | |
283 /* ??? Ug. Actually unlinking the thing is problematic, | |
284 given what we'd have to coordinate with our callers. */ | |
285 SET_INSN_DELETED (insn); | |
286 goto insn_done; | |
287 } | |
288 | |
289 /* Last insn wasn't last? */ | |
290 if (must_be_last) | |
291 return FALSE; | |
292 | |
293 if (modified_in_p (test, insn)) | |
294 { | |
295 if (!mod_ok) | |
296 return FALSE; | |
297 must_be_last = TRUE; | |
298 } | |
299 | |
300 /* Now build the conditional form of the instruction. */ | |
301 pattern = PATTERN (insn); | |
302 xtest = copy_rtx (test); | |
303 | |
304 /* If this is already a COND_EXEC, rewrite the test to be an AND of the | |
305 two conditions. */ | |
306 if (GET_CODE (pattern) == COND_EXEC) | |
307 { | |
308 if (GET_MODE (xtest) != GET_MODE (COND_EXEC_TEST (pattern))) | |
309 return FALSE; | |
310 | |
311 xtest = gen_rtx_AND (GET_MODE (xtest), xtest, | |
312 COND_EXEC_TEST (pattern)); | |
313 pattern = COND_EXEC_CODE (pattern); | |
314 } | |
315 | |
316 pattern = gen_rtx_COND_EXEC (VOIDmode, xtest, pattern); | |
317 | |
318 /* If the machine needs to modify the insn being conditionally executed, | |
319 say for example to force a constant integer operand into a temp | |
320 register, do so here. */ | |
321 #ifdef IFCVT_MODIFY_INSN | |
322 IFCVT_MODIFY_INSN (ce_info, pattern, insn); | |
323 if (! pattern) | |
324 return FALSE; | |
325 #endif | |
326 | |
327 validate_change (insn, &PATTERN (insn), pattern, 1); | |
328 | |
329 if (CALL_P (insn) && prob_val) | |
330 validate_change (insn, ®_NOTES (insn), | |
331 alloc_EXPR_LIST (REG_BR_PROB, prob_val, | |
332 REG_NOTES (insn)), 1); | |
333 | |
334 insn_done: | |
335 if (insn == end) | |
336 break; | |
337 } | |
338 | |
339 return TRUE; | |
340 } | |
341 | |
342 /* Return the condition for a jump. Do not do any special processing. */ | |
343 | |
344 static rtx | |
345 cond_exec_get_condition (rtx jump) | |
346 { | |
347 rtx test_if, cond; | |
348 | |
349 if (any_condjump_p (jump)) | |
350 test_if = SET_SRC (pc_set (jump)); | |
351 else | |
352 return NULL_RTX; | |
353 cond = XEXP (test_if, 0); | |
354 | |
355 /* If this branches to JUMP_LABEL when the condition is false, | |
356 reverse the condition. */ | |
357 if (GET_CODE (XEXP (test_if, 2)) == LABEL_REF | |
358 && XEXP (XEXP (test_if, 2), 0) == JUMP_LABEL (jump)) | |
359 { | |
360 enum rtx_code rev = reversed_comparison_code (cond, jump); | |
361 if (rev == UNKNOWN) | |
362 return NULL_RTX; | |
363 | |
364 cond = gen_rtx_fmt_ee (rev, GET_MODE (cond), XEXP (cond, 0), | |
365 XEXP (cond, 1)); | |
366 } | |
367 | |
368 return cond; | |
369 } | |
370 | |
371 /* Given a simple IF-THEN or IF-THEN-ELSE block, attempt to convert it | |
372 to conditional execution. Return TRUE if we were successful at | |
373 converting the block. */ | |
374 | |
375 static int | |
376 cond_exec_process_if_block (ce_if_block_t * ce_info, | |
377 /* if block information */int do_multiple_p) | |
378 { | |
379 basic_block test_bb = ce_info->test_bb; /* last test block */ | |
380 basic_block then_bb = ce_info->then_bb; /* THEN */ | |
381 basic_block else_bb = ce_info->else_bb; /* ELSE or NULL */ | |
382 rtx test_expr; /* expression in IF_THEN_ELSE that is tested */ | |
383 rtx then_start; /* first insn in THEN block */ | |
384 rtx then_end; /* last insn + 1 in THEN block */ | |
385 rtx else_start = NULL_RTX; /* first insn in ELSE block or NULL */ | |
386 rtx else_end = NULL_RTX; /* last insn + 1 in ELSE block */ | |
387 int max; /* max # of insns to convert. */ | |
388 int then_mod_ok; /* whether conditional mods are ok in THEN */ | |
389 rtx true_expr; /* test for else block insns */ | |
390 rtx false_expr; /* test for then block insns */ | |
391 rtx true_prob_val; /* probability of else block */ | |
392 rtx false_prob_val; /* probability of then block */ | |
393 int n_insns; | |
394 enum rtx_code false_code; | |
395 | |
396 /* If test is comprised of && or || elements, and we've failed at handling | |
397 all of them together, just use the last test if it is the special case of | |
398 && elements without an ELSE block. */ | |
399 if (!do_multiple_p && ce_info->num_multiple_test_blocks) | |
400 { | |
401 if (else_bb || ! ce_info->and_and_p) | |
402 return FALSE; | |
403 | |
404 ce_info->test_bb = test_bb = ce_info->last_test_bb; | |
405 ce_info->num_multiple_test_blocks = 0; | |
406 ce_info->num_and_and_blocks = 0; | |
407 ce_info->num_or_or_blocks = 0; | |
408 } | |
409 | |
410 /* Find the conditional jump to the ELSE or JOIN part, and isolate | |
411 the test. */ | |
412 test_expr = cond_exec_get_condition (BB_END (test_bb)); | |
413 if (! test_expr) | |
414 return FALSE; | |
415 | |
416 /* If the conditional jump is more than just a conditional jump, | |
417 then we can not do conditional execution conversion on this block. */ | |
418 if (! onlyjump_p (BB_END (test_bb))) | |
419 return FALSE; | |
420 | |
421 /* Collect the bounds of where we're to search, skipping any labels, jumps | |
422 and notes at the beginning and end of the block. Then count the total | |
423 number of insns and see if it is small enough to convert. */ | |
424 then_start = first_active_insn (then_bb); | |
425 then_end = last_active_insn (then_bb, TRUE); | |
426 n_insns = ce_info->num_then_insns = count_bb_insns (then_bb); | |
427 max = MAX_CONDITIONAL_EXECUTE; | |
428 | |
429 if (else_bb) | |
430 { | |
431 max *= 2; | |
432 else_start = first_active_insn (else_bb); | |
433 else_end = last_active_insn (else_bb, TRUE); | |
434 n_insns += ce_info->num_else_insns = count_bb_insns (else_bb); | |
435 } | |
436 | |
437 if (n_insns > max) | |
438 return FALSE; | |
439 | |
440 /* Map test_expr/test_jump into the appropriate MD tests to use on | |
441 the conditionally executed code. */ | |
442 | |
443 true_expr = test_expr; | |
444 | |
445 false_code = reversed_comparison_code (true_expr, BB_END (test_bb)); | |
446 if (false_code != UNKNOWN) | |
447 false_expr = gen_rtx_fmt_ee (false_code, GET_MODE (true_expr), | |
448 XEXP (true_expr, 0), XEXP (true_expr, 1)); | |
449 else | |
450 false_expr = NULL_RTX; | |
451 | |
452 #ifdef IFCVT_MODIFY_TESTS | |
453 /* If the machine description needs to modify the tests, such as setting a | |
454 conditional execution register from a comparison, it can do so here. */ | |
455 IFCVT_MODIFY_TESTS (ce_info, true_expr, false_expr); | |
456 | |
457 /* See if the conversion failed. */ | |
458 if (!true_expr || !false_expr) | |
459 goto fail; | |
460 #endif | |
461 | |
462 true_prob_val = find_reg_note (BB_END (test_bb), REG_BR_PROB, NULL_RTX); | |
463 if (true_prob_val) | |
464 { | |
465 true_prob_val = XEXP (true_prob_val, 0); | |
466 false_prob_val = GEN_INT (REG_BR_PROB_BASE - INTVAL (true_prob_val)); | |
467 } | |
468 else | |
469 false_prob_val = NULL_RTX; | |
470 | |
471 /* If we have && or || tests, do them here. These tests are in the adjacent | |
472 blocks after the first block containing the test. */ | |
473 if (ce_info->num_multiple_test_blocks > 0) | |
474 { | |
475 basic_block bb = test_bb; | |
476 basic_block last_test_bb = ce_info->last_test_bb; | |
477 | |
478 if (! false_expr) | |
479 goto fail; | |
480 | |
481 do | |
482 { | |
483 rtx start, end; | |
484 rtx t, f; | |
485 enum rtx_code f_code; | |
486 | |
487 bb = block_fallthru (bb); | |
488 start = first_active_insn (bb); | |
489 end = last_active_insn (bb, TRUE); | |
490 if (start | |
491 && ! cond_exec_process_insns (ce_info, start, end, false_expr, | |
492 false_prob_val, FALSE)) | |
493 goto fail; | |
494 | |
495 /* If the conditional jump is more than just a conditional jump, then | |
496 we can not do conditional execution conversion on this block. */ | |
497 if (! onlyjump_p (BB_END (bb))) | |
498 goto fail; | |
499 | |
500 /* Find the conditional jump and isolate the test. */ | |
501 t = cond_exec_get_condition (BB_END (bb)); | |
502 if (! t) | |
503 goto fail; | |
504 | |
505 f_code = reversed_comparison_code (t, BB_END (bb)); | |
506 if (f_code == UNKNOWN) | |
507 goto fail; | |
508 | |
509 f = gen_rtx_fmt_ee (f_code, GET_MODE (t), XEXP (t, 0), XEXP (t, 1)); | |
510 if (ce_info->and_and_p) | |
511 { | |
512 t = gen_rtx_AND (GET_MODE (t), true_expr, t); | |
513 f = gen_rtx_IOR (GET_MODE (t), false_expr, f); | |
514 } | |
515 else | |
516 { | |
517 t = gen_rtx_IOR (GET_MODE (t), true_expr, t); | |
518 f = gen_rtx_AND (GET_MODE (t), false_expr, f); | |
519 } | |
520 | |
521 /* If the machine description needs to modify the tests, such as | |
522 setting a conditional execution register from a comparison, it can | |
523 do so here. */ | |
524 #ifdef IFCVT_MODIFY_MULTIPLE_TESTS | |
525 IFCVT_MODIFY_MULTIPLE_TESTS (ce_info, bb, t, f); | |
526 | |
527 /* See if the conversion failed. */ | |
528 if (!t || !f) | |
529 goto fail; | |
530 #endif | |
531 | |
532 true_expr = t; | |
533 false_expr = f; | |
534 } | |
535 while (bb != last_test_bb); | |
536 } | |
537 | |
538 /* For IF-THEN-ELSE blocks, we don't allow modifications of the test | |
539 on then THEN block. */ | |
540 then_mod_ok = (else_bb == NULL_BLOCK); | |
541 | |
542 /* Go through the THEN and ELSE blocks converting the insns if possible | |
543 to conditional execution. */ | |
544 | |
545 if (then_end | |
546 && (! false_expr | |
547 || ! cond_exec_process_insns (ce_info, then_start, then_end, | |
548 false_expr, false_prob_val, | |
549 then_mod_ok))) | |
550 goto fail; | |
551 | |
552 if (else_bb && else_end | |
553 && ! cond_exec_process_insns (ce_info, else_start, else_end, | |
554 true_expr, true_prob_val, TRUE)) | |
555 goto fail; | |
556 | |
557 /* If we cannot apply the changes, fail. Do not go through the normal fail | |
558 processing, since apply_change_group will call cancel_changes. */ | |
559 if (! apply_change_group ()) | |
560 { | |
561 #ifdef IFCVT_MODIFY_CANCEL | |
562 /* Cancel any machine dependent changes. */ | |
563 IFCVT_MODIFY_CANCEL (ce_info); | |
564 #endif | |
565 return FALSE; | |
566 } | |
567 | |
568 #ifdef IFCVT_MODIFY_FINAL | |
569 /* Do any machine dependent final modifications. */ | |
570 IFCVT_MODIFY_FINAL (ce_info); | |
571 #endif | |
572 | |
573 /* Conversion succeeded. */ | |
574 if (dump_file) | |
575 fprintf (dump_file, "%d insn%s converted to conditional execution.\n", | |
576 n_insns, (n_insns == 1) ? " was" : "s were"); | |
577 | |
578 /* Merge the blocks! */ | |
579 merge_if_block (ce_info); | |
580 cond_exec_changed_p = TRUE; | |
581 return TRUE; | |
582 | |
583 fail: | |
584 #ifdef IFCVT_MODIFY_CANCEL | |
585 /* Cancel any machine dependent changes. */ | |
586 IFCVT_MODIFY_CANCEL (ce_info); | |
587 #endif | |
588 | |
589 cancel_changes (0); | |
590 return FALSE; | |
591 } | |
592 | |
593 /* Used by noce_process_if_block to communicate with its subroutines. | |
594 | |
595 The subroutines know that A and B may be evaluated freely. They | |
596 know that X is a register. They should insert new instructions | |
597 before cond_earliest. */ | |
598 | |
599 struct noce_if_info | |
600 { | |
601 /* The basic blocks that make up the IF-THEN-{ELSE-,}JOIN block. */ | |
602 basic_block test_bb, then_bb, else_bb, join_bb; | |
603 | |
604 /* The jump that ends TEST_BB. */ | |
605 rtx jump; | |
606 | |
607 /* The jump condition. */ | |
608 rtx cond; | |
609 | |
610 /* New insns should be inserted before this one. */ | |
611 rtx cond_earliest; | |
612 | |
613 /* Insns in the THEN and ELSE block. There is always just this | |
614 one insns in those blocks. The insns are single_set insns. | |
615 If there was no ELSE block, INSN_B is the last insn before | |
616 COND_EARLIEST, or NULL_RTX. In the former case, the insn | |
617 operands are still valid, as if INSN_B was moved down below | |
618 the jump. */ | |
619 rtx insn_a, insn_b; | |
620 | |
621 /* The SET_SRC of INSN_A and INSN_B. */ | |
622 rtx a, b; | |
623 | |
624 /* The SET_DEST of INSN_A. */ | |
625 rtx x; | |
626 | |
627 /* True if this if block is not canonical. In the canonical form of | |
628 if blocks, the THEN_BB is the block reached via the fallthru edge | |
629 from TEST_BB. For the noce transformations, we allow the symmetric | |
630 form as well. */ | |
631 bool then_else_reversed; | |
632 | |
633 /* Estimated cost of the particular branch instruction. */ | |
634 int branch_cost; | |
635 }; | |
636 | |
637 static rtx noce_emit_store_flag (struct noce_if_info *, rtx, int, int); | |
638 static int noce_try_move (struct noce_if_info *); | |
639 static int noce_try_store_flag (struct noce_if_info *); | |
640 static int noce_try_addcc (struct noce_if_info *); | |
641 static int noce_try_store_flag_constants (struct noce_if_info *); | |
642 static int noce_try_store_flag_mask (struct noce_if_info *); | |
643 static rtx noce_emit_cmove (struct noce_if_info *, rtx, enum rtx_code, rtx, | |
644 rtx, rtx, rtx); | |
645 static int noce_try_cmove (struct noce_if_info *); | |
646 static int noce_try_cmove_arith (struct noce_if_info *); | |
647 static rtx noce_get_alt_condition (struct noce_if_info *, rtx, rtx *); | |
648 static int noce_try_minmax (struct noce_if_info *); | |
649 static int noce_try_abs (struct noce_if_info *); | |
650 static int noce_try_sign_mask (struct noce_if_info *); | |
651 | |
652 /* Helper function for noce_try_store_flag*. */ | |
653 | |
654 static rtx | |
655 noce_emit_store_flag (struct noce_if_info *if_info, rtx x, int reversep, | |
656 int normalize) | |
657 { | |
658 rtx cond = if_info->cond; | |
659 int cond_complex; | |
660 enum rtx_code code; | |
661 | |
662 cond_complex = (! general_operand (XEXP (cond, 0), VOIDmode) | |
663 || ! general_operand (XEXP (cond, 1), VOIDmode)); | |
664 | |
665 /* If earliest == jump, or when the condition is complex, try to | |
666 build the store_flag insn directly. */ | |
667 | |
668 if (cond_complex) | |
669 { | |
670 rtx set = pc_set (if_info->jump); | |
671 cond = XEXP (SET_SRC (set), 0); | |
672 if (GET_CODE (XEXP (SET_SRC (set), 2)) == LABEL_REF | |
673 && XEXP (XEXP (SET_SRC (set), 2), 0) == JUMP_LABEL (if_info->jump)) | |
674 reversep = !reversep; | |
675 if (if_info->then_else_reversed) | |
676 reversep = !reversep; | |
677 } | |
678 | |
679 if (reversep) | |
680 code = reversed_comparison_code (cond, if_info->jump); | |
681 else | |
682 code = GET_CODE (cond); | |
683 | |
684 if ((if_info->cond_earliest == if_info->jump || cond_complex) | |
685 && (normalize == 0 || STORE_FLAG_VALUE == normalize)) | |
686 { | |
687 rtx tmp; | |
688 | |
689 tmp = gen_rtx_fmt_ee (code, GET_MODE (x), XEXP (cond, 0), | |
690 XEXP (cond, 1)); | |
691 tmp = gen_rtx_SET (VOIDmode, x, tmp); | |
692 | |
693 start_sequence (); | |
694 tmp = emit_insn (tmp); | |
695 | |
696 if (recog_memoized (tmp) >= 0) | |
697 { | |
698 tmp = get_insns (); | |
699 end_sequence (); | |
700 emit_insn (tmp); | |
701 | |
702 if_info->cond_earliest = if_info->jump; | |
703 | |
704 return x; | |
705 } | |
706 | |
707 end_sequence (); | |
708 } | |
709 | |
710 /* Don't even try if the comparison operands or the mode of X are weird. */ | |
711 if (cond_complex || !SCALAR_INT_MODE_P (GET_MODE (x))) | |
712 return NULL_RTX; | |
713 | |
714 return emit_store_flag (x, code, XEXP (cond, 0), | |
715 XEXP (cond, 1), VOIDmode, | |
716 (code == LTU || code == LEU | |
717 || code == GEU || code == GTU), normalize); | |
718 } | |
719 | |
720 /* Emit instruction to move an rtx, possibly into STRICT_LOW_PART. | |
721 X is the destination/target and Y is the value to copy. */ | |
722 | |
723 static void | |
724 noce_emit_move_insn (rtx x, rtx y) | |
725 { | |
726 enum machine_mode outmode; | |
727 rtx outer, inner; | |
728 int bitpos; | |
729 | |
730 if (GET_CODE (x) != STRICT_LOW_PART) | |
731 { | |
732 rtx seq, insn, target; | |
733 optab ot; | |
734 | |
735 start_sequence (); | |
736 /* Check that the SET_SRC is reasonable before calling emit_move_insn, | |
737 otherwise construct a suitable SET pattern ourselves. */ | |
738 insn = (OBJECT_P (y) || CONSTANT_P (y) || GET_CODE (y) == SUBREG) | |
739 ? emit_move_insn (x, y) | |
740 : emit_insn (gen_rtx_SET (VOIDmode, x, y)); | |
741 seq = get_insns (); | |
742 end_sequence (); | |
743 | |
744 if (recog_memoized (insn) <= 0) | |
745 { | |
746 if (GET_CODE (x) == ZERO_EXTRACT) | |
747 { | |
748 rtx op = XEXP (x, 0); | |
749 unsigned HOST_WIDE_INT size = INTVAL (XEXP (x, 1)); | |
750 unsigned HOST_WIDE_INT start = INTVAL (XEXP (x, 2)); | |
751 | |
752 /* store_bit_field expects START to be relative to | |
753 BYTES_BIG_ENDIAN and adjusts this value for machines with | |
754 BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN. In order to be able to | |
755 invoke store_bit_field again it is necessary to have the START | |
756 value from the first call. */ | |
757 if (BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN) | |
758 { | |
759 if (MEM_P (op)) | |
760 start = BITS_PER_UNIT - start - size; | |
761 else | |
762 { | |
763 gcc_assert (REG_P (op)); | |
764 start = BITS_PER_WORD - start - size; | |
765 } | |
766 } | |
767 | |
768 gcc_assert (start < (MEM_P (op) ? BITS_PER_UNIT : BITS_PER_WORD)); | |
769 store_bit_field (op, size, start, GET_MODE (x), y); | |
770 return; | |
771 } | |
772 | |
773 switch (GET_RTX_CLASS (GET_CODE (y))) | |
774 { | |
775 case RTX_UNARY: | |
776 ot = code_to_optab[GET_CODE (y)]; | |
777 if (ot) | |
778 { | |
779 start_sequence (); | |
780 target = expand_unop (GET_MODE (y), ot, XEXP (y, 0), x, 0); | |
781 if (target != NULL_RTX) | |
782 { | |
783 if (target != x) | |
784 emit_move_insn (x, target); | |
785 seq = get_insns (); | |
786 } | |
787 end_sequence (); | |
788 } | |
789 break; | |
790 | |
791 case RTX_BIN_ARITH: | |
792 case RTX_COMM_ARITH: | |
793 ot = code_to_optab[GET_CODE (y)]; | |
794 if (ot) | |
795 { | |
796 start_sequence (); | |
797 target = expand_binop (GET_MODE (y), ot, | |
798 XEXP (y, 0), XEXP (y, 1), | |
799 x, 0, OPTAB_DIRECT); | |
800 if (target != NULL_RTX) | |
801 { | |
802 if (target != x) | |
803 emit_move_insn (x, target); | |
804 seq = get_insns (); | |
805 } | |
806 end_sequence (); | |
807 } | |
808 break; | |
809 | |
810 default: | |
811 break; | |
812 } | |
813 } | |
814 | |
815 emit_insn (seq); | |
816 return; | |
817 } | |
818 | |
819 outer = XEXP (x, 0); | |
820 inner = XEXP (outer, 0); | |
821 outmode = GET_MODE (outer); | |
822 bitpos = SUBREG_BYTE (outer) * BITS_PER_UNIT; | |
823 store_bit_field (inner, GET_MODE_BITSIZE (outmode), bitpos, outmode, y); | |
824 } | |
825 | |
826 /* Return sequence of instructions generated by if conversion. This | |
827 function calls end_sequence() to end the current stream, ensures | |
828 that are instructions are unshared, recognizable non-jump insns. | |
829 On failure, this function returns a NULL_RTX. */ | |
830 | |
831 static rtx | |
832 end_ifcvt_sequence (struct noce_if_info *if_info) | |
833 { | |
834 rtx insn; | |
835 rtx seq = get_insns (); | |
836 | |
837 set_used_flags (if_info->x); | |
838 set_used_flags (if_info->cond); | |
839 unshare_all_rtl_in_chain (seq); | |
840 end_sequence (); | |
841 | |
842 /* Make sure that all of the instructions emitted are recognizable, | |
843 and that we haven't introduced a new jump instruction. | |
844 As an exercise for the reader, build a general mechanism that | |
845 allows proper placement of required clobbers. */ | |
846 for (insn = seq; insn; insn = NEXT_INSN (insn)) | |
847 if (JUMP_P (insn) | |
848 || recog_memoized (insn) == -1) | |
849 return NULL_RTX; | |
850 | |
851 return seq; | |
852 } | |
853 | |
854 /* Convert "if (a != b) x = a; else x = b" into "x = a" and | |
855 "if (a == b) x = a; else x = b" into "x = b". */ | |
856 | |
857 static int | |
858 noce_try_move (struct noce_if_info *if_info) | |
859 { | |
860 rtx cond = if_info->cond; | |
861 enum rtx_code code = GET_CODE (cond); | |
862 rtx y, seq; | |
863 | |
864 if (code != NE && code != EQ) | |
865 return FALSE; | |
866 | |
867 /* This optimization isn't valid if either A or B could be a NaN | |
868 or a signed zero. */ | |
869 if (HONOR_NANS (GET_MODE (if_info->x)) | |
870 || HONOR_SIGNED_ZEROS (GET_MODE (if_info->x))) | |
871 return FALSE; | |
872 | |
873 /* Check whether the operands of the comparison are A and in | |
874 either order. */ | |
875 if ((rtx_equal_p (if_info->a, XEXP (cond, 0)) | |
876 && rtx_equal_p (if_info->b, XEXP (cond, 1))) | |
877 || (rtx_equal_p (if_info->a, XEXP (cond, 1)) | |
878 && rtx_equal_p (if_info->b, XEXP (cond, 0)))) | |
879 { | |
880 y = (code == EQ) ? if_info->a : if_info->b; | |
881 | |
882 /* Avoid generating the move if the source is the destination. */ | |
883 if (! rtx_equal_p (if_info->x, y)) | |
884 { | |
885 start_sequence (); | |
886 noce_emit_move_insn (if_info->x, y); | |
887 seq = end_ifcvt_sequence (if_info); | |
888 if (!seq) | |
889 return FALSE; | |
890 | |
891 emit_insn_before_setloc (seq, if_info->jump, | |
892 INSN_LOCATOR (if_info->insn_a)); | |
893 } | |
894 return TRUE; | |
895 } | |
896 return FALSE; | |
897 } | |
898 | |
899 /* Convert "if (test) x = 1; else x = 0". | |
900 | |
901 Only try 0 and STORE_FLAG_VALUE here. Other combinations will be | |
902 tried in noce_try_store_flag_constants after noce_try_cmove has had | |
903 a go at the conversion. */ | |
904 | |
905 static int | |
906 noce_try_store_flag (struct noce_if_info *if_info) | |
907 { | |
908 int reversep; | |
909 rtx target, seq; | |
910 | |
911 if (GET_CODE (if_info->b) == CONST_INT | |
912 && INTVAL (if_info->b) == STORE_FLAG_VALUE | |
913 && if_info->a == const0_rtx) | |
914 reversep = 0; | |
915 else if (if_info->b == const0_rtx | |
916 && GET_CODE (if_info->a) == CONST_INT | |
917 && INTVAL (if_info->a) == STORE_FLAG_VALUE | |
918 && (reversed_comparison_code (if_info->cond, if_info->jump) | |
919 != UNKNOWN)) | |
920 reversep = 1; | |
921 else | |
922 return FALSE; | |
923 | |
924 start_sequence (); | |
925 | |
926 target = noce_emit_store_flag (if_info, if_info->x, reversep, 0); | |
927 if (target) | |
928 { | |
929 if (target != if_info->x) | |
930 noce_emit_move_insn (if_info->x, target); | |
931 | |
932 seq = end_ifcvt_sequence (if_info); | |
933 if (! seq) | |
934 return FALSE; | |
935 | |
936 emit_insn_before_setloc (seq, if_info->jump, | |
937 INSN_LOCATOR (if_info->insn_a)); | |
938 return TRUE; | |
939 } | |
940 else | |
941 { | |
942 end_sequence (); | |
943 return FALSE; | |
944 } | |
945 } | |
946 | |
947 /* Convert "if (test) x = a; else x = b", for A and B constant. */ | |
948 | |
949 static int | |
950 noce_try_store_flag_constants (struct noce_if_info *if_info) | |
951 { | |
952 rtx target, seq; | |
953 int reversep; | |
954 HOST_WIDE_INT itrue, ifalse, diff, tmp; | |
955 int normalize, can_reverse; | |
956 enum machine_mode mode; | |
957 | |
958 if (GET_CODE (if_info->a) == CONST_INT | |
959 && GET_CODE (if_info->b) == CONST_INT) | |
960 { | |
961 mode = GET_MODE (if_info->x); | |
962 ifalse = INTVAL (if_info->a); | |
963 itrue = INTVAL (if_info->b); | |
964 | |
965 /* Make sure we can represent the difference between the two values. */ | |
966 if ((itrue - ifalse > 0) | |
967 != ((ifalse < 0) != (itrue < 0) ? ifalse < 0 : ifalse < itrue)) | |
968 return FALSE; | |
969 | |
970 diff = trunc_int_for_mode (itrue - ifalse, mode); | |
971 | |
972 can_reverse = (reversed_comparison_code (if_info->cond, if_info->jump) | |
973 != UNKNOWN); | |
974 | |
975 reversep = 0; | |
976 if (diff == STORE_FLAG_VALUE || diff == -STORE_FLAG_VALUE) | |
977 normalize = 0; | |
978 else if (ifalse == 0 && exact_log2 (itrue) >= 0 | |
979 && (STORE_FLAG_VALUE == 1 | |
980 || if_info->branch_cost >= 2)) | |
981 normalize = 1; | |
982 else if (itrue == 0 && exact_log2 (ifalse) >= 0 && can_reverse | |
983 && (STORE_FLAG_VALUE == 1 || if_info->branch_cost >= 2)) | |
984 normalize = 1, reversep = 1; | |
985 else if (itrue == -1 | |
986 && (STORE_FLAG_VALUE == -1 | |
987 || if_info->branch_cost >= 2)) | |
988 normalize = -1; | |
989 else if (ifalse == -1 && can_reverse | |
990 && (STORE_FLAG_VALUE == -1 || if_info->branch_cost >= 2)) | |
991 normalize = -1, reversep = 1; | |
992 else if ((if_info->branch_cost >= 2 && STORE_FLAG_VALUE == -1) | |
993 || if_info->branch_cost >= 3) | |
994 normalize = -1; | |
995 else | |
996 return FALSE; | |
997 | |
998 if (reversep) | |
999 { | |
1000 tmp = itrue; itrue = ifalse; ifalse = tmp; | |
1001 diff = trunc_int_for_mode (-diff, mode); | |
1002 } | |
1003 | |
1004 start_sequence (); | |
1005 target = noce_emit_store_flag (if_info, if_info->x, reversep, normalize); | |
1006 if (! target) | |
1007 { | |
1008 end_sequence (); | |
1009 return FALSE; | |
1010 } | |
1011 | |
1012 /* if (test) x = 3; else x = 4; | |
1013 => x = 3 + (test == 0); */ | |
1014 if (diff == STORE_FLAG_VALUE || diff == -STORE_FLAG_VALUE) | |
1015 { | |
1016 target = expand_simple_binop (mode, | |
1017 (diff == STORE_FLAG_VALUE | |
1018 ? PLUS : MINUS), | |
1019 GEN_INT (ifalse), target, if_info->x, 0, | |
1020 OPTAB_WIDEN); | |
1021 } | |
1022 | |
1023 /* if (test) x = 8; else x = 0; | |
1024 => x = (test != 0) << 3; */ | |
1025 else if (ifalse == 0 && (tmp = exact_log2 (itrue)) >= 0) | |
1026 { | |
1027 target = expand_simple_binop (mode, ASHIFT, | |
1028 target, GEN_INT (tmp), if_info->x, 0, | |
1029 OPTAB_WIDEN); | |
1030 } | |
1031 | |
1032 /* if (test) x = -1; else x = b; | |
1033 => x = -(test != 0) | b; */ | |
1034 else if (itrue == -1) | |
1035 { | |
1036 target = expand_simple_binop (mode, IOR, | |
1037 target, GEN_INT (ifalse), if_info->x, 0, | |
1038 OPTAB_WIDEN); | |
1039 } | |
1040 | |
1041 /* if (test) x = a; else x = b; | |
1042 => x = (-(test != 0) & (b - a)) + a; */ | |
1043 else | |
1044 { | |
1045 target = expand_simple_binop (mode, AND, | |
1046 target, GEN_INT (diff), if_info->x, 0, | |
1047 OPTAB_WIDEN); | |
1048 if (target) | |
1049 target = expand_simple_binop (mode, PLUS, | |
1050 target, GEN_INT (ifalse), | |
1051 if_info->x, 0, OPTAB_WIDEN); | |
1052 } | |
1053 | |
1054 if (! target) | |
1055 { | |
1056 end_sequence (); | |
1057 return FALSE; | |
1058 } | |
1059 | |
1060 if (target != if_info->x) | |
1061 noce_emit_move_insn (if_info->x, target); | |
1062 | |
1063 seq = end_ifcvt_sequence (if_info); | |
1064 if (!seq) | |
1065 return FALSE; | |
1066 | |
1067 emit_insn_before_setloc (seq, if_info->jump, | |
1068 INSN_LOCATOR (if_info->insn_a)); | |
1069 return TRUE; | |
1070 } | |
1071 | |
1072 return FALSE; | |
1073 } | |
1074 | |
1075 /* Convert "if (test) foo++" into "foo += (test != 0)", and | |
1076 similarly for "foo--". */ | |
1077 | |
1078 static int | |
1079 noce_try_addcc (struct noce_if_info *if_info) | |
1080 { | |
1081 rtx target, seq; | |
1082 int subtract, normalize; | |
1083 | |
1084 if (GET_CODE (if_info->a) == PLUS | |
1085 && rtx_equal_p (XEXP (if_info->a, 0), if_info->b) | |
1086 && (reversed_comparison_code (if_info->cond, if_info->jump) | |
1087 != UNKNOWN)) | |
1088 { | |
1089 rtx cond = if_info->cond; | |
1090 enum rtx_code code = reversed_comparison_code (cond, if_info->jump); | |
1091 | |
1092 /* First try to use addcc pattern. */ | |
1093 if (general_operand (XEXP (cond, 0), VOIDmode) | |
1094 && general_operand (XEXP (cond, 1), VOIDmode)) | |
1095 { | |
1096 start_sequence (); | |
1097 target = emit_conditional_add (if_info->x, code, | |
1098 XEXP (cond, 0), | |
1099 XEXP (cond, 1), | |
1100 VOIDmode, | |
1101 if_info->b, | |
1102 XEXP (if_info->a, 1), | |
1103 GET_MODE (if_info->x), | |
1104 (code == LTU || code == GEU | |
1105 || code == LEU || code == GTU)); | |
1106 if (target) | |
1107 { | |
1108 if (target != if_info->x) | |
1109 noce_emit_move_insn (if_info->x, target); | |
1110 | |
1111 seq = end_ifcvt_sequence (if_info); | |
1112 if (!seq) | |
1113 return FALSE; | |
1114 | |
1115 emit_insn_before_setloc (seq, if_info->jump, | |
1116 INSN_LOCATOR (if_info->insn_a)); | |
1117 return TRUE; | |
1118 } | |
1119 end_sequence (); | |
1120 } | |
1121 | |
1122 /* If that fails, construct conditional increment or decrement using | |
1123 setcc. */ | |
1124 if (if_info->branch_cost >= 2 | |
1125 && (XEXP (if_info->a, 1) == const1_rtx | |
1126 || XEXP (if_info->a, 1) == constm1_rtx)) | |
1127 { | |
1128 start_sequence (); | |
1129 if (STORE_FLAG_VALUE == INTVAL (XEXP (if_info->a, 1))) | |
1130 subtract = 0, normalize = 0; | |
1131 else if (-STORE_FLAG_VALUE == INTVAL (XEXP (if_info->a, 1))) | |
1132 subtract = 1, normalize = 0; | |
1133 else | |
1134 subtract = 0, normalize = INTVAL (XEXP (if_info->a, 1)); | |
1135 | |
1136 | |
1137 target = noce_emit_store_flag (if_info, | |
1138 gen_reg_rtx (GET_MODE (if_info->x)), | |
1139 1, normalize); | |
1140 | |
1141 if (target) | |
1142 target = expand_simple_binop (GET_MODE (if_info->x), | |
1143 subtract ? MINUS : PLUS, | |
1144 if_info->b, target, if_info->x, | |
1145 0, OPTAB_WIDEN); | |
1146 if (target) | |
1147 { | |
1148 if (target != if_info->x) | |
1149 noce_emit_move_insn (if_info->x, target); | |
1150 | |
1151 seq = end_ifcvt_sequence (if_info); | |
1152 if (!seq) | |
1153 return FALSE; | |
1154 | |
1155 emit_insn_before_setloc (seq, if_info->jump, | |
1156 INSN_LOCATOR (if_info->insn_a)); | |
1157 return TRUE; | |
1158 } | |
1159 end_sequence (); | |
1160 } | |
1161 } | |
1162 | |
1163 return FALSE; | |
1164 } | |
1165 | |
1166 /* Convert "if (test) x = 0;" to "x &= -(test == 0);" */ | |
1167 | |
1168 static int | |
1169 noce_try_store_flag_mask (struct noce_if_info *if_info) | |
1170 { | |
1171 rtx target, seq; | |
1172 int reversep; | |
1173 | |
1174 reversep = 0; | |
1175 if ((if_info->branch_cost >= 2 | |
1176 || STORE_FLAG_VALUE == -1) | |
1177 && ((if_info->a == const0_rtx | |
1178 && rtx_equal_p (if_info->b, if_info->x)) | |
1179 || ((reversep = (reversed_comparison_code (if_info->cond, | |
1180 if_info->jump) | |
1181 != UNKNOWN)) | |
1182 && if_info->b == const0_rtx | |
1183 && rtx_equal_p (if_info->a, if_info->x)))) | |
1184 { | |
1185 start_sequence (); | |
1186 target = noce_emit_store_flag (if_info, | |
1187 gen_reg_rtx (GET_MODE (if_info->x)), | |
1188 reversep, -1); | |
1189 if (target) | |
1190 target = expand_simple_binop (GET_MODE (if_info->x), AND, | |
1191 if_info->x, | |
1192 target, if_info->x, 0, | |
1193 OPTAB_WIDEN); | |
1194 | |
1195 if (target) | |
1196 { | |
1197 if (target != if_info->x) | |
1198 noce_emit_move_insn (if_info->x, target); | |
1199 | |
1200 seq = end_ifcvt_sequence (if_info); | |
1201 if (!seq) | |
1202 return FALSE; | |
1203 | |
1204 emit_insn_before_setloc (seq, if_info->jump, | |
1205 INSN_LOCATOR (if_info->insn_a)); | |
1206 return TRUE; | |
1207 } | |
1208 | |
1209 end_sequence (); | |
1210 } | |
1211 | |
1212 return FALSE; | |
1213 } | |
1214 | |
1215 /* Helper function for noce_try_cmove and noce_try_cmove_arith. */ | |
1216 | |
1217 static rtx | |
1218 noce_emit_cmove (struct noce_if_info *if_info, rtx x, enum rtx_code code, | |
1219 rtx cmp_a, rtx cmp_b, rtx vfalse, rtx vtrue) | |
1220 { | |
1221 /* If earliest == jump, try to build the cmove insn directly. | |
1222 This is helpful when combine has created some complex condition | |
1223 (like for alpha's cmovlbs) that we can't hope to regenerate | |
1224 through the normal interface. */ | |
1225 | |
1226 if (if_info->cond_earliest == if_info->jump) | |
1227 { | |
1228 rtx tmp; | |
1229 | |
1230 tmp = gen_rtx_fmt_ee (code, GET_MODE (if_info->cond), cmp_a, cmp_b); | |
1231 tmp = gen_rtx_IF_THEN_ELSE (GET_MODE (x), tmp, vtrue, vfalse); | |
1232 tmp = gen_rtx_SET (VOIDmode, x, tmp); | |
1233 | |
1234 start_sequence (); | |
1235 tmp = emit_insn (tmp); | |
1236 | |
1237 if (recog_memoized (tmp) >= 0) | |
1238 { | |
1239 tmp = get_insns (); | |
1240 end_sequence (); | |
1241 emit_insn (tmp); | |
1242 | |
1243 return x; | |
1244 } | |
1245 | |
1246 end_sequence (); | |
1247 } | |
1248 | |
1249 /* Don't even try if the comparison operands are weird. */ | |
1250 if (! general_operand (cmp_a, GET_MODE (cmp_a)) | |
1251 || ! general_operand (cmp_b, GET_MODE (cmp_b))) | |
1252 return NULL_RTX; | |
1253 | |
1254 #if HAVE_conditional_move | |
1255 return emit_conditional_move (x, code, cmp_a, cmp_b, VOIDmode, | |
1256 vtrue, vfalse, GET_MODE (x), | |
1257 (code == LTU || code == GEU | |
1258 || code == LEU || code == GTU)); | |
1259 #else | |
1260 /* We'll never get here, as noce_process_if_block doesn't call the | |
1261 functions involved. Ifdef code, however, should be discouraged | |
1262 because it leads to typos in the code not selected. However, | |
1263 emit_conditional_move won't exist either. */ | |
1264 return NULL_RTX; | |
1265 #endif | |
1266 } | |
1267 | |
1268 /* Try only simple constants and registers here. More complex cases | |
1269 are handled in noce_try_cmove_arith after noce_try_store_flag_arith | |
1270 has had a go at it. */ | |
1271 | |
1272 static int | |
1273 noce_try_cmove (struct noce_if_info *if_info) | |
1274 { | |
1275 enum rtx_code code; | |
1276 rtx target, seq; | |
1277 | |
1278 if ((CONSTANT_P (if_info->a) || register_operand (if_info->a, VOIDmode)) | |
1279 && (CONSTANT_P (if_info->b) || register_operand (if_info->b, VOIDmode))) | |
1280 { | |
1281 start_sequence (); | |
1282 | |
1283 code = GET_CODE (if_info->cond); | |
1284 target = noce_emit_cmove (if_info, if_info->x, code, | |
1285 XEXP (if_info->cond, 0), | |
1286 XEXP (if_info->cond, 1), | |
1287 if_info->a, if_info->b); | |
1288 | |
1289 if (target) | |
1290 { | |
1291 if (target != if_info->x) | |
1292 noce_emit_move_insn (if_info->x, target); | |
1293 | |
1294 seq = end_ifcvt_sequence (if_info); | |
1295 if (!seq) | |
1296 return FALSE; | |
1297 | |
1298 emit_insn_before_setloc (seq, if_info->jump, | |
1299 INSN_LOCATOR (if_info->insn_a)); | |
1300 return TRUE; | |
1301 } | |
1302 else | |
1303 { | |
1304 end_sequence (); | |
1305 return FALSE; | |
1306 } | |
1307 } | |
1308 | |
1309 return FALSE; | |
1310 } | |
1311 | |
1312 /* Try more complex cases involving conditional_move. */ | |
1313 | |
1314 static int | |
1315 noce_try_cmove_arith (struct noce_if_info *if_info) | |
1316 { | |
1317 rtx a = if_info->a; | |
1318 rtx b = if_info->b; | |
1319 rtx x = if_info->x; | |
1320 rtx orig_a, orig_b; | |
1321 rtx insn_a, insn_b; | |
1322 rtx tmp, target; | |
1323 int is_mem = 0; | |
1324 int insn_cost; | |
1325 enum rtx_code code; | |
1326 | |
1327 /* A conditional move from two memory sources is equivalent to a | |
1328 conditional on their addresses followed by a load. Don't do this | |
1329 early because it'll screw alias analysis. Note that we've | |
1330 already checked for no side effects. */ | |
1331 /* ??? FIXME: Magic number 5. */ | |
1332 if (cse_not_expected | |
1333 && MEM_P (a) && MEM_P (b) | |
1334 && if_info->branch_cost >= 5) | |
1335 { | |
1336 a = XEXP (a, 0); | |
1337 b = XEXP (b, 0); | |
1338 x = gen_reg_rtx (Pmode); | |
1339 is_mem = 1; | |
1340 } | |
1341 | |
1342 /* ??? We could handle this if we knew that a load from A or B could | |
1343 not fault. This is also true if we've already loaded | |
1344 from the address along the path from ENTRY. */ | |
1345 else if (may_trap_p (a) || may_trap_p (b)) | |
1346 return FALSE; | |
1347 | |
1348 /* if (test) x = a + b; else x = c - d; | |
1349 => y = a + b; | |
1350 x = c - d; | |
1351 if (test) | |
1352 x = y; | |
1353 */ | |
1354 | |
1355 code = GET_CODE (if_info->cond); | |
1356 insn_a = if_info->insn_a; | |
1357 insn_b = if_info->insn_b; | |
1358 | |
1359 /* Total insn_rtx_cost should be smaller than branch cost. Exit | |
1360 if insn_rtx_cost can't be estimated. */ | |
1361 if (insn_a) | |
1362 { | |
1363 insn_cost = insn_rtx_cost (PATTERN (insn_a), | |
1364 optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn_a))); | |
1365 if (insn_cost == 0 || insn_cost > COSTS_N_INSNS (if_info->branch_cost)) | |
1366 return FALSE; | |
1367 } | |
1368 else | |
1369 insn_cost = 0; | |
1370 | |
1371 if (insn_b) | |
1372 { | |
1373 insn_cost += insn_rtx_cost (PATTERN (insn_b), | |
1374 optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn_b))); | |
1375 if (insn_cost == 0 || insn_cost > COSTS_N_INSNS (if_info->branch_cost)) | |
1376 return FALSE; | |
1377 } | |
1378 | |
1379 /* Possibly rearrange operands to make things come out more natural. */ | |
1380 if (reversed_comparison_code (if_info->cond, if_info->jump) != UNKNOWN) | |
1381 { | |
1382 int reversep = 0; | |
1383 if (rtx_equal_p (b, x)) | |
1384 reversep = 1; | |
1385 else if (general_operand (b, GET_MODE (b))) | |
1386 reversep = 1; | |
1387 | |
1388 if (reversep) | |
1389 { | |
1390 code = reversed_comparison_code (if_info->cond, if_info->jump); | |
1391 tmp = a, a = b, b = tmp; | |
1392 tmp = insn_a, insn_a = insn_b, insn_b = tmp; | |
1393 } | |
1394 } | |
1395 | |
1396 start_sequence (); | |
1397 | |
1398 orig_a = a; | |
1399 orig_b = b; | |
1400 | |
1401 /* If either operand is complex, load it into a register first. | |
1402 The best way to do this is to copy the original insn. In this | |
1403 way we preserve any clobbers etc that the insn may have had. | |
1404 This is of course not possible in the IS_MEM case. */ | |
1405 if (! general_operand (a, GET_MODE (a))) | |
1406 { | |
1407 rtx set; | |
1408 | |
1409 if (is_mem) | |
1410 { | |
1411 tmp = gen_reg_rtx (GET_MODE (a)); | |
1412 tmp = emit_insn (gen_rtx_SET (VOIDmode, tmp, a)); | |
1413 } | |
1414 else if (! insn_a) | |
1415 goto end_seq_and_fail; | |
1416 else | |
1417 { | |
1418 a = gen_reg_rtx (GET_MODE (a)); | |
1419 tmp = copy_rtx (insn_a); | |
1420 set = single_set (tmp); | |
1421 SET_DEST (set) = a; | |
1422 tmp = emit_insn (PATTERN (tmp)); | |
1423 } | |
1424 if (recog_memoized (tmp) < 0) | |
1425 goto end_seq_and_fail; | |
1426 } | |
1427 if (! general_operand (b, GET_MODE (b))) | |
1428 { | |
1429 rtx set, last; | |
1430 | |
1431 if (is_mem) | |
1432 { | |
1433 tmp = gen_reg_rtx (GET_MODE (b)); | |
1434 tmp = gen_rtx_SET (VOIDmode, tmp, b); | |
1435 } | |
1436 else if (! insn_b) | |
1437 goto end_seq_and_fail; | |
1438 else | |
1439 { | |
1440 b = gen_reg_rtx (GET_MODE (b)); | |
1441 tmp = copy_rtx (insn_b); | |
1442 set = single_set (tmp); | |
1443 SET_DEST (set) = b; | |
1444 tmp = PATTERN (tmp); | |
1445 } | |
1446 | |
1447 /* If insn to set up A clobbers any registers B depends on, try to | |
1448 swap insn that sets up A with the one that sets up B. If even | |
1449 that doesn't help, punt. */ | |
1450 last = get_last_insn (); | |
1451 if (last && modified_in_p (orig_b, last)) | |
1452 { | |
1453 tmp = emit_insn_before (tmp, get_insns ()); | |
1454 if (modified_in_p (orig_a, tmp)) | |
1455 goto end_seq_and_fail; | |
1456 } | |
1457 else | |
1458 tmp = emit_insn (tmp); | |
1459 | |
1460 if (recog_memoized (tmp) < 0) | |
1461 goto end_seq_and_fail; | |
1462 } | |
1463 | |
1464 target = noce_emit_cmove (if_info, x, code, XEXP (if_info->cond, 0), | |
1465 XEXP (if_info->cond, 1), a, b); | |
1466 | |
1467 if (! target) | |
1468 goto end_seq_and_fail; | |
1469 | |
1470 /* If we're handling a memory for above, emit the load now. */ | |
1471 if (is_mem) | |
1472 { | |
1473 tmp = gen_rtx_MEM (GET_MODE (if_info->x), target); | |
1474 | |
1475 /* Copy over flags as appropriate. */ | |
1476 if (MEM_VOLATILE_P (if_info->a) || MEM_VOLATILE_P (if_info->b)) | |
1477 MEM_VOLATILE_P (tmp) = 1; | |
1478 if (MEM_IN_STRUCT_P (if_info->a) && MEM_IN_STRUCT_P (if_info->b)) | |
1479 MEM_IN_STRUCT_P (tmp) = 1; | |
1480 if (MEM_SCALAR_P (if_info->a) && MEM_SCALAR_P (if_info->b)) | |
1481 MEM_SCALAR_P (tmp) = 1; | |
1482 if (MEM_ALIAS_SET (if_info->a) == MEM_ALIAS_SET (if_info->b)) | |
1483 set_mem_alias_set (tmp, MEM_ALIAS_SET (if_info->a)); | |
1484 set_mem_align (tmp, | |
1485 MIN (MEM_ALIGN (if_info->a), MEM_ALIGN (if_info->b))); | |
1486 | |
1487 noce_emit_move_insn (if_info->x, tmp); | |
1488 } | |
1489 else if (target != x) | |
1490 noce_emit_move_insn (x, target); | |
1491 | |
1492 tmp = end_ifcvt_sequence (if_info); | |
1493 if (!tmp) | |
1494 return FALSE; | |
1495 | |
1496 emit_insn_before_setloc (tmp, if_info->jump, INSN_LOCATOR (if_info->insn_a)); | |
1497 return TRUE; | |
1498 | |
1499 end_seq_and_fail: | |
1500 end_sequence (); | |
1501 return FALSE; | |
1502 } | |
1503 | |
1504 /* For most cases, the simplified condition we found is the best | |
1505 choice, but this is not the case for the min/max/abs transforms. | |
1506 For these we wish to know that it is A or B in the condition. */ | |
1507 | |
1508 static rtx | |
1509 noce_get_alt_condition (struct noce_if_info *if_info, rtx target, | |
1510 rtx *earliest) | |
1511 { | |
1512 rtx cond, set, insn; | |
1513 int reverse; | |
1514 | |
1515 /* If target is already mentioned in the known condition, return it. */ | |
1516 if (reg_mentioned_p (target, if_info->cond)) | |
1517 { | |
1518 *earliest = if_info->cond_earliest; | |
1519 return if_info->cond; | |
1520 } | |
1521 | |
1522 set = pc_set (if_info->jump); | |
1523 cond = XEXP (SET_SRC (set), 0); | |
1524 reverse | |
1525 = GET_CODE (XEXP (SET_SRC (set), 2)) == LABEL_REF | |
1526 && XEXP (XEXP (SET_SRC (set), 2), 0) == JUMP_LABEL (if_info->jump); | |
1527 if (if_info->then_else_reversed) | |
1528 reverse = !reverse; | |
1529 | |
1530 /* If we're looking for a constant, try to make the conditional | |
1531 have that constant in it. There are two reasons why it may | |
1532 not have the constant we want: | |
1533 | |
1534 1. GCC may have needed to put the constant in a register, because | |
1535 the target can't compare directly against that constant. For | |
1536 this case, we look for a SET immediately before the comparison | |
1537 that puts a constant in that register. | |
1538 | |
1539 2. GCC may have canonicalized the conditional, for example | |
1540 replacing "if x < 4" with "if x <= 3". We can undo that (or | |
1541 make equivalent types of changes) to get the constants we need | |
1542 if they're off by one in the right direction. */ | |
1543 | |
1544 if (GET_CODE (target) == CONST_INT) | |
1545 { | |
1546 enum rtx_code code = GET_CODE (if_info->cond); | |
1547 rtx op_a = XEXP (if_info->cond, 0); | |
1548 rtx op_b = XEXP (if_info->cond, 1); | |
1549 rtx prev_insn; | |
1550 | |
1551 /* First, look to see if we put a constant in a register. */ | |
1552 prev_insn = prev_nonnote_insn (if_info->cond_earliest); | |
1553 if (prev_insn | |
1554 && BLOCK_NUM (prev_insn) == BLOCK_NUM (if_info->cond_earliest) | |
1555 && INSN_P (prev_insn) | |
1556 && GET_CODE (PATTERN (prev_insn)) == SET) | |
1557 { | |
1558 rtx src = find_reg_equal_equiv_note (prev_insn); | |
1559 if (!src) | |
1560 src = SET_SRC (PATTERN (prev_insn)); | |
1561 if (GET_CODE (src) == CONST_INT) | |
1562 { | |
1563 if (rtx_equal_p (op_a, SET_DEST (PATTERN (prev_insn)))) | |
1564 op_a = src; | |
1565 else if (rtx_equal_p (op_b, SET_DEST (PATTERN (prev_insn)))) | |
1566 op_b = src; | |
1567 | |
1568 if (GET_CODE (op_a) == CONST_INT) | |
1569 { | |
1570 rtx tmp = op_a; | |
1571 op_a = op_b; | |
1572 op_b = tmp; | |
1573 code = swap_condition (code); | |
1574 } | |
1575 } | |
1576 } | |
1577 | |
1578 /* Now, look to see if we can get the right constant by | |
1579 adjusting the conditional. */ | |
1580 if (GET_CODE (op_b) == CONST_INT) | |
1581 { | |
1582 HOST_WIDE_INT desired_val = INTVAL (target); | |
1583 HOST_WIDE_INT actual_val = INTVAL (op_b); | |
1584 | |
1585 switch (code) | |
1586 { | |
1587 case LT: | |
1588 if (actual_val == desired_val + 1) | |
1589 { | |
1590 code = LE; | |
1591 op_b = GEN_INT (desired_val); | |
1592 } | |
1593 break; | |
1594 case LE: | |
1595 if (actual_val == desired_val - 1) | |
1596 { | |
1597 code = LT; | |
1598 op_b = GEN_INT (desired_val); | |
1599 } | |
1600 break; | |
1601 case GT: | |
1602 if (actual_val == desired_val - 1) | |
1603 { | |
1604 code = GE; | |
1605 op_b = GEN_INT (desired_val); | |
1606 } | |
1607 break; | |
1608 case GE: | |
1609 if (actual_val == desired_val + 1) | |
1610 { | |
1611 code = GT; | |
1612 op_b = GEN_INT (desired_val); | |
1613 } | |
1614 break; | |
1615 default: | |
1616 break; | |
1617 } | |
1618 } | |
1619 | |
1620 /* If we made any changes, generate a new conditional that is | |
1621 equivalent to what we started with, but has the right | |
1622 constants in it. */ | |
1623 if (code != GET_CODE (if_info->cond) | |
1624 || op_a != XEXP (if_info->cond, 0) | |
1625 || op_b != XEXP (if_info->cond, 1)) | |
1626 { | |
1627 cond = gen_rtx_fmt_ee (code, GET_MODE (cond), op_a, op_b); | |
1628 *earliest = if_info->cond_earliest; | |
1629 return cond; | |
1630 } | |
1631 } | |
1632 | |
1633 cond = canonicalize_condition (if_info->jump, cond, reverse, | |
1634 earliest, target, false, true); | |
1635 if (! cond || ! reg_mentioned_p (target, cond)) | |
1636 return NULL; | |
1637 | |
1638 /* We almost certainly searched back to a different place. | |
1639 Need to re-verify correct lifetimes. */ | |
1640 | |
1641 /* X may not be mentioned in the range (cond_earliest, jump]. */ | |
1642 for (insn = if_info->jump; insn != *earliest; insn = PREV_INSN (insn)) | |
1643 if (INSN_P (insn) && reg_overlap_mentioned_p (if_info->x, PATTERN (insn))) | |
1644 return NULL; | |
1645 | |
1646 /* A and B may not be modified in the range [cond_earliest, jump). */ | |
1647 for (insn = *earliest; insn != if_info->jump; insn = NEXT_INSN (insn)) | |
1648 if (INSN_P (insn) | |
1649 && (modified_in_p (if_info->a, insn) | |
1650 || modified_in_p (if_info->b, insn))) | |
1651 return NULL; | |
1652 | |
1653 return cond; | |
1654 } | |
1655 | |
1656 /* Convert "if (a < b) x = a; else x = b;" to "x = min(a, b);", etc. */ | |
1657 | |
1658 static int | |
1659 noce_try_minmax (struct noce_if_info *if_info) | |
1660 { | |
1661 rtx cond, earliest, target, seq; | |
1662 enum rtx_code code, op; | |
1663 int unsignedp; | |
1664 | |
1665 /* ??? Reject modes with NaNs or signed zeros since we don't know how | |
1666 they will be resolved with an SMIN/SMAX. It wouldn't be too hard | |
1667 to get the target to tell us... */ | |
1668 if (HONOR_SIGNED_ZEROS (GET_MODE (if_info->x)) | |
1669 || HONOR_NANS (GET_MODE (if_info->x))) | |
1670 return FALSE; | |
1671 | |
1672 cond = noce_get_alt_condition (if_info, if_info->a, &earliest); | |
1673 if (!cond) | |
1674 return FALSE; | |
1675 | |
1676 /* Verify the condition is of the form we expect, and canonicalize | |
1677 the comparison code. */ | |
1678 code = GET_CODE (cond); | |
1679 if (rtx_equal_p (XEXP (cond, 0), if_info->a)) | |
1680 { | |
1681 if (! rtx_equal_p (XEXP (cond, 1), if_info->b)) | |
1682 return FALSE; | |
1683 } | |
1684 else if (rtx_equal_p (XEXP (cond, 1), if_info->a)) | |
1685 { | |
1686 if (! rtx_equal_p (XEXP (cond, 0), if_info->b)) | |
1687 return FALSE; | |
1688 code = swap_condition (code); | |
1689 } | |
1690 else | |
1691 return FALSE; | |
1692 | |
1693 /* Determine what sort of operation this is. Note that the code is for | |
1694 a taken branch, so the code->operation mapping appears backwards. */ | |
1695 switch (code) | |
1696 { | |
1697 case LT: | |
1698 case LE: | |
1699 case UNLT: | |
1700 case UNLE: | |
1701 op = SMAX; | |
1702 unsignedp = 0; | |
1703 break; | |
1704 case GT: | |
1705 case GE: | |
1706 case UNGT: | |
1707 case UNGE: | |
1708 op = SMIN; | |
1709 unsignedp = 0; | |
1710 break; | |
1711 case LTU: | |
1712 case LEU: | |
1713 op = UMAX; | |
1714 unsignedp = 1; | |
1715 break; | |
1716 case GTU: | |
1717 case GEU: | |
1718 op = UMIN; | |
1719 unsignedp = 1; | |
1720 break; | |
1721 default: | |
1722 return FALSE; | |
1723 } | |
1724 | |
1725 start_sequence (); | |
1726 | |
1727 target = expand_simple_binop (GET_MODE (if_info->x), op, | |
1728 if_info->a, if_info->b, | |
1729 if_info->x, unsignedp, OPTAB_WIDEN); | |
1730 if (! target) | |
1731 { | |
1732 end_sequence (); | |
1733 return FALSE; | |
1734 } | |
1735 if (target != if_info->x) | |
1736 noce_emit_move_insn (if_info->x, target); | |
1737 | |
1738 seq = end_ifcvt_sequence (if_info); | |
1739 if (!seq) | |
1740 return FALSE; | |
1741 | |
1742 emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATOR (if_info->insn_a)); | |
1743 if_info->cond = cond; | |
1744 if_info->cond_earliest = earliest; | |
1745 | |
1746 return TRUE; | |
1747 } | |
1748 | |
1749 /* Convert "if (a < 0) x = -a; else x = a;" to "x = abs(a);", etc. */ | |
1750 | |
1751 static int | |
1752 noce_try_abs (struct noce_if_info *if_info) | |
1753 { | |
1754 rtx cond, earliest, target, seq, a, b, c; | |
1755 int negate; | |
1756 | |
1757 /* Reject modes with signed zeros. */ | |
1758 if (HONOR_SIGNED_ZEROS (GET_MODE (if_info->x))) | |
1759 return FALSE; | |
1760 | |
1761 /* Recognize A and B as constituting an ABS or NABS. The canonical | |
1762 form is a branch around the negation, taken when the object is the | |
1763 first operand of a comparison against 0 that evaluates to true. */ | |
1764 a = if_info->a; | |
1765 b = if_info->b; | |
1766 if (GET_CODE (a) == NEG && rtx_equal_p (XEXP (a, 0), b)) | |
1767 negate = 0; | |
1768 else if (GET_CODE (b) == NEG && rtx_equal_p (XEXP (b, 0), a)) | |
1769 { | |
1770 c = a; a = b; b = c; | |
1771 negate = 1; | |
1772 } | |
1773 else | |
1774 return FALSE; | |
1775 | |
1776 cond = noce_get_alt_condition (if_info, b, &earliest); | |
1777 if (!cond) | |
1778 return FALSE; | |
1779 | |
1780 /* Verify the condition is of the form we expect. */ | |
1781 if (rtx_equal_p (XEXP (cond, 0), b)) | |
1782 c = XEXP (cond, 1); | |
1783 else if (rtx_equal_p (XEXP (cond, 1), b)) | |
1784 { | |
1785 c = XEXP (cond, 0); | |
1786 negate = !negate; | |
1787 } | |
1788 else | |
1789 return FALSE; | |
1790 | |
1791 /* Verify that C is zero. Search one step backward for a | |
1792 REG_EQUAL note or a simple source if necessary. */ | |
1793 if (REG_P (c)) | |
1794 { | |
1795 rtx set, insn = prev_nonnote_insn (earliest); | |
1796 if (insn | |
1797 && BLOCK_NUM (insn) == BLOCK_NUM (earliest) | |
1798 && (set = single_set (insn)) | |
1799 && rtx_equal_p (SET_DEST (set), c)) | |
1800 { | |
1801 rtx note = find_reg_equal_equiv_note (insn); | |
1802 if (note) | |
1803 c = XEXP (note, 0); | |
1804 else | |
1805 c = SET_SRC (set); | |
1806 } | |
1807 else | |
1808 return FALSE; | |
1809 } | |
1810 if (MEM_P (c) | |
1811 && GET_CODE (XEXP (c, 0)) == SYMBOL_REF | |
1812 && CONSTANT_POOL_ADDRESS_P (XEXP (c, 0))) | |
1813 c = get_pool_constant (XEXP (c, 0)); | |
1814 | |
1815 /* Work around funny ideas get_condition has wrt canonicalization. | |
1816 Note that these rtx constants are known to be CONST_INT, and | |
1817 therefore imply integer comparisons. */ | |
1818 if (c == constm1_rtx && GET_CODE (cond) == GT) | |
1819 ; | |
1820 else if (c == const1_rtx && GET_CODE (cond) == LT) | |
1821 ; | |
1822 else if (c != CONST0_RTX (GET_MODE (b))) | |
1823 return FALSE; | |
1824 | |
1825 /* Determine what sort of operation this is. */ | |
1826 switch (GET_CODE (cond)) | |
1827 { | |
1828 case LT: | |
1829 case LE: | |
1830 case UNLT: | |
1831 case UNLE: | |
1832 negate = !negate; | |
1833 break; | |
1834 case GT: | |
1835 case GE: | |
1836 case UNGT: | |
1837 case UNGE: | |
1838 break; | |
1839 default: | |
1840 return FALSE; | |
1841 } | |
1842 | |
1843 start_sequence (); | |
1844 | |
1845 target = expand_abs_nojump (GET_MODE (if_info->x), b, if_info->x, 1); | |
1846 | |
1847 /* ??? It's a quandary whether cmove would be better here, especially | |
1848 for integers. Perhaps combine will clean things up. */ | |
1849 if (target && negate) | |
1850 target = expand_simple_unop (GET_MODE (target), NEG, target, if_info->x, 0); | |
1851 | |
1852 if (! target) | |
1853 { | |
1854 end_sequence (); | |
1855 return FALSE; | |
1856 } | |
1857 | |
1858 if (target != if_info->x) | |
1859 noce_emit_move_insn (if_info->x, target); | |
1860 | |
1861 seq = end_ifcvt_sequence (if_info); | |
1862 if (!seq) | |
1863 return FALSE; | |
1864 | |
1865 emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATOR (if_info->insn_a)); | |
1866 if_info->cond = cond; | |
1867 if_info->cond_earliest = earliest; | |
1868 | |
1869 return TRUE; | |
1870 } | |
1871 | |
1872 /* Convert "if (m < 0) x = b; else x = 0;" to "x = (m >> C) & b;". */ | |
1873 | |
1874 static int | |
1875 noce_try_sign_mask (struct noce_if_info *if_info) | |
1876 { | |
1877 rtx cond, t, m, c, seq; | |
1878 enum machine_mode mode; | |
1879 enum rtx_code code; | |
1880 bool t_unconditional; | |
1881 | |
1882 cond = if_info->cond; | |
1883 code = GET_CODE (cond); | |
1884 m = XEXP (cond, 0); | |
1885 c = XEXP (cond, 1); | |
1886 | |
1887 t = NULL_RTX; | |
1888 if (if_info->a == const0_rtx) | |
1889 { | |
1890 if ((code == LT && c == const0_rtx) | |
1891 || (code == LE && c == constm1_rtx)) | |
1892 t = if_info->b; | |
1893 } | |
1894 else if (if_info->b == const0_rtx) | |
1895 { | |
1896 if ((code == GE && c == const0_rtx) | |
1897 || (code == GT && c == constm1_rtx)) | |
1898 t = if_info->a; | |
1899 } | |
1900 | |
1901 if (! t || side_effects_p (t)) | |
1902 return FALSE; | |
1903 | |
1904 /* We currently don't handle different modes. */ | |
1905 mode = GET_MODE (t); | |
1906 if (GET_MODE (m) != mode) | |
1907 return FALSE; | |
1908 | |
1909 /* This is only profitable if T is unconditionally executed/evaluated in the | |
1910 original insn sequence or T is cheap. The former happens if B is the | |
1911 non-zero (T) value and if INSN_B was taken from TEST_BB, or there was no | |
1912 INSN_B which can happen for e.g. conditional stores to memory. For the | |
1913 cost computation use the block TEST_BB where the evaluation will end up | |
1914 after the transformation. */ | |
1915 t_unconditional = | |
1916 (t == if_info->b | |
1917 && (if_info->insn_b == NULL_RTX | |
1918 || BLOCK_FOR_INSN (if_info->insn_b) == if_info->test_bb)); | |
1919 if (!(t_unconditional | |
1920 || (rtx_cost (t, SET, optimize_bb_for_speed_p (if_info->test_bb)) | |
1921 < COSTS_N_INSNS (2)))) | |
1922 return FALSE; | |
1923 | |
1924 start_sequence (); | |
1925 /* Use emit_store_flag to generate "m < 0 ? -1 : 0" instead of expanding | |
1926 "(signed) m >> 31" directly. This benefits targets with specialized | |
1927 insns to obtain the signmask, but still uses ashr_optab otherwise. */ | |
1928 m = emit_store_flag (gen_reg_rtx (mode), LT, m, const0_rtx, mode, 0, -1); | |
1929 t = m ? expand_binop (mode, and_optab, m, t, NULL_RTX, 0, OPTAB_DIRECT) | |
1930 : NULL_RTX; | |
1931 | |
1932 if (!t) | |
1933 { | |
1934 end_sequence (); | |
1935 return FALSE; | |
1936 } | |
1937 | |
1938 noce_emit_move_insn (if_info->x, t); | |
1939 | |
1940 seq = end_ifcvt_sequence (if_info); | |
1941 if (!seq) | |
1942 return FALSE; | |
1943 | |
1944 emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATOR (if_info->insn_a)); | |
1945 return TRUE; | |
1946 } | |
1947 | |
1948 | |
1949 /* Optimize away "if (x & C) x |= C" and similar bit manipulation | |
1950 transformations. */ | |
1951 | |
1952 static int | |
1953 noce_try_bitop (struct noce_if_info *if_info) | |
1954 { | |
1955 rtx cond, x, a, result, seq; | |
1956 enum machine_mode mode; | |
1957 enum rtx_code code; | |
1958 int bitnum; | |
1959 | |
1960 x = if_info->x; | |
1961 cond = if_info->cond; | |
1962 code = GET_CODE (cond); | |
1963 | |
1964 /* Check for no else condition. */ | |
1965 if (! rtx_equal_p (x, if_info->b)) | |
1966 return FALSE; | |
1967 | |
1968 /* Check for a suitable condition. */ | |
1969 if (code != NE && code != EQ) | |
1970 return FALSE; | |
1971 if (XEXP (cond, 1) != const0_rtx) | |
1972 return FALSE; | |
1973 cond = XEXP (cond, 0); | |
1974 | |
1975 /* ??? We could also handle AND here. */ | |
1976 if (GET_CODE (cond) == ZERO_EXTRACT) | |
1977 { | |
1978 if (XEXP (cond, 1) != const1_rtx | |
1979 || GET_CODE (XEXP (cond, 2)) != CONST_INT | |
1980 || ! rtx_equal_p (x, XEXP (cond, 0))) | |
1981 return FALSE; | |
1982 bitnum = INTVAL (XEXP (cond, 2)); | |
1983 mode = GET_MODE (x); | |
1984 if (BITS_BIG_ENDIAN) | |
1985 bitnum = GET_MODE_BITSIZE (mode) - 1 - bitnum; | |
1986 if (bitnum < 0 || bitnum >= HOST_BITS_PER_WIDE_INT) | |
1987 return FALSE; | |
1988 } | |
1989 else | |
1990 return FALSE; | |
1991 | |
1992 a = if_info->a; | |
1993 if (GET_CODE (a) == IOR || GET_CODE (a) == XOR) | |
1994 { | |
1995 /* Check for "if (X & C) x = x op C". */ | |
1996 if (! rtx_equal_p (x, XEXP (a, 0)) | |
1997 || GET_CODE (XEXP (a, 1)) != CONST_INT | |
1998 || (INTVAL (XEXP (a, 1)) & GET_MODE_MASK (mode)) | |
1999 != (unsigned HOST_WIDE_INT) 1 << bitnum) | |
2000 return FALSE; | |
2001 | |
2002 /* if ((x & C) == 0) x |= C; is transformed to x |= C. */ | |
2003 /* if ((x & C) != 0) x |= C; is transformed to nothing. */ | |
2004 if (GET_CODE (a) == IOR) | |
2005 result = (code == NE) ? a : NULL_RTX; | |
2006 else if (code == NE) | |
2007 { | |
2008 /* if ((x & C) == 0) x ^= C; is transformed to x |= C. */ | |
2009 result = gen_int_mode ((HOST_WIDE_INT) 1 << bitnum, mode); | |
2010 result = simplify_gen_binary (IOR, mode, x, result); | |
2011 } | |
2012 else | |
2013 { | |
2014 /* if ((x & C) != 0) x ^= C; is transformed to x &= ~C. */ | |
2015 result = gen_int_mode (~((HOST_WIDE_INT) 1 << bitnum), mode); | |
2016 result = simplify_gen_binary (AND, mode, x, result); | |
2017 } | |
2018 } | |
2019 else if (GET_CODE (a) == AND) | |
2020 { | |
2021 /* Check for "if (X & C) x &= ~C". */ | |
2022 if (! rtx_equal_p (x, XEXP (a, 0)) | |
2023 || GET_CODE (XEXP (a, 1)) != CONST_INT | |
2024 || (INTVAL (XEXP (a, 1)) & GET_MODE_MASK (mode)) | |
2025 != (~((HOST_WIDE_INT) 1 << bitnum) & GET_MODE_MASK (mode))) | |
2026 return FALSE; | |
2027 | |
2028 /* if ((x & C) == 0) x &= ~C; is transformed to nothing. */ | |
2029 /* if ((x & C) != 0) x &= ~C; is transformed to x &= ~C. */ | |
2030 result = (code == EQ) ? a : NULL_RTX; | |
2031 } | |
2032 else | |
2033 return FALSE; | |
2034 | |
2035 if (result) | |
2036 { | |
2037 start_sequence (); | |
2038 noce_emit_move_insn (x, result); | |
2039 seq = end_ifcvt_sequence (if_info); | |
2040 if (!seq) | |
2041 return FALSE; | |
2042 | |
2043 emit_insn_before_setloc (seq, if_info->jump, | |
2044 INSN_LOCATOR (if_info->insn_a)); | |
2045 } | |
2046 return TRUE; | |
2047 } | |
2048 | |
2049 | |
2050 /* Similar to get_condition, only the resulting condition must be | |
2051 valid at JUMP, instead of at EARLIEST. | |
2052 | |
2053 If THEN_ELSE_REVERSED is true, the fallthrough does not go to the | |
2054 THEN block of the caller, and we have to reverse the condition. */ | |
2055 | |
2056 static rtx | |
2057 noce_get_condition (rtx jump, rtx *earliest, bool then_else_reversed) | |
2058 { | |
2059 rtx cond, set, tmp; | |
2060 bool reverse; | |
2061 | |
2062 if (! any_condjump_p (jump)) | |
2063 return NULL_RTX; | |
2064 | |
2065 set = pc_set (jump); | |
2066 | |
2067 /* If this branches to JUMP_LABEL when the condition is false, | |
2068 reverse the condition. */ | |
2069 reverse = (GET_CODE (XEXP (SET_SRC (set), 2)) == LABEL_REF | |
2070 && XEXP (XEXP (SET_SRC (set), 2), 0) == JUMP_LABEL (jump)); | |
2071 | |
2072 /* We may have to reverse because the caller's if block is not canonical, | |
2073 i.e. the THEN block isn't the fallthrough block for the TEST block | |
2074 (see find_if_header). */ | |
2075 if (then_else_reversed) | |
2076 reverse = !reverse; | |
2077 | |
2078 /* If the condition variable is a register and is MODE_INT, accept it. */ | |
2079 | |
2080 cond = XEXP (SET_SRC (set), 0); | |
2081 tmp = XEXP (cond, 0); | |
2082 if (REG_P (tmp) && GET_MODE_CLASS (GET_MODE (tmp)) == MODE_INT) | |
2083 { | |
2084 *earliest = jump; | |
2085 | |
2086 if (reverse) | |
2087 cond = gen_rtx_fmt_ee (reverse_condition (GET_CODE (cond)), | |
2088 GET_MODE (cond), tmp, XEXP (cond, 1)); | |
2089 return cond; | |
2090 } | |
2091 | |
2092 /* Otherwise, fall back on canonicalize_condition to do the dirty | |
2093 work of manipulating MODE_CC values and COMPARE rtx codes. */ | |
2094 return canonicalize_condition (jump, cond, reverse, earliest, | |
2095 NULL_RTX, false, true); | |
2096 } | |
2097 | |
2098 /* Return true if OP is ok for if-then-else processing. */ | |
2099 | |
2100 static int | |
2101 noce_operand_ok (const_rtx op) | |
2102 { | |
2103 /* We special-case memories, so handle any of them with | |
2104 no address side effects. */ | |
2105 if (MEM_P (op)) | |
2106 return ! side_effects_p (XEXP (op, 0)); | |
2107 | |
2108 if (side_effects_p (op)) | |
2109 return FALSE; | |
2110 | |
2111 return ! may_trap_p (op); | |
2112 } | |
2113 | |
2114 /* Return true if a write into MEM may trap or fault. */ | |
2115 | |
2116 static bool | |
2117 noce_mem_write_may_trap_or_fault_p (const_rtx mem) | |
2118 { | |
2119 rtx addr; | |
2120 | |
2121 if (MEM_READONLY_P (mem)) | |
2122 return true; | |
2123 | |
2124 if (may_trap_or_fault_p (mem)) | |
2125 return true; | |
2126 | |
2127 addr = XEXP (mem, 0); | |
2128 | |
2129 /* Call target hook to avoid the effects of -fpic etc.... */ | |
2130 addr = targetm.delegitimize_address (addr); | |
2131 | |
2132 while (addr) | |
2133 switch (GET_CODE (addr)) | |
2134 { | |
2135 case CONST: | |
2136 case PRE_DEC: | |
2137 case PRE_INC: | |
2138 case POST_DEC: | |
2139 case POST_INC: | |
2140 case POST_MODIFY: | |
2141 addr = XEXP (addr, 0); | |
2142 break; | |
2143 case LO_SUM: | |
2144 case PRE_MODIFY: | |
2145 addr = XEXP (addr, 1); | |
2146 break; | |
2147 case PLUS: | |
2148 if (GET_CODE (XEXP (addr, 1)) == CONST_INT) | |
2149 addr = XEXP (addr, 0); | |
2150 else | |
2151 return false; | |
2152 break; | |
2153 case LABEL_REF: | |
2154 return true; | |
2155 case SYMBOL_REF: | |
2156 if (SYMBOL_REF_DECL (addr) | |
2157 && decl_readonly_section (SYMBOL_REF_DECL (addr), 0)) | |
2158 return true; | |
2159 return false; | |
2160 default: | |
2161 return false; | |
2162 } | |
2163 | |
2164 return false; | |
2165 } | |
2166 | |
2167 /* Return whether we can use store speculation for MEM. TOP_BB is the | |
2168 basic block above the conditional block where we are considering | |
2169 doing the speculative store. We look for whether MEM is set | |
2170 unconditionally later in the function. */ | |
2171 | |
2172 static bool | |
2173 noce_can_store_speculate_p (basic_block top_bb, const_rtx mem) | |
2174 { | |
2175 basic_block dominator; | |
2176 | |
2177 for (dominator = get_immediate_dominator (CDI_POST_DOMINATORS, top_bb); | |
2178 dominator != NULL; | |
2179 dominator = get_immediate_dominator (CDI_POST_DOMINATORS, dominator)) | |
2180 { | |
2181 rtx insn; | |
2182 | |
2183 FOR_BB_INSNS (dominator, insn) | |
2184 { | |
2185 /* If we see something that might be a memory barrier, we | |
2186 have to stop looking. Even if the MEM is set later in | |
2187 the function, we still don't want to set it | |
2188 unconditionally before the barrier. */ | |
2189 if (INSN_P (insn) | |
2190 && (volatile_insn_p (PATTERN (insn)) | |
2191 || (CALL_P (insn) && (!RTL_CONST_CALL_P (insn))))) | |
2192 return false; | |
2193 | |
2194 if (memory_modified_in_insn_p (mem, insn)) | |
2195 return true; | |
2196 if (modified_in_p (XEXP (mem, 0), insn)) | |
2197 return false; | |
2198 | |
2199 } | |
2200 } | |
2201 | |
2202 return false; | |
2203 } | |
2204 | |
2205 /* Given a simple IF-THEN-JOIN or IF-THEN-ELSE-JOIN block, attempt to convert | |
2206 it without using conditional execution. Return TRUE if we were successful | |
2207 at converting the block. */ | |
2208 | |
2209 static int | |
2210 noce_process_if_block (struct noce_if_info *if_info) | |
2211 { | |
2212 basic_block test_bb = if_info->test_bb; /* test block */ | |
2213 basic_block then_bb = if_info->then_bb; /* THEN */ | |
2214 basic_block else_bb = if_info->else_bb; /* ELSE or NULL */ | |
2215 basic_block join_bb = if_info->join_bb; /* JOIN */ | |
2216 rtx jump = if_info->jump; | |
2217 rtx cond = if_info->cond; | |
2218 rtx insn_a, insn_b; | |
2219 rtx set_a, set_b; | |
2220 rtx orig_x, x, a, b; | |
2221 | |
2222 /* We're looking for patterns of the form | |
2223 | |
2224 (1) if (...) x = a; else x = b; | |
2225 (2) x = b; if (...) x = a; | |
2226 (3) if (...) x = a; // as if with an initial x = x. | |
2227 | |
2228 The later patterns require jumps to be more expensive. | |
2229 | |
2230 ??? For future expansion, look for multiple X in such patterns. */ | |
2231 | |
2232 /* Look for one of the potential sets. */ | |
2233 insn_a = first_active_insn (then_bb); | |
2234 if (! insn_a | |
2235 || insn_a != last_active_insn (then_bb, FALSE) | |
2236 || (set_a = single_set (insn_a)) == NULL_RTX) | |
2237 return FALSE; | |
2238 | |
2239 x = SET_DEST (set_a); | |
2240 a = SET_SRC (set_a); | |
2241 | |
2242 /* Look for the other potential set. Make sure we've got equivalent | |
2243 destinations. */ | |
2244 /* ??? This is overconservative. Storing to two different mems is | |
2245 as easy as conditionally computing the address. Storing to a | |
2246 single mem merely requires a scratch memory to use as one of the | |
2247 destination addresses; often the memory immediately below the | |
2248 stack pointer is available for this. */ | |
2249 set_b = NULL_RTX; | |
2250 if (else_bb) | |
2251 { | |
2252 insn_b = first_active_insn (else_bb); | |
2253 if (! insn_b | |
2254 || insn_b != last_active_insn (else_bb, FALSE) | |
2255 || (set_b = single_set (insn_b)) == NULL_RTX | |
2256 || ! rtx_equal_p (x, SET_DEST (set_b))) | |
2257 return FALSE; | |
2258 } | |
2259 else | |
2260 { | |
2261 insn_b = prev_nonnote_insn (if_info->cond_earliest); | |
2262 /* We're going to be moving the evaluation of B down from above | |
2263 COND_EARLIEST to JUMP. Make sure the relevant data is still | |
2264 intact. */ | |
2265 if (! insn_b | |
2266 || BLOCK_NUM (insn_b) != BLOCK_NUM (if_info->cond_earliest) | |
2267 || !NONJUMP_INSN_P (insn_b) | |
2268 || (set_b = single_set (insn_b)) == NULL_RTX | |
2269 || ! rtx_equal_p (x, SET_DEST (set_b)) | |
2270 || ! noce_operand_ok (SET_SRC (set_b)) | |
2271 || reg_overlap_mentioned_p (x, SET_SRC (set_b)) | |
2272 || modified_between_p (SET_SRC (set_b), | |
2273 PREV_INSN (if_info->cond_earliest), jump) | |
2274 /* Likewise with X. In particular this can happen when | |
2275 noce_get_condition looks farther back in the instruction | |
2276 stream than one might expect. */ | |
2277 || reg_overlap_mentioned_p (x, cond) | |
2278 || reg_overlap_mentioned_p (x, a) | |
2279 || modified_between_p (x, PREV_INSN (if_info->cond_earliest), jump)) | |
2280 insn_b = set_b = NULL_RTX; | |
2281 } | |
2282 | |
2283 /* If x has side effects then only the if-then-else form is safe to | |
2284 convert. But even in that case we would need to restore any notes | |
2285 (such as REG_INC) at then end. That can be tricky if | |
2286 noce_emit_move_insn expands to more than one insn, so disable the | |
2287 optimization entirely for now if there are side effects. */ | |
2288 if (side_effects_p (x)) | |
2289 return FALSE; | |
2290 | |
2291 b = (set_b ? SET_SRC (set_b) : x); | |
2292 | |
2293 /* Only operate on register destinations, and even then avoid extending | |
2294 the lifetime of hard registers on small register class machines. */ | |
2295 orig_x = x; | |
2296 if (!REG_P (x) | |
2297 || (SMALL_REGISTER_CLASSES | |
2298 && REGNO (x) < FIRST_PSEUDO_REGISTER)) | |
2299 { | |
2300 if (GET_MODE (x) == BLKmode) | |
2301 return FALSE; | |
2302 | |
2303 if (GET_CODE (x) == ZERO_EXTRACT | |
2304 && (GET_CODE (XEXP (x, 1)) != CONST_INT | |
2305 || GET_CODE (XEXP (x, 2)) != CONST_INT)) | |
2306 return FALSE; | |
2307 | |
2308 x = gen_reg_rtx (GET_MODE (GET_CODE (x) == STRICT_LOW_PART | |
2309 ? XEXP (x, 0) : x)); | |
2310 } | |
2311 | |
2312 /* Don't operate on sources that may trap or are volatile. */ | |
2313 if (! noce_operand_ok (a) || ! noce_operand_ok (b)) | |
2314 return FALSE; | |
2315 | |
2316 retry: | |
2317 /* Set up the info block for our subroutines. */ | |
2318 if_info->insn_a = insn_a; | |
2319 if_info->insn_b = insn_b; | |
2320 if_info->x = x; | |
2321 if_info->a = a; | |
2322 if_info->b = b; | |
2323 | |
2324 /* Try optimizations in some approximation of a useful order. */ | |
2325 /* ??? Should first look to see if X is live incoming at all. If it | |
2326 isn't, we don't need anything but an unconditional set. */ | |
2327 | |
2328 /* Look and see if A and B are really the same. Avoid creating silly | |
2329 cmove constructs that no one will fix up later. */ | |
2330 if (rtx_equal_p (a, b)) | |
2331 { | |
2332 /* If we have an INSN_B, we don't have to create any new rtl. Just | |
2333 move the instruction that we already have. If we don't have an | |
2334 INSN_B, that means that A == X, and we've got a noop move. In | |
2335 that case don't do anything and let the code below delete INSN_A. */ | |
2336 if (insn_b && else_bb) | |
2337 { | |
2338 rtx note; | |
2339 | |
2340 if (else_bb && insn_b == BB_END (else_bb)) | |
2341 BB_END (else_bb) = PREV_INSN (insn_b); | |
2342 reorder_insns (insn_b, insn_b, PREV_INSN (jump)); | |
2343 | |
2344 /* If there was a REG_EQUAL note, delete it since it may have been | |
2345 true due to this insn being after a jump. */ | |
2346 if ((note = find_reg_note (insn_b, REG_EQUAL, NULL_RTX)) != 0) | |
2347 remove_note (insn_b, note); | |
2348 | |
2349 insn_b = NULL_RTX; | |
2350 } | |
2351 /* If we have "x = b; if (...) x = a;", and x has side-effects, then | |
2352 x must be executed twice. */ | |
2353 else if (insn_b && side_effects_p (orig_x)) | |
2354 return FALSE; | |
2355 | |
2356 x = orig_x; | |
2357 goto success; | |
2358 } | |
2359 | |
2360 if (!set_b && MEM_P (orig_x)) | |
2361 { | |
2362 /* Disallow the "if (...) x = a;" form (implicit "else x = x;") | |
2363 for optimizations if writing to x may trap or fault, | |
2364 i.e. it's a memory other than a static var or a stack slot, | |
2365 is misaligned on strict aligned machines or is read-only. If | |
2366 x is a read-only memory, then the program is valid only if we | |
2367 avoid the store into it. If there are stores on both the | |
2368 THEN and ELSE arms, then we can go ahead with the conversion; | |
2369 either the program is broken, or the condition is always | |
2370 false such that the other memory is selected. */ | |
2371 if (noce_mem_write_may_trap_or_fault_p (orig_x)) | |
2372 return FALSE; | |
2373 | |
2374 /* Avoid store speculation: given "if (...) x = a" where x is a | |
2375 MEM, we only want to do the store if x is always set | |
2376 somewhere in the function. This avoids cases like | |
2377 if (pthread_mutex_trylock(mutex)) | |
2378 ++global_variable; | |
2379 where we only want global_variable to be changed if the mutex | |
2380 is held. FIXME: This should ideally be expressed directly in | |
2381 RTL somehow. */ | |
2382 if (!noce_can_store_speculate_p (test_bb, orig_x)) | |
2383 return FALSE; | |
2384 } | |
2385 | |
2386 if (noce_try_move (if_info)) | |
2387 goto success; | |
2388 if (noce_try_store_flag (if_info)) | |
2389 goto success; | |
2390 if (noce_try_bitop (if_info)) | |
2391 goto success; | |
2392 if (noce_try_minmax (if_info)) | |
2393 goto success; | |
2394 if (noce_try_abs (if_info)) | |
2395 goto success; | |
2396 if (HAVE_conditional_move | |
2397 && noce_try_cmove (if_info)) | |
2398 goto success; | |
2399 if (! HAVE_conditional_execution) | |
2400 { | |
2401 if (noce_try_store_flag_constants (if_info)) | |
2402 goto success; | |
2403 if (noce_try_addcc (if_info)) | |
2404 goto success; | |
2405 if (noce_try_store_flag_mask (if_info)) | |
2406 goto success; | |
2407 if (HAVE_conditional_move | |
2408 && noce_try_cmove_arith (if_info)) | |
2409 goto success; | |
2410 if (noce_try_sign_mask (if_info)) | |
2411 goto success; | |
2412 } | |
2413 | |
2414 if (!else_bb && set_b) | |
2415 { | |
2416 insn_b = set_b = NULL_RTX; | |
2417 b = orig_x; | |
2418 goto retry; | |
2419 } | |
2420 | |
2421 return FALSE; | |
2422 | |
2423 success: | |
2424 | |
2425 /* If we used a temporary, fix it up now. */ | |
2426 if (orig_x != x) | |
2427 { | |
2428 rtx seq; | |
2429 | |
2430 start_sequence (); | |
2431 noce_emit_move_insn (orig_x, x); | |
2432 seq = get_insns (); | |
2433 set_used_flags (orig_x); | |
2434 unshare_all_rtl_in_chain (seq); | |
2435 end_sequence (); | |
2436 | |
2437 emit_insn_before_setloc (seq, BB_END (test_bb), INSN_LOCATOR (insn_a)); | |
2438 } | |
2439 | |
2440 /* The original THEN and ELSE blocks may now be removed. The test block | |
2441 must now jump to the join block. If the test block and the join block | |
2442 can be merged, do so. */ | |
2443 if (else_bb) | |
2444 { | |
2445 delete_basic_block (else_bb); | |
2446 num_true_changes++; | |
2447 } | |
2448 else | |
2449 remove_edge (find_edge (test_bb, join_bb)); | |
2450 | |
2451 remove_edge (find_edge (then_bb, join_bb)); | |
2452 redirect_edge_and_branch_force (single_succ_edge (test_bb), join_bb); | |
2453 delete_basic_block (then_bb); | |
2454 num_true_changes++; | |
2455 | |
2456 if (can_merge_blocks_p (test_bb, join_bb)) | |
2457 { | |
2458 merge_blocks (test_bb, join_bb); | |
2459 num_true_changes++; | |
2460 } | |
2461 | |
2462 num_updated_if_blocks++; | |
2463 return TRUE; | |
2464 } | |
2465 | |
2466 /* Check whether a block is suitable for conditional move conversion. | |
2467 Every insn must be a simple set of a register to a constant or a | |
2468 register. For each assignment, store the value in the array VALS, | |
2469 indexed by register number, then store the register number in | |
2470 REGS. COND is the condition we will test. */ | |
2471 | |
2472 static int | |
2473 check_cond_move_block (basic_block bb, rtx *vals, VEC (int, heap) **regs, rtx cond) | |
2474 { | |
2475 rtx insn; | |
2476 | |
2477 /* We can only handle simple jumps at the end of the basic block. | |
2478 It is almost impossible to update the CFG otherwise. */ | |
2479 insn = BB_END (bb); | |
2480 if (JUMP_P (insn) && !onlyjump_p (insn)) | |
2481 return FALSE; | |
2482 | |
2483 FOR_BB_INSNS (bb, insn) | |
2484 { | |
2485 rtx set, dest, src; | |
2486 | |
2487 if (!INSN_P (insn) || JUMP_P (insn)) | |
2488 continue; | |
2489 set = single_set (insn); | |
2490 if (!set) | |
2491 return FALSE; | |
2492 | |
2493 dest = SET_DEST (set); | |
2494 src = SET_SRC (set); | |
2495 if (!REG_P (dest) | |
2496 || (SMALL_REGISTER_CLASSES && HARD_REGISTER_P (dest))) | |
2497 return FALSE; | |
2498 | |
2499 if (!CONSTANT_P (src) && !register_operand (src, VOIDmode)) | |
2500 return FALSE; | |
2501 | |
2502 if (side_effects_p (src) || side_effects_p (dest)) | |
2503 return FALSE; | |
2504 | |
2505 if (may_trap_p (src) || may_trap_p (dest)) | |
2506 return FALSE; | |
2507 | |
2508 /* Don't try to handle this if the source register was | |
2509 modified earlier in the block. */ | |
2510 if ((REG_P (src) | |
2511 && vals[REGNO (src)] != NULL) | |
2512 || (GET_CODE (src) == SUBREG && REG_P (SUBREG_REG (src)) | |
2513 && vals[REGNO (SUBREG_REG (src))] != NULL)) | |
2514 return FALSE; | |
2515 | |
2516 /* Don't try to handle this if the destination register was | |
2517 modified earlier in the block. */ | |
2518 if (vals[REGNO (dest)] != NULL) | |
2519 return FALSE; | |
2520 | |
2521 /* Don't try to handle this if the condition uses the | |
2522 destination register. */ | |
2523 if (reg_overlap_mentioned_p (dest, cond)) | |
2524 return FALSE; | |
2525 | |
2526 /* Don't try to handle this if the source register is modified | |
2527 later in the block. */ | |
2528 if (!CONSTANT_P (src) | |
2529 && modified_between_p (src, insn, NEXT_INSN (BB_END (bb)))) | |
2530 return FALSE; | |
2531 | |
2532 vals[REGNO (dest)] = src; | |
2533 | |
2534 VEC_safe_push (int, heap, *regs, REGNO (dest)); | |
2535 } | |
2536 | |
2537 return TRUE; | |
2538 } | |
2539 | |
2540 /* Given a basic block BB suitable for conditional move conversion, | |
2541 a condition COND, and arrays THEN_VALS and ELSE_VALS containing the | |
2542 register values depending on COND, emit the insns in the block as | |
2543 conditional moves. If ELSE_BLOCK is true, THEN_BB was already | |
2544 processed. The caller has started a sequence for the conversion. | |
2545 Return true if successful, false if something goes wrong. */ | |
2546 | |
2547 static bool | |
2548 cond_move_convert_if_block (struct noce_if_info *if_infop, | |
2549 basic_block bb, rtx cond, | |
2550 rtx *then_vals, rtx *else_vals, | |
2551 bool else_block_p) | |
2552 { | |
2553 enum rtx_code code; | |
2554 rtx insn, cond_arg0, cond_arg1; | |
2555 | |
2556 code = GET_CODE (cond); | |
2557 cond_arg0 = XEXP (cond, 0); | |
2558 cond_arg1 = XEXP (cond, 1); | |
2559 | |
2560 FOR_BB_INSNS (bb, insn) | |
2561 { | |
2562 rtx set, target, dest, t, e; | |
2563 unsigned int regno; | |
2564 | |
2565 if (!INSN_P (insn) || JUMP_P (insn)) | |
2566 continue; | |
2567 set = single_set (insn); | |
2568 gcc_assert (set && REG_P (SET_DEST (set))); | |
2569 | |
2570 dest = SET_DEST (set); | |
2571 regno = REGNO (dest); | |
2572 | |
2573 t = then_vals[regno]; | |
2574 e = else_vals[regno]; | |
2575 | |
2576 if (else_block_p) | |
2577 { | |
2578 /* If this register was set in the then block, we already | |
2579 handled this case there. */ | |
2580 if (t) | |
2581 continue; | |
2582 t = dest; | |
2583 gcc_assert (e); | |
2584 } | |
2585 else | |
2586 { | |
2587 gcc_assert (t); | |
2588 if (!e) | |
2589 e = dest; | |
2590 } | |
2591 | |
2592 target = noce_emit_cmove (if_infop, dest, code, cond_arg0, cond_arg1, | |
2593 t, e); | |
2594 if (!target) | |
2595 return false; | |
2596 | |
2597 if (target != dest) | |
2598 noce_emit_move_insn (dest, target); | |
2599 } | |
2600 | |
2601 return true; | |
2602 } | |
2603 | |
2604 /* Given a simple IF-THEN-JOIN or IF-THEN-ELSE-JOIN block, attempt to convert | |
2605 it using only conditional moves. Return TRUE if we were successful at | |
2606 converting the block. */ | |
2607 | |
2608 static int | |
2609 cond_move_process_if_block (struct noce_if_info *if_info) | |
2610 { | |
2611 basic_block test_bb = if_info->test_bb; | |
2612 basic_block then_bb = if_info->then_bb; | |
2613 basic_block else_bb = if_info->else_bb; | |
2614 basic_block join_bb = if_info->join_bb; | |
2615 rtx jump = if_info->jump; | |
2616 rtx cond = if_info->cond; | |
2617 rtx seq, loc_insn; | |
2618 int max_reg, size, c, reg; | |
2619 rtx *then_vals; | |
2620 rtx *else_vals; | |
2621 VEC (int, heap) *then_regs = NULL; | |
2622 VEC (int, heap) *else_regs = NULL; | |
2623 unsigned int i; | |
2624 | |
2625 /* Build a mapping for each block to the value used for each | |
2626 register. */ | |
2627 max_reg = max_reg_num (); | |
2628 size = (max_reg + 1) * sizeof (rtx); | |
2629 then_vals = (rtx *) alloca (size); | |
2630 else_vals = (rtx *) alloca (size); | |
2631 memset (then_vals, 0, size); | |
2632 memset (else_vals, 0, size); | |
2633 | |
2634 /* Make sure the blocks are suitable. */ | |
2635 if (!check_cond_move_block (then_bb, then_vals, &then_regs, cond) | |
2636 || (else_bb && !check_cond_move_block (else_bb, else_vals, &else_regs, cond))) | |
2637 { | |
2638 VEC_free (int, heap, then_regs); | |
2639 VEC_free (int, heap, else_regs); | |
2640 return FALSE; | |
2641 } | |
2642 | |
2643 /* Make sure the blocks can be used together. If the same register | |
2644 is set in both blocks, and is not set to a constant in both | |
2645 cases, then both blocks must set it to the same register. We | |
2646 have already verified that if it is set to a register, that the | |
2647 source register does not change after the assignment. Also count | |
2648 the number of registers set in only one of the blocks. */ | |
2649 c = 0; | |
2650 for (i = 0; VEC_iterate (int, then_regs, i, reg); i++) | |
2651 { | |
2652 if (!then_vals[reg] && !else_vals[reg]) | |
2653 continue; | |
2654 | |
2655 if (!else_vals[reg]) | |
2656 ++c; | |
2657 else | |
2658 { | |
2659 if (!CONSTANT_P (then_vals[reg]) | |
2660 && !CONSTANT_P (else_vals[reg]) | |
2661 && !rtx_equal_p (then_vals[reg], else_vals[reg])) | |
2662 { | |
2663 VEC_free (int, heap, then_regs); | |
2664 VEC_free (int, heap, else_regs); | |
2665 return FALSE; | |
2666 } | |
2667 } | |
2668 } | |
2669 | |
2670 /* Finish off c for MAX_CONDITIONAL_EXECUTE. */ | |
2671 for (i = 0; VEC_iterate (int, else_regs, i, reg); ++i) | |
2672 if (!then_vals[reg]) | |
2673 ++c; | |
2674 | |
2675 /* Make sure it is reasonable to convert this block. What matters | |
2676 is the number of assignments currently made in only one of the | |
2677 branches, since if we convert we are going to always execute | |
2678 them. */ | |
2679 if (c > MAX_CONDITIONAL_EXECUTE) | |
2680 { | |
2681 VEC_free (int, heap, then_regs); | |
2682 VEC_free (int, heap, else_regs); | |
2683 return FALSE; | |
2684 } | |
2685 | |
2686 /* Try to emit the conditional moves. First do the then block, | |
2687 then do anything left in the else blocks. */ | |
2688 start_sequence (); | |
2689 if (!cond_move_convert_if_block (if_info, then_bb, cond, | |
2690 then_vals, else_vals, false) | |
2691 || (else_bb | |
2692 && !cond_move_convert_if_block (if_info, else_bb, cond, | |
2693 then_vals, else_vals, true))) | |
2694 { | |
2695 end_sequence (); | |
2696 VEC_free (int, heap, then_regs); | |
2697 VEC_free (int, heap, else_regs); | |
2698 return FALSE; | |
2699 } | |
2700 seq = end_ifcvt_sequence (if_info); | |
2701 if (!seq) | |
2702 { | |
2703 VEC_free (int, heap, then_regs); | |
2704 VEC_free (int, heap, else_regs); | |
2705 return FALSE; | |
2706 } | |
2707 | |
2708 loc_insn = first_active_insn (then_bb); | |
2709 if (!loc_insn) | |
2710 { | |
2711 loc_insn = first_active_insn (else_bb); | |
2712 gcc_assert (loc_insn); | |
2713 } | |
2714 emit_insn_before_setloc (seq, jump, INSN_LOCATOR (loc_insn)); | |
2715 | |
2716 if (else_bb) | |
2717 { | |
2718 delete_basic_block (else_bb); | |
2719 num_true_changes++; | |
2720 } | |
2721 else | |
2722 remove_edge (find_edge (test_bb, join_bb)); | |
2723 | |
2724 remove_edge (find_edge (then_bb, join_bb)); | |
2725 redirect_edge_and_branch_force (single_succ_edge (test_bb), join_bb); | |
2726 delete_basic_block (then_bb); | |
2727 num_true_changes++; | |
2728 | |
2729 if (can_merge_blocks_p (test_bb, join_bb)) | |
2730 { | |
2731 merge_blocks (test_bb, join_bb); | |
2732 num_true_changes++; | |
2733 } | |
2734 | |
2735 num_updated_if_blocks++; | |
2736 | |
2737 VEC_free (int, heap, then_regs); | |
2738 VEC_free (int, heap, else_regs); | |
2739 return TRUE; | |
2740 } | |
2741 | |
2742 | |
2743 /* Determine if a given basic block heads a simple IF-THEN-JOIN or an | |
2744 IF-THEN-ELSE-JOIN block. | |
2745 | |
2746 If so, we'll try to convert the insns to not require the branch, | |
2747 using only transformations that do not require conditional execution. | |
2748 | |
2749 Return TRUE if we were successful at converting the block. */ | |
2750 | |
2751 static int | |
2752 noce_find_if_block (basic_block test_bb, | |
2753 edge then_edge, edge else_edge, | |
2754 int pass) | |
2755 { | |
2756 basic_block then_bb, else_bb, join_bb; | |
2757 bool then_else_reversed = false; | |
2758 rtx jump, cond; | |
2759 rtx cond_earliest; | |
2760 struct noce_if_info if_info; | |
2761 | |
2762 /* We only ever should get here before reload. */ | |
2763 gcc_assert (!reload_completed); | |
2764 | |
2765 /* Recognize an IF-THEN-ELSE-JOIN block. */ | |
2766 if (single_pred_p (then_edge->dest) | |
2767 && single_succ_p (then_edge->dest) | |
2768 && single_pred_p (else_edge->dest) | |
2769 && single_succ_p (else_edge->dest) | |
2770 && single_succ (then_edge->dest) == single_succ (else_edge->dest)) | |
2771 { | |
2772 then_bb = then_edge->dest; | |
2773 else_bb = else_edge->dest; | |
2774 join_bb = single_succ (then_bb); | |
2775 } | |
2776 /* Recognize an IF-THEN-JOIN block. */ | |
2777 else if (single_pred_p (then_edge->dest) | |
2778 && single_succ_p (then_edge->dest) | |
2779 && single_succ (then_edge->dest) == else_edge->dest) | |
2780 { | |
2781 then_bb = then_edge->dest; | |
2782 else_bb = NULL_BLOCK; | |
2783 join_bb = else_edge->dest; | |
2784 } | |
2785 /* Recognize an IF-ELSE-JOIN block. We can have those because the order | |
2786 of basic blocks in cfglayout mode does not matter, so the fallthrough | |
2787 edge can go to any basic block (and not just to bb->next_bb, like in | |
2788 cfgrtl mode). */ | |
2789 else if (single_pred_p (else_edge->dest) | |
2790 && single_succ_p (else_edge->dest) | |
2791 && single_succ (else_edge->dest) == then_edge->dest) | |
2792 { | |
2793 /* The noce transformations do not apply to IF-ELSE-JOIN blocks. | |
2794 To make this work, we have to invert the THEN and ELSE blocks | |
2795 and reverse the jump condition. */ | |
2796 then_bb = else_edge->dest; | |
2797 else_bb = NULL_BLOCK; | |
2798 join_bb = single_succ (then_bb); | |
2799 then_else_reversed = true; | |
2800 } | |
2801 else | |
2802 /* Not a form we can handle. */ | |
2803 return FALSE; | |
2804 | |
2805 /* The edges of the THEN and ELSE blocks cannot have complex edges. */ | |
2806 if (single_succ_edge (then_bb)->flags & EDGE_COMPLEX) | |
2807 return FALSE; | |
2808 if (else_bb | |
2809 && single_succ_edge (else_bb)->flags & EDGE_COMPLEX) | |
2810 return FALSE; | |
2811 | |
2812 num_possible_if_blocks++; | |
2813 | |
2814 if (dump_file) | |
2815 { | |
2816 fprintf (dump_file, | |
2817 "\nIF-THEN%s-JOIN block found, pass %d, test %d, then %d", | |
2818 (else_bb) ? "-ELSE" : "", | |
2819 pass, test_bb->index, then_bb->index); | |
2820 | |
2821 if (else_bb) | |
2822 fprintf (dump_file, ", else %d", else_bb->index); | |
2823 | |
2824 fprintf (dump_file, ", join %d\n", join_bb->index); | |
2825 } | |
2826 | |
2827 /* If the conditional jump is more than just a conditional | |
2828 jump, then we can not do if-conversion on this block. */ | |
2829 jump = BB_END (test_bb); | |
2830 if (! onlyjump_p (jump)) | |
2831 return FALSE; | |
2832 | |
2833 /* If this is not a standard conditional jump, we can't parse it. */ | |
2834 cond = noce_get_condition (jump, | |
2835 &cond_earliest, | |
2836 then_else_reversed); | |
2837 if (!cond) | |
2838 return FALSE; | |
2839 | |
2840 /* We must be comparing objects whose modes imply the size. */ | |
2841 if (GET_MODE (XEXP (cond, 0)) == BLKmode) | |
2842 return FALSE; | |
2843 | |
2844 /* Initialize an IF_INFO struct to pass around. */ | |
2845 memset (&if_info, 0, sizeof if_info); | |
2846 if_info.test_bb = test_bb; | |
2847 if_info.then_bb = then_bb; | |
2848 if_info.else_bb = else_bb; | |
2849 if_info.join_bb = join_bb; | |
2850 if_info.cond = cond; | |
2851 if_info.cond_earliest = cond_earliest; | |
2852 if_info.jump = jump; | |
2853 if_info.then_else_reversed = then_else_reversed; | |
2854 if_info.branch_cost = BRANCH_COST (optimize_bb_for_speed_p (test_bb), | |
2855 predictable_edge_p (then_edge)); | |
2856 | |
2857 /* Do the real work. */ | |
2858 | |
2859 if (noce_process_if_block (&if_info)) | |
2860 return TRUE; | |
2861 | |
2862 if (HAVE_conditional_move | |
2863 && cond_move_process_if_block (&if_info)) | |
2864 return TRUE; | |
2865 | |
2866 return FALSE; | |
2867 } | |
2868 | |
2869 | |
2870 /* Merge the blocks and mark for local life update. */ | |
2871 | |
2872 static void | |
2873 merge_if_block (struct ce_if_block * ce_info) | |
2874 { | |
2875 basic_block test_bb = ce_info->test_bb; /* last test block */ | |
2876 basic_block then_bb = ce_info->then_bb; /* THEN */ | |
2877 basic_block else_bb = ce_info->else_bb; /* ELSE or NULL */ | |
2878 basic_block join_bb = ce_info->join_bb; /* join block */ | |
2879 basic_block combo_bb; | |
2880 | |
2881 /* All block merging is done into the lower block numbers. */ | |
2882 | |
2883 combo_bb = test_bb; | |
2884 df_set_bb_dirty (test_bb); | |
2885 | |
2886 /* Merge any basic blocks to handle && and || subtests. Each of | |
2887 the blocks are on the fallthru path from the predecessor block. */ | |
2888 if (ce_info->num_multiple_test_blocks > 0) | |
2889 { | |
2890 basic_block bb = test_bb; | |
2891 basic_block last_test_bb = ce_info->last_test_bb; | |
2892 basic_block fallthru = block_fallthru (bb); | |
2893 | |
2894 do | |
2895 { | |
2896 bb = fallthru; | |
2897 fallthru = block_fallthru (bb); | |
2898 merge_blocks (combo_bb, bb); | |
2899 num_true_changes++; | |
2900 } | |
2901 while (bb != last_test_bb); | |
2902 } | |
2903 | |
2904 /* Merge TEST block into THEN block. Normally the THEN block won't have a | |
2905 label, but it might if there were || tests. That label's count should be | |
2906 zero, and it normally should be removed. */ | |
2907 | |
2908 if (then_bb) | |
2909 { | |
2910 merge_blocks (combo_bb, then_bb); | |
2911 num_true_changes++; | |
2912 } | |
2913 | |
2914 /* The ELSE block, if it existed, had a label. That label count | |
2915 will almost always be zero, but odd things can happen when labels | |
2916 get their addresses taken. */ | |
2917 if (else_bb) | |
2918 { | |
2919 merge_blocks (combo_bb, else_bb); | |
2920 num_true_changes++; | |
2921 } | |
2922 | |
2923 /* If there was no join block reported, that means it was not adjacent | |
2924 to the others, and so we cannot merge them. */ | |
2925 | |
2926 if (! join_bb) | |
2927 { | |
2928 rtx last = BB_END (combo_bb); | |
2929 | |
2930 /* The outgoing edge for the current COMBO block should already | |
2931 be correct. Verify this. */ | |
2932 if (EDGE_COUNT (combo_bb->succs) == 0) | |
2933 gcc_assert (find_reg_note (last, REG_NORETURN, NULL) | |
2934 || (NONJUMP_INSN_P (last) | |
2935 && GET_CODE (PATTERN (last)) == TRAP_IF | |
2936 && (TRAP_CONDITION (PATTERN (last)) | |
2937 == const_true_rtx))); | |
2938 | |
2939 else | |
2940 /* There should still be something at the end of the THEN or ELSE | |
2941 blocks taking us to our final destination. */ | |
2942 gcc_assert (JUMP_P (last) | |
2943 || (EDGE_SUCC (combo_bb, 0)->dest == EXIT_BLOCK_PTR | |
2944 && CALL_P (last) | |
2945 && SIBLING_CALL_P (last)) | |
2946 || ((EDGE_SUCC (combo_bb, 0)->flags & EDGE_EH) | |
2947 && can_throw_internal (last))); | |
2948 } | |
2949 | |
2950 /* The JOIN block may have had quite a number of other predecessors too. | |
2951 Since we've already merged the TEST, THEN and ELSE blocks, we should | |
2952 have only one remaining edge from our if-then-else diamond. If there | |
2953 is more than one remaining edge, it must come from elsewhere. There | |
2954 may be zero incoming edges if the THEN block didn't actually join | |
2955 back up (as with a call to a non-return function). */ | |
2956 else if (EDGE_COUNT (join_bb->preds) < 2 | |
2957 && join_bb != EXIT_BLOCK_PTR) | |
2958 { | |
2959 /* We can merge the JOIN cleanly and update the dataflow try | |
2960 again on this pass.*/ | |
2961 merge_blocks (combo_bb, join_bb); | |
2962 num_true_changes++; | |
2963 } | |
2964 else | |
2965 { | |
2966 /* We cannot merge the JOIN. */ | |
2967 | |
2968 /* The outgoing edge for the current COMBO block should already | |
2969 be correct. Verify this. */ | |
2970 gcc_assert (single_succ_p (combo_bb) | |
2971 && single_succ (combo_bb) == join_bb); | |
2972 | |
2973 /* Remove the jump and cruft from the end of the COMBO block. */ | |
2974 if (join_bb != EXIT_BLOCK_PTR) | |
2975 tidy_fallthru_edge (single_succ_edge (combo_bb)); | |
2976 } | |
2977 | |
2978 num_updated_if_blocks++; | |
2979 } | |
2980 | |
2981 /* Find a block ending in a simple IF condition and try to transform it | |
2982 in some way. When converting a multi-block condition, put the new code | |
2983 in the first such block and delete the rest. Return a pointer to this | |
2984 first block if some transformation was done. Return NULL otherwise. */ | |
2985 | |
2986 static basic_block | |
2987 find_if_header (basic_block test_bb, int pass) | |
2988 { | |
2989 ce_if_block_t ce_info; | |
2990 edge then_edge; | |
2991 edge else_edge; | |
2992 | |
2993 /* The kind of block we're looking for has exactly two successors. */ | |
2994 if (EDGE_COUNT (test_bb->succs) != 2) | |
2995 return NULL; | |
2996 | |
2997 then_edge = EDGE_SUCC (test_bb, 0); | |
2998 else_edge = EDGE_SUCC (test_bb, 1); | |
2999 | |
3000 if (df_get_bb_dirty (then_edge->dest)) | |
3001 return NULL; | |
3002 if (df_get_bb_dirty (else_edge->dest)) | |
3003 return NULL; | |
3004 | |
3005 /* Neither edge should be abnormal. */ | |
3006 if ((then_edge->flags & EDGE_COMPLEX) | |
3007 || (else_edge->flags & EDGE_COMPLEX)) | |
3008 return NULL; | |
3009 | |
3010 /* Nor exit the loop. */ | |
3011 if ((then_edge->flags & EDGE_LOOP_EXIT) | |
3012 || (else_edge->flags & EDGE_LOOP_EXIT)) | |
3013 return NULL; | |
3014 | |
3015 /* The THEN edge is canonically the one that falls through. */ | |
3016 if (then_edge->flags & EDGE_FALLTHRU) | |
3017 ; | |
3018 else if (else_edge->flags & EDGE_FALLTHRU) | |
3019 { | |
3020 edge e = else_edge; | |
3021 else_edge = then_edge; | |
3022 then_edge = e; | |
3023 } | |
3024 else | |
3025 /* Otherwise this must be a multiway branch of some sort. */ | |
3026 return NULL; | |
3027 | |
3028 memset (&ce_info, '\0', sizeof (ce_info)); | |
3029 ce_info.test_bb = test_bb; | |
3030 ce_info.then_bb = then_edge->dest; | |
3031 ce_info.else_bb = else_edge->dest; | |
3032 ce_info.pass = pass; | |
3033 | |
3034 #ifdef IFCVT_INIT_EXTRA_FIELDS | |
3035 IFCVT_INIT_EXTRA_FIELDS (&ce_info); | |
3036 #endif | |
3037 | |
3038 if (! reload_completed | |
3039 && noce_find_if_block (test_bb, then_edge, else_edge, pass)) | |
3040 goto success; | |
3041 | |
3042 if (HAVE_conditional_execution && reload_completed | |
3043 && cond_exec_find_if_block (&ce_info)) | |
3044 goto success; | |
3045 | |
3046 if (HAVE_trap && HAVE_conditional_trap | |
3047 && find_cond_trap (test_bb, then_edge, else_edge)) | |
3048 goto success; | |
3049 | |
3050 if (dom_info_state (CDI_POST_DOMINATORS) >= DOM_NO_FAST_QUERY | |
3051 && (! HAVE_conditional_execution || reload_completed)) | |
3052 { | |
3053 if (find_if_case_1 (test_bb, then_edge, else_edge)) | |
3054 goto success; | |
3055 if (find_if_case_2 (test_bb, then_edge, else_edge)) | |
3056 goto success; | |
3057 } | |
3058 | |
3059 return NULL; | |
3060 | |
3061 success: | |
3062 if (dump_file) | |
3063 fprintf (dump_file, "Conversion succeeded on pass %d.\n", pass); | |
3064 /* Set this so we continue looking. */ | |
3065 cond_exec_changed_p = TRUE; | |
3066 return ce_info.test_bb; | |
3067 } | |
3068 | |
3069 /* Return true if a block has two edges, one of which falls through to the next | |
3070 block, and the other jumps to a specific block, so that we can tell if the | |
3071 block is part of an && test or an || test. Returns either -1 or the number | |
3072 of non-note, non-jump, non-USE/CLOBBER insns in the block. */ | |
3073 | |
3074 static int | |
3075 block_jumps_and_fallthru_p (basic_block cur_bb, basic_block target_bb) | |
3076 { | |
3077 edge cur_edge; | |
3078 int fallthru_p = FALSE; | |
3079 int jump_p = FALSE; | |
3080 rtx insn; | |
3081 rtx end; | |
3082 int n_insns = 0; | |
3083 edge_iterator ei; | |
3084 | |
3085 if (!cur_bb || !target_bb) | |
3086 return -1; | |
3087 | |
3088 /* If no edges, obviously it doesn't jump or fallthru. */ | |
3089 if (EDGE_COUNT (cur_bb->succs) == 0) | |
3090 return FALSE; | |
3091 | |
3092 FOR_EACH_EDGE (cur_edge, ei, cur_bb->succs) | |
3093 { | |
3094 if (cur_edge->flags & EDGE_COMPLEX) | |
3095 /* Anything complex isn't what we want. */ | |
3096 return -1; | |
3097 | |
3098 else if (cur_edge->flags & EDGE_FALLTHRU) | |
3099 fallthru_p = TRUE; | |
3100 | |
3101 else if (cur_edge->dest == target_bb) | |
3102 jump_p = TRUE; | |
3103 | |
3104 else | |
3105 return -1; | |
3106 } | |
3107 | |
3108 if ((jump_p & fallthru_p) == 0) | |
3109 return -1; | |
3110 | |
3111 /* Don't allow calls in the block, since this is used to group && and || | |
3112 together for conditional execution support. ??? we should support | |
3113 conditional execution support across calls for IA-64 some day, but | |
3114 for now it makes the code simpler. */ | |
3115 end = BB_END (cur_bb); | |
3116 insn = BB_HEAD (cur_bb); | |
3117 | |
3118 while (insn != NULL_RTX) | |
3119 { | |
3120 if (CALL_P (insn)) | |
3121 return -1; | |
3122 | |
3123 if (INSN_P (insn) | |
3124 && !JUMP_P (insn) | |
3125 && GET_CODE (PATTERN (insn)) != USE | |
3126 && GET_CODE (PATTERN (insn)) != CLOBBER) | |
3127 n_insns++; | |
3128 | |
3129 if (insn == end) | |
3130 break; | |
3131 | |
3132 insn = NEXT_INSN (insn); | |
3133 } | |
3134 | |
3135 return n_insns; | |
3136 } | |
3137 | |
3138 /* Determine if a given basic block heads a simple IF-THEN or IF-THEN-ELSE | |
3139 block. If so, we'll try to convert the insns to not require the branch. | |
3140 Return TRUE if we were successful at converting the block. */ | |
3141 | |
3142 static int | |
3143 cond_exec_find_if_block (struct ce_if_block * ce_info) | |
3144 { | |
3145 basic_block test_bb = ce_info->test_bb; | |
3146 basic_block then_bb = ce_info->then_bb; | |
3147 basic_block else_bb = ce_info->else_bb; | |
3148 basic_block join_bb = NULL_BLOCK; | |
3149 edge cur_edge; | |
3150 basic_block next; | |
3151 edge_iterator ei; | |
3152 | |
3153 ce_info->last_test_bb = test_bb; | |
3154 | |
3155 /* We only ever should get here after reload, | |
3156 and only if we have conditional execution. */ | |
3157 gcc_assert (HAVE_conditional_execution && reload_completed); | |
3158 | |
3159 /* Discover if any fall through predecessors of the current test basic block | |
3160 were && tests (which jump to the else block) or || tests (which jump to | |
3161 the then block). */ | |
3162 if (single_pred_p (test_bb) | |
3163 && single_pred_edge (test_bb)->flags == EDGE_FALLTHRU) | |
3164 { | |
3165 basic_block bb = single_pred (test_bb); | |
3166 basic_block target_bb; | |
3167 int max_insns = MAX_CONDITIONAL_EXECUTE; | |
3168 int n_insns; | |
3169 | |
3170 /* Determine if the preceding block is an && or || block. */ | |
3171 if ((n_insns = block_jumps_and_fallthru_p (bb, else_bb)) >= 0) | |
3172 { | |
3173 ce_info->and_and_p = TRUE; | |
3174 target_bb = else_bb; | |
3175 } | |
3176 else if ((n_insns = block_jumps_and_fallthru_p (bb, then_bb)) >= 0) | |
3177 { | |
3178 ce_info->and_and_p = FALSE; | |
3179 target_bb = then_bb; | |
3180 } | |
3181 else | |
3182 target_bb = NULL_BLOCK; | |
3183 | |
3184 if (target_bb && n_insns <= max_insns) | |
3185 { | |
3186 int total_insns = 0; | |
3187 int blocks = 0; | |
3188 | |
3189 ce_info->last_test_bb = test_bb; | |
3190 | |
3191 /* Found at least one && or || block, look for more. */ | |
3192 do | |
3193 { | |
3194 ce_info->test_bb = test_bb = bb; | |
3195 total_insns += n_insns; | |
3196 blocks++; | |
3197 | |
3198 if (!single_pred_p (bb)) | |
3199 break; | |
3200 | |
3201 bb = single_pred (bb); | |
3202 n_insns = block_jumps_and_fallthru_p (bb, target_bb); | |
3203 } | |
3204 while (n_insns >= 0 && (total_insns + n_insns) <= max_insns); | |
3205 | |
3206 ce_info->num_multiple_test_blocks = blocks; | |
3207 ce_info->num_multiple_test_insns = total_insns; | |
3208 | |
3209 if (ce_info->and_and_p) | |
3210 ce_info->num_and_and_blocks = blocks; | |
3211 else | |
3212 ce_info->num_or_or_blocks = blocks; | |
3213 } | |
3214 } | |
3215 | |
3216 /* The THEN block of an IF-THEN combo must have exactly one predecessor, | |
3217 other than any || blocks which jump to the THEN block. */ | |
3218 if ((EDGE_COUNT (then_bb->preds) - ce_info->num_or_or_blocks) != 1) | |
3219 return FALSE; | |
3220 | |
3221 /* The edges of the THEN and ELSE blocks cannot have complex edges. */ | |
3222 FOR_EACH_EDGE (cur_edge, ei, then_bb->preds) | |
3223 { | |
3224 if (cur_edge->flags & EDGE_COMPLEX) | |
3225 return FALSE; | |
3226 } | |
3227 | |
3228 FOR_EACH_EDGE (cur_edge, ei, else_bb->preds) | |
3229 { | |
3230 if (cur_edge->flags & EDGE_COMPLEX) | |
3231 return FALSE; | |
3232 } | |
3233 | |
3234 /* The THEN block of an IF-THEN combo must have zero or one successors. */ | |
3235 if (EDGE_COUNT (then_bb->succs) > 0 | |
3236 && (!single_succ_p (then_bb) | |
3237 || (single_succ_edge (then_bb)->flags & EDGE_COMPLEX) | |
3238 || (epilogue_completed && tablejump_p (BB_END (then_bb), NULL, NULL)))) | |
3239 return FALSE; | |
3240 | |
3241 /* If the THEN block has no successors, conditional execution can still | |
3242 make a conditional call. Don't do this unless the ELSE block has | |
3243 only one incoming edge -- the CFG manipulation is too ugly otherwise. | |
3244 Check for the last insn of the THEN block being an indirect jump, which | |
3245 is listed as not having any successors, but confuses the rest of the CE | |
3246 code processing. ??? we should fix this in the future. */ | |
3247 if (EDGE_COUNT (then_bb->succs) == 0) | |
3248 { | |
3249 if (single_pred_p (else_bb)) | |
3250 { | |
3251 rtx last_insn = BB_END (then_bb); | |
3252 | |
3253 while (last_insn | |
3254 && NOTE_P (last_insn) | |
3255 && last_insn != BB_HEAD (then_bb)) | |
3256 last_insn = PREV_INSN (last_insn); | |
3257 | |
3258 if (last_insn | |
3259 && JUMP_P (last_insn) | |
3260 && ! simplejump_p (last_insn)) | |
3261 return FALSE; | |
3262 | |
3263 join_bb = else_bb; | |
3264 else_bb = NULL_BLOCK; | |
3265 } | |
3266 else | |
3267 return FALSE; | |
3268 } | |
3269 | |
3270 /* If the THEN block's successor is the other edge out of the TEST block, | |
3271 then we have an IF-THEN combo without an ELSE. */ | |
3272 else if (single_succ (then_bb) == else_bb) | |
3273 { | |
3274 join_bb = else_bb; | |
3275 else_bb = NULL_BLOCK; | |
3276 } | |
3277 | |
3278 /* If the THEN and ELSE block meet in a subsequent block, and the ELSE | |
3279 has exactly one predecessor and one successor, and the outgoing edge | |
3280 is not complex, then we have an IF-THEN-ELSE combo. */ | |
3281 else if (single_succ_p (else_bb) | |
3282 && single_succ (then_bb) == single_succ (else_bb) | |
3283 && single_pred_p (else_bb) | |
3284 && ! (single_succ_edge (else_bb)->flags & EDGE_COMPLEX) | |
3285 && ! (epilogue_completed && tablejump_p (BB_END (else_bb), NULL, NULL))) | |
3286 join_bb = single_succ (else_bb); | |
3287 | |
3288 /* Otherwise it is not an IF-THEN or IF-THEN-ELSE combination. */ | |
3289 else | |
3290 return FALSE; | |
3291 | |
3292 num_possible_if_blocks++; | |
3293 | |
3294 if (dump_file) | |
3295 { | |
3296 fprintf (dump_file, | |
3297 "\nIF-THEN%s block found, pass %d, start block %d " | |
3298 "[insn %d], then %d [%d]", | |
3299 (else_bb) ? "-ELSE" : "", | |
3300 ce_info->pass, | |
3301 test_bb->index, | |
3302 BB_HEAD (test_bb) ? (int)INSN_UID (BB_HEAD (test_bb)) : -1, | |
3303 then_bb->index, | |
3304 BB_HEAD (then_bb) ? (int)INSN_UID (BB_HEAD (then_bb)) : -1); | |
3305 | |
3306 if (else_bb) | |
3307 fprintf (dump_file, ", else %d [%d]", | |
3308 else_bb->index, | |
3309 BB_HEAD (else_bb) ? (int)INSN_UID (BB_HEAD (else_bb)) : -1); | |
3310 | |
3311 fprintf (dump_file, ", join %d [%d]", | |
3312 join_bb->index, | |
3313 BB_HEAD (join_bb) ? (int)INSN_UID (BB_HEAD (join_bb)) : -1); | |
3314 | |
3315 if (ce_info->num_multiple_test_blocks > 0) | |
3316 fprintf (dump_file, ", %d %s block%s last test %d [%d]", | |
3317 ce_info->num_multiple_test_blocks, | |
3318 (ce_info->and_and_p) ? "&&" : "||", | |
3319 (ce_info->num_multiple_test_blocks == 1) ? "" : "s", | |
3320 ce_info->last_test_bb->index, | |
3321 ((BB_HEAD (ce_info->last_test_bb)) | |
3322 ? (int)INSN_UID (BB_HEAD (ce_info->last_test_bb)) | |
3323 : -1)); | |
3324 | |
3325 fputc ('\n', dump_file); | |
3326 } | |
3327 | |
3328 /* Make sure IF, THEN, and ELSE, blocks are adjacent. Actually, we get the | |
3329 first condition for free, since we've already asserted that there's a | |
3330 fallthru edge from IF to THEN. Likewise for the && and || blocks, since | |
3331 we checked the FALLTHRU flag, those are already adjacent to the last IF | |
3332 block. */ | |
3333 /* ??? As an enhancement, move the ELSE block. Have to deal with | |
3334 BLOCK notes, if by no other means than backing out the merge if they | |
3335 exist. Sticky enough I don't want to think about it now. */ | |
3336 next = then_bb; | |
3337 if (else_bb && (next = next->next_bb) != else_bb) | |
3338 return FALSE; | |
3339 if ((next = next->next_bb) != join_bb && join_bb != EXIT_BLOCK_PTR) | |
3340 { | |
3341 if (else_bb) | |
3342 join_bb = NULL; | |
3343 else | |
3344 return FALSE; | |
3345 } | |
3346 | |
3347 /* Do the real work. */ | |
3348 | |
3349 ce_info->else_bb = else_bb; | |
3350 ce_info->join_bb = join_bb; | |
3351 | |
3352 /* If we have && and || tests, try to first handle combining the && and || | |
3353 tests into the conditional code, and if that fails, go back and handle | |
3354 it without the && and ||, which at present handles the && case if there | |
3355 was no ELSE block. */ | |
3356 if (cond_exec_process_if_block (ce_info, TRUE)) | |
3357 return TRUE; | |
3358 | |
3359 if (ce_info->num_multiple_test_blocks) | |
3360 { | |
3361 cancel_changes (0); | |
3362 | |
3363 if (cond_exec_process_if_block (ce_info, FALSE)) | |
3364 return TRUE; | |
3365 } | |
3366 | |
3367 return FALSE; | |
3368 } | |
3369 | |
3370 /* Convert a branch over a trap, or a branch | |
3371 to a trap, into a conditional trap. */ | |
3372 | |
3373 static int | |
3374 find_cond_trap (basic_block test_bb, edge then_edge, edge else_edge) | |
3375 { | |
3376 basic_block then_bb = then_edge->dest; | |
3377 basic_block else_bb = else_edge->dest; | |
3378 basic_block other_bb, trap_bb; | |
3379 rtx trap, jump, cond, cond_earliest, seq; | |
3380 enum rtx_code code; | |
3381 | |
3382 /* Locate the block with the trap instruction. */ | |
3383 /* ??? While we look for no successors, we really ought to allow | |
3384 EH successors. Need to fix merge_if_block for that to work. */ | |
3385 if ((trap = block_has_only_trap (then_bb)) != NULL) | |
3386 trap_bb = then_bb, other_bb = else_bb; | |
3387 else if ((trap = block_has_only_trap (else_bb)) != NULL) | |
3388 trap_bb = else_bb, other_bb = then_bb; | |
3389 else | |
3390 return FALSE; | |
3391 | |
3392 if (dump_file) | |
3393 { | |
3394 fprintf (dump_file, "\nTRAP-IF block found, start %d, trap %d\n", | |
3395 test_bb->index, trap_bb->index); | |
3396 } | |
3397 | |
3398 /* If this is not a standard conditional jump, we can't parse it. */ | |
3399 jump = BB_END (test_bb); | |
3400 cond = noce_get_condition (jump, &cond_earliest, false); | |
3401 if (! cond) | |
3402 return FALSE; | |
3403 | |
3404 /* If the conditional jump is more than just a conditional jump, then | |
3405 we can not do if-conversion on this block. */ | |
3406 if (! onlyjump_p (jump)) | |
3407 return FALSE; | |
3408 | |
3409 /* We must be comparing objects whose modes imply the size. */ | |
3410 if (GET_MODE (XEXP (cond, 0)) == BLKmode) | |
3411 return FALSE; | |
3412 | |
3413 /* Reverse the comparison code, if necessary. */ | |
3414 code = GET_CODE (cond); | |
3415 if (then_bb == trap_bb) | |
3416 { | |
3417 code = reversed_comparison_code (cond, jump); | |
3418 if (code == UNKNOWN) | |
3419 return FALSE; | |
3420 } | |
3421 | |
3422 /* Attempt to generate the conditional trap. */ | |
3423 seq = gen_cond_trap (code, copy_rtx (XEXP (cond, 0)), | |
3424 copy_rtx (XEXP (cond, 1)), | |
3425 TRAP_CODE (PATTERN (trap))); | |
3426 if (seq == NULL) | |
3427 return FALSE; | |
3428 | |
3429 /* Emit the new insns before cond_earliest. */ | |
3430 emit_insn_before_setloc (seq, cond_earliest, INSN_LOCATOR (trap)); | |
3431 | |
3432 /* Delete the trap block if possible. */ | |
3433 remove_edge (trap_bb == then_bb ? then_edge : else_edge); | |
3434 df_set_bb_dirty (test_bb); | |
3435 df_set_bb_dirty (then_bb); | |
3436 df_set_bb_dirty (else_bb); | |
3437 | |
3438 if (EDGE_COUNT (trap_bb->preds) == 0) | |
3439 { | |
3440 delete_basic_block (trap_bb); | |
3441 num_true_changes++; | |
3442 } | |
3443 | |
3444 /* Wire together the blocks again. */ | |
3445 if (current_ir_type () == IR_RTL_CFGLAYOUT) | |
3446 single_succ_edge (test_bb)->flags |= EDGE_FALLTHRU; | |
3447 else | |
3448 { | |
3449 rtx lab, newjump; | |
3450 | |
3451 lab = JUMP_LABEL (jump); | |
3452 newjump = emit_jump_insn_after (gen_jump (lab), jump); | |
3453 LABEL_NUSES (lab) += 1; | |
3454 JUMP_LABEL (newjump) = lab; | |
3455 emit_barrier_after (newjump); | |
3456 } | |
3457 delete_insn (jump); | |
3458 | |
3459 if (can_merge_blocks_p (test_bb, other_bb)) | |
3460 { | |
3461 merge_blocks (test_bb, other_bb); | |
3462 num_true_changes++; | |
3463 } | |
3464 | |
3465 num_updated_if_blocks++; | |
3466 return TRUE; | |
3467 } | |
3468 | |
3469 /* Subroutine of find_cond_trap: if BB contains only a trap insn, | |
3470 return it. */ | |
3471 | |
3472 static rtx | |
3473 block_has_only_trap (basic_block bb) | |
3474 { | |
3475 rtx trap; | |
3476 | |
3477 /* We're not the exit block. */ | |
3478 if (bb == EXIT_BLOCK_PTR) | |
3479 return NULL_RTX; | |
3480 | |
3481 /* The block must have no successors. */ | |
3482 if (EDGE_COUNT (bb->succs) > 0) | |
3483 return NULL_RTX; | |
3484 | |
3485 /* The only instruction in the THEN block must be the trap. */ | |
3486 trap = first_active_insn (bb); | |
3487 if (! (trap == BB_END (bb) | |
3488 && GET_CODE (PATTERN (trap)) == TRAP_IF | |
3489 && TRAP_CONDITION (PATTERN (trap)) == const_true_rtx)) | |
3490 return NULL_RTX; | |
3491 | |
3492 return trap; | |
3493 } | |
3494 | |
3495 /* Look for IF-THEN-ELSE cases in which one of THEN or ELSE is | |
3496 transformable, but not necessarily the other. There need be no | |
3497 JOIN block. | |
3498 | |
3499 Return TRUE if we were successful at converting the block. | |
3500 | |
3501 Cases we'd like to look at: | |
3502 | |
3503 (1) | |
3504 if (test) goto over; // x not live | |
3505 x = a; | |
3506 goto label; | |
3507 over: | |
3508 | |
3509 becomes | |
3510 | |
3511 x = a; | |
3512 if (! test) goto label; | |
3513 | |
3514 (2) | |
3515 if (test) goto E; // x not live | |
3516 x = big(); | |
3517 goto L; | |
3518 E: | |
3519 x = b; | |
3520 goto M; | |
3521 | |
3522 becomes | |
3523 | |
3524 x = b; | |
3525 if (test) goto M; | |
3526 x = big(); | |
3527 goto L; | |
3528 | |
3529 (3) // This one's really only interesting for targets that can do | |
3530 // multiway branching, e.g. IA-64 BBB bundles. For other targets | |
3531 // it results in multiple branches on a cache line, which often | |
3532 // does not sit well with predictors. | |
3533 | |
3534 if (test1) goto E; // predicted not taken | |
3535 x = a; | |
3536 if (test2) goto F; | |
3537 ... | |
3538 E: | |
3539 x = b; | |
3540 J: | |
3541 | |
3542 becomes | |
3543 | |
3544 x = a; | |
3545 if (test1) goto E; | |
3546 if (test2) goto F; | |
3547 | |
3548 Notes: | |
3549 | |
3550 (A) Don't do (2) if the branch is predicted against the block we're | |
3551 eliminating. Do it anyway if we can eliminate a branch; this requires | |
3552 that the sole successor of the eliminated block postdominate the other | |
3553 side of the if. | |
3554 | |
3555 (B) With CE, on (3) we can steal from both sides of the if, creating | |
3556 | |
3557 if (test1) x = a; | |
3558 if (!test1) x = b; | |
3559 if (test1) goto J; | |
3560 if (test2) goto F; | |
3561 ... | |
3562 J: | |
3563 | |
3564 Again, this is most useful if J postdominates. | |
3565 | |
3566 (C) CE substitutes for helpful life information. | |
3567 | |
3568 (D) These heuristics need a lot of work. */ | |
3569 | |
3570 /* Tests for case 1 above. */ | |
3571 | |
3572 static int | |
3573 find_if_case_1 (basic_block test_bb, edge then_edge, edge else_edge) | |
3574 { | |
3575 basic_block then_bb = then_edge->dest; | |
3576 basic_block else_bb = else_edge->dest; | |
3577 basic_block new_bb; | |
3578 int then_bb_index; | |
3579 | |
3580 /* If we are partitioning hot/cold basic blocks, we don't want to | |
3581 mess up unconditional or indirect jumps that cross between hot | |
3582 and cold sections. | |
3583 | |
3584 Basic block partitioning may result in some jumps that appear to | |
3585 be optimizable (or blocks that appear to be mergeable), but which really | |
3586 must be left untouched (they are required to make it safely across | |
3587 partition boundaries). See the comments at the top of | |
3588 bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */ | |
3589 | |
3590 if ((BB_END (then_bb) | |
3591 && find_reg_note (BB_END (then_bb), REG_CROSSING_JUMP, NULL_RTX)) | |
3592 || (BB_END (test_bb) | |
3593 && find_reg_note (BB_END (test_bb), REG_CROSSING_JUMP, NULL_RTX)) | |
3594 || (BB_END (else_bb) | |
3595 && find_reg_note (BB_END (else_bb), REG_CROSSING_JUMP, | |
3596 NULL_RTX))) | |
3597 return FALSE; | |
3598 | |
3599 /* THEN has one successor. */ | |
3600 if (!single_succ_p (then_bb)) | |
3601 return FALSE; | |
3602 | |
3603 /* THEN does not fall through, but is not strange either. */ | |
3604 if (single_succ_edge (then_bb)->flags & (EDGE_COMPLEX | EDGE_FALLTHRU)) | |
3605 return FALSE; | |
3606 | |
3607 /* THEN has one predecessor. */ | |
3608 if (!single_pred_p (then_bb)) | |
3609 return FALSE; | |
3610 | |
3611 /* THEN must do something. */ | |
3612 if (forwarder_block_p (then_bb)) | |
3613 return FALSE; | |
3614 | |
3615 num_possible_if_blocks++; | |
3616 if (dump_file) | |
3617 fprintf (dump_file, | |
3618 "\nIF-CASE-1 found, start %d, then %d\n", | |
3619 test_bb->index, then_bb->index); | |
3620 | |
3621 /* THEN is small. */ | |
3622 if (! cheap_bb_rtx_cost_p (then_bb, | |
3623 COSTS_N_INSNS (BRANCH_COST (optimize_bb_for_speed_p (then_edge->src), | |
3624 predictable_edge_p (then_edge))))) | |
3625 return FALSE; | |
3626 | |
3627 /* Registers set are dead, or are predicable. */ | |
3628 if (! dead_or_predicable (test_bb, then_bb, else_bb, | |
3629 single_succ (then_bb), 1)) | |
3630 return FALSE; | |
3631 | |
3632 /* Conversion went ok, including moving the insns and fixing up the | |
3633 jump. Adjust the CFG to match. */ | |
3634 | |
3635 /* We can avoid creating a new basic block if then_bb is immediately | |
3636 followed by else_bb, i.e. deleting then_bb allows test_bb to fall | |
3637 thru to else_bb. */ | |
3638 | |
3639 if (then_bb->next_bb == else_bb | |
3640 && then_bb->prev_bb == test_bb | |
3641 && else_bb != EXIT_BLOCK_PTR) | |
3642 { | |
3643 redirect_edge_succ (FALLTHRU_EDGE (test_bb), else_bb); | |
3644 new_bb = 0; | |
3645 } | |
3646 else | |
3647 new_bb = redirect_edge_and_branch_force (FALLTHRU_EDGE (test_bb), | |
3648 else_bb); | |
3649 | |
3650 df_set_bb_dirty (test_bb); | |
3651 df_set_bb_dirty (else_bb); | |
3652 | |
3653 then_bb_index = then_bb->index; | |
3654 delete_basic_block (then_bb); | |
3655 | |
3656 /* Make rest of code believe that the newly created block is the THEN_BB | |
3657 block we removed. */ | |
3658 if (new_bb) | |
3659 { | |
3660 df_bb_replace (then_bb_index, new_bb); | |
3661 /* Since the fallthru edge was redirected from test_bb to new_bb, | |
3662 we need to ensure that new_bb is in the same partition as | |
3663 test bb (you can not fall through across section boundaries). */ | |
3664 BB_COPY_PARTITION (new_bb, test_bb); | |
3665 } | |
3666 | |
3667 num_true_changes++; | |
3668 num_updated_if_blocks++; | |
3669 | |
3670 return TRUE; | |
3671 } | |
3672 | |
3673 /* Test for case 2 above. */ | |
3674 | |
3675 static int | |
3676 find_if_case_2 (basic_block test_bb, edge then_edge, edge else_edge) | |
3677 { | |
3678 basic_block then_bb = then_edge->dest; | |
3679 basic_block else_bb = else_edge->dest; | |
3680 edge else_succ; | |
3681 rtx note; | |
3682 | |
3683 /* If we are partitioning hot/cold basic blocks, we don't want to | |
3684 mess up unconditional or indirect jumps that cross between hot | |
3685 and cold sections. | |
3686 | |
3687 Basic block partitioning may result in some jumps that appear to | |
3688 be optimizable (or blocks that appear to be mergeable), but which really | |
3689 must be left untouched (they are required to make it safely across | |
3690 partition boundaries). See the comments at the top of | |
3691 bb-reorder.c:partition_hot_cold_basic_blocks for complete details. */ | |
3692 | |
3693 if ((BB_END (then_bb) | |
3694 && find_reg_note (BB_END (then_bb), REG_CROSSING_JUMP, NULL_RTX)) | |
3695 || (BB_END (test_bb) | |
3696 && find_reg_note (BB_END (test_bb), REG_CROSSING_JUMP, NULL_RTX)) | |
3697 || (BB_END (else_bb) | |
3698 && find_reg_note (BB_END (else_bb), REG_CROSSING_JUMP, | |
3699 NULL_RTX))) | |
3700 return FALSE; | |
3701 | |
3702 /* ELSE has one successor. */ | |
3703 if (!single_succ_p (else_bb)) | |
3704 return FALSE; | |
3705 else | |
3706 else_succ = single_succ_edge (else_bb); | |
3707 | |
3708 /* ELSE outgoing edge is not complex. */ | |
3709 if (else_succ->flags & EDGE_COMPLEX) | |
3710 return FALSE; | |
3711 | |
3712 /* ELSE has one predecessor. */ | |
3713 if (!single_pred_p (else_bb)) | |
3714 return FALSE; | |
3715 | |
3716 /* THEN is not EXIT. */ | |
3717 if (then_bb->index < NUM_FIXED_BLOCKS) | |
3718 return FALSE; | |
3719 | |
3720 /* ELSE is predicted or SUCC(ELSE) postdominates THEN. */ | |
3721 note = find_reg_note (BB_END (test_bb), REG_BR_PROB, NULL_RTX); | |
3722 if (note && INTVAL (XEXP (note, 0)) >= REG_BR_PROB_BASE / 2) | |
3723 ; | |
3724 else if (else_succ->dest->index < NUM_FIXED_BLOCKS | |
3725 || dominated_by_p (CDI_POST_DOMINATORS, then_bb, | |
3726 else_succ->dest)) | |
3727 ; | |
3728 else | |
3729 return FALSE; | |
3730 | |
3731 num_possible_if_blocks++; | |
3732 if (dump_file) | |
3733 fprintf (dump_file, | |
3734 "\nIF-CASE-2 found, start %d, else %d\n", | |
3735 test_bb->index, else_bb->index); | |
3736 | |
3737 /* ELSE is small. */ | |
3738 if (! cheap_bb_rtx_cost_p (else_bb, | |
3739 COSTS_N_INSNS (BRANCH_COST (optimize_bb_for_speed_p (else_edge->src), | |
3740 predictable_edge_p (else_edge))))) | |
3741 return FALSE; | |
3742 | |
3743 /* Registers set are dead, or are predicable. */ | |
3744 if (! dead_or_predicable (test_bb, else_bb, then_bb, else_succ->dest, 0)) | |
3745 return FALSE; | |
3746 | |
3747 /* Conversion went ok, including moving the insns and fixing up the | |
3748 jump. Adjust the CFG to match. */ | |
3749 | |
3750 df_set_bb_dirty (test_bb); | |
3751 df_set_bb_dirty (then_bb); | |
3752 delete_basic_block (else_bb); | |
3753 | |
3754 num_true_changes++; | |
3755 num_updated_if_blocks++; | |
3756 | |
3757 /* ??? We may now fallthru from one of THEN's successors into a join | |
3758 block. Rerun cleanup_cfg? Examine things manually? Wait? */ | |
3759 | |
3760 return TRUE; | |
3761 } | |
3762 | |
3763 /* A subroutine of dead_or_predicable called through for_each_rtx. | |
3764 Return 1 if a memory is found. */ | |
3765 | |
3766 static int | |
3767 find_memory (rtx *px, void *data ATTRIBUTE_UNUSED) | |
3768 { | |
3769 return MEM_P (*px); | |
3770 } | |
3771 | |
3772 /* Used by the code above to perform the actual rtl transformations. | |
3773 Return TRUE if successful. | |
3774 | |
3775 TEST_BB is the block containing the conditional branch. MERGE_BB | |
3776 is the block containing the code to manipulate. NEW_DEST is the | |
3777 label TEST_BB should be branching to after the conversion. | |
3778 REVERSEP is true if the sense of the branch should be reversed. */ | |
3779 | |
3780 static int | |
3781 dead_or_predicable (basic_block test_bb, basic_block merge_bb, | |
3782 basic_block other_bb, basic_block new_dest, int reversep) | |
3783 { | |
3784 rtx head, end, jump, earliest = NULL_RTX, old_dest, new_label = NULL_RTX; | |
3785 | |
3786 jump = BB_END (test_bb); | |
3787 | |
3788 /* Find the extent of the real code in the merge block. */ | |
3789 head = BB_HEAD (merge_bb); | |
3790 end = BB_END (merge_bb); | |
3791 | |
3792 /* If merge_bb ends with a tablejump, predicating/moving insn's | |
3793 into test_bb and then deleting merge_bb will result in the jumptable | |
3794 that follows merge_bb being removed along with merge_bb and then we | |
3795 get an unresolved reference to the jumptable. */ | |
3796 if (tablejump_p (end, NULL, NULL)) | |
3797 return FALSE; | |
3798 | |
3799 if (LABEL_P (head)) | |
3800 head = NEXT_INSN (head); | |
3801 if (NOTE_P (head)) | |
3802 { | |
3803 if (head == end) | |
3804 { | |
3805 head = end = NULL_RTX; | |
3806 goto no_body; | |
3807 } | |
3808 head = NEXT_INSN (head); | |
3809 } | |
3810 | |
3811 if (JUMP_P (end)) | |
3812 { | |
3813 if (head == end) | |
3814 { | |
3815 head = end = NULL_RTX; | |
3816 goto no_body; | |
3817 } | |
3818 end = PREV_INSN (end); | |
3819 } | |
3820 | |
3821 /* Disable handling dead code by conditional execution if the machine needs | |
3822 to do anything funny with the tests, etc. */ | |
3823 #ifndef IFCVT_MODIFY_TESTS | |
3824 if (HAVE_conditional_execution) | |
3825 { | |
3826 /* In the conditional execution case, we have things easy. We know | |
3827 the condition is reversible. We don't have to check life info | |
3828 because we're going to conditionally execute the code anyway. | |
3829 All that's left is making sure the insns involved can actually | |
3830 be predicated. */ | |
3831 | |
3832 rtx cond, prob_val; | |
3833 | |
3834 cond = cond_exec_get_condition (jump); | |
3835 if (! cond) | |
3836 return FALSE; | |
3837 | |
3838 prob_val = find_reg_note (jump, REG_BR_PROB, NULL_RTX); | |
3839 if (prob_val) | |
3840 prob_val = XEXP (prob_val, 0); | |
3841 | |
3842 if (reversep) | |
3843 { | |
3844 enum rtx_code rev = reversed_comparison_code (cond, jump); | |
3845 if (rev == UNKNOWN) | |
3846 return FALSE; | |
3847 cond = gen_rtx_fmt_ee (rev, GET_MODE (cond), XEXP (cond, 0), | |
3848 XEXP (cond, 1)); | |
3849 if (prob_val) | |
3850 prob_val = GEN_INT (REG_BR_PROB_BASE - INTVAL (prob_val)); | |
3851 } | |
3852 | |
3853 if (! cond_exec_process_insns ((ce_if_block_t *)0, head, end, cond, | |
3854 prob_val, 0)) | |
3855 goto cancel; | |
3856 | |
3857 earliest = jump; | |
3858 } | |
3859 else | |
3860 #endif | |
3861 { | |
3862 /* In the non-conditional execution case, we have to verify that there | |
3863 are no trapping operations, no calls, no references to memory, and | |
3864 that any registers modified are dead at the branch site. */ | |
3865 | |
3866 rtx insn, cond, prev; | |
3867 bitmap merge_set, test_live, test_set; | |
3868 unsigned i, fail = 0; | |
3869 bitmap_iterator bi; | |
3870 | |
3871 /* Check for no calls or trapping operations. */ | |
3872 for (insn = head; ; insn = NEXT_INSN (insn)) | |
3873 { | |
3874 if (CALL_P (insn)) | |
3875 return FALSE; | |
3876 if (INSN_P (insn)) | |
3877 { | |
3878 if (may_trap_p (PATTERN (insn))) | |
3879 return FALSE; | |
3880 | |
3881 /* ??? Even non-trapping memories such as stack frame | |
3882 references must be avoided. For stores, we collect | |
3883 no lifetime info; for reads, we'd have to assert | |
3884 true_dependence false against every store in the | |
3885 TEST range. */ | |
3886 if (for_each_rtx (&PATTERN (insn), find_memory, NULL)) | |
3887 return FALSE; | |
3888 } | |
3889 if (insn == end) | |
3890 break; | |
3891 } | |
3892 | |
3893 if (! any_condjump_p (jump)) | |
3894 return FALSE; | |
3895 | |
3896 /* Find the extent of the conditional. */ | |
3897 cond = noce_get_condition (jump, &earliest, false); | |
3898 if (! cond) | |
3899 return FALSE; | |
3900 | |
3901 /* Collect: | |
3902 MERGE_SET = set of registers set in MERGE_BB | |
3903 TEST_LIVE = set of registers live at EARLIEST | |
3904 TEST_SET = set of registers set between EARLIEST and the | |
3905 end of the block. */ | |
3906 | |
3907 merge_set = BITMAP_ALLOC (®_obstack); | |
3908 test_live = BITMAP_ALLOC (®_obstack); | |
3909 test_set = BITMAP_ALLOC (®_obstack); | |
3910 | |
3911 /* ??? bb->local_set is only valid during calculate_global_regs_live, | |
3912 so we must recompute usage for MERGE_BB. Not so bad, I suppose, | |
3913 since we've already asserted that MERGE_BB is small. */ | |
3914 /* If we allocated new pseudos (e.g. in the conditional move | |
3915 expander called from noce_emit_cmove), we must resize the | |
3916 array first. */ | |
3917 if (max_regno < max_reg_num ()) | |
3918 max_regno = max_reg_num (); | |
3919 | |
3920 FOR_BB_INSNS (merge_bb, insn) | |
3921 { | |
3922 if (INSN_P (insn)) | |
3923 { | |
3924 unsigned int uid = INSN_UID (insn); | |
3925 df_ref *def_rec; | |
3926 for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++) | |
3927 { | |
3928 df_ref def = *def_rec; | |
3929 bitmap_set_bit (merge_set, DF_REF_REGNO (def)); | |
3930 } | |
3931 } | |
3932 } | |
3933 | |
3934 /* For small register class machines, don't lengthen lifetimes of | |
3935 hard registers before reload. */ | |
3936 if (SMALL_REGISTER_CLASSES && ! reload_completed) | |
3937 { | |
3938 EXECUTE_IF_SET_IN_BITMAP (merge_set, 0, i, bi) | |
3939 { | |
3940 if (i < FIRST_PSEUDO_REGISTER | |
3941 && ! fixed_regs[i] | |
3942 && ! global_regs[i]) | |
3943 fail = 1; | |
3944 } | |
3945 } | |
3946 | |
3947 /* For TEST, we're interested in a range of insns, not a whole block. | |
3948 Moreover, we're interested in the insns live from OTHER_BB. */ | |
3949 | |
3950 /* The loop below takes the set of live registers | |
3951 after JUMP, and calculates the live set before EARLIEST. */ | |
3952 bitmap_copy (test_live, df_get_live_in (other_bb)); | |
3953 df_simulate_initialize_backwards (test_bb, test_live); | |
3954 for (insn = jump; ; insn = prev) | |
3955 { | |
3956 if (INSN_P (insn)) | |
3957 { | |
3958 df_simulate_find_defs (insn, test_set); | |
3959 df_simulate_one_insn_backwards (test_bb, insn, test_live); | |
3960 } | |
3961 prev = PREV_INSN (insn); | |
3962 if (insn == earliest) | |
3963 break; | |
3964 } | |
3965 | |
3966 /* We can perform the transformation if | |
3967 MERGE_SET & (TEST_SET | TEST_LIVE) | |
3968 and | |
3969 TEST_SET & DF_LIVE_IN (merge_bb) | |
3970 are empty. */ | |
3971 | |
3972 if (bitmap_intersect_p (test_set, merge_set) | |
3973 || bitmap_intersect_p (test_live, merge_set) | |
3974 || bitmap_intersect_p (test_set, df_get_live_in (merge_bb))) | |
3975 fail = 1; | |
3976 | |
3977 BITMAP_FREE (merge_set); | |
3978 BITMAP_FREE (test_live); | |
3979 BITMAP_FREE (test_set); | |
3980 | |
3981 if (fail) | |
3982 return FALSE; | |
3983 } | |
3984 | |
3985 no_body: | |
3986 /* We don't want to use normal invert_jump or redirect_jump because | |
3987 we don't want to delete_insn called. Also, we want to do our own | |
3988 change group management. */ | |
3989 | |
3990 old_dest = JUMP_LABEL (jump); | |
3991 if (other_bb != new_dest) | |
3992 { | |
3993 new_label = block_label (new_dest); | |
3994 if (reversep | |
3995 ? ! invert_jump_1 (jump, new_label) | |
3996 : ! redirect_jump_1 (jump, new_label)) | |
3997 goto cancel; | |
3998 } | |
3999 | |
4000 if (! apply_change_group ()) | |
4001 return FALSE; | |
4002 | |
4003 if (other_bb != new_dest) | |
4004 { | |
4005 redirect_jump_2 (jump, old_dest, new_label, 0, reversep); | |
4006 | |
4007 redirect_edge_succ (BRANCH_EDGE (test_bb), new_dest); | |
4008 if (reversep) | |
4009 { | |
4010 gcov_type count, probability; | |
4011 count = BRANCH_EDGE (test_bb)->count; | |
4012 BRANCH_EDGE (test_bb)->count = FALLTHRU_EDGE (test_bb)->count; | |
4013 FALLTHRU_EDGE (test_bb)->count = count; | |
4014 probability = BRANCH_EDGE (test_bb)->probability; | |
4015 BRANCH_EDGE (test_bb)->probability | |
4016 = FALLTHRU_EDGE (test_bb)->probability; | |
4017 FALLTHRU_EDGE (test_bb)->probability = probability; | |
4018 update_br_prob_note (test_bb); | |
4019 } | |
4020 } | |
4021 | |
4022 /* Move the insns out of MERGE_BB to before the branch. */ | |
4023 if (head != NULL) | |
4024 { | |
4025 rtx insn; | |
4026 | |
4027 if (end == BB_END (merge_bb)) | |
4028 BB_END (merge_bb) = PREV_INSN (head); | |
4029 | |
4030 /* PR 21767: When moving insns above a conditional branch, REG_EQUAL | |
4031 notes might become invalid. */ | |
4032 insn = head; | |
4033 do | |
4034 { | |
4035 rtx note, set; | |
4036 | |
4037 if (! INSN_P (insn)) | |
4038 continue; | |
4039 note = find_reg_note (insn, REG_EQUAL, NULL_RTX); | |
4040 if (! note) | |
4041 continue; | |
4042 set = single_set (insn); | |
4043 if (!set || !function_invariant_p (SET_SRC (set))) | |
4044 remove_note (insn, note); | |
4045 } while (insn != end && (insn = NEXT_INSN (insn))); | |
4046 | |
4047 reorder_insns (head, end, PREV_INSN (earliest)); | |
4048 } | |
4049 | |
4050 /* Remove the jump and edge if we can. */ | |
4051 if (other_bb == new_dest) | |
4052 { | |
4053 delete_insn (jump); | |
4054 remove_edge (BRANCH_EDGE (test_bb)); | |
4055 /* ??? Can't merge blocks here, as then_bb is still in use. | |
4056 At minimum, the merge will get done just before bb-reorder. */ | |
4057 } | |
4058 | |
4059 return TRUE; | |
4060 | |
4061 cancel: | |
4062 cancel_changes (0); | |
4063 return FALSE; | |
4064 } | |
4065 | |
4066 /* Main entry point for all if-conversion. */ | |
4067 | |
4068 static void | |
4069 if_convert (void) | |
4070 { | |
4071 basic_block bb; | |
4072 int pass; | |
4073 | |
4074 if (optimize == 1) | |
4075 { | |
4076 df_live_add_problem (); | |
4077 df_live_set_all_dirty (); | |
4078 } | |
4079 | |
4080 num_possible_if_blocks = 0; | |
4081 num_updated_if_blocks = 0; | |
4082 num_true_changes = 0; | |
4083 | |
4084 loop_optimizer_init (AVOID_CFG_MODIFICATIONS); | |
4085 mark_loop_exit_edges (); | |
4086 loop_optimizer_finalize (); | |
4087 free_dominance_info (CDI_DOMINATORS); | |
4088 | |
4089 /* Compute postdominators. */ | |
4090 calculate_dominance_info (CDI_POST_DOMINATORS); | |
4091 | |
4092 df_set_flags (DF_LR_RUN_DCE); | |
4093 | |
4094 /* Go through each of the basic blocks looking for things to convert. If we | |
4095 have conditional execution, we make multiple passes to allow us to handle | |
4096 IF-THEN{-ELSE} blocks within other IF-THEN{-ELSE} blocks. */ | |
4097 pass = 0; | |
4098 do | |
4099 { | |
4100 df_analyze (); | |
4101 /* Only need to do dce on the first pass. */ | |
4102 df_clear_flags (DF_LR_RUN_DCE); | |
4103 cond_exec_changed_p = FALSE; | |
4104 pass++; | |
4105 | |
4106 #ifdef IFCVT_MULTIPLE_DUMPS | |
4107 if (dump_file && pass > 1) | |
4108 fprintf (dump_file, "\n\n========== Pass %d ==========\n", pass); | |
4109 #endif | |
4110 | |
4111 FOR_EACH_BB (bb) | |
4112 { | |
4113 basic_block new_bb; | |
4114 while (!df_get_bb_dirty (bb) | |
4115 && (new_bb = find_if_header (bb, pass)) != NULL) | |
4116 bb = new_bb; | |
4117 } | |
4118 | |
4119 #ifdef IFCVT_MULTIPLE_DUMPS | |
4120 if (dump_file && cond_exec_changed_p) | |
4121 print_rtl_with_bb (dump_file, get_insns ()); | |
4122 #endif | |
4123 } | |
4124 while (cond_exec_changed_p); | |
4125 | |
4126 #ifdef IFCVT_MULTIPLE_DUMPS | |
4127 if (dump_file) | |
4128 fprintf (dump_file, "\n\n========== no more changes\n"); | |
4129 #endif | |
4130 | |
4131 free_dominance_info (CDI_POST_DOMINATORS); | |
4132 | |
4133 if (dump_file) | |
4134 fflush (dump_file); | |
4135 | |
4136 clear_aux_for_blocks (); | |
4137 | |
4138 /* If we allocated new pseudos, we must resize the array for sched1. */ | |
4139 if (max_regno < max_reg_num ()) | |
4140 max_regno = max_reg_num (); | |
4141 | |
4142 /* Write the final stats. */ | |
4143 if (dump_file && num_possible_if_blocks > 0) | |
4144 { | |
4145 fprintf (dump_file, | |
4146 "\n%d possible IF blocks searched.\n", | |
4147 num_possible_if_blocks); | |
4148 fprintf (dump_file, | |
4149 "%d IF blocks converted.\n", | |
4150 num_updated_if_blocks); | |
4151 fprintf (dump_file, | |
4152 "%d true changes made.\n\n\n", | |
4153 num_true_changes); | |
4154 } | |
4155 | |
4156 if (optimize == 1) | |
4157 df_remove_problem (df_live); | |
4158 | |
4159 #ifdef ENABLE_CHECKING | |
4160 verify_flow_info (); | |
4161 #endif | |
4162 } | |
4163 | |
4164 static bool | |
4165 gate_handle_if_conversion (void) | |
4166 { | |
4167 return (optimize > 0) | |
4168 && dbg_cnt (if_conversion); | |
4169 } | |
4170 | |
4171 /* If-conversion and CFG cleanup. */ | |
4172 static unsigned int | |
4173 rest_of_handle_if_conversion (void) | |
4174 { | |
4175 if (flag_if_conversion) | |
4176 { | |
4177 if (dump_file) | |
4178 dump_flow_info (dump_file, dump_flags); | |
4179 cleanup_cfg (CLEANUP_EXPENSIVE); | |
4180 if_convert (); | |
4181 } | |
4182 | |
4183 cleanup_cfg (0); | |
4184 return 0; | |
4185 } | |
4186 | |
4187 struct rtl_opt_pass pass_rtl_ifcvt = | |
4188 { | |
4189 { | |
4190 RTL_PASS, | |
4191 "ce1", /* name */ | |
4192 gate_handle_if_conversion, /* gate */ | |
4193 rest_of_handle_if_conversion, /* execute */ | |
4194 NULL, /* sub */ | |
4195 NULL, /* next */ | |
4196 0, /* static_pass_number */ | |
4197 TV_IFCVT, /* tv_id */ | |
4198 0, /* properties_required */ | |
4199 0, /* properties_provided */ | |
4200 0, /* properties_destroyed */ | |
4201 0, /* todo_flags_start */ | |
4202 TODO_df_finish | TODO_verify_rtl_sharing | | |
4203 TODO_dump_func /* todo_flags_finish */ | |
4204 } | |
4205 }; | |
4206 | |
4207 static bool | |
4208 gate_handle_if_after_combine (void) | |
4209 { | |
4210 return optimize > 0 && flag_if_conversion | |
4211 && dbg_cnt (if_after_combine); | |
4212 } | |
4213 | |
4214 | |
4215 /* Rerun if-conversion, as combine may have simplified things enough | |
4216 to now meet sequence length restrictions. */ | |
4217 static unsigned int | |
4218 rest_of_handle_if_after_combine (void) | |
4219 { | |
4220 if_convert (); | |
4221 return 0; | |
4222 } | |
4223 | |
4224 struct rtl_opt_pass pass_if_after_combine = | |
4225 { | |
4226 { | |
4227 RTL_PASS, | |
4228 "ce2", /* name */ | |
4229 gate_handle_if_after_combine, /* gate */ | |
4230 rest_of_handle_if_after_combine, /* execute */ | |
4231 NULL, /* sub */ | |
4232 NULL, /* next */ | |
4233 0, /* static_pass_number */ | |
4234 TV_IFCVT, /* tv_id */ | |
4235 0, /* properties_required */ | |
4236 0, /* properties_provided */ | |
4237 0, /* properties_destroyed */ | |
4238 0, /* todo_flags_start */ | |
4239 TODO_df_finish | TODO_verify_rtl_sharing | | |
4240 TODO_dump_func | | |
4241 TODO_ggc_collect /* todo_flags_finish */ | |
4242 } | |
4243 }; | |
4244 | |
4245 | |
4246 static bool | |
4247 gate_handle_if_after_reload (void) | |
4248 { | |
4249 return optimize > 0 && flag_if_conversion2 | |
4250 && dbg_cnt (if_after_reload); | |
4251 } | |
4252 | |
4253 static unsigned int | |
4254 rest_of_handle_if_after_reload (void) | |
4255 { | |
4256 if_convert (); | |
4257 return 0; | |
4258 } | |
4259 | |
4260 | |
4261 struct rtl_opt_pass pass_if_after_reload = | |
4262 { | |
4263 { | |
4264 RTL_PASS, | |
4265 "ce3", /* name */ | |
4266 gate_handle_if_after_reload, /* gate */ | |
4267 rest_of_handle_if_after_reload, /* execute */ | |
4268 NULL, /* sub */ | |
4269 NULL, /* next */ | |
4270 0, /* static_pass_number */ | |
4271 TV_IFCVT2, /* tv_id */ | |
4272 0, /* properties_required */ | |
4273 0, /* properties_provided */ | |
4274 0, /* properties_destroyed */ | |
4275 0, /* todo_flags_start */ | |
4276 TODO_df_finish | TODO_verify_rtl_sharing | | |
4277 TODO_dump_func | | |
4278 TODO_ggc_collect /* todo_flags_finish */ | |
4279 } | |
4280 }; |