Line data Source code
1 : /* If-conversion support.
2 : Copyright (C) 2000-2026 Free Software Foundation, Inc.
3 :
4 : This file is part of GCC.
5 :
6 : GCC is free software; you can redistribute it and/or modify it
7 : under the terms of the GNU General Public License as published by
8 : the Free Software Foundation; either version 3, or (at your option)
9 : any later version.
10 :
11 : GCC is distributed in the hope that it will be useful, but WITHOUT
12 : ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 : or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
14 : License for more details.
15 :
16 : You should have received a copy of the GNU General Public License
17 : along with GCC; see the file COPYING3. If not see
18 : <http://www.gnu.org/licenses/>. */
19 :
20 : #include "config.h"
21 : #include "system.h"
22 : #include "coretypes.h"
23 : #include "backend.h"
24 : #include "target.h"
25 : #include "rtl.h"
26 : #include "tree.h"
27 : #include "cfghooks.h"
28 : #include "df.h"
29 : #include "memmodel.h"
30 : #include "tm_p.h"
31 : #include "expmed.h"
32 : #include "optabs.h"
33 : #include "regs.h"
34 : #include "emit-rtl.h"
35 : #include "recog.h"
36 :
37 : #include "cfgrtl.h"
38 : #include "cfganal.h"
39 : #include "cfgcleanup.h"
40 : #include "explow.h"
41 : #include "expr.h"
42 : #include "output.h"
43 : #include "cfgloop.h"
44 : #include "tree-pass.h"
45 : #include "dbgcnt.h"
46 : #include "shrink-wrap.h"
47 : #include "rtl-iter.h"
48 : #include "ifcvt.h"
49 :
50 : /* The number of instructions this pass may make run unconditionally in place
51 : of a branch. The conditional-execution path uses it as the number of insns
52 : it may predicate. The branchless paths use it as the number of insns they
53 : may speculate. The default charges the cost of an unpredictable branch,
54 : plus one. Some targets override it. */
55 :
56 : #ifndef MAX_CONDITIONAL_EXECUTE
57 : #define MAX_CONDITIONAL_EXECUTE \
58 : (BRANCH_COST (optimize_function_for_speed_p (cfun), false) \
59 : + 1)
60 : #endif
61 :
62 : #define NULL_BLOCK ((basic_block) NULL)
63 :
64 : /* Which of the three RTL if-conversion passes is running. ce1 runs before
65 : combine, ce2 after combine and ce3 after reload. The cost model treats the
66 : pre-combine run specially, so the phase is recorded here. */
67 : enum ifcvt_phase
68 : {
69 : IFCVT_BEFORE_COMBINE, /* ce1. */
70 : IFCVT_AFTER_COMBINE, /* ce2. */
71 : IFCVT_AFTER_RELOAD /* ce3. */
72 : };
73 :
74 : /* The if-conversion pass currently running. */
75 : static ifcvt_phase ifcvt_pass_phase;
76 :
77 : /* True if the target has the cbranchcc4 optab. */
78 : static bool have_cbranchcc4;
79 :
80 : /* # of IF-THEN or IF-THEN-ELSE blocks we looked at */
81 : static int num_possible_if_blocks;
82 :
83 : /* # of IF-THEN or IF-THEN-ELSE blocks were converted to conditional
84 : execution. */
85 : static int num_updated_if_blocks;
86 :
87 : /* # of changes made. */
88 : static int num_true_changes;
89 :
90 : /* Whether this pass over the function converted anything, so that another
91 : pass may find further opportunities in what it left behind. Every
92 : successful conversion sets it, not only the conditional-execution one. */
93 : static bool ifcvt_changed_p;
94 :
95 : /* Forward references. */
96 : static bool noce_operand_ok (const_rtx);
97 : static void merge_if_block (ce_if_block *);
98 : static bool find_cond_trap (basic_block, edge, edge);
99 : static bool cond_exec_find_if_block (ce_if_block *);
100 : static bool find_if_case_1 (basic_block, edge, edge);
101 : static bool find_if_case_2 (basic_block, edge, edge);
102 : static bool dead_or_predicable (basic_block, basic_block, basic_block,
103 : edge, bool);
104 : static rtx_insn *block_has_only_trap (basic_block);
105 : static void init_noce_multiple_sets_info (basic_block,
106 : auto_delete_vec<noce_multiple_sets_info> &);
107 : static bool noce_convert_multiple_sets_1 (noce_if_info *, rtx,
108 : auto_delete_vec<noce_multiple_sets_info> &,
109 : auto_delete_vec<noce_multiple_sets_info> &, unsigned,
110 : const vec<unsigned> &, int *, bool *);
111 :
112 : /* Count the number of non-jump active insns in BB. */
113 :
114 : static int
115 0 : count_bb_insns (const_basic_block bb)
116 : {
117 0 : int count = 0;
118 0 : rtx_insn *insn = BB_HEAD (bb);
119 :
120 0 : while (1)
121 : {
122 0 : if (active_insn_p (insn) && !JUMP_P (insn))
123 0 : count++;
124 :
125 0 : if (insn == BB_END (bb))
126 : break;
127 0 : insn = NEXT_INSN (insn);
128 : }
129 :
130 0 : return count;
131 : }
132 :
133 : /* Determine whether the total insn_cost on non-jump insns in
134 : basic block BB is less than MAX_COST. This function returns
135 : false if the cost of any instruction could not be estimated.
136 :
137 : The cost of the non-jump insns in BB is scaled by REG_BR_PROB_BASE
138 : as those insns are being speculated. MAX_COST is scaled with SCALE
139 : plus a small fudge factor. */
140 :
141 : static bool
142 3059923 : cheap_bb_rtx_cost_p (const_basic_block bb,
143 : profile_probability prob, int max_cost)
144 : {
145 3059923 : int count = 0;
146 3059923 : rtx_insn *insn = BB_HEAD (bb);
147 3059923 : bool speed = optimize_bb_for_speed_p (bb);
148 3059923 : int scale = prob.initialized_p () ? prob.to_reg_br_prob_base ()
149 : : REG_BR_PROB_BASE;
150 :
151 : /* Set scale to REG_BR_PROB_BASE to void the identical scaling
152 : applied to insn_cost when optimizing for size. Only do
153 : this after combine because if-conversion might interfere with
154 : passes before combine.
155 :
156 : Use optimize_function_for_speed_p instead of the pre-defined
157 : variable speed to make sure it is set to same value for all
158 : basic blocks in one if-conversion transformation. */
159 3059923 : if (!optimize_function_for_speed_p (cfun)
160 3059923 : && ifcvt_pass_phase != IFCVT_BEFORE_COMBINE)
161 : scale = REG_BR_PROB_BASE;
162 : /* Our branch probability/scaling factors are just estimates and don't
163 : account for cases where we can get speculation for free and other
164 : secondary benefits. So we fudge the scale factor to make speculating
165 : appear a little more profitable when optimizing for performance. */
166 : else
167 3008926 : scale += REG_BR_PROB_BASE / 8;
168 :
169 :
170 3059923 : max_cost *= scale;
171 :
172 12920075 : while (1)
173 : {
174 15979998 : if (NONJUMP_INSN_P (insn))
175 : {
176 : /* Inline-asm's cost is not very estimatable.
177 : It could be a costly instruction but the
178 : estimate would be the same as a non costly
179 : instruction. */
180 4580298 : if (asm_noperands (PATTERN (insn)) >= 0)
181 : return false;
182 :
183 4577597 : int cost = insn_cost (insn, speed) * REG_BR_PROB_BASE;
184 4577597 : if (cost == 0)
185 : return false;
186 :
187 : /* If this instruction is the load or set of a "stack" register,
188 : such as a floating point register on x87, then the cost of
189 : speculatively executing this insn may need to include
190 : the additional cost of popping its result off of the
191 : register stack. Unfortunately, correctly recognizing and
192 : accounting for this additional overhead is tricky, so for
193 : now we simply prohibit such speculative execution. */
194 : #ifdef STACK_REGS
195 4527060 : {
196 4527060 : rtx set = single_set (insn);
197 4527060 : if (set && STACK_REG_P (SET_DEST (set)))
198 : return false;
199 : }
200 : #endif
201 :
202 4523154 : count += cost;
203 4523154 : if (count >= max_cost)
204 : return false;
205 : }
206 11399700 : else if (CALL_P (insn))
207 : return false;
208 :
209 13508430 : if (insn == BB_END (bb))
210 : break;
211 12920075 : insn = NEXT_INSN (insn);
212 12920075 : }
213 :
214 : return true;
215 : }
216 :
217 : /* Return the first non-jump active insn in the basic block. */
218 :
219 : static rtx_insn *
220 1533450 : first_active_insn (basic_block bb)
221 : {
222 1533450 : rtx_insn *insn = BB_HEAD (bb);
223 :
224 1533450 : if (LABEL_P (insn))
225 : {
226 280884 : if (insn == BB_END (bb))
227 : return NULL;
228 280884 : insn = NEXT_INSN (insn);
229 : }
230 :
231 5157291 : while (NOTE_P (insn) || DEBUG_INSN_P (insn))
232 : {
233 3623841 : if (insn == BB_END (bb))
234 : return NULL;
235 3623841 : insn = NEXT_INSN (insn);
236 : }
237 :
238 1533450 : if (JUMP_P (insn))
239 0 : return NULL;
240 :
241 : return insn;
242 : }
243 :
244 : /* Return the last non-jump active insn in the basic block. */
245 :
246 : static rtx_insn *
247 2570283 : last_active_insn (basic_block bb, bool skip_use_p)
248 : {
249 2570283 : rtx_insn *insn = BB_END (bb);
250 2570283 : rtx_insn *head = BB_HEAD (bb);
251 :
252 2570283 : while (NOTE_P (insn)
253 : || JUMP_P (insn)
254 : || DEBUG_INSN_P (insn)
255 6248977 : || (skip_use_p
256 0 : && NONJUMP_INSN_P (insn)
257 0 : && GET_CODE (PATTERN (insn)) == USE))
258 : {
259 3678930 : if (insn == head)
260 : return NULL;
261 3678694 : insn = PREV_INSN (insn);
262 : }
263 :
264 2570047 : if (LABEL_P (insn))
265 76 : return NULL;
266 :
267 : return insn;
268 : }
269 :
270 : /* Return the active insn before INSN inside basic block CURR_BB. */
271 :
272 : static rtx_insn *
273 0 : find_active_insn_before (basic_block curr_bb, rtx_insn *insn)
274 : {
275 0 : if (!insn || insn == BB_HEAD (curr_bb))
276 : return NULL;
277 :
278 0 : while ((insn = PREV_INSN (insn)) != NULL_RTX)
279 : {
280 0 : if (NONJUMP_INSN_P (insn) || JUMP_P (insn) || CALL_P (insn))
281 : break;
282 :
283 : /* No other active insn all the way to the start of the basic block. */
284 0 : if (insn == BB_HEAD (curr_bb))
285 : return NULL;
286 : }
287 :
288 : return insn;
289 : }
290 :
291 : /* Return the active insn after INSN inside basic block CURR_BB. */
292 :
293 : static rtx_insn *
294 0 : find_active_insn_after (basic_block curr_bb, rtx_insn *insn)
295 : {
296 0 : if (!insn || insn == BB_END (curr_bb))
297 : return NULL;
298 :
299 0 : while ((insn = NEXT_INSN (insn)) != NULL_RTX)
300 : {
301 0 : if (NONJUMP_INSN_P (insn) || JUMP_P (insn) || CALL_P (insn))
302 : break;
303 :
304 : /* No other active insn all the way to the end of the basic block. */
305 0 : if (insn == BB_END (curr_bb))
306 : return NULL;
307 : }
308 :
309 : return insn;
310 : }
311 :
312 : /* Return the basic block reached by falling through the basic block BB. */
313 :
314 : static basic_block
315 0 : block_fallthru (basic_block bb)
316 : {
317 0 : edge e = find_fallthru_edge (bb->succs);
318 :
319 0 : return (e) ? e->dest : NULL_BLOCK;
320 : }
321 :
322 : /* Return true if RTXs A and B can be safely interchanged. */
323 :
324 : static bool
325 495834 : rtx_interchangeable_p (const_rtx a, const_rtx b)
326 : {
327 495834 : if (!rtx_equal_p (a, b))
328 : return false;
329 :
330 183925 : if (GET_CODE (a) != MEM)
331 : return true;
332 :
333 : /* A dead type-unsafe memory reference is legal, but a live type-unsafe memory
334 : reference is not. Interchanging a dead type-unsafe memory reference with
335 : a live type-safe one creates a live type-unsafe memory reference, in other
336 : words, it makes the program illegal.
337 : We check here conservatively whether the two memory references have equal
338 : memory attributes. */
339 :
340 2373 : return mem_attrs_eq_p (get_mem_attrs (a), get_mem_attrs (b));
341 : }
342 :
343 :
344 : /* Go through the insns from START to END, converting them to conditional
345 : execution format if possible. CE_INFO describes the if-block being
346 : converted and is only read by the target IFCVT_MODIFY_INSN macro. TEST is
347 : the conditional-execution test to predicate them on and PROB_VAL the
348 : probability that it holds. MOD_OK allows one insn that modifies TEST, in
349 : which case it must be the last one. Return TRUE if all of the non-note
350 : insns were processed. */
351 :
352 : static bool
353 0 : cond_exec_process_insns (ce_if_block *ce_info ATTRIBUTE_UNUSED,
354 : rtx_insn *start, rtx end, rtx test,
355 : profile_probability prob_val, bool mod_ok)
356 : {
357 0 : bool must_be_last = false;
358 0 : rtx_insn *insn;
359 0 : rtx xtest;
360 0 : rtx pattern;
361 :
362 0 : if (!start || !end)
363 : return false;
364 :
365 0 : for (insn = start; ; insn = NEXT_INSN (insn))
366 : {
367 : /* dwarf2out can't cope with conditional prologues. */
368 0 : if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_PROLOGUE_END)
369 : return false;
370 :
371 0 : if (NOTE_P (insn) || DEBUG_INSN_P (insn))
372 0 : goto insn_done;
373 :
374 0 : gcc_assert (NONJUMP_INSN_P (insn) || CALL_P (insn));
375 :
376 : /* dwarf2out can't cope with conditional unwind info. */
377 0 : if (RTX_FRAME_RELATED_P (insn))
378 : return false;
379 :
380 : /* Remove USE insns that get in the way. */
381 0 : if (reload_completed && GET_CODE (PATTERN (insn)) == USE)
382 : {
383 : /* ??? Ug. Actually unlinking the thing is problematic,
384 : given what we'd have to coordinate with our callers. */
385 0 : SET_INSN_DELETED (insn);
386 0 : goto insn_done;
387 : }
388 :
389 : /* Last insn wasn't last? */
390 0 : if (must_be_last)
391 : return false;
392 :
393 0 : if (modified_in_p (test, insn))
394 : {
395 0 : if (!mod_ok)
396 : return false;
397 : must_be_last = true;
398 : }
399 :
400 : /* Now build the conditional form of the instruction. */
401 0 : pattern = PATTERN (insn);
402 0 : xtest = copy_rtx (test);
403 :
404 : /* If this is already a COND_EXEC, rewrite the test to be an AND of the
405 : two conditions. */
406 0 : if (GET_CODE (pattern) == COND_EXEC)
407 : {
408 0 : if (GET_MODE (xtest) != GET_MODE (COND_EXEC_TEST (pattern)))
409 : return false;
410 :
411 0 : xtest = gen_rtx_AND (GET_MODE (xtest), xtest,
412 : COND_EXEC_TEST (pattern));
413 0 : pattern = COND_EXEC_CODE (pattern);
414 : }
415 :
416 0 : pattern = gen_rtx_COND_EXEC (VOIDmode, xtest, pattern);
417 :
418 : /* If the machine needs to modify the insn being conditionally executed,
419 : say for example to force a constant integer operand into a temp
420 : register, do so here. */
421 : #ifdef IFCVT_MODIFY_INSN
422 : IFCVT_MODIFY_INSN (ce_info, pattern, insn);
423 : if (! pattern)
424 : return false;
425 : #endif
426 :
427 0 : validate_change (insn, &PATTERN (insn), pattern, 1);
428 :
429 0 : if (CALL_P (insn) && prob_val.initialized_p ())
430 0 : validate_change (insn, ®_NOTES (insn),
431 : gen_rtx_INT_LIST ((machine_mode) REG_BR_PROB,
432 : prob_val.to_reg_br_prob_note (),
433 : REG_NOTES (insn)), 1);
434 :
435 0 : insn_done:
436 0 : if (insn == end)
437 : break;
438 0 : }
439 :
440 : return true;
441 : }
442 :
443 : /* Return the condition for a jump. Do not do any special processing. */
444 :
445 : static rtx
446 196748 : cond_exec_get_condition (rtx_insn *jump, bool get_reversed = false)
447 : {
448 196748 : rtx test_if, cond;
449 :
450 196748 : if (any_condjump_p (jump))
451 196748 : test_if = SET_SRC (pc_set (jump));
452 : else
453 : return NULL_RTX;
454 196748 : cond = XEXP (test_if, 0);
455 :
456 : /* If this branches to JUMP_LABEL when the condition is false,
457 : reverse the condition. */
458 196748 : if (get_reversed
459 196748 : || (GET_CODE (XEXP (test_if, 2)) == LABEL_REF
460 0 : && label_ref_label (XEXP (test_if, 2))
461 0 : == JUMP_LABEL (jump)))
462 : {
463 98374 : enum rtx_code rev = reversed_comparison_code (cond, jump);
464 98374 : if (rev == UNKNOWN)
465 : return NULL_RTX;
466 :
467 98374 : cond = gen_rtx_fmt_ee (rev, GET_MODE (cond), XEXP (cond, 0),
468 : XEXP (cond, 1));
469 : }
470 :
471 : return cond;
472 : }
473 :
474 : /* Given a simple IF-THEN or IF-THEN-ELSE block described by CE_INFO, attempt
475 : to convert it to conditional execution. DO_MULTIPLE_P allows CE_INFO's
476 : recorded chain of && or || test blocks to be converted as well. Return
477 : TRUE if we were successful at converting the block. */
478 :
479 : static bool
480 0 : cond_exec_process_if_block (ce_if_block *ce_info, bool do_multiple_p)
481 : {
482 0 : basic_block test_bb = ce_info->test_bb; /* last test block */
483 0 : basic_block then_bb = ce_info->then_bb; /* THEN */
484 0 : basic_block else_bb = ce_info->else_bb; /* ELSE or NULL */
485 0 : rtx test_expr; /* expression in IF_THEN_ELSE that is tested */
486 0 : rtx_insn *then_start; /* first insn in THEN block */
487 0 : rtx_insn *then_end; /* last insn + 1 in THEN block */
488 0 : rtx_insn *else_start = NULL; /* first insn in ELSE block or NULL */
489 0 : rtx_insn *else_end = NULL; /* last insn + 1 in ELSE block */
490 0 : int max; /* max # of insns to convert. */
491 0 : bool then_mod_ok; /* whether conditional mods are ok in THEN */
492 0 : rtx true_expr; /* test for else block insns */
493 0 : rtx false_expr; /* test for then block insns */
494 0 : profile_probability true_prob_val;/* probability of else block */
495 0 : profile_probability false_prob_val;/* probability of then block */
496 0 : rtx_insn *then_last_head = NULL; /* Last match at the head of THEN */
497 0 : rtx_insn *else_last_head = NULL; /* Last match at the head of ELSE */
498 0 : rtx_insn *then_first_tail = NULL; /* First match at the tail of THEN */
499 0 : rtx_insn *else_first_tail = NULL; /* First match at the tail of ELSE */
500 0 : int then_n_insns, else_n_insns, n_insns;
501 0 : enum rtx_code false_code;
502 0 : rtx note;
503 :
504 : /* If test is comprised of && or || elements, and we've failed at handling
505 : all of them together, just use the last test if it is the special case of
506 : && elements without an ELSE block. */
507 0 : if (!do_multiple_p && ce_info->num_multiple_test_blocks)
508 : {
509 0 : if (else_bb || ! ce_info->and_and_p)
510 : return false;
511 :
512 0 : ce_info->test_bb = test_bb = ce_info->last_test_bb;
513 0 : ce_info->num_multiple_test_blocks = 0;
514 0 : ce_info->num_and_and_blocks = 0;
515 0 : ce_info->num_or_or_blocks = 0;
516 : }
517 :
518 : /* Find the conditional jump to the ELSE or JOIN part, and isolate
519 : the test. */
520 0 : test_expr = cond_exec_get_condition (BB_END (test_bb));
521 0 : if (! test_expr)
522 : return false;
523 :
524 : /* If the conditional jump is more than just a conditional jump,
525 : then we cannot do conditional execution conversion on this block. */
526 0 : if (! onlyjump_p (BB_END (test_bb)))
527 : return false;
528 :
529 : /* Collect the bounds of where we're to search, skipping any labels, jumps
530 : and notes at the beginning and end of the block. Then count the total
531 : number of insns and see if it is small enough to convert. */
532 0 : then_start = first_active_insn (then_bb);
533 0 : then_end = last_active_insn (then_bb, true);
534 0 : then_n_insns = ce_info->num_then_insns = count_bb_insns (then_bb);
535 0 : n_insns = then_n_insns;
536 0 : max = MAX_CONDITIONAL_EXECUTE;
537 :
538 0 : if (else_bb)
539 : {
540 0 : int n_matching;
541 :
542 0 : max *= 2;
543 0 : else_start = first_active_insn (else_bb);
544 0 : else_end = last_active_insn (else_bb, true);
545 0 : else_n_insns = ce_info->num_else_insns = count_bb_insns (else_bb);
546 0 : n_insns += else_n_insns;
547 :
548 : /* Look for matching sequences at the head and tail of the two blocks,
549 : and limit the range of insns to be converted if possible. */
550 0 : n_matching = flow_find_cross_jump (then_bb, else_bb,
551 : &then_first_tail, &else_first_tail,
552 : NULL);
553 0 : if (then_first_tail == BB_HEAD (then_bb))
554 0 : then_start = then_end = NULL;
555 0 : if (else_first_tail == BB_HEAD (else_bb))
556 0 : else_start = else_end = NULL;
557 :
558 0 : if (n_matching > 0)
559 : {
560 0 : if (then_end)
561 0 : then_end = find_active_insn_before (then_bb, then_first_tail);
562 0 : if (else_end)
563 0 : else_end = find_active_insn_before (else_bb, else_first_tail);
564 0 : n_insns -= 2 * n_matching;
565 : }
566 :
567 0 : if (then_start
568 0 : && else_start
569 : && then_n_insns > n_matching
570 0 : && else_n_insns > n_matching)
571 : {
572 0 : int longest_match = MIN (then_n_insns - n_matching,
573 : else_n_insns - n_matching);
574 0 : n_matching
575 0 : = flow_find_head_matching_sequence (then_bb, else_bb,
576 : &then_last_head,
577 : &else_last_head,
578 : longest_match);
579 :
580 0 : if (n_matching > 0)
581 : {
582 0 : rtx_insn *insn;
583 :
584 : /* We won't pass the insns in the head sequence to
585 : cond_exec_process_insns, so we need to test them here
586 : to make sure that they don't clobber the condition. */
587 0 : for (insn = BB_HEAD (then_bb);
588 0 : insn != NEXT_INSN (then_last_head);
589 0 : insn = NEXT_INSN (insn))
590 0 : if (!LABEL_P (insn) && !NOTE_P (insn)
591 0 : && !DEBUG_INSN_P (insn)
592 0 : && modified_in_p (test_expr, insn))
593 : return false;
594 : }
595 :
596 0 : if (then_last_head == then_end)
597 0 : then_start = then_end = NULL;
598 0 : if (else_last_head == else_end)
599 0 : else_start = else_end = NULL;
600 :
601 0 : if (n_matching > 0)
602 : {
603 0 : if (then_start)
604 0 : then_start = find_active_insn_after (then_bb, then_last_head);
605 0 : if (else_start)
606 0 : else_start = find_active_insn_after (else_bb, else_last_head);
607 0 : n_insns -= 2 * n_matching;
608 : }
609 : }
610 : }
611 :
612 0 : if (n_insns > max)
613 : return false;
614 :
615 : /* Map test_expr/test_jump into the appropriate MD tests to use on
616 : the conditionally executed code. */
617 :
618 0 : true_expr = test_expr;
619 :
620 0 : false_code = reversed_comparison_code (true_expr, BB_END (test_bb));
621 0 : if (false_code != UNKNOWN)
622 0 : false_expr = gen_rtx_fmt_ee (false_code, GET_MODE (true_expr),
623 : XEXP (true_expr, 0), XEXP (true_expr, 1));
624 : else
625 : false_expr = NULL_RTX;
626 :
627 : #ifdef IFCVT_MODIFY_TESTS
628 : /* If the machine description needs to modify the tests, such as setting a
629 : conditional execution register from a comparison, it can do so here. */
630 : IFCVT_MODIFY_TESTS (ce_info, true_expr, false_expr);
631 :
632 : /* See if the conversion failed. */
633 : if (!true_expr || !false_expr)
634 : goto fail;
635 : #endif
636 :
637 0 : note = find_reg_note (BB_END (test_bb), REG_BR_PROB, NULL_RTX);
638 0 : if (note)
639 : {
640 0 : true_prob_val = profile_probability::from_reg_br_prob_note (XINT (note, 0));
641 0 : false_prob_val = true_prob_val.invert ();
642 : }
643 : else
644 : {
645 : true_prob_val = profile_probability::uninitialized ();
646 : false_prob_val = profile_probability::uninitialized ();
647 : }
648 :
649 : /* If we have && or || tests, do them here. These tests are in the adjacent
650 : blocks after the first block containing the test. */
651 0 : if (ce_info->num_multiple_test_blocks > 0)
652 : {
653 0 : basic_block bb = test_bb;
654 0 : basic_block last_test_bb = ce_info->last_test_bb;
655 :
656 0 : if (! false_expr)
657 0 : goto fail;
658 :
659 0 : do
660 : {
661 0 : rtx_insn *start, *end;
662 0 : rtx t, f;
663 0 : enum rtx_code f_code;
664 :
665 0 : bb = block_fallthru (bb);
666 0 : start = first_active_insn (bb);
667 0 : end = last_active_insn (bb, true);
668 0 : if (start
669 0 : && ! cond_exec_process_insns (ce_info, start, end, false_expr,
670 : false_prob_val, false))
671 0 : goto fail;
672 :
673 : /* If the conditional jump is more than just a conditional jump, then
674 : we cannot do conditional execution conversion on this block. */
675 0 : if (! onlyjump_p (BB_END (bb)))
676 0 : goto fail;
677 :
678 : /* Find the conditional jump and isolate the test. */
679 0 : t = cond_exec_get_condition (BB_END (bb));
680 0 : if (! t)
681 0 : goto fail;
682 :
683 0 : f_code = reversed_comparison_code (t, BB_END (bb));
684 0 : if (f_code == UNKNOWN)
685 0 : goto fail;
686 :
687 0 : f = gen_rtx_fmt_ee (f_code, GET_MODE (t), XEXP (t, 0), XEXP (t, 1));
688 0 : if (ce_info->and_and_p)
689 : {
690 0 : t = gen_rtx_AND (GET_MODE (t), true_expr, t);
691 0 : f = gen_rtx_IOR (GET_MODE (t), false_expr, f);
692 : }
693 : else
694 : {
695 0 : t = gen_rtx_IOR (GET_MODE (t), true_expr, t);
696 0 : f = gen_rtx_AND (GET_MODE (t), false_expr, f);
697 : }
698 :
699 : /* If the machine description needs to modify the tests, such as
700 : setting a conditional execution register from a comparison, it can
701 : do so here. */
702 : #ifdef IFCVT_MODIFY_MULTIPLE_TESTS
703 : IFCVT_MODIFY_MULTIPLE_TESTS (ce_info, bb, t, f);
704 :
705 : /* See if the conversion failed. */
706 : if (!t || !f)
707 : goto fail;
708 : #endif
709 :
710 0 : true_expr = t;
711 0 : false_expr = f;
712 : }
713 0 : while (bb != last_test_bb);
714 : }
715 :
716 : /* For IF-THEN-ELSE blocks, we don't allow modifications of the test
717 : on then THEN block. */
718 0 : then_mod_ok = (else_bb == NULL_BLOCK);
719 :
720 : /* Go through the THEN and ELSE blocks converting the insns if possible
721 : to conditional execution. */
722 :
723 0 : if (then_end
724 0 : && (! false_expr
725 0 : || ! cond_exec_process_insns (ce_info, then_start, then_end,
726 : false_expr, false_prob_val,
727 : then_mod_ok)))
728 0 : goto fail;
729 :
730 0 : if (else_bb && else_end
731 0 : && ! cond_exec_process_insns (ce_info, else_start, else_end,
732 : true_expr, true_prob_val, true))
733 0 : goto fail;
734 :
735 : /* If we cannot apply the changes, fail. Do not go through the normal fail
736 : processing, since apply_change_group will call cancel_changes. */
737 0 : if (! apply_change_group ())
738 : {
739 : #ifdef IFCVT_MODIFY_CANCEL
740 : /* Cancel any machine dependent changes. */
741 : IFCVT_MODIFY_CANCEL (ce_info);
742 : #endif
743 : return false;
744 : }
745 :
746 : #ifdef IFCVT_MODIFY_FINAL
747 : /* Do any machine dependent final modifications. */
748 : IFCVT_MODIFY_FINAL (ce_info);
749 : #endif
750 :
751 : /* Conversion succeeded. */
752 0 : if (dump_file)
753 0 : fprintf (dump_file, "%d insn%s converted to conditional execution.\n",
754 : n_insns, (n_insns == 1) ? " was" : "s were");
755 :
756 : /* Merge the blocks! If we had matching sequences, make sure to delete one
757 : copy at the appropriate location first: delete the copy in the THEN branch
758 : for a tail sequence so that the remaining one is executed last for both
759 : branches, and delete the copy in the ELSE branch for a head sequence so
760 : that the remaining one is executed first for both branches. */
761 0 : if (then_first_tail)
762 : {
763 0 : rtx_insn *from = then_first_tail;
764 0 : if (!INSN_P (from))
765 0 : from = find_active_insn_after (then_bb, from);
766 0 : delete_insn_chain (from, get_last_bb_insn (then_bb), false);
767 : }
768 0 : if (else_last_head)
769 0 : delete_insn_chain (first_active_insn (else_bb), else_last_head, false);
770 :
771 0 : merge_if_block (ce_info);
772 0 : ifcvt_changed_p = true;
773 0 : return true;
774 :
775 0 : fail:
776 : #ifdef IFCVT_MODIFY_CANCEL
777 : /* Cancel any machine dependent changes. */
778 : IFCVT_MODIFY_CANCEL (ce_info);
779 : #endif
780 :
781 0 : cancel_changes (0);
782 0 : return false;
783 : }
784 :
785 : /* Return the condition to use when the arms of IF_INFO's if-region are
786 : swapped, and set *CODE to its comparison code. When the reversed condition
787 : has no rtx of its own the original condition is returned alongside the
788 : reversed code, which is the form the store-flag and conditional-move
789 : expanders take. *CODE is UNKNOWN if the condition cannot be reversed. */
790 :
791 : static rtx
792 179624 : noce_reversed_cond (noce_if_info *if_info, enum rtx_code *code)
793 : {
794 179624 : if (if_info->rev_cond)
795 : {
796 179624 : *code = GET_CODE (if_info->rev_cond);
797 179624 : return if_info->rev_cond;
798 : }
799 :
800 0 : *code = reversed_comparison_code (if_info->cond, if_info->jump);
801 0 : return if_info->cond;
802 : }
803 :
804 : /* Return the comparison code for reversed condition for IF_INFO,
805 : or UNKNOWN if reversing the condition is not possible. */
806 :
807 : static inline enum rtx_code
808 104395 : noce_reversed_cond_code (noce_if_info *if_info)
809 : {
810 104395 : enum rtx_code code;
811 11230 : noce_reversed_cond (if_info, &code);
812 104395 : return code;
813 : }
814 :
815 : /* A register definition and its dependency level. */
816 :
817 : struct noce_parallel_cost_node
818 : {
819 : rtx dest;
820 : unsigned int level;
821 : };
822 :
823 : /* Return true if INSN is a unit-cost register SET supported by the parallel
824 : cost model. Store the SET in *SET. */
825 :
826 : static bool
827 473240 : noce_parallel_costed_insn_p (rtx_insn *insn, bool speed_p, rtx *set)
828 : {
829 473240 : *set = single_set (insn);
830 473240 : if (!*set)
831 : return false;
832 :
833 473019 : rtx dest = SET_DEST (*set);
834 473019 : rtx src = SET_SRC (*set);
835 :
836 473019 : return (REG_P (dest)
837 471438 : && !contains_mem_rtx_p (src)
838 452123 : && !side_effects_p (src)
839 452123 : && !may_trap_p (src)
840 922292 : && set_rtx_cost (*set, speed_p) == COSTS_N_INSNS (1));
841 : }
842 :
843 : /* Return the dependency level for an instruction reading SRC. A use of a
844 : register defined at level N requires level N + 1. */
845 :
846 : static unsigned int
847 429790 : noce_dependency_level (const vec<noce_parallel_cost_node> &defs, rtx src)
848 : {
849 429790 : unsigned int level = 0;
850 :
851 1300333 : for (unsigned int i = 0; i < defs.length (); ++i)
852 870543 : if (reg_overlap_mentioned_p (defs[i].dest, src))
853 870543 : level = MAX (level, defs[i].level + 1);
854 :
855 429790 : return level;
856 : }
857 :
858 : /* Estimate the cost of SEQ using the target issue rate. Unit-cost register
859 : operations are grouped by RAW dependency level. The cost of each level is
860 : its instruction count divided by the issue rate, rounded up. Fall back to
861 : serial cost if any instruction cannot be modeled.
862 :
863 : In an instrumented build of all SPEC CPU2017 Integer rate benchmarks
864 : for RISC-V, the analysis handled 16,947 of 30,120 candidates (56.26%).
865 : It reduced the cost for 15,024 of the handled candidates (88.65%).
866 : The parallel-to-serial cost ratios for the handled candidates were:
867 :
868 : 0.8 < ratio <= 1.0 11.54 percent
869 : 0.6 < ratio <= 0.8 47.31 percent
870 : 0.4 < ratio <= 0.6 40.24 percent
871 : 0.2 < ratio <= 0.4 0.91 percent
872 : 0.0 < ratio <= 0.2 0.00 percent. */
873 :
874 : static unsigned int
875 186371 : noce_parallel_seq_cost (rtx_insn *seq, bool speed_p)
876 : {
877 186371 : unsigned int serial_cost = seq_cost (seq, speed_p);
878 :
879 186371 : if (!speed_p || !targetm.sched.issue_rate)
880 : return serial_cost;
881 :
882 126856 : unsigned int issue_rate = MAX (targetm.sched.issue_rate (), 1);
883 :
884 : /* Track prior definitions and instruction counts per dependency level. */
885 126856 : auto_vec<noce_parallel_cost_node> defs;
886 126856 : auto_vec<unsigned int> insns_per_level;
887 :
888 556646 : for (rtx_insn *insn = seq; insn; insn = NEXT_INSN (insn))
889 : {
890 473240 : rtx set;
891 :
892 473240 : if (!NONDEBUG_INSN_P (insn))
893 0 : continue;
894 :
895 473240 : if (!noce_parallel_costed_insn_p (insn, speed_p, &set))
896 43450 : return serial_cost;
897 :
898 429790 : unsigned int level = noce_dependency_level (defs, SET_SRC (set));
899 :
900 429790 : if (insns_per_level.length () <= level)
901 249341 : insns_per_level.safe_grow_cleared (level + 1, true);
902 429790 : ++insns_per_level[level];
903 :
904 429790 : noce_parallel_cost_node node = { SET_DEST (set), level };
905 429790 : defs.safe_push (node);
906 : }
907 :
908 : unsigned int parallel_cost = 0;
909 292956 : for (unsigned int i = 0; i < insns_per_level.length (); ++i)
910 209550 : parallel_cost += COSTS_N_INSNS (CEIL (insns_per_level[i], issue_rate));
911 :
912 : /* set_rtx_cost and insn_cost can disagree, so cap the estimate at the
913 : serial cost. */
914 83406 : return MIN (serial_cost, parallel_cost);
915 126856 : }
916 :
917 : /* Return true if SEQ is a good candidate as a replacement for the
918 : if-convertible sequence described in IF_INFO.
919 : This is the default implementation that targets can override
920 : through a target hook. */
921 :
922 : bool
923 186371 : default_noce_conversion_profitable_p (rtx_insn *seq,
924 : noce_if_info *if_info)
925 : {
926 186371 : bool speed_p = if_info->speed_p;
927 :
928 : /* Cost up the new sequence. */
929 186371 : unsigned int cost = noce_parallel_seq_cost (seq, speed_p);
930 :
931 186371 : if (cost <= if_info->original_cost)
932 : return true;
933 :
934 : /* When compiling for size, we can make a reasonably accurately guess
935 : at the size growth. When compiling for speed, use the maximum. */
936 83146 : return speed_p && cost <= if_info->max_seq_cost;
937 : }
938 :
939 : /* Helper function for noce_try_store_flag*. Return NULL_RTX on failure,
940 : including when REVERSEP is requested but the condition cannot be
941 : reversed; callers may rely on this and need not pre-check. */
942 :
943 : static rtx
944 58521 : noce_emit_store_flag (noce_if_info *if_info, rtx x, bool reversep,
945 : int normalize)
946 : {
947 58521 : rtx cond = if_info->cond;
948 58521 : bool cond_complex;
949 58521 : enum rtx_code code;
950 :
951 58521 : cond_complex = (! general_operand (XEXP (cond, 0), VOIDmode)
952 58521 : || ! general_operand (XEXP (cond, 1), VOIDmode));
953 :
954 : /* If earliest == jump, or when the condition is complex, try to
955 : build the store_flag insn directly. */
956 :
957 34606 : if (cond_complex)
958 : {
959 23915 : rtx set = pc_set (if_info->jump);
960 23915 : cond = XEXP (SET_SRC (set), 0);
961 23915 : if (GET_CODE (XEXP (SET_SRC (set), 2)) == LABEL_REF
962 23915 : && label_ref_label (XEXP (SET_SRC (set), 2)) == JUMP_LABEL (if_info->jump))
963 0 : reversep = !reversep;
964 23915 : if (if_info->then_else_reversed)
965 21162 : reversep = !reversep;
966 : }
967 34606 : else if (reversep
968 17781 : && if_info->rev_cond
969 17781 : && general_operand (XEXP (if_info->rev_cond, 0), VOIDmode)
970 52387 : && general_operand (XEXP (if_info->rev_cond, 1), VOIDmode))
971 : {
972 17781 : cond = if_info->rev_cond;
973 17781 : reversep = false;
974 : }
975 :
976 58521 : if (reversep)
977 4410 : code = reversed_comparison_code (cond, if_info->jump);
978 : else
979 54111 : code = GET_CODE (cond);
980 :
981 : /* reversed_comparison_code returns UNKNOWN for an unordered code, or a
982 : CC-mode compare it cannot trace; neither path below can use that. */
983 58521 : if (code == UNKNOWN)
984 : return NULL_RTX;
985 :
986 58521 : if ((if_info->cond_earliest == if_info->jump || cond_complex)
987 23915 : && (normalize == 0 || STORE_FLAG_VALUE == normalize))
988 : {
989 18195 : rtx src = gen_rtx_fmt_ee (code, GET_MODE (x), XEXP (cond, 0),
990 : XEXP (cond, 1));
991 18195 : rtx set = gen_rtx_SET (x, src);
992 :
993 18195 : start_sequence ();
994 18195 : rtx_insn *insn = emit_insn (set);
995 :
996 18195 : if (recog_memoized (insn) >= 0)
997 : {
998 7910 : rtx_insn *seq = end_sequence ();
999 7910 : emit_insn (seq);
1000 :
1001 7910 : if_info->cond_earliest = if_info->jump;
1002 :
1003 7910 : return x;
1004 : }
1005 :
1006 10285 : end_sequence ();
1007 : }
1008 :
1009 : /* Don't even try if the comparison operands or the mode of X are weird. */
1010 50611 : if (cond_complex || !SCALAR_INT_MODE_P (GET_MODE (x)))
1011 : return NULL_RTX;
1012 :
1013 : /* Don't try if mode of X is more than the max fixed mode size. */
1014 103788 : if (known_le (MAX_FIXED_MODE_SIZE, GET_MODE_BITSIZE (GET_MODE (x))))
1015 : return NULL_RTX;
1016 :
1017 33261 : return emit_store_flag (x, code, XEXP (cond, 0),
1018 : XEXP (cond, 1), VOIDmode,
1019 33261 : (code == LTU || code == LEU
1020 66522 : || code == GEU || code == GTU), normalize);
1021 : }
1022 :
1023 : /* Return true if X can be safely forced into a register by copy_to_mode_reg
1024 : / force_operand. */
1025 :
1026 : static bool
1027 2096855 : noce_can_force_operand (rtx x)
1028 : {
1029 2097300 : if (general_operand (x, VOIDmode))
1030 : return true;
1031 557361 : if (SUBREG_P (x))
1032 : {
1033 445 : if (!noce_can_force_operand (SUBREG_REG (x)))
1034 : return false;
1035 : return true;
1036 : }
1037 556916 : if (ARITHMETIC_P (x))
1038 : {
1039 463646 : if (!noce_can_force_operand (XEXP (x, 0))
1040 463646 : || !noce_can_force_operand (XEXP (x, 1)))
1041 : return false;
1042 457872 : switch (GET_CODE (x))
1043 : {
1044 : case MULT:
1045 : case MOD:
1046 : case UDIV:
1047 : case UMOD:
1048 : return true;
1049 1851 : case DIV:
1050 1851 : if (INTEGRAL_MODE_P (GET_MODE (x)))
1051 : return true;
1052 : /* FALLTHRU */
1053 443963 : default:
1054 443963 : auto optab = code_to_optab (GET_CODE (x));
1055 443963 : if (!optab)
1056 : return false;
1057 433991 : return optab_handler (optab, GET_MODE (x)) != CODE_FOR_nothing;
1058 : }
1059 : }
1060 93270 : if (UNARY_P (x))
1061 : {
1062 84196 : if (!noce_can_force_operand (XEXP (x, 0)))
1063 : return false;
1064 84175 : switch (GET_CODE (x))
1065 : {
1066 : case ZERO_EXTEND:
1067 : case SIGN_EXTEND:
1068 : case TRUNCATE:
1069 : case FLOAT_EXTEND:
1070 : case FLOAT_TRUNCATE:
1071 : case FIX:
1072 : case UNSIGNED_FIX:
1073 : case FLOAT:
1074 : case UNSIGNED_FLOAT:
1075 : return true;
1076 13265 : default:
1077 13265 : auto optab = code_to_optab (GET_CODE (x));
1078 13265 : if (!optab)
1079 : return false;
1080 13265 : return optab_handler (optab, GET_MODE (x)) != CODE_FOR_nothing;
1081 : }
1082 : }
1083 : return false;
1084 : }
1085 :
1086 : /* Emit instruction to move an rtx, possibly into STRICT_LOW_PART.
1087 : X is the destination/target and Y is the value to copy. */
1088 :
1089 : static void
1090 148219 : noce_emit_move_insn (rtx x, rtx y)
1091 : {
1092 148219 : machine_mode outmode;
1093 148219 : rtx outer, inner;
1094 148219 : poly_int64 bitpos;
1095 :
1096 148219 : if (GET_CODE (x) != STRICT_LOW_PART)
1097 : {
1098 148219 : rtx_insn *seq, *insn;
1099 148219 : rtx target;
1100 148219 : optab ot;
1101 :
1102 148219 : start_sequence ();
1103 : /* Check that the SET_SRC is reasonable before calling emit_move_insn,
1104 : otherwise construct a suitable SET pattern ourselves. */
1105 148299 : insn = (OBJECT_P (y) || CONSTANT_P (y) || GET_CODE (y) == SUBREG)
1106 148299 : ? emit_move_insn (x, y)
1107 109324 : : emit_insn (gen_rtx_SET (x, y));
1108 148219 : seq = end_sequence ();
1109 :
1110 148219 : if (recog_memoized (insn) <= 0)
1111 : {
1112 68706 : if (GET_CODE (x) == ZERO_EXTRACT)
1113 : {
1114 0 : rtx op = XEXP (x, 0);
1115 0 : unsigned HOST_WIDE_INT size = INTVAL (XEXP (x, 1));
1116 0 : unsigned HOST_WIDE_INT start = INTVAL (XEXP (x, 2));
1117 :
1118 : /* store_bit_field expects START to be relative to
1119 : BYTES_BIG_ENDIAN and adjusts this value for machines with
1120 : BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN. In order to be able to
1121 : invoke store_bit_field again it is necessary to have the START
1122 : value from the first call. */
1123 0 : if (BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN)
1124 : {
1125 : if (MEM_P (op))
1126 : start = BITS_PER_UNIT - start - size;
1127 : else
1128 : {
1129 : gcc_assert (REG_P (op));
1130 : start = BITS_PER_WORD - start - size;
1131 : }
1132 : }
1133 :
1134 0 : gcc_assert (start < (MEM_P (op) ? BITS_PER_UNIT : BITS_PER_WORD));
1135 0 : store_bit_field (op, size, start, 0, 0, GET_MODE (x), y, false,
1136 : false);
1137 0 : return;
1138 : }
1139 :
1140 68706 : switch (GET_RTX_CLASS (GET_CODE (y)))
1141 : {
1142 1058 : case RTX_UNARY:
1143 1058 : ot = code_to_optab (GET_CODE (y));
1144 1058 : if (ot && noce_can_force_operand (XEXP (y, 0)))
1145 : {
1146 820 : start_sequence ();
1147 820 : target = expand_unop (GET_MODE (y), ot, XEXP (y, 0), x, 0);
1148 820 : if (target != NULL_RTX)
1149 : {
1150 820 : if (target != x)
1151 0 : emit_move_insn (x, target);
1152 820 : seq = get_insns ();
1153 : }
1154 820 : end_sequence ();
1155 : }
1156 : break;
1157 :
1158 36815 : case RTX_BIN_ARITH:
1159 36815 : case RTX_COMM_ARITH:
1160 36815 : ot = code_to_optab (GET_CODE (y));
1161 36815 : if (ot
1162 36815 : && noce_can_force_operand (XEXP (y, 0))
1163 73630 : && noce_can_force_operand (XEXP (y, 1)))
1164 : {
1165 36815 : start_sequence ();
1166 36815 : target = expand_binop (GET_MODE (y), ot,
1167 : XEXP (y, 0), XEXP (y, 1),
1168 : x, 0, OPTAB_DIRECT);
1169 36815 : if (target != NULL_RTX)
1170 : {
1171 36815 : if (target != x)
1172 0 : emit_move_insn (x, target);
1173 36815 : seq = get_insns ();
1174 : }
1175 36815 : end_sequence ();
1176 : }
1177 : break;
1178 :
1179 : default:
1180 : break;
1181 : }
1182 : }
1183 :
1184 148219 : emit_insn (seq);
1185 148219 : return;
1186 : }
1187 :
1188 0 : outer = XEXP (x, 0);
1189 0 : inner = XEXP (outer, 0);
1190 0 : outmode = GET_MODE (outer);
1191 0 : bitpos = SUBREG_BYTE (outer) * BITS_PER_UNIT;
1192 0 : store_bit_field (inner, GET_MODE_BITSIZE (outmode), bitpos,
1193 : 0, 0, outmode, y, false, false);
1194 : }
1195 :
1196 : /* Return the CC reg if it is used in COND. */
1197 :
1198 : static rtx
1199 4151628 : cc_in_cond (rtx cond)
1200 : {
1201 4151628 : if (have_cbranchcc4 && cond
1202 4151628 : && GET_MODE_CLASS (GET_MODE (XEXP (cond, 0))) == MODE_CC)
1203 142740 : return XEXP (cond, 0);
1204 :
1205 : return NULL_RTX;
1206 : }
1207 :
1208 : struct noce_cc_reg_set
1209 : {
1210 : HARD_REG_SET set;
1211 : unsigned int fixed_regno1;
1212 : unsigned int fixed_regno2;
1213 : };
1214 :
1215 : /* If DEST is a hard condition-code register, add it to the set in DATA.
1216 : PAT is the SET or CLOBBER that writes DEST. */
1217 :
1218 : static void
1219 1013247 : noce_record_cc_reg_set (rtx dest, const_rtx pat ATTRIBUTE_UNUSED, void *data)
1220 : {
1221 1013247 : noce_cc_reg_set *cc_regs = (noce_cc_reg_set *) data;
1222 :
1223 1011645 : if (REG_P (dest) && HARD_REGISTER_P (dest)
1224 1370516 : && (GET_MODE_CLASS (GET_MODE (dest)) == MODE_CC
1225 0 : || REGNO (dest) == targetm.flags_regnum
1226 0 : || REGNO (dest) == cc_regs->fixed_regno1
1227 0 : || REGNO (dest) == cc_regs->fixed_regno2))
1228 357269 : add_to_hard_reg_set (&cc_regs->set, GET_MODE (dest), REGNO (dest));
1229 1013247 : }
1230 :
1231 : /* Return true if SEQ writes a condition-code register that still holds a
1232 : value which is live on exit from TEST_BB.
1233 :
1234 : An if-converted sequence is emitted immediately before the jump that ends
1235 : TEST_BB, and the conversion then removes that jump, so a condition code
1236 : that is live out of TEST_BB is one which a later block still reads.
1237 : Expanding a conditional move can emit a fresh comparison, and that would
1238 : destroy it. */
1239 :
1240 : static bool
1241 227241 : noce_clobbers_live_cc_p (basic_block test_bb, rtx_insn *seq)
1242 : {
1243 227241 : noce_cc_reg_set cc_regs;
1244 227241 : CLEAR_HARD_REG_SET (cc_regs.set);
1245 227241 : cc_regs.fixed_regno1 = INVALID_REGNUM;
1246 227241 : cc_regs.fixed_regno2 = INVALID_REGNUM;
1247 227241 : targetm.fixed_condition_code_regs (&cc_regs.fixed_regno1,
1248 : &cc_regs.fixed_regno2);
1249 1318380 : for (rtx_insn *insn = seq; insn; insn = NEXT_INSN (insn))
1250 863898 : note_stores (insn, noce_record_cc_reg_set, &cc_regs);
1251 :
1252 227241 : bitmap live_out = df_get_live_out (test_bb);
1253 227241 : hard_reg_set_iterator hrsi;
1254 227241 : unsigned int regno;
1255 415080 : EXECUTE_IF_SET_IN_HARD_REG_SET (cc_regs.set, 0, regno, hrsi)
1256 188251 : if (bitmap_bit_p (live_out, regno))
1257 : return true;
1258 :
1259 : return false;
1260 : }
1261 :
1262 : /* Return sequence of instructions generated by if conversion. This
1263 : function calls end_sequence() to end the current stream, ensures
1264 : that the instructions are unshared, recognizable non-jump insns.
1265 : On failure, this function returns a NULL_RTX. */
1266 :
1267 : static rtx_insn *
1268 226073 : end_ifcvt_sequence (noce_if_info *if_info)
1269 : {
1270 226073 : rtx_insn *insn;
1271 226073 : rtx_insn *seq = get_insns ();
1272 226073 : rtx cc = cc_in_cond (if_info->cond);
1273 :
1274 226073 : set_used_flags (if_info->x);
1275 226073 : set_used_flags (if_info->cond);
1276 226073 : set_used_flags (if_info->a);
1277 226073 : set_used_flags (if_info->b);
1278 :
1279 1166065 : for (insn = seq; insn; insn = NEXT_INSN (insn))
1280 713919 : set_used_flags (insn);
1281 :
1282 226073 : unshare_all_rtl_in_chain (seq);
1283 226073 : end_sequence ();
1284 :
1285 : /* Make sure that all of the instructions emitted are recognizable,
1286 : and that we haven't introduced a new jump instruction.
1287 : As an exercise for the reader, build a general mechanism that
1288 : allows proper placement of required clobbers. */
1289 1133617 : for (insn = seq; insn; insn = NEXT_INSN (insn))
1290 713417 : if (JUMP_P (insn)
1291 713417 : || recog_memoized (insn) == -1
1292 : /* Make sure new generated code does not clobber CC. */
1293 1394963 : || (cc && set_of (cc, insn)))
1294 : return NULL;
1295 :
1296 : /* CC above only covers the condition code read by the converted branch. */
1297 194127 : if (noce_clobbers_live_cc_p (if_info->test_bb, seq))
1298 412 : return NULL;
1299 :
1300 : return seq;
1301 : }
1302 :
1303 : /* Return true iff the then and else basic block (if it exists)
1304 : consist of a single simple set instruction. */
1305 :
1306 : static bool
1307 3171219 : noce_simple_bbs (noce_if_info *if_info)
1308 : {
1309 0 : if (!if_info->then_simple)
1310 : return false;
1311 :
1312 2937608 : if (if_info->else_bb)
1313 0 : return if_info->else_simple;
1314 :
1315 : return true;
1316 : }
1317 :
1318 : /* Commit the wound-up candidate SEQ produced by a noce transform for IF_INFO.
1319 : Reject it (returning false, emitting nothing) if it failed to build, or if
1320 : CHECK_PROFITABLE and the target deems it not worthwhile. Otherwise emit it
1321 : before the branch, record NAME as the winning transform and return true.
1322 : This is the shared tail of the noce_try_* matchers. */
1323 :
1324 : static bool
1325 211217 : noce_commit_sequence (noce_if_info *if_info, rtx_insn *seq,
1326 : bool check_profitable, const char *name)
1327 : {
1328 211217 : if (!seq
1329 136585 : || (check_profitable
1330 135073 : && !targetm.noce_conversion_profitable_p (seq, if_info)))
1331 : return false;
1332 :
1333 141164 : emit_insn_before_setloc (seq, if_info->jump,
1334 141164 : INSN_LOCATION (if_info->insn_a));
1335 141164 : if_info->transform_name = name;
1336 141164 : return true;
1337 : }
1338 :
1339 : /* Convert "if (a != b) x = a; else x = b" into "x = a" and
1340 : "if (a == b) x = a; else x = b" into "x = b". */
1341 :
1342 : static bool
1343 252720 : noce_try_move (noce_if_info *if_info)
1344 : {
1345 252720 : rtx cond = if_info->cond;
1346 252720 : enum rtx_code code = GET_CODE (cond);
1347 252720 : rtx y;
1348 252720 : rtx_insn *seq;
1349 :
1350 252720 : if (code != NE && code != EQ)
1351 : return false;
1352 :
1353 256651 : if (!noce_simple_bbs (if_info))
1354 : return false;
1355 :
1356 : /* This optimization isn't valid if either A or B could be a NaN
1357 : or a signed zero. */
1358 176527 : if (HONOR_NANS (if_info->x)
1359 176527 : || HONOR_SIGNED_ZEROS (if_info->x))
1360 : return false;
1361 :
1362 : /* Check whether the operands of the comparison are A and B, in
1363 : either order. */
1364 151421 : if ((rtx_equal_p (if_info->a, XEXP (cond, 0))
1365 2311 : && rtx_equal_p (if_info->b, XEXP (cond, 1)))
1366 153720 : || (rtx_equal_p (if_info->a, XEXP (cond, 1))
1367 15645 : && rtx_equal_p (if_info->b, XEXP (cond, 0))))
1368 : {
1369 21 : if (!rtx_interchangeable_p (if_info->a, if_info->b))
1370 : return false;
1371 :
1372 0 : y = (code == EQ) ? if_info->a : if_info->b;
1373 :
1374 : /* Avoid generating the move if the source is the destination. */
1375 0 : if (! rtx_equal_p (if_info->x, y))
1376 : {
1377 0 : start_sequence ();
1378 0 : noce_emit_move_insn (if_info->x, y);
1379 0 : seq = end_ifcvt_sequence (if_info);
1380 0 : if (!seq)
1381 : return false;
1382 :
1383 0 : emit_insn_before_setloc (seq, if_info->jump,
1384 0 : INSN_LOCATION (if_info->insn_a));
1385 : }
1386 0 : if_info->transform_name = "noce_try_move";
1387 0 : return true;
1388 : }
1389 : return false;
1390 : }
1391 :
1392 : /* TEMP holds an all-ones or all-zeros splat of a tested sign bit. Return an
1393 : rtx that narrows it to VAL or zero, expanded into TARGET where possible, or
1394 : NULL_RTX if the expansion failed.
1395 :
1396 : The obvious form is a mask, but since the value is known to be -1 or 0 a
1397 : shift is sometimes cheaper: a logical right shift constructs 2^n-1 and a
1398 : left shift constructs ~(2^n-1). Some targets do not have efficient shifts,
1399 : so build the RTL for each applicable form and expand the cheapest. */
1400 :
1401 : static rtx
1402 82 : noce_splat_to_const (machine_mode mode, rtx temp, HOST_WIDE_INT val,
1403 : rtx target)
1404 : {
1405 82 : rtx and_form = gen_rtx_AND (mode, temp, GEN_INT (val));
1406 164 : rtx shift_left = gen_rtx_ASHIFT (mode, temp, GEN_INT (ctz_hwi (val)));
1407 82 : HOST_WIDE_INT rshift_count
1408 164 : = clz_hwi (val) & (GET_MODE_PRECISION (mode).to_constant () - 1);
1409 82 : rtx shift_right = gen_rtx_LSHIFTRT (mode, temp, GEN_INT (rshift_count));
1410 82 : bool speed_p = optimize_insn_for_speed_p ();
1411 :
1412 82 : if (exact_log2 (val + 1) >= 0
1413 50 : && (rtx_cost (shift_right, mode, SET, 1, speed_p)
1414 25 : < rtx_cost (and_form, mode, SET, 1, speed_p)))
1415 3 : return expand_simple_binop (mode, LSHIFTRT, temp, GEN_INT (rshift_count),
1416 3 : target, false, OPTAB_WIDEN);
1417 :
1418 79 : if (exact_log2 (~val + 1) >= 0
1419 0 : && (rtx_cost (shift_left, mode, SET, 1, speed_p)
1420 0 : < rtx_cost (and_form, mode, SET, 1, speed_p)))
1421 0 : return expand_simple_binop (mode, ASHIFT, temp, GEN_INT (ctz_hwi (val)),
1422 0 : target, false, OPTAB_WIDEN);
1423 :
1424 79 : return expand_simple_binop (mode, AND, temp, GEN_INT (val), target, false,
1425 79 : OPTAB_WIDEN);
1426 : }
1427 :
1428 : /* If a sign bit test is selecting across constants, we may be able
1429 : to generate efficient code utilizing the -1/0 result of a sign
1430 : bit splat idiom.
1431 :
1432 : Do this before trying the generalized conditional move as these
1433 : (when applicable) are hopefully faster than a conditional move. */
1434 :
1435 : static bool
1436 200275 : noce_try_sign_bit_splat (noce_if_info *if_info)
1437 : {
1438 200275 : rtx cond = if_info->cond;
1439 200275 : enum rtx_code code = GET_CODE (cond);
1440 :
1441 : /* We're looking for sign bit tests, so only a few cases are
1442 : interesting. LT/GE 0 LE/GT -1. */
1443 200275 : if (((code == LT || code == GE)
1444 11194 : && XEXP (cond, 1) == CONST0_RTX (GET_MODE (cond)))
1445 197766 : || ((code == LE || code == GT)
1446 11352 : && XEXP (cond, 1) == CONSTM1_RTX (GET_MODE (cond))))
1447 : ;
1448 : else
1449 : return false;
1450 :
1451 : /* It would be good if this could be extended since constant synthesis
1452 : on some platforms will result in blocks which fail this test. */
1453 10876 : if (!noce_simple_bbs (if_info))
1454 : return false;
1455 :
1456 : /* Only try this for constants in the true/false arms and a REG
1457 : destination. We could select between 0 and a REG pretty
1458 : easily with a logical AND. */
1459 6059 : if (!CONST_INT_P (if_info->a)
1460 1990 : || !CONST_INT_P (if_info->b)
1461 681 : || !REG_P (if_info->x))
1462 : return false;
1463 :
1464 681 : machine_mode mode = GET_MODE (if_info->x);
1465 :
1466 : /* If the mode of the destination does not match the mode of
1467 : the value we're testing, then this optimization is not valid. */
1468 681 : if (mode != GET_MODE (XEXP (cond, 0)))
1469 : return false;
1470 :
1471 212 : HOST_WIDE_INT val_a = INTVAL (if_info->a);
1472 212 : HOST_WIDE_INT val_b = INTVAL (if_info->b);
1473 :
1474 212 : rtx_insn *seq;
1475 212 : start_sequence ();
1476 :
1477 : /* We're testing the sign bit of this operand. */
1478 212 : rtx condop = XEXP (cond, 0);
1479 :
1480 : /* To splat the sign bit we arithmetically shift the
1481 : input value right by the size of the object - 1 bits.
1482 :
1483 : Note some targets do not have strong shifters, but do have
1484 : alternative ways to generate the sign bit splat. The
1485 : profitability test when we end the sequence should reject
1486 : cases when the branchy sequence is better. */
1487 212 : int splat_count = GET_MODE_BITSIZE (GET_MODE (condop)).to_constant () - 1;
1488 212 : rtx splat = GEN_INT (splat_count);
1489 :
1490 212 : rtx temp;
1491 212 : temp = expand_simple_binop (GET_MODE (XEXP (cond, 0)), ASHIFTRT,
1492 : XEXP (cond, 0), splat, NULL_RTX,
1493 : false, OPTAB_WIDEN);
1494 212 : if (!temp)
1495 0 : goto fail;
1496 :
1497 : /* IOR of anything with -1 still results in -1. So we can
1498 : IOR the other operand to generate a select between -1 and
1499 : an arbitrary constant. */
1500 212 : if (val_a == -1)
1501 : {
1502 50 : if (code == LT || code == LE)
1503 : {
1504 2 : temp = expand_simple_unop (mode, NOT, temp, NULL_RTX, true);
1505 2 : if (!temp)
1506 0 : goto fail;
1507 : }
1508 :
1509 50 : temp = expand_simple_binop (mode, IOR, temp, GEN_INT (val_b),
1510 : if_info->x, false, OPTAB_WIDEN);
1511 : }
1512 : /* AND of anything with 0 is still zero. So we can AND
1513 : with the -1 operand with the a constant to select
1514 : between the constant and zero. */
1515 162 : else if (val_b == 0)
1516 : {
1517 0 : if (code == LT || code == LE)
1518 : {
1519 0 : temp = expand_simple_unop (mode, NOT, temp, NULL_RTX, true);
1520 0 : if (!temp)
1521 0 : goto fail;
1522 : }
1523 :
1524 0 : temp = noce_splat_to_const (mode, temp, val_a, if_info->x);
1525 : }
1526 : /* Same cases, but with the test or arms swapped. These
1527 : can be realized as well, though it typically costs
1528 : an extra instruction. */
1529 162 : else if (val_b == -1)
1530 : {
1531 46 : if (code != LT && code != LE)
1532 : {
1533 2 : temp = expand_simple_unop (mode, NOT, temp, NULL_RTX, true);
1534 2 : if (!temp)
1535 0 : goto fail;
1536 : }
1537 :
1538 46 : temp = expand_simple_binop (mode, IOR, temp, GEN_INT (val_a),
1539 : if_info->x, false, OPTAB_WIDEN);
1540 : }
1541 116 : else if (val_a == 0)
1542 : {
1543 82 : if (code != LT && code != LE)
1544 : {
1545 9 : temp = expand_simple_unop (mode, NOT, temp, NULL_RTX, true);
1546 9 : if (!temp)
1547 0 : goto fail;
1548 : }
1549 :
1550 82 : temp = noce_splat_to_const (mode, temp, val_b, if_info->x);
1551 : }
1552 : /* Nothing worked. */
1553 : else
1554 : temp = NULL_RTX;
1555 :
1556 178 : if (!temp)
1557 34 : goto fail;
1558 :
1559 : /* Move into the final destination if the value wasn't
1560 : constructed there. */
1561 178 : if (if_info->x != temp)
1562 0 : emit_move_insn (if_info->x, temp);
1563 :
1564 : /* This ends the sequence and tests the cost model. */
1565 178 : seq = end_ifcvt_sequence (if_info);
1566 178 : return noce_commit_sequence (if_info, seq, true, "splat_sign_bit_trivial");
1567 :
1568 34 : fail:
1569 34 : end_ifcvt_sequence (if_info);
1570 34 : return false;
1571 : }
1572 :
1573 :
1574 : /* Try forming an IF_THEN_ELSE (cond, b, a) and collapsing that
1575 : through simplify_rtx. Sometimes that can eliminate the IF_THEN_ELSE.
1576 : If that is the case, emit the result into x. */
1577 :
1578 : static bool
1579 252720 : noce_try_ifelse_collapse (noce_if_info * if_info)
1580 : {
1581 338605 : if (!noce_simple_bbs (if_info))
1582 : return false;
1583 :
1584 234042 : machine_mode mode = GET_MODE (if_info->x);
1585 234042 : rtx if_then_else = simplify_gen_ternary (IF_THEN_ELSE, mode, mode,
1586 : if_info->cond, if_info->b,
1587 : if_info->a);
1588 :
1589 234042 : if (GET_CODE (if_then_else) == IF_THEN_ELSE)
1590 : return false;
1591 :
1592 48631 : rtx_insn *seq;
1593 48631 : start_sequence ();
1594 48631 : noce_emit_move_insn (if_info->x, if_then_else);
1595 48631 : seq = end_ifcvt_sequence (if_info);
1596 48631 : return noce_commit_sequence (if_info, seq, false, "noce_try_ifelse_collapse");
1597 : }
1598 :
1599 :
1600 : /* Convert "if (test) x = 1; else x = 0".
1601 :
1602 : Only try 0 and STORE_FLAG_VALUE here. Other combinations will be
1603 : tried in noce_try_store_flag_constants after noce_try_cmove has had
1604 : a go at the conversion. */
1605 :
1606 : static bool
1607 234922 : noce_try_store_flag (noce_if_info *if_info)
1608 : {
1609 234922 : bool reversep;
1610 234922 : rtx target;
1611 234922 : rtx_insn *seq;
1612 :
1613 307523 : if (!noce_simple_bbs (if_info))
1614 : return false;
1615 :
1616 216244 : if (CONST_INT_P (if_info->b)
1617 73873 : && INTVAL (if_info->b) == STORE_FLAG_VALUE
1618 13355 : && if_info->a == const0_rtx)
1619 : reversep = false;
1620 205759 : else if (if_info->b == const0_rtx
1621 30457 : && CONST_INT_P (if_info->a)
1622 20804 : && INTVAL (if_info->a) == STORE_FLAG_VALUE)
1623 : reversep = true;
1624 : else
1625 : return false;
1626 :
1627 30834 : start_sequence ();
1628 :
1629 30834 : target = noce_emit_store_flag (if_info, if_info->x, reversep, 0);
1630 30834 : if (target)
1631 : {
1632 26001 : if (target != if_info->x)
1633 2982 : noce_emit_move_insn (if_info->x, target);
1634 :
1635 26001 : seq = end_ifcvt_sequence (if_info);
1636 26001 : return noce_commit_sequence (if_info, seq, false, "noce_try_store_flag");
1637 : }
1638 : else
1639 : {
1640 4833 : end_sequence ();
1641 4833 : return false;
1642 : }
1643 : }
1644 :
1645 :
1646 : /* Convert "if (test) x = -A; else x = A" into
1647 : x = A; if (test) x = -x if the machine can do the
1648 : conditional negate form of this cheaply.
1649 : Try this before noce_try_cmove that will just load the
1650 : immediates into two registers and do a conditional select
1651 : between them. If the target has a conditional negate or
1652 : conditional invert operation we can save a potentially
1653 : expensive constant synthesis. */
1654 :
1655 : static bool
1656 208837 : noce_try_inverse_constants (noce_if_info *if_info)
1657 : {
1658 271799 : if (!noce_simple_bbs (if_info))
1659 : return false;
1660 :
1661 190159 : if (!CONST_INT_P (if_info->a)
1662 51593 : || !CONST_INT_P (if_info->b)
1663 21282 : || !REG_P (if_info->x))
1664 : return false;
1665 :
1666 21282 : machine_mode mode = GET_MODE (if_info->x);
1667 :
1668 21282 : HOST_WIDE_INT val_a = INTVAL (if_info->a);
1669 21282 : HOST_WIDE_INT val_b = INTVAL (if_info->b);
1670 :
1671 21282 : rtx cond = if_info->cond;
1672 :
1673 21282 : rtx x = if_info->x;
1674 21282 : rtx target;
1675 :
1676 21282 : start_sequence ();
1677 :
1678 21282 : rtx_code code;
1679 21282 : if (val_b != HOST_WIDE_INT_MIN && val_a == -val_b)
1680 : code = NEG;
1681 19991 : else if (val_a == ~val_b)
1682 : code = NOT;
1683 : else
1684 : {
1685 19923 : end_sequence ();
1686 19923 : return false;
1687 : }
1688 :
1689 1359 : rtx tmp = gen_reg_rtx (mode);
1690 1359 : noce_emit_move_insn (tmp, if_info->a);
1691 :
1692 1359 : target = emit_conditional_neg_or_complement (x, code, mode, cond, tmp, tmp);
1693 :
1694 1359 : if (target)
1695 : {
1696 0 : rtx_insn *seq = get_insns ();
1697 :
1698 0 : if (!seq)
1699 : {
1700 0 : end_sequence ();
1701 0 : return false;
1702 : }
1703 :
1704 0 : if (target != if_info->x)
1705 0 : noce_emit_move_insn (if_info->x, target);
1706 :
1707 0 : seq = end_ifcvt_sequence (if_info);
1708 0 : return noce_commit_sequence (if_info, seq, false,
1709 : "noce_try_inverse_constants");
1710 : }
1711 :
1712 1359 : end_sequence ();
1713 1359 : return false;
1714 : }
1715 :
1716 : /* Check if OP is supported by conditional zero based if conversion,
1717 : returning TRUE if satisfied otherwise FALSE.
1718 :
1719 : OP is the operation to check. */
1720 :
1721 : static bool
1722 586348 : noce_cond_zero_binary_op_supported (rtx op)
1723 : {
1724 586348 : enum rtx_code opcode = GET_CODE (op);
1725 :
1726 0 : if (opcode == PLUS || opcode == MINUS || opcode == IOR || opcode == XOR
1727 : || opcode == ASHIFT || opcode == ASHIFTRT || opcode == LSHIFTRT
1728 : || opcode == ROTATE || opcode == ROTATERT || opcode == AND)
1729 0 : return true;
1730 :
1731 : return false;
1732 : }
1733 :
1734 : /* Convert "if (test) x = a; else x = a OP c " where c is 2^n.
1735 :
1736 : We can shift the output of a set flag insn left to generate 2^n
1737 : cheaply, then apply OP unconditionally. This works even if the
1738 : target does not have a conditional zero idiom. On targets such
1739 : as RISC-V this sequence may also encode better.
1740 :
1741 : This is based on noce_try_store_flag_constants. */
1742 :
1743 : static bool
1744 205676 : noce_try_shifted_store_flag (noce_if_info *if_info)
1745 : {
1746 205676 : rtx target;
1747 205676 : rtx_insn *seq;
1748 205676 : machine_mode mode = GET_MODE (if_info->x);
1749 205676 : rtx common = NULL_RTX;
1750 205676 : rtx_code code = UNKNOWN;
1751 :
1752 205676 : if (STORE_FLAG_VALUE != 1)
1753 : return false;
1754 :
1755 265551 : if (!noce_simple_bbs (if_info))
1756 : return false;
1757 :
1758 186998 : rtx a = if_info->a;
1759 186998 : rtx b = if_info->b;
1760 :
1761 : /* Most binary operators are allowed, essentially the same set
1762 : as the condzero arithmetic paths, with the exception of AND
1763 : which could be handled if we were inclined. */
1764 186998 : int shiftval;
1765 186998 : bool reversed = false;
1766 186998 : if (noce_cond_zero_binary_op_supported (a)
1767 24216 : && GET_CODE (a) != AND
1768 24010 : && GET_CODE (b) == REG
1769 20385 : && rtx_equal_p (XEXP (a, 0), b)
1770 18403 : && CONST_INT_P (XEXP (a, 1))
1771 8979 : && pow2p_hwi (INTVAL (XEXP (a, 1))))
1772 : {
1773 6634 : code = GET_CODE (a);
1774 6634 : common = XEXP (a, 0);
1775 6634 : shiftval = exact_log2 (INTVAL (XEXP (a, 1)));
1776 :
1777 : /* When the condition is true, we branch around A and thus we want
1778 : the condition reversed from what you might expect. */
1779 : reversed = true;
1780 : }
1781 180364 : else if (noce_cond_zero_binary_op_supported (b)
1782 2141 : && GET_CODE (b) != AND
1783 2110 : && GET_CODE (a) == REG
1784 230 : && rtx_equal_p (XEXP (b, 0), a)
1785 89 : && CONST_INT_P (XEXP (b, 1))
1786 62 : && pow2p_hwi (INTVAL (XEXP (b, 1))))
1787 : {
1788 31 : code = GET_CODE (b);
1789 31 : common = XEXP (b, 0);
1790 31 : shiftval = exact_log2 (INTVAL (XEXP (b, 1)));
1791 : }
1792 :
1793 :
1794 : /* If CODE hasn't been reset, then the basic expression form was wrong and
1795 : we can not optimize. */
1796 6665 : if (code == UNKNOWN)
1797 : return false;
1798 :
1799 6665 : start_sequence ();
1800 :
1801 : /* If X and COMMON are the same, then we're going to need a temporary. */
1802 6665 : if (rtx_equal_p (common, if_info->x))
1803 : {
1804 6068 : common = gen_reg_rtx (mode);
1805 6068 : noce_emit_move_insn (common, if_info->x);
1806 : }
1807 :
1808 6665 : target = noce_emit_store_flag (if_info, if_info->x, reversed, 1);
1809 6665 : if (!target)
1810 : {
1811 745 : end_sequence ();
1812 745 : return false;
1813 : }
1814 :
1815 : /* Right now TARGET has the value 1/0. A left shift will produce the
1816 : target value. Unnecessary if the shift value is zero. */
1817 5920 : if (shiftval != 0)
1818 1218 : target = expand_simple_binop (mode, ASHIFT, target,
1819 : GEN_INT (shiftval),
1820 : NULL_RTX, 0, OPTAB_WIDEN);
1821 :
1822 5920 : if (!target)
1823 : {
1824 0 : end_sequence ();
1825 0 : return false;
1826 : }
1827 :
1828 : /* Now we just need to apply the code to COMMON and TARGET. */
1829 5920 : target = expand_simple_binop (mode, code,
1830 : common, target,
1831 : NULL_RTX, 0, OPTAB_WIDEN);
1832 :
1833 5920 : if (!target)
1834 : {
1835 0 : end_sequence ();
1836 0 : return false;
1837 : }
1838 :
1839 : /* If necessary, store the result into the proper destination. */
1840 5920 : if (target != if_info->x)
1841 5920 : noce_emit_move_insn (if_info->x, target);
1842 :
1843 5920 : seq = end_ifcvt_sequence (if_info);
1844 5920 : return noce_commit_sequence (if_info, seq, true,
1845 5920 : "noce_try_shifted_store_flag");
1846 : }
1847 :
1848 :
1849 : /* Set *DIFF to ITRUE - IFALSE truncated to MODE and return true. Return
1850 : false, leaving *DIFF alone, when that difference is not representable and
1851 : so cannot be used to build a store-flag sequence. */
1852 :
1853 : static bool
1854 21774 : noce_representable_diff_p (HOST_WIDE_INT ifalse, HOST_WIDE_INT itrue,
1855 : machine_mode mode, HOST_WIDE_INT *diff)
1856 : {
1857 21774 : HOST_WIDE_INT d = (unsigned HOST_WIDE_INT) itrue - ifalse;
1858 :
1859 21774 : if ((d > 0) != ((ifalse < 0) != (itrue < 0) ? ifalse < 0 : ifalse < itrue))
1860 : return false;
1861 :
1862 21639 : *diff = trunc_int_for_mode (d, mode);
1863 21639 : return true;
1864 : }
1865 :
1866 : /* Convert "if (test) x = a; else x = b", for A and B constant.
1867 : Also allow A = y + c1, B = y + c2, with a common y between A
1868 : and B. */
1869 :
1870 : static bool
1871 208837 : noce_try_store_flag_constants (noce_if_info *if_info)
1872 : {
1873 208837 : rtx target;
1874 208837 : rtx_insn *seq;
1875 208837 : bool reversep;
1876 208837 : HOST_WIDE_INT itrue, ifalse, diff, tmp;
1877 208837 : int normalize;
1878 208837 : bool can_reverse;
1879 208837 : machine_mode mode = GET_MODE (if_info->x);
1880 208837 : rtx common = NULL_RTX;
1881 :
1882 208837 : rtx a = if_info->a;
1883 208837 : rtx b = if_info->b;
1884 :
1885 : /* Handle cases like x := test ? y + 3 : y + 4. */
1886 208837 : if (GET_CODE (a) == PLUS
1887 22334 : && GET_CODE (b) == PLUS
1888 1447 : && CONST_INT_P (XEXP (a, 1))
1889 570 : && CONST_INT_P (XEXP (b, 1))
1890 494 : && rtx_equal_p (XEXP (a, 0), XEXP (b, 0))
1891 : /* Allow expressions that are not using the result or plain
1892 : registers where we handle overlap below. */
1893 209281 : && (REG_P (XEXP (a, 0))
1894 6 : || (noce_operand_ok (XEXP (a, 0))
1895 6 : && ! reg_overlap_mentioned_p (if_info->x, XEXP (a, 0)))))
1896 : {
1897 444 : common = XEXP (a, 0);
1898 444 : a = XEXP (a, 1);
1899 444 : b = XEXP (b, 1);
1900 : }
1901 :
1902 271799 : if (!noce_simple_bbs (if_info))
1903 : return false;
1904 :
1905 190159 : if (CONST_INT_P (a)
1906 52025 : && CONST_INT_P (b))
1907 : {
1908 21714 : ifalse = INTVAL (a);
1909 21714 : itrue = INTVAL (b);
1910 21714 : bool subtract_flag_p = false;
1911 :
1912 21714 : if (!noce_representable_diff_p (ifalse, itrue, mode, &diff))
1913 : return false;
1914 :
1915 21600 : can_reverse = noce_reversed_cond_code (if_info) != UNKNOWN;
1916 21600 : reversep = false;
1917 21600 : if (diff == STORE_FLAG_VALUE || diff == -STORE_FLAG_VALUE)
1918 : {
1919 12009 : normalize = 0;
1920 : /* We could collapse these cases but it is easier to follow the
1921 : diff/STORE_FLAG_VALUE combinations when they are listed
1922 : explicitly. */
1923 :
1924 : /* test ? 3 : 4
1925 : => 4 + (test != 0). */
1926 12009 : if (diff < 0 && STORE_FLAG_VALUE < 0)
1927 : reversep = false;
1928 : /* test ? 4 : 3
1929 : => can_reverse | 4 + (test == 0)
1930 : !can_reverse | 3 - (test != 0). */
1931 12009 : else if (diff > 0 && STORE_FLAG_VALUE < 0)
1932 : {
1933 : reversep = can_reverse;
1934 : subtract_flag_p = !can_reverse;
1935 : /* If we need to subtract the flag and we have PLUS-immediate
1936 : A and B then it is unlikely to be beneficial to play tricks
1937 : here. */
1938 : if (subtract_flag_p && common)
1939 : return false;
1940 : }
1941 : /* test ? 3 : 4
1942 : => can_reverse | 3 + (test == 0)
1943 : !can_reverse | 4 - (test != 0). */
1944 12009 : else if (diff < 0 && STORE_FLAG_VALUE > 0)
1945 : {
1946 6105 : reversep = can_reverse;
1947 6105 : subtract_flag_p = !can_reverse;
1948 : /* If we need to subtract the flag and we have PLUS-immediate
1949 : A and B then it is unlikely to be beneficial to play tricks
1950 : here. */
1951 6105 : if (subtract_flag_p && common)
1952 : return false;
1953 : }
1954 : /* test ? 4 : 3
1955 : => 4 + (test != 0). */
1956 : else if (diff > 0 && STORE_FLAG_VALUE > 0)
1957 : reversep = false;
1958 : else
1959 : gcc_unreachable ();
1960 : }
1961 : /* Is this (cond) ? 2^n : 0? */
1962 532 : else if (ifalse == 0 && pow2p_hwi (itrue)
1963 9591 : && STORE_FLAG_VALUE == 1)
1964 : normalize = 1;
1965 : /* Is this (cond) ? 0 : 2^n? */
1966 388 : else if (itrue == 0 && pow2p_hwi (ifalse)
1967 9584 : && STORE_FLAG_VALUE == 1)
1968 : {
1969 : normalize = 1;
1970 : reversep = true;
1971 : }
1972 : /* Is this (cond) ? -1 : x? */
1973 : else if (itrue == -1
1974 : && STORE_FLAG_VALUE == -1)
1975 : normalize = -1;
1976 : /* Is this (cond) ? x : -1? */
1977 : else if (ifalse == -1
1978 : && STORE_FLAG_VALUE == -1)
1979 : {
1980 : normalize = -1;
1981 : reversep = true;
1982 : }
1983 : else
1984 : return false;
1985 :
1986 6105 : if (reversep)
1987 : {
1988 6106 : std::swap (itrue, ifalse);
1989 6106 : diff = trunc_int_for_mode (-(unsigned HOST_WIDE_INT) diff, mode);
1990 : }
1991 :
1992 12017 : start_sequence ();
1993 :
1994 : /* If we have x := test ? x + 3 : x + 4 then move the original
1995 : x out of the way while we store flags. */
1996 12017 : if (common && rtx_equal_p (common, if_info->x))
1997 : {
1998 5 : common = gen_reg_rtx (mode);
1999 5 : noce_emit_move_insn (common, if_info->x);
2000 : }
2001 :
2002 12017 : target = noce_emit_store_flag (if_info, if_info->x, reversep, normalize);
2003 12017 : if (! target)
2004 : {
2005 4869 : end_sequence ();
2006 4869 : return false;
2007 : }
2008 :
2009 : /* if (test) x = 3; else x = 4;
2010 : => x = 3 + (test == 0); */
2011 7148 : if (diff == STORE_FLAG_VALUE || diff == -STORE_FLAG_VALUE)
2012 : {
2013 : /* Add the common part now. This may allow combine to merge this
2014 : with the store flag operation earlier into some sort of conditional
2015 : increment/decrement if the target allows it. */
2016 7140 : if (common)
2017 28 : target = expand_simple_binop (mode, PLUS,
2018 : target, common,
2019 : target, 0, OPTAB_WIDEN);
2020 :
2021 : /* Always use ifalse here. It should have been swapped with itrue
2022 : when appropriate when reversep is true. */
2023 14280 : target = expand_simple_binop (mode, subtract_flag_p ? MINUS : PLUS,
2024 7140 : gen_int_mode (ifalse, mode), target,
2025 : if_info->x, 0, OPTAB_WIDEN);
2026 : }
2027 : /* Other cases are not beneficial when the original A and B are PLUS
2028 : expressions. */
2029 8 : else if (common)
2030 : {
2031 0 : end_sequence ();
2032 0 : return false;
2033 : }
2034 : /* if (test) x = 8; else x = 0;
2035 : => x = (test != 0) << 3; */
2036 8 : else if (ifalse == 0 && (tmp = exact_log2 (itrue)) >= 0)
2037 : {
2038 8 : target = expand_simple_binop (mode, ASHIFT,
2039 : target, GEN_INT (tmp), if_info->x, 0,
2040 : OPTAB_WIDEN);
2041 : }
2042 :
2043 : /* if (test) x = -1; else x = b;
2044 : => x = -(test != 0) | b; */
2045 0 : else if (itrue == -1)
2046 : {
2047 0 : target = expand_simple_binop (mode, IOR,
2048 0 : target, gen_int_mode (ifalse, mode),
2049 : if_info->x, 0, OPTAB_WIDEN);
2050 : }
2051 : else
2052 : {
2053 0 : end_sequence ();
2054 0 : return false;
2055 : }
2056 :
2057 7148 : if (! target)
2058 : {
2059 0 : end_sequence ();
2060 0 : return false;
2061 : }
2062 :
2063 7148 : if (target != if_info->x)
2064 0 : noce_emit_move_insn (if_info->x, target);
2065 :
2066 7148 : seq = end_ifcvt_sequence (if_info);
2067 7148 : return noce_commit_sequence (if_info, seq, true,
2068 7148 : "noce_try_store_flag_constants");
2069 : }
2070 :
2071 : return false;
2072 : }
2073 :
2074 : /* This is trying to capture cases like dest = cond ? a : -1.
2075 :
2076 : The basic idea is to use a store-flag insn to generate a -1/0
2077 : value (directly or indirectly), then IOR that with the other
2078 : input. */
2079 : static bool
2080 200097 : noce_try_store_flag_logical (noce_if_info *if_info)
2081 : {
2082 200097 : rtx a = if_info->a;
2083 200097 : rtx b = if_info->b;
2084 200097 : rtx dest = if_info->x;
2085 200097 : machine_mode mode = GET_MODE (dest);
2086 :
2087 200097 : if (STORE_FLAG_VALUE != -1 && STORE_FLAG_VALUE != 1)
2088 : return false;
2089 :
2090 259669 : if (!noce_simple_bbs (if_info))
2091 : return false;
2092 :
2093 181419 : bool swapped = STORE_FLAG_VALUE == -1;
2094 181419 : if (a == CONSTM1_RTX (GET_MODE (dest))
2095 1644 : && if_info->rev_cond)
2096 : {
2097 : std::swap (a, b);
2098 181419 : swapped = !swapped;
2099 : }
2100 :
2101 181419 : if (b != CONSTM1_RTX (GET_MODE (dest)))
2102 : return false;
2103 :
2104 : /* If the other arm is not a REG/SUBREG, then punt. This is primarily to
2105 : let the target handle the constant case, which it can likely do better.
2106 : It also means we don't have to worry about non terminal expressions. */
2107 2518 : if (!REG_P (a) && !SUBREG_P (a))
2108 : return false;
2109 :
2110 : /* At this point we've got dest = cond ? a : -1. Emit the store flag and
2111 : adjust its value (if necessary) to -1/0. */
2112 999 : start_sequence ();
2113 999 : rtx temp = gen_reg_rtx (mode);
2114 999 : rtx target = noce_emit_store_flag (if_info, temp, !swapped, 0);
2115 999 : if (!target)
2116 : {
2117 88 : end_sequence ();
2118 88 : return false;
2119 : }
2120 :
2121 911 : if (STORE_FLAG_VALUE == 1)
2122 : {
2123 911 : rtx x = gen_rtx_PLUS (mode, target, CONSTM1_RTX (mode));
2124 911 : emit_move_insn (target, x);
2125 : }
2126 :
2127 : /* Now we've got -1/0 in TARGET. We can just IOR with A. */
2128 911 : rtx x = gen_rtx_IOR (mode, target, a);
2129 911 : emit_move_insn (dest, x);
2130 :
2131 : /* We've generated all the RTL, make sure it recognizes and is
2132 : profitable. */
2133 911 : rtx_insn *seq = end_ifcvt_sequence (if_info);
2134 911 : return noce_commit_sequence (if_info, seq, true,
2135 911 : "noce_try_store_flag_logical");
2136 : }
2137 :
2138 : /* Convert "if (test) foo++" into "foo += (test != 0)", and
2139 : similarly for "foo--". */
2140 :
2141 : static bool
2142 157509 : noce_try_addcc (noce_if_info *if_info)
2143 : {
2144 157509 : rtx target;
2145 157509 : rtx_insn *seq;
2146 157509 : bool subtract;
2147 157509 : int normalize;
2148 :
2149 200578 : if (!noce_simple_bbs (if_info))
2150 : return false;
2151 :
2152 138831 : if (GET_CODE (if_info->a) == PLUS
2153 14775 : && rtx_equal_p (XEXP (if_info->a, 0), if_info->b)
2154 150061 : && noce_reversed_cond_code (if_info) != UNKNOWN)
2155 : {
2156 11230 : enum rtx_code code;
2157 11230 : rtx cond = noce_reversed_cond (if_info, &code);
2158 :
2159 : /* First try to use addcc pattern. */
2160 11230 : if (general_operand (XEXP (cond, 0), VOIDmode)
2161 11230 : && general_operand (XEXP (cond, 1), VOIDmode))
2162 : {
2163 10924 : start_sequence ();
2164 32772 : target = emit_conditional_add (if_info->x, code,
2165 : XEXP (cond, 0),
2166 : XEXP (cond, 1),
2167 : VOIDmode,
2168 : if_info->b,
2169 10924 : XEXP (if_info->a, 1),
2170 10924 : GET_MODE (if_info->x),
2171 10533 : (code == LTU || code == GEU
2172 21404 : || code == LEU || code == GTU));
2173 10924 : if (target)
2174 : {
2175 332 : if (target != if_info->x)
2176 0 : noce_emit_move_insn (if_info->x, target);
2177 :
2178 332 : seq = end_ifcvt_sequence (if_info);
2179 332 : return noce_commit_sequence (if_info, seq, true,
2180 1162 : "noce_try_addcc");
2181 : }
2182 10592 : end_sequence ();
2183 : }
2184 :
2185 : /* If that fails, construct conditional increment or decrement using
2186 : setcc. We're changing a branch and an increment to a comparison and
2187 : an ADD/SUB. */
2188 10898 : if (XEXP (if_info->a, 1) == const1_rtx
2189 9934 : || XEXP (if_info->a, 1) == constm1_rtx)
2190 : {
2191 1519 : start_sequence ();
2192 1519 : if (STORE_FLAG_VALUE == INTVAL (XEXP (if_info->a, 1)))
2193 : subtract = false, normalize = 0;
2194 555 : else if (-STORE_FLAG_VALUE == INTVAL (XEXP (if_info->a, 1)))
2195 : subtract = true, normalize = 0;
2196 : else
2197 0 : subtract = false, normalize = INTVAL (XEXP (if_info->a, 1));
2198 :
2199 :
2200 1519 : target = noce_emit_store_flag (if_info,
2201 1519 : gen_reg_rtx (GET_MODE (if_info->x)),
2202 : true, normalize);
2203 :
2204 1519 : if (target)
2205 1128 : target = expand_simple_binop (GET_MODE (if_info->x),
2206 : subtract ? MINUS : PLUS,
2207 : if_info->b, target, if_info->x,
2208 : 0, OPTAB_WIDEN);
2209 830 : if (target)
2210 : {
2211 830 : if (target != if_info->x)
2212 0 : noce_emit_move_insn (if_info->x, target);
2213 :
2214 830 : seq = end_ifcvt_sequence (if_info);
2215 830 : return noce_commit_sequence (if_info, seq, true,
2216 830 : "noce_try_addcc");
2217 : }
2218 689 : end_sequence ();
2219 : }
2220 : }
2221 :
2222 : return false;
2223 : }
2224 :
2225 : /* Convert "if (test) x = 0;" to "x &= -(test == 0);" */
2226 :
2227 : static bool
2228 156606 : noce_try_store_flag_mask (noce_if_info *if_info)
2229 : {
2230 156606 : rtx target;
2231 156606 : rtx_insn *seq;
2232 :
2233 199631 : if (!noce_simple_bbs (if_info))
2234 : return false;
2235 :
2236 : /* Match "if (test) x = 0;" and, with the arms the other way round,
2237 : "if (!test) x = 0;". */
2238 137928 : bool zero_a = (if_info->a == const0_rtx
2239 137928 : && (REG_P (if_info->b)
2240 1681 : || rtx_equal_p (if_info->b, if_info->x)));
2241 137928 : bool zero_b = (if_info->b == const0_rtx
2242 137928 : && (REG_P (if_info->a)
2243 13145 : || rtx_equal_p (if_info->a, if_info->x)));
2244 :
2245 137926 : if (zero_a || zero_b)
2246 : {
2247 1151 : bool reversep = !zero_a;
2248 1151 : start_sequence ();
2249 1151 : target = noce_emit_store_flag (if_info,
2250 1151 : gen_reg_rtx (GET_MODE (if_info->x)),
2251 : reversep, -1);
2252 1151 : if (target)
2253 301 : target = expand_simple_binop (GET_MODE (if_info->x), AND,
2254 : reversep ? if_info->a : if_info->b,
2255 : target, if_info->x, 0,
2256 : OPTAB_WIDEN);
2257 :
2258 301 : if (target)
2259 : {
2260 301 : if (target != if_info->x)
2261 0 : noce_emit_move_insn (if_info->x, target);
2262 :
2263 301 : seq = end_ifcvt_sequence (if_info);
2264 301 : return noce_commit_sequence (if_info, seq, true,
2265 301 : "noce_try_store_flag_mask");
2266 : }
2267 :
2268 850 : end_sequence ();
2269 : }
2270 :
2271 : return false;
2272 : }
2273 :
2274 : /* Emit a conditional move selecting VTRUE or VFALSE into X, and return the
2275 : destination it landed in, or NULL_RTX on failure. CODE, CMP_A and CMP_B
2276 : give the canonicalized comparison. CC_CMP and REV_CC_CMP, when given, are
2277 : the non-canonicalized condition and its reverse, which let a target emit
2278 : the move without materializing its own compare. */
2279 :
2280 : static rtx
2281 518668 : noce_emit_cmove (noce_if_info *if_info, rtx x, enum rtx_code code,
2282 : rtx cmp_a, rtx cmp_b, rtx vfalse, rtx vtrue,
2283 : rtx cc_cmp = NULL, rtx rev_cc_cmp = NULL)
2284 : {
2285 518668 : rtx target;
2286 518668 : bool unsignedp;
2287 :
2288 : /* If earliest == jump, try to build the cmove insn directly.
2289 : This is helpful when combine has created some complex condition
2290 : (like for alpha's cmovlbs) that we can't hope to regenerate
2291 : through the normal interface. */
2292 :
2293 518668 : if (if_info->cond_earliest == if_info->jump)
2294 : {
2295 4758 : rtx cond = gen_rtx_fmt_ee (code, GET_MODE (if_info->cond), cmp_a, cmp_b);
2296 4758 : rtx if_then_else = gen_rtx_IF_THEN_ELSE (GET_MODE (x),
2297 : cond, vtrue, vfalse);
2298 4758 : rtx set = gen_rtx_SET (x, if_then_else);
2299 :
2300 4758 : start_sequence ();
2301 4758 : rtx_insn *insn = emit_insn (set);
2302 :
2303 4758 : if (recog_memoized (insn) >= 0)
2304 : {
2305 1451 : rtx_insn *seq = end_sequence ();
2306 1451 : emit_insn (seq);
2307 :
2308 1451 : return x;
2309 : }
2310 :
2311 3307 : end_sequence ();
2312 : }
2313 :
2314 1034434 : unsignedp = (code == LTU || code == GEU
2315 517217 : || code == LEU || code == GTU);
2316 :
2317 517217 : if (cc_cmp != NULL_RTX && rev_cc_cmp != NULL_RTX)
2318 106350 : target = emit_conditional_move (x, cc_cmp, rev_cc_cmp,
2319 106350 : vtrue, vfalse, GET_MODE (x));
2320 : else
2321 : {
2322 : /* Don't even try if the comparison operands are weird
2323 : except that the target supports cbranchcc4. */
2324 410867 : if (! general_operand (cmp_a, GET_MODE (cmp_a))
2325 410867 : || ! general_operand (cmp_b, GET_MODE (cmp_b)))
2326 : {
2327 25272 : if (!have_cbranchcc4
2328 25272 : || GET_MODE_CLASS (GET_MODE (cmp_a)) != MODE_CC
2329 3048 : || cmp_b != const0_rtx)
2330 : return NULL_RTX;
2331 : }
2332 :
2333 388643 : target = emit_conditional_move (x, { code, cmp_a, cmp_b, VOIDmode },
2334 388643 : vtrue, vfalse, GET_MODE (x),
2335 : unsignedp);
2336 : }
2337 :
2338 494993 : if (target)
2339 : return target;
2340 :
2341 : /* We might be faced with a situation like:
2342 :
2343 : x = (reg:M TARGET)
2344 : vtrue = (subreg:M (reg:N VTRUE) BYTE)
2345 : vfalse = (subreg:M (reg:N VFALSE) BYTE)
2346 :
2347 : We can't do a conditional move in mode M, but it's possible that we
2348 : could do a conditional move in mode N instead and take a subreg of
2349 : the result.
2350 :
2351 : If we can't create new pseudos, though, don't bother. */
2352 43188 : if (reload_completed)
2353 : return NULL_RTX;
2354 :
2355 43188 : if (GET_CODE (vtrue) == SUBREG && GET_CODE (vfalse) == SUBREG)
2356 : {
2357 23 : rtx reg_vtrue = SUBREG_REG (vtrue);
2358 23 : rtx reg_vfalse = SUBREG_REG (vfalse);
2359 23 : poly_uint64 byte_vtrue = SUBREG_BYTE (vtrue);
2360 23 : poly_uint64 byte_vfalse = SUBREG_BYTE (vfalse);
2361 23 : rtx promoted_target;
2362 :
2363 23 : if (GET_MODE (reg_vtrue) != GET_MODE (reg_vfalse)
2364 23 : || maybe_ne (byte_vtrue, byte_vfalse)
2365 23 : || (SUBREG_PROMOTED_VAR_P (vtrue)
2366 23 : != SUBREG_PROMOTED_VAR_P (vfalse))
2367 23 : || (SUBREG_PROMOTED_GET (vtrue)
2368 23 : != SUBREG_PROMOTED_GET (vfalse)))
2369 : return NULL_RTX;
2370 :
2371 23 : promoted_target = gen_reg_rtx (GET_MODE (reg_vtrue));
2372 :
2373 46 : target = emit_conditional_move (promoted_target,
2374 : { code, cmp_a, cmp_b, VOIDmode },
2375 : reg_vtrue, reg_vfalse,
2376 23 : GET_MODE (reg_vtrue), unsignedp);
2377 : /* Nope, couldn't do it in that mode either. */
2378 23 : if (!target)
2379 : return NULL_RTX;
2380 :
2381 6 : target = gen_rtx_SUBREG (GET_MODE (vtrue), promoted_target, byte_vtrue);
2382 6 : SUBREG_PROMOTED_VAR_P (target) = SUBREG_PROMOTED_VAR_P (vtrue);
2383 6 : SUBREG_PROMOTED_SET (target, SUBREG_PROMOTED_GET (vtrue));
2384 6 : emit_move_insn (x, target);
2385 6 : return x;
2386 : }
2387 : else
2388 : return NULL_RTX;
2389 : }
2390 :
2391 : /* Return true if X is a constant or register operand suitable for simple
2392 : conditional-move handling. */
2393 :
2394 : static bool
2395 2577490 : noce_simple_cmove_operand_p (rtx x)
2396 : {
2397 2577490 : return CONSTANT_P (x) || register_operand (x, VOIDmode);
2398 : }
2399 :
2400 : /* Try only simple constants and registers here. More complex cases are
2401 : handled in noce_try_cmove_arith, which the dispatch table reaches after
2402 : the store-flag matchers have had a go. */
2403 :
2404 : static bool
2405 200097 : noce_try_cmove (noce_if_info *if_info)
2406 : {
2407 200097 : enum rtx_code code;
2408 200097 : rtx target;
2409 200097 : rtx_insn *seq;
2410 :
2411 259669 : if (!noce_simple_bbs (if_info))
2412 : return false;
2413 :
2414 181419 : if (noce_simple_cmove_operand_p (if_info->a)
2415 181419 : && noce_simple_cmove_operand_p (if_info->b))
2416 : {
2417 82692 : start_sequence ();
2418 :
2419 82692 : code = GET_CODE (if_info->cond);
2420 82692 : target = noce_emit_cmove (if_info, if_info->x, code,
2421 : XEXP (if_info->cond, 0),
2422 : XEXP (if_info->cond, 1),
2423 : if_info->a, if_info->b);
2424 :
2425 82692 : if (target)
2426 : {
2427 56583 : if (target != if_info->x)
2428 0 : noce_emit_move_insn (if_info->x, target);
2429 :
2430 56583 : seq = end_ifcvt_sequence (if_info);
2431 56583 : return noce_commit_sequence (if_info, seq, true, "noce_try_cmove");
2432 : }
2433 : /* If both a and b are constants try a last-ditch transformation:
2434 : if (test) x = a; else x = b;
2435 : => x = (-(test != 0) & (b - a)) + a;
2436 : Try this only if the target-specific expansion above has failed.
2437 : The target-specific expander may want to generate sequences that
2438 : we don't know about, so give them a chance before trying this
2439 : approach. */
2440 26109 : else if (!targetm.have_conditional_execution ()
2441 26109 : && CONST_INT_P (if_info->a) && CONST_INT_P (if_info->b))
2442 : {
2443 5336 : machine_mode mode = GET_MODE (if_info->x);
2444 5336 : HOST_WIDE_INT ifalse = INTVAL (if_info->a);
2445 5336 : HOST_WIDE_INT itrue = INTVAL (if_info->b);
2446 5336 : rtx target = noce_emit_store_flag (if_info, if_info->x, false, -1);
2447 5336 : if (!target)
2448 : {
2449 5276 : end_sequence ();
2450 5276 : return false;
2451 : }
2452 :
2453 60 : HOST_WIDE_INT diff;
2454 60 : if (!noce_representable_diff_p (ifalse, itrue, mode, &diff))
2455 : {
2456 21 : end_sequence ();
2457 21 : return false;
2458 : }
2459 :
2460 39 : target = expand_simple_binop (mode, AND,
2461 39 : target, gen_int_mode (diff, mode),
2462 : if_info->x, 0, OPTAB_WIDEN);
2463 39 : if (target)
2464 39 : target = expand_simple_binop (mode, PLUS,
2465 39 : target, gen_int_mode (ifalse, mode),
2466 : if_info->x, 0, OPTAB_WIDEN);
2467 39 : if (target)
2468 : {
2469 39 : if (target != if_info->x)
2470 0 : noce_emit_move_insn (if_info->x, target);
2471 :
2472 39 : seq = end_ifcvt_sequence (if_info);
2473 39 : return noce_commit_sequence (if_info, seq, true,
2474 39 : "noce_try_cmove");
2475 : }
2476 : else
2477 : {
2478 0 : end_sequence ();
2479 0 : return false;
2480 : }
2481 : }
2482 : else
2483 20773 : end_sequence ();
2484 : }
2485 :
2486 : return false;
2487 : }
2488 :
2489 : /* Return true if X contains a conditional code mode rtx. */
2490 :
2491 : static bool
2492 2879813 : contains_ccmode_rtx_p (rtx x)
2493 : {
2494 2879813 : subrtx_iterator::array_type array;
2495 7364177 : FOR_EACH_SUBRTX (iter, array, x, ALL)
2496 4531650 : if (GET_MODE_CLASS (GET_MODE (*iter)) == MODE_CC)
2497 47286 : return true;
2498 :
2499 2832527 : return false;
2500 2879813 : }
2501 :
2502 : /* Helper for bb_valid_for_noce_process_p. Validate that
2503 : the rtx insn INSN is a single set that does not set
2504 : the conditional register CC and is in general valid for
2505 : if-conversion. */
2506 :
2507 : static bool
2508 3630250 : insn_valid_noce_process_p (rtx_insn *insn, rtx cc)
2509 : {
2510 3630250 : if (!insn
2511 3629938 : || !NONJUMP_INSN_P (insn)
2512 6541768 : || (cc && set_of (cc, insn)))
2513 : return false;
2514 :
2515 2899938 : rtx sset = single_set (insn);
2516 :
2517 : /* Currently support only simple single sets in test_bb. */
2518 2899938 : if (!sset
2519 2893501 : || !noce_operand_ok (SET_DEST (sset))
2520 2879813 : || contains_ccmode_rtx_p (SET_DEST (sset))
2521 5732465 : || !noce_operand_ok (SET_SRC (sset)))
2522 130699 : return false;
2523 :
2524 : return true;
2525 : }
2526 :
2527 :
2528 : /* Return true iff the registers that the insns in BB_A set do not get
2529 : used in BB_B. If TO_RENAME is non-NULL then it is a location that will be
2530 : renamed later by the caller and so conflicts on it should be ignored
2531 : in this function. */
2532 :
2533 : static bool
2534 53908 : bbs_ok_for_cmove_arith (basic_block bb_a, basic_block bb_b, rtx to_rename)
2535 : {
2536 53908 : rtx_insn *a_insn;
2537 53908 : auto_bitmap bba_sets (®_obstack);
2538 :
2539 53908 : df_ref def;
2540 53908 : df_ref use;
2541 :
2542 285234 : FOR_BB_INSNS (bb_a, a_insn)
2543 : {
2544 231326 : if (!active_insn_p (a_insn))
2545 155022 : continue;
2546 :
2547 76304 : rtx sset_a = single_set (a_insn);
2548 :
2549 76304 : if (!sset_a)
2550 : return false;
2551 : /* Record all registers that BB_A sets. */
2552 185721 : FOR_EACH_INSN_DEF (def, a_insn)
2553 109417 : if (!(to_rename && DF_REF_REG (def) == to_rename))
2554 56752 : bitmap_set_bit (bba_sets, DF_REF_REGNO (def));
2555 : }
2556 :
2557 53908 : rtx_insn *b_insn;
2558 :
2559 285298 : FOR_BB_INSNS (bb_b, b_insn)
2560 : {
2561 231490 : if (!active_insn_p (b_insn))
2562 155193 : continue;
2563 :
2564 76297 : rtx sset_b = single_set (b_insn);
2565 :
2566 76297 : if (!sset_b)
2567 : return false;
2568 :
2569 : /* Make sure this is a REG and not some instance
2570 : of ZERO_EXTRACT or non-paradoxical SUBREG or other dangerous stuff.
2571 : If we have a memory destination then we have a pair of simple
2572 : basic blocks performing an operation of the form [addr] = c ? a : b.
2573 : bb_valid_for_noce_process_p will have ensured that these are
2574 : the only stores present. In that case [addr] should be the location
2575 : to be renamed. Assert that the callers set this up properly. */
2576 76297 : if (MEM_P (SET_DEST (sset_b)))
2577 1234 : gcc_assert (rtx_equal_p (SET_DEST (sset_b), to_rename));
2578 75063 : else if (!REG_P (SET_DEST (sset_b))
2579 128928 : && !paradoxical_subreg_p (SET_DEST (sset_b)))
2580 : return false;
2581 :
2582 : /* If the insn uses a reg set in BB_A return false. */
2583 148436 : FOR_EACH_INSN_USE (use, b_insn)
2584 72239 : if (bitmap_bit_p (bba_sets, DF_REF_REGNO (use)))
2585 : return false;
2586 :
2587 : }
2588 :
2589 : return true;
2590 53908 : }
2591 :
2592 : /* Emit copies of all the active instructions in BB except the last.
2593 : This is a helper for noce_try_cmove_arith. */
2594 :
2595 : static void
2596 14132 : noce_emit_all_but_last (basic_block bb)
2597 : {
2598 14132 : rtx_insn *last = last_active_insn (bb, false);
2599 14132 : rtx_insn *insn;
2600 144654 : FOR_BB_INSNS (bb, insn)
2601 : {
2602 116390 : if (insn != last && active_insn_p (insn))
2603 : {
2604 35989 : rtx_insn *to_emit = as_a <rtx_insn *> (copy_rtx (insn));
2605 :
2606 35989 : emit_insn (PATTERN (to_emit));
2607 : }
2608 : }
2609 14132 : }
2610 :
2611 : /* Helper for noce_try_cmove_arith. Emit the pattern TO_EMIT and return
2612 : the resulting insn or NULL if it's not a valid insn. */
2613 :
2614 : static rtx_insn *
2615 140548 : noce_emit_insn (rtx to_emit)
2616 : {
2617 140548 : gcc_assert (to_emit);
2618 140548 : rtx_insn *insn = emit_insn (to_emit);
2619 :
2620 140548 : if (recog_memoized (insn) < 0)
2621 193 : return NULL;
2622 :
2623 : return insn;
2624 : }
2625 :
2626 : /* Helper for noce_try_cmove_arith. Emit a copy of the insns up to
2627 : and including the penultimate one in BB if it is not simple
2628 : (as indicated by SIMPLE). Then emit LAST_INSN as the last
2629 : insn in the block. The reason for that is that LAST_INSN may
2630 : have been modified by the preparation in noce_try_cmove_arith. */
2631 :
2632 : static bool
2633 142930 : noce_emit_bb (rtx last_insn, basic_block bb, bool simple)
2634 : {
2635 142930 : if (bb && !simple)
2636 14132 : noce_emit_all_but_last (bb);
2637 :
2638 142930 : if (last_insn && !noce_emit_insn (last_insn))
2639 193 : return false;
2640 :
2641 : return true;
2642 : }
2643 :
2644 : /* Try more complex cases involving conditional_move. */
2645 :
2646 : static bool
2647 146415 : noce_try_cmove_arith (noce_if_info *if_info)
2648 : {
2649 146415 : rtx a = if_info->a;
2650 146415 : rtx b = if_info->b;
2651 146415 : rtx x = if_info->x;
2652 146415 : rtx orig_a, orig_b;
2653 146415 : rtx_insn *insn_a, *insn_b;
2654 146415 : bool a_simple = if_info->then_simple;
2655 146415 : bool b_simple = if_info->else_simple;
2656 146415 : basic_block then_bb = if_info->then_bb;
2657 146415 : basic_block else_bb = if_info->else_bb;
2658 146415 : rtx target;
2659 146415 : bool is_mem = false;
2660 146415 : enum rtx_code code;
2661 146415 : rtx cond = if_info->cond;
2662 146415 : rtx_insn *ifcvt_seq;
2663 :
2664 : /* A conditional move from two memory sources is equivalent to a
2665 : conditional on their addresses followed by a load. Don't do this
2666 : early because it'll screw alias analysis. Note that we've
2667 : already checked for no side effects. */
2668 146415 : if (cse_not_expected
2669 48015 : && MEM_P (a) && MEM_P (b)
2670 149089 : && MEM_ADDR_SPACE (a) == MEM_ADDR_SPACE (b))
2671 : {
2672 2673 : machine_mode address_mode = get_address_mode (a);
2673 :
2674 2673 : a = XEXP (a, 0);
2675 2673 : b = XEXP (b, 0);
2676 2673 : x = gen_reg_rtx (address_mode);
2677 2673 : is_mem = true;
2678 : }
2679 :
2680 : /* ??? We could handle this if we knew that a load from A or B could
2681 : not trap or fault. This is also true if we've already loaded
2682 : from the address along the path from ENTRY. */
2683 143742 : else if (may_trap_or_fault_p (a) || may_trap_or_fault_p (b))
2684 : return false;
2685 :
2686 : /* if (test) x = a + b; else x = c - d;
2687 : => y = a + b;
2688 : x = c - d;
2689 : if (test)
2690 : x = y;
2691 : */
2692 :
2693 91809 : code = GET_CODE (cond);
2694 91809 : insn_a = if_info->insn_a;
2695 91809 : insn_b = if_info->insn_b;
2696 :
2697 91809 : machine_mode x_mode = GET_MODE (x);
2698 :
2699 91809 : if (!can_conditionally_move_p (x_mode))
2700 : return false;
2701 :
2702 : /* Possibly rearrange operands to make things come out more natural. */
2703 71565 : if (noce_reversed_cond_code (if_info) != UNKNOWN)
2704 : {
2705 71565 : bool reversep = false;
2706 71565 : if (rtx_equal_p (b, x))
2707 : reversep = true;
2708 45548 : else if (general_operand (b, GET_MODE (b)))
2709 : reversep = true;
2710 :
2711 : if (reversep)
2712 : {
2713 63795 : cond = noce_reversed_cond (if_info, &code);
2714 63795 : std::swap (a, b);
2715 63795 : std::swap (insn_a, insn_b);
2716 63795 : std::swap (a_simple, b_simple);
2717 63795 : std::swap (then_bb, else_bb);
2718 : }
2719 : }
2720 :
2721 27768 : if (then_bb && else_bb
2722 98569 : && (!bbs_ok_for_cmove_arith (then_bb, else_bb, if_info->orig_x)
2723 26904 : || !bbs_ok_for_cmove_arith (else_bb, then_bb, if_info->orig_x)))
2724 : return false;
2725 :
2726 71465 : start_sequence ();
2727 :
2728 : /* If one of the blocks is empty then the corresponding B or A value
2729 : came from the test block. The non-empty complex block that we will
2730 : emit might clobber the register used by B or A, so move it to a pseudo
2731 : first. */
2732 :
2733 71465 : rtx tmp_a = NULL_RTX;
2734 71465 : rtx tmp_b = NULL_RTX;
2735 :
2736 71465 : if (b_simple || !else_bb)
2737 59353 : tmp_b = gen_reg_rtx (x_mode);
2738 :
2739 71465 : if (a_simple || !then_bb)
2740 69445 : tmp_a = gen_reg_rtx (x_mode);
2741 :
2742 71465 : orig_a = a;
2743 71465 : orig_b = b;
2744 :
2745 71465 : rtx emit_a = NULL_RTX;
2746 71465 : rtx emit_b = NULL_RTX;
2747 71465 : rtx_insn *tmp_insn = NULL;
2748 71465 : bool modified_in_a = false;
2749 71465 : bool modified_in_b = false;
2750 : /* If either operand is complex, load it into a register first.
2751 : The best way to do this is to copy the original insn. In this
2752 : way we preserve any clobbers etc that the insn may have had.
2753 : This is of course not possible in the IS_MEM case. */
2754 :
2755 71465 : if (! general_operand (a, GET_MODE (a)) || tmp_a)
2756 : {
2757 :
2758 70749 : if (is_mem)
2759 : {
2760 2672 : rtx reg = gen_reg_rtx (GET_MODE (a));
2761 2672 : emit_a = gen_rtx_SET (reg, a);
2762 : }
2763 : else
2764 : {
2765 68077 : if (insn_a)
2766 : {
2767 42005 : a = tmp_a ? tmp_a : gen_reg_rtx (GET_MODE (a));
2768 :
2769 42005 : rtx_insn *copy_of_a = as_a <rtx_insn *> (copy_rtx (insn_a));
2770 42005 : rtx set = single_set (copy_of_a);
2771 42005 : SET_DEST (set) = a;
2772 :
2773 42005 : emit_a = PATTERN (copy_of_a);
2774 : }
2775 : else
2776 : {
2777 26072 : rtx tmp_reg = tmp_a ? tmp_a : gen_reg_rtx (GET_MODE (a));
2778 26072 : emit_a = gen_rtx_SET (tmp_reg, a);
2779 26072 : a = tmp_reg;
2780 : }
2781 : }
2782 : }
2783 :
2784 71465 : if (! general_operand (b, GET_MODE (b)) || tmp_b)
2785 : {
2786 69799 : if (is_mem)
2787 : {
2788 2672 : rtx reg = gen_reg_rtx (GET_MODE (b));
2789 2672 : emit_b = gen_rtx_SET (reg, b);
2790 : }
2791 : else
2792 : {
2793 67127 : if (insn_b)
2794 : {
2795 66937 : b = tmp_b ? tmp_b : gen_reg_rtx (GET_MODE (b));
2796 66937 : rtx_insn *copy_of_b = as_a <rtx_insn *> (copy_rtx (insn_b));
2797 66937 : rtx set = single_set (copy_of_b);
2798 :
2799 66937 : SET_DEST (set) = b;
2800 66937 : emit_b = PATTERN (copy_of_b);
2801 : }
2802 : else
2803 : {
2804 190 : rtx tmp_reg = tmp_b ? tmp_b : gen_reg_rtx (GET_MODE (b));
2805 190 : emit_b = gen_rtx_SET (tmp_reg, b);
2806 190 : b = tmp_reg;
2807 : }
2808 : }
2809 : }
2810 :
2811 71465 : modified_in_a = emit_a != NULL_RTX && modified_in_p (orig_b, emit_a);
2812 71465 : if (tmp_b && then_bb)
2813 : {
2814 76620 : FOR_BB_INSNS (then_bb, tmp_insn)
2815 : /* Don't check inside insn_a. We will have changed it to emit_a
2816 : with a destination that doesn't conflict. */
2817 57889 : if (!(insn_a && tmp_insn == insn_a)
2818 97047 : && modified_in_p (orig_b, tmp_insn))
2819 : {
2820 : modified_in_a = true;
2821 : break;
2822 : }
2823 :
2824 : }
2825 :
2826 71465 : modified_in_b = emit_b != NULL_RTX && modified_in_p (orig_a, emit_b);
2827 71465 : if (tmp_a && else_bb)
2828 : {
2829 330167 : FOR_BB_INSNS (else_bb, tmp_insn)
2830 : /* Don't check inside insn_b. We will have changed it to emit_b
2831 : with a destination that doesn't conflict. */
2832 261465 : if (!(insn_b && tmp_insn == insn_b)
2833 454228 : && modified_in_p (orig_a, tmp_insn))
2834 : {
2835 : modified_in_b = true;
2836 : break;
2837 : }
2838 : }
2839 :
2840 : /* If insn to set up A clobbers any registers B depends on, try to
2841 : swap insn that sets up A with the one that sets up B. If even
2842 : that doesn't help, punt. */
2843 71465 : if (modified_in_a && !modified_in_b)
2844 : {
2845 0 : if (!noce_emit_bb (emit_b, else_bb, b_simple))
2846 0 : goto end_seq_and_fail;
2847 :
2848 0 : if (!noce_emit_bb (emit_a, then_bb, a_simple))
2849 0 : goto end_seq_and_fail;
2850 : }
2851 71465 : else if (!modified_in_a)
2852 : {
2853 71465 : if (!noce_emit_bb (emit_a, then_bb, a_simple))
2854 0 : goto end_seq_and_fail;
2855 :
2856 71465 : if (!noce_emit_bb (emit_b, else_bb, b_simple))
2857 193 : goto end_seq_and_fail;
2858 : }
2859 : else
2860 0 : goto end_seq_and_fail;
2861 :
2862 71272 : target = noce_emit_cmove (if_info, x, code, XEXP (cond, 0), XEXP (cond, 1),
2863 : a, b);
2864 :
2865 71272 : if (! target)
2866 17466 : goto end_seq_and_fail;
2867 :
2868 : /* If we're handling a memory for above, emit the load now. */
2869 53806 : if (is_mem)
2870 : {
2871 2281 : rtx mem = gen_rtx_MEM (GET_MODE (if_info->x), target);
2872 :
2873 : /* Copy over flags as appropriate. */
2874 2281 : if (MEM_VOLATILE_P (if_info->a) || MEM_VOLATILE_P (if_info->b))
2875 0 : MEM_VOLATILE_P (mem) = 1;
2876 2281 : if (MEM_ALIAS_SET (if_info->a) == MEM_ALIAS_SET (if_info->b))
2877 2084 : set_mem_alias_set (mem, MEM_ALIAS_SET (if_info->a));
2878 4562 : set_mem_align (mem,
2879 2281 : MIN (MEM_ALIGN (if_info->a), MEM_ALIGN (if_info->b)));
2880 :
2881 2281 : gcc_assert (MEM_ADDR_SPACE (if_info->a) == MEM_ADDR_SPACE (if_info->b));
2882 2281 : set_mem_addr_space (mem, MEM_ADDR_SPACE (if_info->a));
2883 :
2884 2281 : noce_emit_move_insn (if_info->x, mem);
2885 : }
2886 51525 : else if (target != x)
2887 0 : noce_emit_move_insn (x, target);
2888 :
2889 53806 : ifcvt_seq = end_ifcvt_sequence (if_info);
2890 53806 : return noce_commit_sequence (if_info, ifcvt_seq, true,
2891 53806 : "noce_try_cmove_arith");
2892 :
2893 17659 : end_seq_and_fail:
2894 17659 : end_sequence ();
2895 17659 : return false;
2896 : }
2897 :
2898 : /* For most cases, the simplified condition we found is the best
2899 : choice, but this is not the case for the min/max/abs transforms.
2900 : For these we wish to know that it is A or B in the condition. */
2901 :
2902 : static rtx
2903 161328 : noce_get_alt_condition (noce_if_info *if_info, rtx target,
2904 : rtx_insn **earliest)
2905 : {
2906 161328 : rtx cond, set;
2907 161328 : rtx_insn *insn;
2908 161328 : bool reverse;
2909 :
2910 : /* If target is already mentioned in the known condition, return it. */
2911 161328 : if (reg_mentioned_p (target, if_info->cond))
2912 : {
2913 8252 : *earliest = if_info->cond_earliest;
2914 8252 : return if_info->cond;
2915 : }
2916 :
2917 153076 : set = pc_set (if_info->jump);
2918 153076 : cond = XEXP (SET_SRC (set), 0);
2919 153076 : reverse
2920 306152 : = GET_CODE (XEXP (SET_SRC (set), 2)) == LABEL_REF
2921 153076 : && label_ref_label (XEXP (SET_SRC (set), 2)) == JUMP_LABEL (if_info->jump);
2922 153076 : if (if_info->then_else_reversed)
2923 24490 : reverse = !reverse;
2924 :
2925 : /* If we're looking for a constant, try to make the conditional
2926 : have that constant in it. There are two reasons why it may
2927 : not have the constant we want:
2928 :
2929 : 1. GCC may have needed to put the constant in a register, because
2930 : the target can't compare directly against that constant. For
2931 : this case, we look for a SET immediately before the comparison
2932 : that puts a constant in that register.
2933 :
2934 : 2. GCC may have canonicalized the conditional, for example
2935 : replacing "if x < 4" with "if x <= 3". We can undo that (or
2936 : make equivalent types of changes) to get the constants we need
2937 : if they're off by one in the right direction. */
2938 :
2939 153076 : if (CONST_INT_P (target))
2940 : {
2941 46664 : enum rtx_code code = GET_CODE (if_info->cond);
2942 46664 : rtx op_a = XEXP (if_info->cond, 0);
2943 46664 : rtx op_b = XEXP (if_info->cond, 1);
2944 46664 : rtx_insn *prev_insn;
2945 :
2946 : /* First, look to see if we put a constant in a register. */
2947 46664 : prev_insn = prev_nonnote_nondebug_insn (if_info->cond_earliest);
2948 46664 : if (prev_insn
2949 46553 : && BLOCK_FOR_INSN (prev_insn)
2950 46553 : == BLOCK_FOR_INSN (if_info->cond_earliest)
2951 37100 : && INSN_P (prev_insn)
2952 79642 : && GET_CODE (PATTERN (prev_insn)) == SET)
2953 : {
2954 25524 : rtx src = find_reg_equal_equiv_note (prev_insn);
2955 25524 : if (!src)
2956 25358 : src = SET_SRC (PATTERN (prev_insn));
2957 25524 : if (CONST_INT_P (src))
2958 : {
2959 15012 : if (rtx_equal_p (op_a, SET_DEST (PATTERN (prev_insn))))
2960 : op_a = src;
2961 14651 : else if (rtx_equal_p (op_b, SET_DEST (PATTERN (prev_insn))))
2962 1073 : op_b = src;
2963 :
2964 15012 : if (CONST_INT_P (op_a))
2965 : {
2966 361 : std::swap (op_a, op_b);
2967 361 : code = swap_condition (code);
2968 : }
2969 : }
2970 : }
2971 :
2972 : /* Now, look to see if we can get the right constant by
2973 : adjusting the conditional. */
2974 46664 : if (CONST_INT_P (op_b))
2975 : {
2976 24180 : HOST_WIDE_INT desired_val = INTVAL (target);
2977 24180 : HOST_WIDE_INT actual_val = INTVAL (op_b);
2978 :
2979 24180 : switch (code)
2980 : {
2981 1162 : case LT:
2982 1162 : if (desired_val != HOST_WIDE_INT_MAX
2983 1147 : && actual_val == desired_val + 1)
2984 : {
2985 174 : code = LE;
2986 174 : op_b = GEN_INT (desired_val);
2987 : }
2988 : break;
2989 3 : case LE:
2990 3 : if (desired_val != HOST_WIDE_INT_MIN
2991 3 : && actual_val == desired_val - 1)
2992 : {
2993 0 : code = LT;
2994 0 : op_b = GEN_INT (desired_val);
2995 : }
2996 : break;
2997 1700 : case GT:
2998 1700 : if (desired_val != HOST_WIDE_INT_MIN
2999 1700 : && actual_val == desired_val - 1)
3000 : {
3001 235 : code = GE;
3002 235 : op_b = GEN_INT (desired_val);
3003 : }
3004 : break;
3005 40 : case GE:
3006 40 : if (desired_val != HOST_WIDE_INT_MAX
3007 25 : && actual_val == desired_val + 1)
3008 : {
3009 3 : code = GT;
3010 3 : op_b = GEN_INT (desired_val);
3011 : }
3012 : break;
3013 : default:
3014 : break;
3015 : }
3016 : }
3017 :
3018 : /* If we made any changes, generate a new conditional that is
3019 : equivalent to what we started with, but has the right
3020 : constants in it. */
3021 46664 : if (code != GET_CODE (if_info->cond)
3022 45892 : || op_a != XEXP (if_info->cond, 0)
3023 45891 : || op_b != XEXP (if_info->cond, 1))
3024 : {
3025 1846 : cond = gen_rtx_fmt_ee (code, GET_MODE (cond), op_a, op_b);
3026 1846 : *earliest = if_info->cond_earliest;
3027 1846 : return cond;
3028 : }
3029 : }
3030 :
3031 151230 : cond = canonicalize_condition (if_info->jump, cond, reverse,
3032 : earliest, target, have_cbranchcc4, true);
3033 151230 : if (! cond || ! reg_mentioned_p (target, cond))
3034 : return NULL;
3035 :
3036 : /* We almost certainly searched back to a different place.
3037 : Need to re-verify correct lifetimes. */
3038 :
3039 : /* X may not be mentioned in the range (cond_earliest, jump]. */
3040 0 : for (insn = if_info->jump; insn != *earliest; insn = PREV_INSN (insn))
3041 0 : if (INSN_P (insn) && reg_overlap_mentioned_p (if_info->x, PATTERN (insn)))
3042 : return NULL;
3043 :
3044 : /* A and B may not be modified in the range [cond_earliest, jump). */
3045 0 : for (insn = *earliest; insn != if_info->jump; insn = NEXT_INSN (insn))
3046 0 : if (INSN_P (insn)
3047 0 : && (modified_in_p (if_info->a, insn)
3048 0 : || modified_in_p (if_info->b, insn)))
3049 : return NULL;
3050 :
3051 : return cond;
3052 : }
3053 :
3054 : /* Convert "if (a < b) x = a; else x = b;" to "x = min(a, b);", etc. */
3055 :
3056 : static bool
3057 208921 : noce_try_minmax (noce_if_info *if_info)
3058 : {
3059 208921 : rtx cond, target;
3060 208921 : rtx_insn *earliest, *seq;
3061 208921 : enum rtx_code code, op;
3062 208921 : bool unsignedp;
3063 :
3064 271910 : if (!noce_simple_bbs (if_info))
3065 : return false;
3066 :
3067 : /* ??? Reject modes with NaNs or signed zeros since we don't know how
3068 : they will be resolved with an SMIN/SMAX. It wouldn't be too hard
3069 : to get the target to tell us... */
3070 190243 : if (HONOR_SIGNED_ZEROS (if_info->x)
3071 190243 : || HONOR_NANS (if_info->x))
3072 : return false;
3073 :
3074 160351 : cond = noce_get_alt_condition (if_info, if_info->a, &earliest);
3075 160351 : if (!cond)
3076 : return false;
3077 :
3078 : /* Verify the condition is of the form we expect, and canonicalize
3079 : the comparison code. */
3080 10073 : code = GET_CODE (cond);
3081 10073 : if (rtx_equal_p (XEXP (cond, 0), if_info->a))
3082 : {
3083 2562 : if (! rtx_equal_p (XEXP (cond, 1), if_info->b))
3084 : return false;
3085 : }
3086 7511 : else if (rtx_equal_p (XEXP (cond, 1), if_info->a))
3087 : {
3088 4698 : if (! rtx_equal_p (XEXP (cond, 0), if_info->b))
3089 : return false;
3090 45 : code = swap_condition (code);
3091 : }
3092 : else
3093 : return false;
3094 :
3095 : /* Determine what sort of operation this is. Note that the code is for
3096 : a taken branch, so the code->operation mapping appears backwards. */
3097 60 : switch (code)
3098 : {
3099 : case LT:
3100 : case LE:
3101 : case UNLT:
3102 : case UNLE:
3103 : op = SMAX;
3104 : unsignedp = false;
3105 : break;
3106 17 : case GT:
3107 17 : case GE:
3108 17 : case UNGT:
3109 17 : case UNGE:
3110 17 : op = SMIN;
3111 17 : unsignedp = false;
3112 17 : break;
3113 3 : case LTU:
3114 3 : case LEU:
3115 3 : op = UMAX;
3116 3 : unsignedp = true;
3117 3 : break;
3118 20 : case GTU:
3119 20 : case GEU:
3120 20 : op = UMIN;
3121 20 : unsignedp = true;
3122 20 : break;
3123 : default:
3124 : return false;
3125 : }
3126 :
3127 60 : start_sequence ();
3128 :
3129 60 : target = expand_simple_binop (GET_MODE (if_info->x), op,
3130 : if_info->a, if_info->b,
3131 : if_info->x, unsignedp, OPTAB_WIDEN);
3132 60 : if (! target)
3133 : {
3134 0 : end_sequence ();
3135 0 : return false;
3136 : }
3137 60 : if (target != if_info->x)
3138 0 : noce_emit_move_insn (if_info->x, target);
3139 :
3140 60 : seq = end_ifcvt_sequence (if_info);
3141 60 : if (!seq)
3142 : return false;
3143 :
3144 60 : emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATION (if_info->insn_a));
3145 60 : if_info->cond = cond;
3146 60 : if_info->cond_earliest = earliest;
3147 60 : if_info->rev_cond = NULL_RTX;
3148 60 : if_info->transform_name = "noce_try_minmax";
3149 :
3150 60 : return true;
3151 : }
3152 :
3153 : /* Convert "if (a < 0) x = -a; else x = a;" to "x = abs(a);",
3154 : "if (a < 0) x = ~a; else x = a;" to "x = one_cmpl_abs(a);",
3155 : etc. */
3156 :
3157 : static bool
3158 208861 : noce_try_abs (noce_if_info *if_info)
3159 : {
3160 208861 : rtx cond, target, a, b, c;
3161 208861 : rtx_insn *earliest, *seq;
3162 208861 : bool negate;
3163 208861 : bool one_cmpl = false;
3164 :
3165 271841 : if (!noce_simple_bbs (if_info))
3166 : return false;
3167 :
3168 : /* Reject modes with signed zeros. */
3169 190183 : if (HONOR_SIGNED_ZEROS (if_info->x))
3170 : return false;
3171 :
3172 : /* Recognize A and B as constituting an ABS or NABS. The canonical
3173 : form is a branch around the negation, taken when the object is the
3174 : first operand of a comparison against 0 that evaluates to true. */
3175 160299 : a = if_info->a;
3176 160299 : b = if_info->b;
3177 160299 : if (GET_CODE (a) == NEG && rtx_equal_p (XEXP (a, 0), b))
3178 : negate = false;
3179 159352 : else if (GET_CODE (b) == NEG && rtx_equal_p (XEXP (b, 0), a))
3180 : {
3181 : std::swap (a, b);
3182 : negate = true;
3183 : }
3184 159322 : else if (GET_CODE (a) == NOT && rtx_equal_p (XEXP (a, 0), b))
3185 : {
3186 : negate = false;
3187 : one_cmpl = true;
3188 : }
3189 159322 : else if (GET_CODE (b) == NOT && rtx_equal_p (XEXP (b, 0), a))
3190 : {
3191 : std::swap (a, b);
3192 : negate = true;
3193 : one_cmpl = true;
3194 : }
3195 : else
3196 : return false;
3197 :
3198 977 : cond = noce_get_alt_condition (if_info, b, &earliest);
3199 977 : if (!cond)
3200 : return false;
3201 :
3202 : /* Verify the condition is of the form we expect. */
3203 25 : if (rtx_equal_p (XEXP (cond, 0), b))
3204 25 : c = XEXP (cond, 1);
3205 0 : else if (rtx_equal_p (XEXP (cond, 1), b))
3206 : {
3207 0 : c = XEXP (cond, 0);
3208 0 : negate = !negate;
3209 : }
3210 : else
3211 : return false;
3212 :
3213 : /* Verify that C is zero. Search one step backward for a
3214 : REG_EQUAL note or a simple source if necessary. */
3215 25 : if (REG_P (c))
3216 : {
3217 0 : rtx set;
3218 0 : rtx_insn *insn = prev_nonnote_nondebug_insn (earliest);
3219 0 : if (insn
3220 0 : && BLOCK_FOR_INSN (insn) == BLOCK_FOR_INSN (earliest)
3221 0 : && (set = single_set (insn))
3222 0 : && rtx_equal_p (SET_DEST (set), c))
3223 : {
3224 0 : rtx note = find_reg_equal_equiv_note (insn);
3225 0 : if (note)
3226 0 : c = XEXP (note, 0);
3227 : else
3228 0 : c = SET_SRC (set);
3229 : }
3230 : else
3231 : return false;
3232 : }
3233 25 : if (MEM_P (c)
3234 0 : && GET_CODE (XEXP (c, 0)) == SYMBOL_REF
3235 25 : && CONSTANT_POOL_ADDRESS_P (XEXP (c, 0)))
3236 0 : c = get_pool_constant (XEXP (c, 0));
3237 :
3238 : /* Work around funny ideas get_condition has wrt canonicalization.
3239 : Note that these rtx constants are known to be CONST_INT, and
3240 : therefore imply integer comparisons.
3241 : The one_cmpl case is more complicated, as we want to handle
3242 : only x < 0 ? ~x : x or x >= 0 ? x : ~x to one_cmpl_abs (x)
3243 : and x < 0 ? x : ~x or x >= 0 ? ~x : x to ~one_cmpl_abs (x),
3244 : but not other cases (x > -1 is equivalent of x >= 0). */
3245 25 : if (c == constm1_rtx && GET_CODE (cond) == GT)
3246 : ;
3247 1 : else if (c == const1_rtx && GET_CODE (cond) == LT)
3248 : {
3249 0 : if (one_cmpl)
3250 : return false;
3251 : }
3252 1 : else if (c == CONST0_RTX (GET_MODE (b)))
3253 : {
3254 0 : if (one_cmpl
3255 0 : && GET_CODE (cond) != GE
3256 0 : && GET_CODE (cond) != LT)
3257 : return false;
3258 : }
3259 : else
3260 : return false;
3261 :
3262 : /* Determine what sort of operation this is. */
3263 24 : switch (GET_CODE (cond))
3264 : {
3265 0 : case LT:
3266 0 : case LE:
3267 0 : case UNLT:
3268 0 : case UNLE:
3269 0 : negate = !negate;
3270 0 : break;
3271 : case GT:
3272 : case GE:
3273 : case UNGT:
3274 : case UNGE:
3275 : break;
3276 : default:
3277 : return false;
3278 : }
3279 :
3280 24 : start_sequence ();
3281 24 : if (one_cmpl)
3282 0 : target = expand_one_cmpl_abs_nojump (GET_MODE (if_info->x), b,
3283 : if_info->x);
3284 : else
3285 24 : target = expand_abs_nojump (GET_MODE (if_info->x), b, if_info->x, 1);
3286 :
3287 : /* ??? It's a quandary whether cmove would be better here, especially
3288 : for integers. Perhaps combine will clean things up. */
3289 24 : if (target && negate)
3290 : {
3291 0 : if (one_cmpl)
3292 0 : target = expand_simple_unop (GET_MODE (target), NOT, target,
3293 : if_info->x, 0);
3294 : else
3295 0 : target = expand_simple_unop (GET_MODE (target), NEG, target,
3296 : if_info->x, 0);
3297 : }
3298 :
3299 24 : if (! target)
3300 : {
3301 0 : end_sequence ();
3302 0 : return false;
3303 : }
3304 :
3305 24 : if (target != if_info->x)
3306 0 : noce_emit_move_insn (if_info->x, target);
3307 :
3308 24 : seq = end_ifcvt_sequence (if_info);
3309 24 : if (!seq)
3310 : return false;
3311 :
3312 24 : emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATION (if_info->insn_a));
3313 24 : if_info->cond = cond;
3314 24 : if_info->cond_earliest = earliest;
3315 24 : if_info->rev_cond = NULL_RTX;
3316 24 : if_info->transform_name = "noce_try_abs";
3317 :
3318 24 : return true;
3319 : }
3320 :
3321 : /* Convert "if (m < 0) x = b; else x = 0;" to "x = (m >> C) & b;". */
3322 :
3323 : static bool
3324 111472 : noce_try_sign_mask (noce_if_info *if_info)
3325 : {
3326 111472 : rtx cond, t, m, c;
3327 111472 : rtx_insn *seq;
3328 111472 : machine_mode mode;
3329 111472 : enum rtx_code code;
3330 111472 : bool t_unconditional;
3331 :
3332 137053 : if (!noce_simple_bbs (if_info))
3333 : return false;
3334 :
3335 99962 : cond = if_info->cond;
3336 99962 : code = GET_CODE (cond);
3337 99962 : m = XEXP (cond, 0);
3338 99962 : c = XEXP (cond, 1);
3339 :
3340 99962 : t = NULL_RTX;
3341 99962 : if (if_info->a == const0_rtx)
3342 : {
3343 2650 : if ((code == LT && c == const0_rtx)
3344 2621 : || (code == LE && c == constm1_rtx))
3345 29 : t = if_info->b;
3346 : }
3347 97312 : else if (if_info->b == const0_rtx)
3348 : {
3349 10905 : if ((code == GE && c == const0_rtx)
3350 10905 : || (code == GT && c == constm1_rtx))
3351 : t = if_info->a;
3352 : }
3353 :
3354 95 : if (! t || side_effects_p (t))
3355 : return false;
3356 :
3357 : /* We currently don't handle different modes. */
3358 95 : mode = GET_MODE (t);
3359 95 : if (GET_MODE (m) != mode)
3360 : return false;
3361 :
3362 : /* This is only profitable if T is unconditionally executed/evaluated in the
3363 : original insn sequence or T is cheap and can't trap or fault. The former
3364 : happens if B is the non-zero (T) value and if INSN_B was taken from
3365 : TEST_BB, or there was no INSN_B which can happen for e.g. conditional
3366 : stores to memory. For the cost computation use the block TEST_BB where
3367 : the evaluation will end up after the transformation. */
3368 43 : t_unconditional
3369 86 : = (t == if_info->b
3370 43 : && (if_info->insn_b == NULL_RTX
3371 0 : || BLOCK_FOR_INSN (if_info->insn_b) == if_info->test_bb));
3372 86 : if (!(t_unconditional
3373 43 : || ((set_src_cost (t, mode, if_info->speed_p)
3374 : < COSTS_N_INSNS (2))
3375 37 : && !may_trap_or_fault_p (t))))
3376 : return false;
3377 :
3378 0 : if (!noce_can_force_operand (t))
3379 : return false;
3380 :
3381 0 : start_sequence ();
3382 : /* Use emit_store_flag to generate "m < 0 ? -1 : 0" instead of expanding
3383 : "(signed) m >> 31" directly. This benefits targets with specialized
3384 : insns to obtain the signmask, but still uses ashr_optab otherwise. */
3385 0 : m = emit_store_flag (gen_reg_rtx (mode), LT, m, const0_rtx, mode, 0, -1);
3386 0 : t = m ? expand_binop (mode, and_optab, m, t, NULL_RTX, 0, OPTAB_DIRECT)
3387 : : NULL_RTX;
3388 :
3389 0 : if (!t)
3390 : {
3391 0 : end_sequence ();
3392 0 : return false;
3393 : }
3394 :
3395 0 : noce_emit_move_insn (if_info->x, t);
3396 :
3397 0 : seq = end_ifcvt_sequence (if_info);
3398 0 : return noce_commit_sequence (if_info, seq, false, "noce_try_sign_mask");
3399 : }
3400 :
3401 : /* Return the arithmetic operation in X, looking through an extension. */
3402 :
3403 : static rtx
3404 218986 : noce_cond_arith_operation (rtx x)
3405 : {
3406 218986 : enum rtx_code code = GET_CODE (x);
3407 218986 : if (code == SIGN_EXTEND || code == ZERO_EXTEND)
3408 527 : x = XEXP (x, 0);
3409 :
3410 218986 : return noce_cond_zero_binary_op_supported (x) ? x : NULL_RTX;
3411 : }
3412 :
3413 : /* Return true if X contains an EXT_CODE extension from its mode to
3414 : OUTER_MODE. */
3415 :
3416 : static bool
3417 0 : noce_operand_known_extended_p (rtx x, machine_mode outer_mode,
3418 : enum rtx_code ext_code)
3419 : {
3420 0 : machine_mode inner_mode = GET_MODE (x);
3421 0 : unsigned int precision = GET_MODE_PRECISION (outer_mode).to_constant ();
3422 0 : unsigned int inner_precision
3423 0 : = GET_MODE_PRECISION (inner_mode).to_constant ();
3424 0 : if (ext_code == SIGN_EXTEND)
3425 0 : return (num_sign_bit_copies (x, outer_mode)
3426 0 : > precision - inner_precision);
3427 :
3428 0 : if (ext_code == ZERO_EXTEND)
3429 0 : return (HWI_COMPUTABLE_MODE_P (outer_mode)
3430 0 : && (nonzero_bits (x, outer_mode)
3431 0 : & ~GET_MODE_MASK (inner_mode)) == 0);
3432 :
3433 : return false;
3434 : }
3435 :
3436 : /* Return the register or constant that EXP selects on: EXP itself for a
3437 : register or a constant, the inner register of a subreg, and NULL_RTX for
3438 : anything else. */
3439 :
3440 : static rtx
3441 28176 : get_base_reg_or_constant (rtx exp)
3442 : {
3443 0 : if (REG_P (exp))
3444 : return exp;
3445 5124 : else if (SUBREG_P (exp))
3446 309 : return SUBREG_REG (exp);
3447 4815 : else if (CONST_INT_P (exp))
3448 0 : return exp;
3449 : return NULL_RTX;
3450 : }
3451 :
3452 : /* Try to convert if-then-else with conditional zero, returning TRUE on
3453 : success or FALSE on failure. IF_INFO describes the if-conversion scenario
3454 : under consideration.
3455 :
3456 : It verifies the branch structure on the left and transforms it into the
3457 : branchless sequence on the right, with a backend-provided conditional zero
3458 : or orig for operand z. If true, tmp is z, 0 otherwise (y op 0 is the same
3459 : as y for most op).
3460 :
3461 : if (cond) | tmp = cond ? z : 0
3462 : x = y op z | x = y op tmp
3463 : else |
3464 : x = y |
3465 :
3466 : AND is special as it needs to be handled differently.
3467 :
3468 : tmp = !cond ? y : 0
3469 : x = (y & z) | tmp
3470 :
3471 : Also for AND try:
3472 :
3473 : tmp = cond ? z : -1
3474 : x = y op tmp
3475 :
3476 : to see if it is cheaper to produce `!cond ? y : 0` or `cond ? z : -1`. */
3477 :
3478 : static bool
3479 156597 : noce_try_cond_arith (noce_if_info *if_info)
3480 : {
3481 156597 : rtx target, a, b, a_op0, a_op1, outer_a;
3482 156597 : rtx cond = if_info->cond;
3483 156597 : rtx_code code = GET_CODE (cond);
3484 156597 : rtx_insn *seq;
3485 156597 : rtx_code op;
3486 156597 : machine_mode mode = GET_MODE (if_info->x);
3487 :
3488 : /* Scalar integral modes are only supported here.
3489 : Could support scalar floating point but that
3490 : would be only with -ffast-math and might
3491 : be worse than a branch. */
3492 156597 : if (!SCALAR_INT_MODE_P (mode))
3493 : return false;
3494 :
3495 165691 : if (!noce_simple_bbs (if_info))
3496 : return false;
3497 :
3498 109493 : a = copy_rtx (if_info->a);
3499 109493 : b = copy_rtx (if_info->b);
3500 109493 : rtx a_arith = noce_cond_arith_operation (a);
3501 109493 : rtx b_arith = noce_cond_arith_operation (b);
3502 :
3503 : /* Canonicalize x = y : (y op z) to x = (y op z) : y. */
3504 109493 : if (REG_P (a) && b_arith)
3505 : {
3506 204 : cond = noce_reversed_cond (if_info, &code);
3507 204 : std::swap (a, b);
3508 204 : a_arith = b_arith;
3509 : }
3510 :
3511 : /* Check if x = (y op z) : y is supported by czero based ifcvt. */
3512 109289 : else if (!(a_arith && REG_P (b)))
3513 95077 : goto fail;
3514 :
3515 14416 : if (code == UNKNOWN)
3516 0 : goto fail;
3517 :
3518 14416 : outer_a = a == a_arith ? NULL_RTX : a;
3519 14416 : a = a_arith;
3520 14416 : op = GET_CODE (a);
3521 :
3522 : /* EXTEND (y op z) : y is valid only when Y already contains the same
3523 : extension of its lowpart. AND uses a different transformation. */
3524 14416 : if (outer_a
3525 0 : && (op == AND
3526 0 : || GET_MODE (outer_a) != mode
3527 0 : || !SCALAR_INT_MODE_P (GET_MODE (a))))
3528 0 : goto fail;
3529 :
3530 : /* Canonicalize x = (z op y) : y to x = (y op z) : y */
3531 14416 : a_op1 = get_base_reg_or_constant (XEXP (a, 1));
3532 13755 : if (a_op1 && rtx_equal_p (a_op1, b) && COMMUTATIVE_ARITH_P (a))
3533 : {
3534 18 : std::swap (XEXP (a, 0), XEXP (a, 1));
3535 18 : a_op1 = get_base_reg_or_constant (XEXP (a, 1));
3536 : }
3537 :
3538 14398 : if (a_op1 == NULL_RTX)
3539 674 : goto fail;
3540 :
3541 : /* Ensure the cond is of form: x = (y op z) : y */
3542 13742 : a_op0 = get_base_reg_or_constant (XEXP (a, 0));
3543 13737 : if (!(a_op0 && rtx_equal_p (a_op0, b)))
3544 1984 : goto fail;
3545 :
3546 11758 : if (outer_a
3547 11758 : && (!SUBREG_P (XEXP (a, 0))
3548 0 : || !subreg_lowpart_p (XEXP (a, 0))
3549 0 : || GET_MODE (SUBREG_REG (XEXP (a, 0))) != mode
3550 0 : || !noce_operand_known_extended_p (XEXP (a, 0), mode,
3551 0 : GET_CODE (outer_a))))
3552 0 : goto fail;
3553 :
3554 11758 : start_sequence ();
3555 :
3556 11758 : if (CONST_INT_P (XEXP (a, 1)))
3557 2880 : target = gen_reg_rtx (GET_MODE (XEXP (a, 0)));
3558 : else
3559 8878 : target = gen_reg_rtx (GET_MODE (XEXP (a, op != AND)));
3560 :
3561 : /* AND requires !cond, instead we swap ops around. */
3562 11758 : target = noce_emit_cmove (if_info, target, code,
3563 : XEXP (cond, 0), XEXP (cond, 1),
3564 : op != AND ? XEXP (a, 1) : const0_rtx,
3565 : op != AND ? const0_rtx : XEXP (a, 0));
3566 11758 : if (!target)
3567 : {
3568 1221 : end_sequence ();
3569 1221 : rtx tmp = XEXP (a, op != AND);
3570 : /* If the cmove fails and this was a lowpart subreg,
3571 : then try the reg part and then putting back the lowpart
3572 : afterwards. */
3573 1221 : if (GET_CODE (tmp) != SUBREG || !subreg_lowpart_p (tmp))
3574 : return false;
3575 0 : tmp = SUBREG_REG (tmp);
3576 : /* Only handle integer scalar modes for the inner mode of
3577 : the subreg. */
3578 0 : if (!SCALAR_INT_MODE_P (GET_MODE (tmp)))
3579 : return false;
3580 :
3581 0 : start_sequence ();
3582 0 : target = gen_reg_rtx (GET_MODE (tmp));
3583 0 : target = noce_emit_cmove (if_info, target, code,
3584 : XEXP (cond, 0), XEXP (cond, 1),
3585 : op != AND ? tmp : const0_rtx,
3586 : op != AND ? const0_rtx : tmp);
3587 0 : if (!target)
3588 0 : goto end_seq_n_fail;
3589 0 : target = rtl_hooks.gen_lowpart_no_emit (GET_MODE (XEXP (a, op != AND)), target);
3590 0 : gcc_assert (target);
3591 : }
3592 :
3593 : /* Every path through the fallback above either returns or produces a
3594 : conditional move, so TARGET is non-null below. */
3595 : gcc_checking_assert (target);
3596 :
3597 10537 : if (outer_a)
3598 : {
3599 0 : XEXP (a, 1) = target;
3600 0 : noce_emit_move_insn (if_info->x, outer_a);
3601 0 : target = if_info->x;
3602 0 : goto success;
3603 : }
3604 :
3605 : /* For AND, try `cond ? z : -1` to see if that is cheaper or the same cost.
3606 : In some cases it will be cheaper to produce the -1 rather than the 0 case. */
3607 10537 : if (op == AND)
3608 : {
3609 84 : rtx_insn *seq0 = end_sequence ();
3610 84 : unsigned cost0 = seq_cost (seq0, if_info->speed_p);
3611 :
3612 : /* Produce `cond ? z : -1`. */
3613 84 : rtx targetm1;
3614 84 : start_sequence ();
3615 84 : targetm1 = gen_reg_rtx (GET_MODE (XEXP (a, 1)));
3616 84 : targetm1 = noce_emit_cmove (if_info, targetm1, code,
3617 : XEXP (cond, 0), XEXP (cond, 1),
3618 : XEXP (a, 1), constm1_rtx);
3619 84 : rtx_insn *seqm1 = end_sequence ();
3620 84 : unsigned costm1 = seq_cost (seqm1, if_info->speed_p);
3621 84 : if (!targetm1)
3622 78 : costm1 = -1u;
3623 :
3624 : /* If -1 is cheaper or the same cost to producing 0, then use that. */
3625 84 : if (costm1 <= cost0)
3626 : {
3627 6 : push_to_sequence (seqm1);
3628 6 : targetm1 = expand_simple_binop (mode, op, a_op0, targetm1,
3629 : if_info->x, 0, OPTAB_WIDEN);
3630 6 : if (targetm1)
3631 : {
3632 6 : target = targetm1;
3633 6 : goto success;
3634 : }
3635 0 : end_sequence ();
3636 : }
3637 :
3638 : /* For 0 the produce sequence is:
3639 : tmp = !cond ? y : 0
3640 : x = (y & z) | tmp */
3641 78 : push_to_sequence (seq0);
3642 78 : rtx a_bin = gen_reg_rtx (mode);
3643 78 : noce_emit_move_insn (a_bin, a);
3644 :
3645 78 : target = expand_simple_binop (mode, IOR, a_bin, target, if_info->x, 0,
3646 : OPTAB_WIDEN);
3647 78 : if (!target)
3648 0 : goto end_seq_n_fail;
3649 78 : goto success;
3650 : }
3651 :
3652 10453 : target = expand_simple_binop (mode, op, a_op0, target, if_info->x, 0,
3653 : OPTAB_WIDEN);
3654 :
3655 10453 : if (!target)
3656 0 : goto end_seq_n_fail;
3657 :
3658 10453 : success:
3659 10537 : if (target != if_info->x)
3660 0 : noce_emit_move_insn (if_info->x, target);
3661 :
3662 10537 : seq = end_ifcvt_sequence (if_info);
3663 10537 : return noce_commit_sequence (if_info, seq, true, "noce_try_cond_arith");
3664 :
3665 0 : end_seq_n_fail:
3666 0 : end_sequence ();
3667 :
3668 156597 : fail:
3669 :
3670 : return false;
3671 : }
3672 :
3673 : /* Optimize away "if (x & C) x |= C" and similar bit manipulation
3674 : transformations. */
3675 :
3676 : static bool
3677 208921 : noce_try_bitop (noce_if_info *if_info)
3678 : {
3679 208921 : rtx cond, x, a, result;
3680 208921 : rtx_insn *seq;
3681 208921 : scalar_int_mode mode;
3682 208921 : enum rtx_code code;
3683 208921 : int bitnum;
3684 :
3685 208921 : x = if_info->x;
3686 208921 : cond = if_info->cond;
3687 208921 : code = GET_CODE (cond);
3688 :
3689 : /* Check for an integer operation. */
3690 208921 : if (!is_a <scalar_int_mode> (GET_MODE (x), &mode))
3691 : return false;
3692 :
3693 234876 : if (!noce_simple_bbs (if_info))
3694 : return false;
3695 :
3696 : /* Check for no else condition. */
3697 158979 : if (! rtx_equal_p (x, if_info->b))
3698 : return false;
3699 :
3700 : /* Check for a suitable condition. */
3701 84053 : if (code != NE && code != EQ)
3702 : return false;
3703 59828 : if (XEXP (cond, 1) != const0_rtx)
3704 : return false;
3705 41439 : cond = XEXP (cond, 0);
3706 :
3707 : /* ??? We could also handle AND here. */
3708 41439 : if (GET_CODE (cond) == ZERO_EXTRACT)
3709 : {
3710 228 : if (XEXP (cond, 1) != const1_rtx
3711 113 : || !CONST_INT_P (XEXP (cond, 2))
3712 341 : || ! rtx_equal_p (x, XEXP (cond, 0)))
3713 : return false;
3714 4 : bitnum = INTVAL (XEXP (cond, 2));
3715 4 : if (BITS_BIG_ENDIAN)
3716 : bitnum = GET_MODE_BITSIZE (mode) - 1 - bitnum;
3717 4 : if (bitnum < 0 || bitnum >= HOST_BITS_PER_WIDE_INT)
3718 : return false;
3719 : }
3720 : else
3721 : return false;
3722 :
3723 4 : a = if_info->a;
3724 4 : if (GET_CODE (a) == IOR || GET_CODE (a) == XOR)
3725 : {
3726 : /* Check for "if (X & C) x = x op C". */
3727 0 : if (! rtx_equal_p (x, XEXP (a, 0))
3728 0 : || !CONST_INT_P (XEXP (a, 1))
3729 0 : || (INTVAL (XEXP (a, 1)) & GET_MODE_MASK (mode))
3730 0 : != HOST_WIDE_INT_1U << bitnum)
3731 : return false;
3732 :
3733 : /* if ((x & C) == 0) x |= C; is transformed to x |= C. */
3734 : /* if ((x & C) != 0) x |= C; is transformed to nothing. */
3735 0 : if (GET_CODE (a) == IOR)
3736 0 : result = (code == NE) ? a : NULL_RTX;
3737 0 : else if (code == NE)
3738 : {
3739 : /* if ((x & C) == 0) x ^= C; is transformed to x |= C. */
3740 0 : result = gen_int_mode (HOST_WIDE_INT_1 << bitnum, mode);
3741 0 : result = simplify_gen_binary (IOR, mode, x, result);
3742 : }
3743 : else
3744 : {
3745 : /* if ((x & C) != 0) x ^= C; is transformed to x &= ~C. */
3746 0 : result = gen_int_mode (~(HOST_WIDE_INT_1 << bitnum), mode);
3747 0 : result = simplify_gen_binary (AND, mode, x, result);
3748 : }
3749 : }
3750 4 : else if (GET_CODE (a) == AND)
3751 : {
3752 : /* Check for "if (X & C) x &= ~C". */
3753 0 : if (! rtx_equal_p (x, XEXP (a, 0))
3754 0 : || !CONST_INT_P (XEXP (a, 1))
3755 0 : || (INTVAL (XEXP (a, 1)) & GET_MODE_MASK (mode))
3756 0 : != (~(HOST_WIDE_INT_1 << bitnum) & GET_MODE_MASK (mode)))
3757 : return false;
3758 :
3759 : /* if ((x & C) == 0) x &= ~C; is transformed to nothing. */
3760 : /* if ((x & C) != 0) x &= ~C; is transformed to x &= ~C. */
3761 0 : result = (code == EQ) ? a : NULL_RTX;
3762 : }
3763 : else
3764 : return false;
3765 :
3766 0 : if (result)
3767 : {
3768 0 : start_sequence ();
3769 0 : noce_emit_move_insn (x, result);
3770 0 : seq = end_ifcvt_sequence (if_info);
3771 0 : if (!seq)
3772 : return false;
3773 :
3774 0 : emit_insn_before_setloc (seq, if_info->jump,
3775 0 : INSN_LOCATION (if_info->insn_a));
3776 : }
3777 0 : if_info->transform_name = "noce_try_bitop";
3778 0 : return true;
3779 : }
3780 :
3781 :
3782 : /* Similar to get_condition, only the resulting condition must be
3783 : valid at JUMP, instead of at EARLIEST.
3784 :
3785 : If THEN_ELSE_REVERSED is true, the fallthrough does not go to the
3786 : THEN block of the caller, and we have to reverse the condition. */
3787 :
3788 : static rtx
3789 4316765 : noce_get_condition (rtx_insn *jump, rtx_insn **earliest,
3790 : bool then_else_reversed)
3791 : {
3792 4316765 : rtx cond, set, tmp;
3793 4316765 : bool reverse;
3794 :
3795 4316765 : if (! any_condjump_p (jump))
3796 : return NULL_RTX;
3797 :
3798 4316765 : set = pc_set (jump);
3799 :
3800 : /* If this branches to JUMP_LABEL when the condition is false,
3801 : reverse the condition. */
3802 8633530 : reverse = (GET_CODE (XEXP (SET_SRC (set), 2)) == LABEL_REF
3803 4316765 : && label_ref_label (XEXP (SET_SRC (set), 2)) == JUMP_LABEL (jump));
3804 :
3805 : /* We may have to reverse because the caller's if block is not canonical,
3806 : i.e. the THEN block isn't the fallthrough block for the TEST block
3807 : (see find_if_header). */
3808 4316765 : if (then_else_reversed)
3809 1914842 : reverse = !reverse;
3810 :
3811 : /* If the condition variable is a register and is MODE_INT, accept it. */
3812 :
3813 4316765 : cond = XEXP (SET_SRC (set), 0);
3814 4316765 : tmp = XEXP (cond, 0);
3815 4316091 : if (REG_P (tmp) && GET_MODE_CLASS (GET_MODE (tmp)) == MODE_INT
3816 4316783 : && (GET_MODE (tmp) != BImode
3817 0 : || !targetm.small_register_classes_for_mode_p (BImode)))
3818 : {
3819 18 : *earliest = jump;
3820 :
3821 18 : if (reverse)
3822 9 : cond = gen_rtx_fmt_ee (reverse_condition (GET_CODE (cond)),
3823 : GET_MODE (cond), tmp, XEXP (cond, 1));
3824 : return cond;
3825 : }
3826 :
3827 : /* Otherwise, fall back on canonicalize_condition to do the dirty
3828 : work of manipulating MODE_CC values and COMPARE rtx codes. */
3829 4316747 : tmp = canonicalize_condition (jump, cond, reverse, earliest,
3830 : NULL_RTX, have_cbranchcc4, true);
3831 :
3832 : /* We don't handle side-effects in the condition, like handling
3833 : REG_INC notes and making sure no duplicate conditions are emitted. */
3834 4316747 : if (tmp != NULL_RTX && side_effects_p (tmp))
3835 8494 : return NULL_RTX;
3836 :
3837 : return tmp;
3838 : }
3839 :
3840 : /* Return true if OP is ok for if-then-else processing. */
3841 :
3842 : static bool
3843 8935745 : noce_operand_ok (const_rtx op)
3844 : {
3845 8935745 : if (side_effects_p (op))
3846 : return false;
3847 :
3848 : /* We special-case memories, so handle any of them with
3849 : no address side effects. */
3850 8914308 : if (MEM_P (op))
3851 1595467 : return ! side_effects_p (XEXP (op, 0));
3852 :
3853 7318841 : return ! may_trap_p (op);
3854 : }
3855 :
3856 : /* Return true iff basic block TEST_BB is valid for noce if-conversion.
3857 : The condition used in this if-conversion is in COND.
3858 : In practice, check that TEST_BB ends with a single set
3859 : x := a and all previous computations
3860 : in TEST_BB don't produce any values that are live after TEST_BB.
3861 : In other words, all the insns in TEST_BB are there only
3862 : to compute a value for x. Add the rtx cost of the insns
3863 : in TEST_BB to COST. Record whether TEST_BB is a single simple
3864 : set instruction in SIMPLE_P. */
3865 :
3866 : static bool
3867 2159531 : bb_valid_for_noce_process_p (basic_block test_bb, rtx cond,
3868 : unsigned int *cost, bool *simple_p)
3869 : {
3870 2159531 : if (!test_bb)
3871 : return false;
3872 :
3873 2159531 : rtx_insn *last_insn = last_active_insn (test_bb, false);
3874 2159531 : rtx last_set = NULL_RTX;
3875 :
3876 2159531 : rtx cc = cc_in_cond (cond);
3877 :
3878 2159531 : if (!insn_valid_noce_process_p (last_insn, cc))
3879 : return false;
3880 :
3881 : /* Punt on blocks ending with asm goto or jumps with other side-effects,
3882 : last_active_insn ignores JUMP_INSNs. */
3883 1530083 : if (JUMP_P (BB_END (test_bb)) && !onlyjump_p (BB_END (test_bb)))
3884 : return false;
3885 :
3886 1530081 : last_set = single_set (last_insn);
3887 :
3888 1530081 : rtx x = SET_DEST (last_set);
3889 1530081 : rtx_insn *first_insn = first_active_insn (test_bb);
3890 1530081 : rtx first_set = single_set (first_insn);
3891 :
3892 1530081 : if (!first_set)
3893 : return false;
3894 :
3895 : /* We have a single simple set, that's okay. */
3896 1516076 : bool speed_p = optimize_bb_for_speed_p (test_bb);
3897 :
3898 1516076 : if (first_insn == last_insn)
3899 : {
3900 549103 : *simple_p = noce_operand_ok (SET_DEST (first_set));
3901 549103 : *cost += pattern_cost (first_set, speed_p);
3902 549103 : return *simple_p;
3903 : }
3904 :
3905 966973 : rtx_insn *prev_last_insn = PREV_INSN (last_insn);
3906 966973 : gcc_assert (prev_last_insn);
3907 :
3908 : /* For now, disallow setting x multiple times in test_bb. */
3909 966973 : if (REG_P (x) && reg_set_between_p (x, first_insn, prev_last_insn))
3910 : return false;
3911 :
3912 819846 : auto_bitmap test_bb_temps (®_obstack);
3913 :
3914 : /* The regs that are live out of test_bb. */
3915 819846 : bitmap test_bb_live_out = df_get_live_out (test_bb);
3916 :
3917 819846 : int potential_cost = pattern_cost (last_set, speed_p);
3918 819846 : rtx_insn *insn;
3919 4490479 : FOR_BB_INSNS (test_bb, insn)
3920 : {
3921 4411774 : if (insn != last_insn)
3922 : {
3923 4333069 : if (!active_insn_p (insn))
3924 2862350 : continue;
3925 :
3926 1470719 : if (!insn_valid_noce_process_p (insn, cc))
3927 : return false;
3928 :
3929 1239156 : rtx sset = single_set (insn);
3930 1239156 : gcc_assert (sset);
3931 1239156 : rtx dest = SET_DEST (sset);
3932 1239156 : if (SUBREG_P (dest))
3933 18583 : dest = SUBREG_REG (dest);
3934 :
3935 1239156 : if (contains_mem_rtx_p (SET_SRC (sset))
3936 866879 : || !REG_P (dest)
3937 1977116 : || reg_overlap_mentioned_p (dest, cond))
3938 : return false;
3939 :
3940 729578 : potential_cost += pattern_cost (sset, speed_p);
3941 729578 : bitmap_set_bit (test_bb_temps, REGNO (dest));
3942 : }
3943 : }
3944 :
3945 : /* If any of the intermediate results in test_bb are live after test_bb
3946 : then fail. */
3947 78705 : if (bitmap_intersect_p (test_bb_live_out, test_bb_temps))
3948 : return false;
3949 :
3950 30516 : *cost += potential_cost;
3951 30516 : *simple_p = false;
3952 30516 : return true;
3953 819846 : }
3954 :
3955 : /* Helper function to emit a cmov sequence encapsulated in
3956 : start_sequence () and end_sequence (). If NEED_CMOV is true
3957 : we call noce_emit_cmove to create a cmove sequence. Otherwise emit
3958 : a simple move. If successful, store the first instruction of the
3959 : sequence in TEMP_DEST and the sequence costs in SEQ_COST. */
3960 :
3961 : static rtx_insn*
3962 393689 : try_emit_cmove_seq (noce_if_info *if_info, rtx temp,
3963 : rtx cond, rtx new_val, rtx old_val, bool need_cmov,
3964 : unsigned *cost, rtx *temp_dest,
3965 : rtx cc_cmp = NULL, rtx rev_cc_cmp = NULL)
3966 : {
3967 393689 : rtx_insn *seq = NULL;
3968 393689 : *cost = 0;
3969 :
3970 393689 : rtx x = XEXP (cond, 0);
3971 393689 : rtx y = XEXP (cond, 1);
3972 393689 : rtx_code cond_code = GET_CODE (cond);
3973 :
3974 393689 : start_sequence ();
3975 :
3976 393689 : if (need_cmov)
3977 317573 : *temp_dest = noce_emit_cmove (if_info, temp, cond_code,
3978 : x, y, new_val, old_val, cc_cmp, rev_cc_cmp);
3979 : else
3980 : {
3981 76116 : *temp_dest = temp;
3982 76116 : if (if_info->then_else_reversed)
3983 2044 : noce_emit_move_insn (temp, old_val);
3984 : else
3985 74072 : noce_emit_move_insn (temp, new_val);
3986 : }
3987 :
3988 393689 : if (*temp_dest != NULL_RTX)
3989 : {
3990 387525 : seq = get_insns ();
3991 387525 : *cost = seq_cost (seq, if_info->speed_p);
3992 : }
3993 :
3994 393689 : end_sequence ();
3995 :
3996 393689 : return seq;
3997 : }
3998 :
3999 : /* Finish a successful noce if-conversion of IF_INFO whose replacement insns
4000 : have already been emitted before the branch. Delete the now-dead THEN
4001 : block, and ELSE too if this was a diamond. An IF-THEN-JOIN also has an edge
4002 : from TEST_BB straight to JOIN_BB that bypassed THEN, and that goes as well.
4003 : An IF-THEN-ELSE-JOIN has no such edge, and deleting ELSE_BB removes its two
4004 : edges instead. Redirect TEST_BB to JOIN_BB and merge the two when the tail
4005 : no longer needs its own block. Count the converted if-block and the CFG
4006 : changes it took. */
4007 :
4008 : static void
4009 178112 : noce_finish_if_conversion (noce_if_info *if_info)
4010 : {
4011 178112 : basic_block test_bb = if_info->test_bb;
4012 178112 : basic_block then_bb = if_info->then_bb;
4013 178112 : basic_block else_bb = if_info->else_bb;
4014 178112 : basic_block join_bb = if_info->join_bb;
4015 :
4016 178112 : if (else_bb)
4017 : {
4018 76209 : delete_basic_block (else_bb);
4019 76209 : num_true_changes++;
4020 : }
4021 : else
4022 101903 : remove_edge (find_edge (test_bb, join_bb));
4023 :
4024 178112 : remove_edge (find_edge (then_bb, join_bb));
4025 178112 : redirect_edge_and_branch_force (single_succ_edge (test_bb), join_bb);
4026 178112 : delete_basic_block (then_bb);
4027 178112 : num_true_changes++;
4028 :
4029 178112 : if (can_merge_blocks_p (test_bb, join_bb))
4030 : {
4031 134343 : merge_blocks (test_bb, join_bb);
4032 134343 : num_true_changes++;
4033 : }
4034 :
4035 178112 : num_updated_if_blocks++;
4036 178112 : }
4037 :
4038 : /* We have something like:
4039 :
4040 : if (x > y)
4041 : { i = EXPR_A; j = EXPR_B; k = EXPR_C; }
4042 :
4043 : Make it:
4044 :
4045 : tmp_i = (x > y) ? EXPR_A : i;
4046 : tmp_j = (x > y) ? EXPR_B : j;
4047 : tmp_k = (x > y) ? EXPR_C : k;
4048 : i = tmp_i;
4049 : j = tmp_j;
4050 : k = tmp_k;
4051 :
4052 : Subsequent passes are expected to clean up the extra moves.
4053 :
4054 : Look for special cases such as writes to one register which are
4055 : read back in another SET, as might occur in a swap idiom or
4056 : similar.
4057 :
4058 : These look like:
4059 :
4060 : if (x > y)
4061 : i = a;
4062 : j = i;
4063 :
4064 : Which we want to rewrite to:
4065 :
4066 : tmp_i = (x > y) ? a : i;
4067 : tmp_j = (x > y) ? tmp_i : j;
4068 : i = tmp_i;
4069 : j = tmp_j;
4070 :
4071 : We can catch these when looking at (SET x y) by keeping a list of the
4072 : registers we would have targeted before if-conversion and looking back
4073 : through it for an overlap with Y. If we find one, we rewire the
4074 : conditional set to use the temporary we introduced earlier.
4075 :
4076 : IF_INFO contains the useful information about the block structure and
4077 : jump instructions. For an IF-THEN-ELSE-JOIN, first evaluate the else
4078 : arm's sets into temporaries and retain their final values for the
4079 : conditional moves. Return true if the replacement is valid and profitable
4080 : and its CFG changes have been committed, otherwise return false. */
4081 :
4082 : static bool
4083 50594 : noce_convert_multiple_sets (noce_if_info *if_info)
4084 : {
4085 50594 : basic_block test_bb = if_info->test_bb;
4086 50594 : basic_block then_bb = if_info->then_bb;
4087 50594 : basic_block else_bb = if_info->else_bb;
4088 50594 : rtx_insn *jump = if_info->jump;
4089 50594 : rtx_insn *cond_earliest;
4090 50594 : rtx_insn *insn;
4091 :
4092 50594 : start_sequence ();
4093 :
4094 : /* Decompose the condition attached to the jump. */
4095 50594 : rtx cond = noce_get_condition (jump, &cond_earliest, false);
4096 :
4097 50594 : auto_delete_vec<noce_multiple_sets_info> insn_info;
4098 50594 : init_noce_multiple_sets_info (then_bb, insn_info);
4099 50594 : gcc_assert (!insn_info.is_empty ());
4100 50594 : unsigned then_count = insn_info.length ();
4101 50594 : location_t sequence_location
4102 50594 : = INSN_LOCATION (insn_info.last ()->unmodified_insn);
4103 :
4104 50594 : auto_delete_vec<noce_multiple_sets_info> else_insn_info;
4105 50594 : auto_vec<unsigned> else_only_indices;
4106 50594 : if (else_bb)
4107 : {
4108 22944 : init_noce_multiple_sets_info (else_bb, else_insn_info);
4109 :
4110 : /* Add one output entry for each live-out destination that is set only
4111 : by the else arm. Record the last definition, which holds the
4112 : value that reaches the join. */
4113 22944 : auto_bitmap then_dests, seen;
4114 86739 : for (unsigned i = 0; i < then_count; ++i)
4115 63795 : bitmap_set_bit (then_dests, REGNO (insn_info[i]->target));
4116 :
4117 86228 : for (int i = else_insn_info.length () - 1; i >= 0; --i)
4118 40340 : if (else_insn_info[i]->need_cmov
4119 38782 : && !bitmap_bit_p (then_dests,
4120 38782 : REGNO (else_insn_info[i]->target))
4121 47269 : && bitmap_set_bit (seen, REGNO (else_insn_info[i]->target)))
4122 6929 : else_only_indices.safe_push (i);
4123 22944 : else_only_indices.reverse ();
4124 :
4125 22944 : unsigned i, else_index;
4126 59426 : FOR_EACH_VEC_ELT (else_only_indices, i, else_index)
4127 : {
4128 6929 : noce_multiple_sets_info *info = new noce_multiple_sets_info;
4129 6929 : noce_multiple_sets_info *else_info = else_insn_info[else_index];
4130 6929 : info->target = else_info->target;
4131 6929 : info->temporary = NULL_RTX;
4132 6929 : info->unmodified_insn = else_info->unmodified_insn;
4133 6929 : info->need_cmov = true;
4134 6929 : insn_info.safe_push (info);
4135 : }
4136 22944 : }
4137 :
4138 : /* Include else-only outputs when enforcing the conversion limit. */
4139 50594 : if (insn_info.length () > (unsigned) param_max_rtl_if_conversion_insns)
4140 : {
4141 0 : end_sequence ();
4142 0 : return false;
4143 : }
4144 :
4145 50594 : int last_needs_comparison = -1;
4146 :
4147 50594 : bool use_cond_earliest = false;
4148 :
4149 50594 : bool ok = noce_convert_multiple_sets_1
4150 50594 : (if_info, cond, insn_info, else_insn_info, then_count, else_only_indices,
4151 : &last_needs_comparison, &use_cond_earliest);
4152 50594 : if (!ok)
4153 : return false;
4154 :
4155 : /* Always perform a second attempt that uses information gathered in the
4156 : first. At least we can omit creating temporaries until we definitely
4157 : need them. The sequence created in the second attempt is never worse
4158 : than the first. */
4159 :
4160 47780 : end_sequence ();
4161 47780 : start_sequence ();
4162 47780 : ok = noce_convert_multiple_sets_1
4163 47780 : (if_info, cond, insn_info, else_insn_info, then_count, else_only_indices,
4164 : &last_needs_comparison, &use_cond_earliest);
4165 :
4166 : /* Actually we should not fail anymore if we reached here,
4167 : but better still check. */
4168 47780 : if (!ok)
4169 : return false;
4170 :
4171 : /* Now fixup the assignments.
4172 : PR116405: Iterate in reverse order and keep track of the targets so that
4173 : a move does not overwrite a subsequent value when multiple instructions
4174 : have the same target. */
4175 47780 : unsigned i;
4176 47780 : noce_multiple_sets_info *info;
4177 47780 : auto_bitmap set_targets (®_obstack);
4178 226242 : FOR_EACH_VEC_ELT_REVERSE (insn_info, i, info)
4179 : {
4180 130682 : gcc_checking_assert (REG_P (info->target));
4181 :
4182 130682 : if (info->target != info->temporary
4183 130682 : && !bitmap_bit_p (set_targets, REGNO (info->target)))
4184 4104 : noce_emit_move_insn (info->target, info->temporary);
4185 :
4186 130682 : bitmap_set_bit (set_targets, REGNO (info->target));
4187 : }
4188 :
4189 : /* Actually emit the sequence if it isn't too expensive. */
4190 47780 : rtx_insn *seq = get_insns ();
4191 :
4192 : /* If the created sequence does not use cond_earliest (but the jump
4193 : does) add its cost to the original_cost before comparing costs. */
4194 47780 : unsigned int original_cost = if_info->original_cost;
4195 47780 : if (if_info->jump != if_info->cond_earliest && !use_cond_earliest)
4196 36273 : if_info->original_cost += insn_cost (if_info->cond_earliest,
4197 : if_info->speed_p);
4198 :
4199 47780 : if (!targetm.noce_conversion_profitable_p (seq, if_info))
4200 : {
4201 14619 : end_sequence ();
4202 14619 : return false;
4203 : }
4204 :
4205 : /* Restore the original cost in case we do not succeed below. */
4206 33161 : if_info->original_cost = original_cost;
4207 :
4208 219423 : for (insn = seq; insn; insn = NEXT_INSN (insn))
4209 186262 : set_used_flags (insn);
4210 :
4211 : /* Mark all our temporaries and targets as used. */
4212 181731 : for (const noce_multiple_sets_info *msi : insn_info)
4213 : {
4214 82248 : set_used_flags (msi->temporary);
4215 82248 : set_used_flags (msi->target);
4216 : }
4217 :
4218 33161 : set_used_flags (cond);
4219 :
4220 33161 : unshare_all_rtl_in_chain (seq);
4221 33161 : end_sequence ();
4222 :
4223 33161 : if (!seq)
4224 : return false;
4225 :
4226 219221 : for (insn = seq; insn; insn = NEXT_INSN (insn))
4227 186107 : if (JUMP_P (insn) || CALL_P (insn)
4228 186107 : || recog_memoized (insn) == -1)
4229 : return false;
4230 :
4231 : /* This path does not go through end_ifcvt_sequence, so apply the same rule
4232 : about condition codes that outlive the if-region. */
4233 33114 : if (noce_clobbers_live_cc_p (test_bb, seq))
4234 : return false;
4235 :
4236 33114 : emit_insn_before_setloc (seq, if_info->jump, sequence_location);
4237 :
4238 33114 : noce_finish_if_conversion (if_info);
4239 :
4240 33114 : if_info->transform_name = "noce_convert_multiple_sets";
4241 33114 : return true;
4242 98374 : }
4243 :
4244 : /* Return true if any insn in SEQ modifies CC_CMP, or REV_CC_CMP when there is
4245 : one. Such a sequence cannot be used to select on that condition. */
4246 :
4247 : static bool
4248 207461 : noce_seq_clobbers_cc_cmp_p (rtx_insn *seq, rtx cc_cmp, rtx rev_cc_cmp)
4249 : {
4250 314583 : for (rtx_insn *insn = seq; insn; insn = NEXT_INSN (insn))
4251 223450 : if (modified_in_p (cc_cmp, insn)
4252 223450 : || (rev_cc_cmp && modified_in_p (rev_cc_cmp, insn)))
4253 : return true;
4254 :
4255 : return false;
4256 : }
4257 :
4258 : /* Try to emit the multiple-set conversion described by IF_INFO, selecting on
4259 : the already decoded jump condition COND. INSN_INFO holds THEN_COUNT
4260 : then-arm entries followed by entries for the else-only definitions recorded
4261 : in ELSE_ONLY_INDICES. For a diamond, evaluate ELSE_INSN_INFO first and
4262 : retain its final values for the conditional moves.
4263 :
4264 : LAST_NEEDS_COMPARISON is -1 on the first attempt. Record in it the last set
4265 : that needs a temporary to preserve the comparison, then use that boundary
4266 : on the second attempt. Set USE_COND_EARLIEST if the emitted sequence uses
4267 : IF_INFO->cond_earliest. Return true if the complete sequence was
4268 : emitted. */
4269 :
4270 : static bool
4271 98374 : noce_convert_multiple_sets_1 (noce_if_info *if_info, rtx cond,
4272 : auto_delete_vec<noce_multiple_sets_info> &insn_info,
4273 : auto_delete_vec<noce_multiple_sets_info>
4274 : &else_insn_info,
4275 : unsigned then_count,
4276 : const vec<unsigned> &else_only_indices,
4277 : int *last_needs_comparison,
4278 : bool *use_cond_earliest)
4279 : {
4280 98374 : rtx_insn *jump = if_info->jump;
4281 :
4282 98374 : rtx cc_cmp = cond_exec_get_condition (jump);
4283 98374 : if (cc_cmp)
4284 98374 : cc_cmp = copy_rtx (cc_cmp);
4285 98374 : rtx rev_cc_cmp = cond_exec_get_condition (jump, /* get_reversed */ true);
4286 98374 : if (rev_cc_cmp)
4287 98374 : rev_cc_cmp = copy_rtx (rev_cc_cmp);
4288 :
4289 98374 : int count = 0;
4290 98374 : bool second_try = *last_needs_comparison != -1;
4291 98374 : *use_cond_earliest = false;
4292 :
4293 : /* For an IF-THEN-ELSE-JOIN, emit the else block's computations first into
4294 : fresh temporaries. This leaves the incoming register values available to
4295 : the then arm. The conditional moves below select the then or else
4296 : values. */
4297 98374 : if (if_info->else_bb)
4298 : {
4299 44038 : int else_count = 0;
4300 44038 : rtx_insn *before_else = get_last_insn ();
4301 44038 : location_t saved_location = curr_insn_location ();
4302 44038 : rtx_insn *else_insn;
4303 255885 : FOR_BB_INSNS (if_info->else_bb, else_insn)
4304 : {
4305 211847 : if (!active_insn_p (else_insn))
4306 138374 : continue;
4307 :
4308 73473 : noce_multiple_sets_info *info = else_insn_info[else_count];
4309 73473 : rtx set = single_set (else_insn);
4310 73473 : gcc_checking_assert (set && REG_P (SET_DEST (set))
4311 : && !HARD_REGISTER_P (SET_DEST (set)));
4312 :
4313 73473 : rtx target = SET_DEST (set);
4314 73473 : rtx value = copy_rtx (SET_SRC (set));
4315 73473 : int i, ii;
4316 153667 : FOR_EACH_VEC_ELT (info->rewired_src, i, ii)
4317 6721 : value = simplify_replace_rtx (value,
4318 6721 : else_insn_info[ii]->target,
4319 6721 : else_insn_info[ii]->temporary);
4320 :
4321 73473 : set_curr_insn_location (INSN_LOCATION (else_insn));
4322 73473 : rtx temporary = copy_to_mode_reg (GET_MODE (target), value);
4323 :
4324 73473 : info->temporary = temporary;
4325 73473 : else_count++;
4326 : }
4327 :
4328 44038 : set_curr_insn_location (saved_location);
4329 :
4330 88076 : gcc_checking_assert (else_count == (int) else_insn_info.length ());
4331 :
4332 : /* These insns run ahead of the conditional moves. If they change a
4333 : register the comparison reads we cannot reuse it, so bail. If they
4334 : only clobber the condition code, drop the shared compare so that every
4335 : move re-materializes its own. */
4336 :
4337 44038 : rtx_insn *first_else
4338 44038 : = before_else ? NEXT_INSN (before_else) : get_insns ();
4339 111361 : for (rtx_insn *ei = first_else; ei; ei = NEXT_INSN (ei))
4340 : {
4341 69080 : if (modified_in_p (cond, ei))
4342 : {
4343 1757 : end_sequence ();
4344 1757 : return false;
4345 : }
4346 67323 : if (cc_cmp
4347 67323 : && (modified_in_p (cc_cmp, ei)
4348 35214 : || (rev_cc_cmp && modified_in_p (rev_cc_cmp, ei))))
4349 : {
4350 : cc_cmp = NULL_RTX;
4351 : rev_cc_cmp = NULL_RTX;
4352 : }
4353 : }
4354 : }
4355 :
4356 719008 : for (count = 0; count < (int) insn_info.length (); ++count)
4357 : {
4358 263944 : noce_multiple_sets_info *info = insn_info[count];
4359 263944 : rtx_insn *insn = info->unmodified_insn;
4360 263944 : rtx set = single_set (insn);
4361 263944 : gcc_checking_assert (set);
4362 :
4363 263944 : rtx target = info->target;
4364 263944 : rtx temp;
4365 263944 : rtx new_val;
4366 263944 : rtx old_val;
4367 :
4368 263944 : if ((unsigned) count < then_count)
4369 : {
4370 250167 : new_val = SET_SRC (set);
4371 :
4372 250167 : int i, ii;
4373 309059 : FOR_EACH_VEC_ELT (info->rewired_src, i, ii)
4374 58892 : new_val = simplify_replace_rtx (new_val, insn_info[ii]->target,
4375 58892 : insn_info[ii]->temporary);
4376 :
4377 250167 : old_val = target;
4378 :
4379 : /* Use the final value assigned to TARGET on the else arm.
4380 : Scanning in reverse is important when the arm assigns the same
4381 : register more than once. */
4382 250167 : if (if_info->else_bb)
4383 332393 : for (int j = else_insn_info.length () - 1; j >= 0; --j)
4384 155915 : if (rtx_equal_p (target, else_insn_info[j]->target))
4385 : {
4386 49498 : old_val = else_insn_info[j]->temporary;
4387 49498 : break;
4388 : }
4389 : }
4390 : else
4391 : {
4392 13777 : unsigned else_index
4393 13777 : = else_only_indices[(unsigned) count - then_count];
4394 13777 : noce_multiple_sets_info *else_info = else_insn_info[else_index];
4395 13777 : gcc_checking_assert (rtx_equal_p (target, else_info->target));
4396 :
4397 13777 : new_val = target;
4398 13777 : old_val = else_info->temporary;
4399 : }
4400 :
4401 : /* As we are transforming
4402 : if (x > y)
4403 : {
4404 : a = b;
4405 : c = d;
4406 : }
4407 : into
4408 : a = (x > y) ...
4409 : c = (x > y) ...
4410 :
4411 : we potentially check x > y before every set.
4412 : Even though the check might be removed by subsequent passes, this means
4413 : that we cannot transform
4414 : if (x > y)
4415 : {
4416 : x = y;
4417 : ...
4418 : }
4419 : into
4420 : x = (x > y) ...
4421 : ...
4422 : since this would invalidate x and the following to-be-removed checks.
4423 : Therefore we introduce a temporary every time we are about to
4424 : overwrite a variable used in the check. Costing of a sequence with
4425 : these is going to be inaccurate so only use temporaries when
4426 : needed.
4427 :
4428 : If performing a second try, we know how many insns require a
4429 : temporary. For the last of these, we can omit creating one. */
4430 263944 : if (reg_overlap_mentioned_p (target, cond)
4431 263944 : && (!second_try || count < *last_needs_comparison))
4432 26365 : temp = gen_reg_rtx (GET_MODE (target));
4433 : else
4434 : temp = target;
4435 :
4436 : /* We have identified swap-style idioms before. A normal
4437 : set will need to be a cmov while the first instruction of a swap-style
4438 : idiom can be a regular move. This helps with costing. */
4439 263944 : bool need_cmov = info->need_cmov;
4440 :
4441 : /* If we had a non-canonical conditional jump (i.e. one where
4442 : the fallthrough is to the "else" case) we need to reverse
4443 : the conditional select. */
4444 263944 : if (if_info->then_else_reversed)
4445 51149 : std::swap (old_val, new_val);
4446 :
4447 : /* Try emitting a conditional move passing the backend the
4448 : canonicalized comparison. The backend is then able to
4449 : recognize expressions like
4450 :
4451 : if (x > y)
4452 : y = x;
4453 :
4454 : as min/max and emit an insn, accordingly. */
4455 263944 : unsigned cost1 = 0, cost2 = 0;
4456 263944 : rtx_insn *seq, *seq1, *seq2 = NULL;
4457 263944 : rtx temp_dest = NULL_RTX, temp_dest1 = NULL_RTX, temp_dest2 = NULL_RTX;
4458 263944 : bool read_comparison = false;
4459 :
4460 263944 : seq1 = try_emit_cmove_seq (if_info, temp, cond,
4461 : new_val, old_val, need_cmov,
4462 : &cost1, &temp_dest1);
4463 :
4464 : /* Here, we try to pass the backend a non-canonicalized cc comparison
4465 : as well. This allows the backend to emit a cmov directly without
4466 : creating an additional compare for each. If successful, costing
4467 : is easier and this sequence is usually preferred. */
4468 263944 : if (cc_cmp)
4469 : {
4470 129745 : seq2 = try_emit_cmove_seq (if_info, temp, cond,
4471 : new_val, old_val, need_cmov,
4472 : &cost2, &temp_dest2, cc_cmp, rev_cc_cmp);
4473 :
4474 : /* The if_then_else in SEQ2 may be affected when cc_cmp/rev_cc_cmp is
4475 : clobbered. We can't safely use the sequence in this case. */
4476 129745 : if (noce_seq_clobbers_cc_cmp_p (seq2, cc_cmp, rev_cc_cmp))
4477 192507 : seq2 = NULL;
4478 : }
4479 :
4480 : /* The backend might have created a sequence that uses the
4481 : condition as a value. Check this. */
4482 :
4483 : /* We cannot handle anything more complex than a reg or constant. */
4484 263944 : if (!REG_P (XEXP (cond, 0)) && !CONSTANT_P (XEXP (cond, 0)))
4485 263944 : read_comparison = true;
4486 :
4487 263944 : if (!REG_P (XEXP (cond, 1)) && !CONSTANT_P (XEXP (cond, 1)))
4488 263944 : read_comparison = true;
4489 :
4490 263944 : rtx_insn *walk = seq2;
4491 263944 : int if_then_else_count = 0;
4492 343754 : while (walk && !read_comparison)
4493 : {
4494 79810 : rtx exprs_to_check[2];
4495 79810 : unsigned int exprs_count = 0;
4496 :
4497 79810 : rtx set = single_set (walk);
4498 79810 : if (set && XEXP (set, 1)
4499 79810 : && GET_CODE (XEXP (set, 1)) == IF_THEN_ELSE)
4500 : {
4501 : /* We assume that this is the cmove created by the backend that
4502 : naturally uses the condition. */
4503 49884 : exprs_to_check[exprs_count++] = XEXP (XEXP (set, 1), 1);
4504 49884 : exprs_to_check[exprs_count++] = XEXP (XEXP (set, 1), 2);
4505 49884 : if_then_else_count++;
4506 : }
4507 29926 : else if (NONDEBUG_INSN_P (walk))
4508 29926 : exprs_to_check[exprs_count++] = PATTERN (walk);
4509 :
4510 : /* Bail if we get more than one if_then_else because the assumption
4511 : above may be incorrect. */
4512 79810 : if (if_then_else_count > 1)
4513 : {
4514 0 : read_comparison = true;
4515 0 : break;
4516 : }
4517 :
4518 209504 : for (unsigned int i = 0; i < exprs_count; i++)
4519 : {
4520 129694 : subrtx_iterator::array_type array;
4521 289723 : FOR_EACH_SUBRTX (iter, array, exprs_to_check[i], NONCONST)
4522 190991 : if (*iter != NULL_RTX
4523 190991 : && (reg_overlap_mentioned_p (XEXP (cond, 0), *iter)
4524 172789 : || reg_overlap_mentioned_p (XEXP (cond, 1), *iter)))
4525 : {
4526 : read_comparison = true;
4527 : break;
4528 : }
4529 129694 : }
4530 :
4531 79810 : walk = NEXT_INSN (walk);
4532 : }
4533 :
4534 : /* Check which version is less expensive. */
4535 263944 : if (seq1 != NULL_RTX && (cost1 <= cost2 || seq2 == NULL_RTX))
4536 : {
4537 211445 : seq = seq1;
4538 211445 : temp_dest = temp_dest1;
4539 211445 : if (!second_try)
4540 106545 : *last_needs_comparison = count;
4541 : }
4542 1124 : else if (seq2 != NULL_RTX)
4543 : {
4544 51595 : seq = seq2;
4545 51595 : temp_dest = temp_dest2;
4546 51595 : if (!second_try && read_comparison)
4547 8750 : *last_needs_comparison = count;
4548 51595 : *use_cond_earliest = true;
4549 : }
4550 : else
4551 : {
4552 : /* Nothing worked, bail out. */
4553 904 : end_sequence ();
4554 1057 : return false;
4555 : }
4556 :
4557 : /* Although we use temporaries if there is register overlap of COND and
4558 : TARGET, it is possible that SEQ modifies COND anyway. For example,
4559 : COND may use the flags register and if INSN clobbers flags then
4560 : we may be unable to emit a valid sequence (e.g. in x86 that would
4561 : require saving and restoring the flags register). */
4562 158140 : if (!second_try)
4563 415962 : for (rtx_insn *iter = seq; iter; iter = NEXT_INSN (iter))
4564 283757 : if (modified_in_p (cond, iter))
4565 : {
4566 153 : end_sequence ();
4567 153 : return false;
4568 : }
4569 :
4570 : /* If SEQ clobbers registers mentioned in cc_cmp/rev_cc_cmp we have to
4571 : fall back on SEQ1 from that point on. Only check when we use SEQ1,
4572 : since SEQ2 has been tested already. */
4573 262887 : if (cc_cmp && seq == seq1
4574 262887 : && noce_seq_clobbers_cc_cmp_p (seq, cc_cmp, rev_cc_cmp))
4575 : {
4576 : cc_cmp = NULL_RTX;
4577 : rev_cc_cmp = NULL_RTX;
4578 : }
4579 :
4580 : /* End the sub sequence and emit to the main sequence. */
4581 262887 : emit_insn (seq);
4582 :
4583 : /* Bookkeeping. */
4584 262887 : info->temporary = temp_dest;
4585 : }
4586 :
4587 : /* Even if we did not actually need the comparison, we want to make sure
4588 : to try a second time in order to get rid of the temporaries. */
4589 95560 : if (*last_needs_comparison == -1)
4590 965 : *last_needs_comparison = 0;
4591 :
4592 : return true;
4593 : }
4594 :
4595 : /* Fill INSN_INFO with one entry per active insn in BB. Find local swap-style
4596 : idioms and mark the first insn (1) that is only a temporary as not needing
4597 : a conditional move, as it is going to be dead afterwards anyway.
4598 :
4599 : (1) int tmp = a;
4600 : a = b;
4601 : b = tmp;
4602 :
4603 : ifcvt
4604 : -->
4605 :
4606 : tmp = a;
4607 : a = cond ? b : a_old;
4608 : b = cond ? tmp : b_old;
4609 :
4610 : Additionally, store the index of insns like (2) when a subsequent
4611 : SET reads from their destination.
4612 :
4613 : (2) int c = a;
4614 : int d = c;
4615 :
4616 : ifcvt
4617 : -->
4618 :
4619 : c = cond ? a : c_old;
4620 : d = cond ? d : c; // Need to use c rather than c_old here. */
4621 :
4622 : static void
4623 73538 : init_noce_multiple_sets_info (basic_block bb,
4624 : auto_delete_vec<noce_multiple_sets_info> &insn_info)
4625 : {
4626 73538 : rtx_insn *insn;
4627 73538 : int count = 0;
4628 73538 : auto_vec<rtx> dests;
4629 73538 : bitmap bb_live_out = df_get_live_out (bb);
4630 :
4631 : /* Iterate over all SETs, storing the destinations in DEST.
4632 : - If we encounter a previously changed register,
4633 : rewire the read to the original source.
4634 : - If we encounter a SET that writes to a destination
4635 : that is not live after this block then the register
4636 : does not need to be moved conditionally. */
4637 494767 : FOR_BB_INSNS (bb, insn)
4638 : {
4639 421229 : if (!active_insn_p (insn))
4640 246965 : continue;
4641 :
4642 174264 : noce_multiple_sets_info *info = new noce_multiple_sets_info;
4643 174264 : info->temporary = NULL_RTX;
4644 174264 : insn_info.safe_push (info);
4645 :
4646 174264 : rtx set = single_set (insn);
4647 174264 : gcc_checking_assert (set);
4648 :
4649 174264 : rtx src = SET_SRC (set);
4650 174264 : rtx dest = SET_DEST (set);
4651 :
4652 174264 : gcc_checking_assert (REG_P (dest) && !HARD_REGISTER_P (dest));
4653 174264 : info->target = dest;
4654 174264 : info->unmodified_insn = insn;
4655 174264 : info->need_cmov = bitmap_bit_p (bb_live_out, REGNO (dest));
4656 :
4657 : /* Check if the current SET's source mentions any previously seen
4658 : destination. Keep only the newest definition of each pseudo register.
4659 : This is quadratic but the number of insns in BB
4660 : is bounded by PARAM_MAX_RTL_IF_CONVERSION_INSNS. */
4661 174264 : auto_bitmap rewired_regs;
4662 343306 : for (int i = count - 1; i >= 0; --i)
4663 169042 : if (reg_mentioned_p (dests[i], src)
4664 169042 : && bitmap_set_bit (rewired_regs, REGNO (dests[i])))
4665 33709 : insn_info[count]->rewired_src.safe_push (i);
4666 :
4667 174264 : dests.safe_push (dest);
4668 174264 : count++;
4669 174264 : }
4670 73538 : }
4671 :
4672 : /* Return true iff basic block TEST_BB is suitable for conversion to a
4673 : series of conditional moves. Unless REQUIRE_MULTIPLE is false, also check
4674 : that we have more than one set (other routines can handle a single set
4675 : better than we would). A diamond arm may have a single set.
4676 : Require no more than PARAM_MAX_RTL_IF_CONVERSION_INSNS sets. While going
4677 : through the insns, store the sum of their potential costs in COST. On
4678 : success, if LIVE_OUT_DESTS is nonnull, record the distinct pseudo
4679 : destinations that are live out of
4680 : TEST_BB. If HAS_NON_SIMPLE_SRC is nonnull, set it when an instruction
4681 : source is neither a constant nor a register operand. On success, if
4682 : INSN_COUNT is nonnull, store the number of active sets in it. */
4683 :
4684 : static bool
4685 2047172 : bb_ok_for_noce_convert_multiple_sets (basic_block test_bb, unsigned *cost,
4686 : bool require_multiple = true,
4687 : bitmap live_out_dests = NULL,
4688 : bool *has_non_simple_src = NULL,
4689 : unsigned *insn_count = NULL)
4690 : {
4691 2047172 : rtx_insn *insn;
4692 2047172 : unsigned count = 0;
4693 2047172 : unsigned param = param_max_rtl_if_conversion_insns;
4694 2047172 : bool speed_p = optimize_bb_for_speed_p (test_bb);
4695 2047172 : unsigned potential_cost = 0;
4696 2047172 : if (live_out_dests)
4697 959734 : bitmap_clear (live_out_dests);
4698 2047172 : if (has_non_simple_src)
4699 959734 : *has_non_simple_src = false;
4700 2047172 : bitmap bb_live_out = NULL;
4701 2047172 : if (live_out_dests)
4702 959734 : bb_live_out = df_get_live_out (test_bb);
4703 :
4704 12474158 : FOR_BB_INSNS (test_bb, insn)
4705 : {
4706 : /* Skip over notes etc. */
4707 12104911 : if (!active_insn_p (insn))
4708 9485955 : continue;
4709 :
4710 : /* We only handle SET insns. */
4711 2618956 : rtx set = single_set (insn);
4712 2618956 : if (set == NULL_RTX)
4713 : return false;
4714 :
4715 2543207 : rtx dest = SET_DEST (set);
4716 2543207 : rtx src = SET_SRC (set);
4717 :
4718 2543207 : if (has_non_simple_src && !noce_simple_cmove_operand_p (src))
4719 594844 : *has_non_simple_src = true;
4720 :
4721 : /* Dependency rewiring is keyed by register number, so restrict
4722 : destinations to pseudos. Hard-register definitions can overlap
4723 : without having the same mode. Do not handle anything involving
4724 : memory loads/stores since it might violate data-race-freedom
4725 : guarantees. Make sure we can force SRC to a register as that may
4726 : be needed in try_emit_cmove_seq. */
4727 2118906 : if (!REG_P (dest) || HARD_REGISTER_P (dest)
4728 1682499 : || contains_mem_rtx_p (src)
4729 3555695 : || !noce_can_force_operand (src))
4730 : return false;
4731 :
4732 : /* Destination and source must be appropriate. */
4733 993315 : if (!noce_operand_ok (dest) || !noce_operand_ok (src))
4734 : return false;
4735 :
4736 : /* We must be able to conditionally move in this mode. */
4737 970543 : if (!can_conditionally_move_p (GET_MODE (dest)))
4738 : return false;
4739 :
4740 941031 : if (bb_live_out && bitmap_bit_p (bb_live_out, REGNO (dest)))
4741 403669 : bitmap_set_bit (live_out_dests, REGNO (dest));
4742 :
4743 941031 : potential_cost += insn_cost (insn, speed_p);
4744 :
4745 941031 : count++;
4746 : }
4747 :
4748 369247 : *cost += potential_cost;
4749 :
4750 : /* If we would only put out one conditional move, the other strategies
4751 : this pass tries are better optimized and will be more appropriate, so
4752 : require more than one set unless REQUIRE_MULTIPLE is false. A diamond
4753 : arm may have one set.
4754 : Some targets want to strictly limit the number of conditional moves
4755 : that are emitted, they set this through PARAM, we need to respect
4756 : that. */
4757 623647 : bool ok = count >= (require_multiple ? 2u : 1u) && count <= param;
4758 369247 : if (ok && insn_count)
4759 252706 : *insn_count = count;
4760 : return ok;
4761 : }
4762 :
4763 : /* Compute average of two given costs weighted by relative probabilities
4764 : of respective basic blocks in an IF-THEN-ELSE. E is the IF-THEN edge.
4765 : With P as the probability to take the IF-THEN branch, return
4766 : P * THEN_COST + (1 - P) * ELSE_COST. Evaluate this as
4767 : ELSE_COST + P * (THEN_COST - ELSE_COST) when THEN_COST >= ELSE_COST, and
4768 : THEN_COST + (1 - P) * (ELSE_COST - THEN_COST) otherwise. Both forms pass
4769 : a nonnegative value to profile_probability::apply and make its rounding
4770 : independent of the CFG arm order. */
4771 : static unsigned
4772 277189 : average_cost (unsigned then_cost, unsigned else_cost, edge e)
4773 : {
4774 277189 : if (then_cost < else_cost)
4775 9997 : return then_cost
4776 9997 : + e->probability.invert ().apply ((gcov_type) else_cost - then_cost);
4777 :
4778 267192 : return else_cost
4779 267192 : + e->probability.apply ((gcov_type) then_cost - else_cost);
4780 : }
4781 :
4782 : /* Return the estimated cost of the original, un-converted if-region described
4783 : by IF_INFO whose THEN and ELSE arms cost THEN_COST and ELSE_COST. BASE_COST
4784 : already accounts for the branch, and any compare, that the conversion
4785 : removes. When optimizing for speed (SPEED_P) only one arm runs, so charge
4786 : the branch-probability-weighted average of the two. When optimizing for
4787 : size both arms are emitted, so sum them. */
4788 :
4789 : static unsigned
4790 320916 : noce_original_region_cost (const noce_if_info *if_info, bool speed_p,
4791 : unsigned base_cost, unsigned then_cost,
4792 : unsigned else_cost)
4793 : {
4794 320916 : if (speed_p)
4795 277189 : return base_cost + average_cost (then_cost, else_cost,
4796 277189 : find_edge (if_info->test_bb,
4797 554378 : if_info->then_bb));
4798 43727 : return base_cost + then_cost + else_cost;
4799 : }
4800 :
4801 : /* Given a simple IF-THEN-JOIN or IF-THEN-ELSE-JOIN block, attempt to convert
4802 : it without using conditional execution. Return TRUE if we were successful
4803 : at converting the block. */
4804 :
4805 : static bool
4806 1910998 : noce_process_if_block (noce_if_info *if_info)
4807 : {
4808 1910998 : basic_block test_bb = if_info->test_bb; /* test block */
4809 1910998 : basic_block then_bb = if_info->then_bb; /* THEN */
4810 1910998 : basic_block else_bb = if_info->else_bb; /* ELSE or NULL */
4811 1910998 : rtx_insn *jump = if_info->jump;
4812 1910998 : rtx cond = if_info->cond;
4813 1910998 : rtx_insn *insn_a, *insn_b;
4814 1910998 : rtx set_a, set_b;
4815 1910998 : rtx orig_x, x, a, b;
4816 :
4817 : /* We're looking for patterns of the form
4818 :
4819 : (1) if (...) x = a; else x = b;
4820 : (2) x = b; if (...) x = a;
4821 : (3) if (...) x = a; // as if with an initial x = x.
4822 : (4) if (...) { x = a; y = b; z = c; } // Like 3, for multiple SETS.
4823 : (5) A multi-set IF-THEN-ELSE-JOIN.
4824 : The later patterns require jumps to be more expensive.
4825 : For the diamond case, defer diamonds with only register and constant
4826 : assignments in both arms to the existing simple conditional-move
4827 : handling. Require at least two distinct live-out pseudos across the
4828 : arms.
4829 : ??? For future expansion, further expand the "multiple X" rules. */
4830 :
4831 : /* The base cost recorded so far covers the branch, and any compare, that
4832 : if-conversion removes. Each candidate path below derives its estimate
4833 : from this base plus the cost of the arms it folds in. If a target
4834 : re-uses the existing CC comparison, noce_convert_multiple_sets accounts
4835 : for that against the base before it calls
4836 : noce_conversion_profitable_p. */
4837 1910998 : unsigned base_cost = if_info->original_cost;
4838 1910998 : bool speed_p = optimize_bb_for_speed_p (test_bb);
4839 :
4840 1910998 : unsigned ms_then_cost = 0, ms_else_cost = 0;
4841 1910998 : unsigned ms_then_insn_count = 0, ms_else_insn_count = 0;
4842 1910998 : bool ms_then_has_non_simple_src, ms_else_has_non_simple_src;
4843 1910998 : auto_bitmap ms_then_live_out_dests, ms_else_live_out_dests;
4844 1910998 : noce_if_info ms_if_info = *if_info;
4845 1910998 : bool multiple_sets_p = false;
4846 :
4847 1910998 : if (HAVE_conditional_move)
4848 : {
4849 1910998 : if (!else_bb)
4850 1087438 : multiple_sets_p
4851 1087438 : = bb_ok_for_noce_convert_multiple_sets (then_bb, &ms_then_cost);
4852 823560 : else if (!if_info->then_else_reversed
4853 823560 : && bb_ok_for_noce_convert_multiple_sets
4854 823560 : (then_bb, &ms_then_cost, false,
4855 : ms_then_live_out_dests, &ms_then_has_non_simple_src,
4856 : &ms_then_insn_count)
4857 959734 : && bb_ok_for_noce_convert_multiple_sets
4858 136174 : (else_bb, &ms_else_cost, false,
4859 : ms_else_live_out_dests, &ms_else_has_non_simple_src,
4860 : &ms_else_insn_count))
4861 : {
4862 116532 : auto_bitmap ms_live_out_dests;
4863 116532 : bitmap_ior (ms_live_out_dests, ms_then_live_out_dests,
4864 116532 : ms_else_live_out_dests);
4865 116532 : unsigned output_count = bitmap_count_bits (ms_live_out_dests);
4866 :
4867 116532 : if (output_count >= 2
4868 50151 : && output_count <= (unsigned) param_max_rtl_if_conversion_insns
4869 50149 : && (ms_then_has_non_simple_src || ms_else_has_non_simple_src))
4870 116532 : multiple_sets_p = true;
4871 116532 : }
4872 : }
4873 :
4874 : /* The diamond conversion evaluates the else arm unconditionally.
4875 : Honor the target limit on the number of instructions made
4876 : unconditional. */
4877 1203970 : if (multiple_sets_p
4878 53625 : && ms_if_info.else_bb
4879 1229945 : && ms_else_insn_count > (unsigned) MAX_CONDITIONAL_EXECUTE)
4880 : multiple_sets_p = false;
4881 :
4882 1907967 : if (multiple_sets_p)
4883 : {
4884 : /* The original code runs the comparison and one arm. Estimate that cost
4885 : and let noce_convert_multiple_sets convert only if the conditional
4886 : moves come out cheaper. */
4887 50594 : ms_if_info.original_cost
4888 101188 : = ms_if_info.else_bb
4889 50594 : ? noce_original_region_cost (&ms_if_info, speed_p, base_cost,
4890 : ms_then_cost, ms_else_cost)
4891 27650 : : base_cost + ms_then_cost;
4892 50594 : if (noce_convert_multiple_sets (&ms_if_info))
4893 : {
4894 33114 : if (dump_file && ms_if_info.transform_name)
4895 2 : fprintf (dump_file, "if-conversion succeeded through %s\n",
4896 : ms_if_info.transform_name);
4897 : return true;
4898 : }
4899 : }
4900 :
4901 1877884 : unsigned int then_cost = 0, else_cost = 0;
4902 1877884 : if (!bb_valid_for_noce_process_p (then_bb, cond, &then_cost,
4903 : &if_info->then_simple))
4904 : return false;
4905 :
4906 480971 : if (else_bb
4907 480971 : && !bb_valid_for_noce_process_p (else_bb, cond, &else_cost,
4908 : &if_info->else_simple))
4909 : return false;
4910 :
4911 297972 : if_info->original_cost
4912 297972 : = noce_original_region_cost (if_info, speed_p, base_cost, then_cost,
4913 : else_cost);
4914 :
4915 297972 : insn_a = last_active_insn (then_bb, false);
4916 297972 : set_a = single_set (insn_a);
4917 297972 : gcc_assert (set_a);
4918 :
4919 297972 : x = SET_DEST (set_a);
4920 297972 : a = SET_SRC (set_a);
4921 :
4922 : /* Look for the other potential set. Make sure we've got equivalent
4923 : destinations. */
4924 : /* ??? This is overconservative. Storing to two different mems is
4925 : as easy as conditionally computing the address. Storing to a
4926 : single mem merely requires a scratch memory to use as one of the
4927 : destination addresses; often the memory immediately below the
4928 : stack pointer is available for this. */
4929 297972 : set_b = NULL_RTX;
4930 297972 : if (else_bb)
4931 : {
4932 98648 : insn_b = last_active_insn (else_bb, false);
4933 98648 : set_b = single_set (insn_b);
4934 98648 : gcc_assert (set_b);
4935 :
4936 98648 : if (!rtx_interchangeable_p (x, SET_DEST (set_b)))
4937 : return false;
4938 : }
4939 : else
4940 : {
4941 199324 : insn_b = if_info->cond_earliest;
4942 539415 : do
4943 539415 : insn_b = prev_nonnote_nondebug_insn (insn_b);
4944 : while (insn_b
4945 536707 : && (BLOCK_FOR_INSN (insn_b)
4946 536707 : == BLOCK_FOR_INSN (if_info->cond_earliest))
4947 1189991 : && !modified_in_p (x, insn_b));
4948 :
4949 : /* We're going to be moving the evaluation of B down from above
4950 : COND_EARLIEST to JUMP. Make sure the relevant data is still
4951 : intact. */
4952 199324 : if (! insn_b
4953 196616 : || BLOCK_FOR_INSN (insn_b) != BLOCK_FOR_INSN (if_info->cond_earliest)
4954 111161 : || !NONJUMP_INSN_P (insn_b)
4955 105437 : || (set_b = single_set (insn_b)) == NULL_RTX
4956 103941 : || ! rtx_interchangeable_p (x, SET_DEST (set_b))
4957 89392 : || ! noce_operand_ok (SET_SRC (set_b))
4958 87421 : || reg_overlap_mentioned_p (x, SET_SRC (set_b))
4959 85964 : || modified_between_p (SET_SRC (set_b), insn_b, jump)
4960 : /* Avoid extending the lifetime of hard registers on small
4961 : register class machines. */
4962 83743 : || (REG_P (SET_SRC (set_b))
4963 20673 : && HARD_REGISTER_P (SET_SRC (set_b))
4964 3671 : && targetm.small_register_classes_for_mode_p
4965 3671 : (GET_MODE (SET_SRC (set_b))))
4966 : /* Likewise with X. In particular this can happen when
4967 : noce_get_condition looks farther back in the instruction
4968 : stream than one might expect. */
4969 80072 : || reg_overlap_mentioned_p (x, cond)
4970 66438 : || reg_overlap_mentioned_p (x, a)
4971 259798 : || modified_between_p (x, insn_b, jump))
4972 : {
4973 : insn_b = NULL;
4974 : set_b = NULL_RTX;
4975 : }
4976 : }
4977 :
4978 : /* If x has side effects then only the if-then-else form is safe to
4979 : convert. But even in that case we would need to restore any notes
4980 : (such as REG_INC) at then end. That can be tricky if
4981 : noce_emit_move_insn expands to more than one insn, so disable the
4982 : optimization entirely for now if there are side effects. */
4983 292535 : if (side_effects_p (x))
4984 : return false;
4985 :
4986 292535 : b = (set_b ? SET_SRC (set_b) : x);
4987 :
4988 : /* Only operate on register destinations, and even then avoid extending
4989 : the lifetime of hard registers on small register class machines. */
4990 292535 : orig_x = x;
4991 292535 : if_info->orig_x = orig_x;
4992 292535 : if (!REG_P (x)
4993 292535 : || (HARD_REGISTER_P (x)
4994 2 : && targetm.small_register_classes_for_mode_p (GET_MODE (x))))
4995 : {
4996 68124 : if (GET_MODE (x) == BLKmode)
4997 : return false;
4998 :
4999 67882 : if (GET_CODE (x) == ZERO_EXTRACT
5000 1 : && (!CONST_INT_P (XEXP (x, 1))
5001 1 : || !CONST_INT_P (XEXP (x, 2))))
5002 : return false;
5003 :
5004 67882 : x = gen_reg_rtx (GET_MODE (GET_CODE (x) == STRICT_LOW_PART
5005 : ? XEXP (x, 0) : x));
5006 : }
5007 :
5008 : /* Don't operate on sources that may trap or are volatile. */
5009 292293 : if (! noce_operand_ok (a) || ! noce_operand_ok (b))
5010 : return false;
5011 :
5012 319302 : retry:
5013 : /* Set up the info block for our subroutines. */
5014 319302 : if_info->insn_a = insn_a;
5015 319302 : if_info->insn_b = insn_b;
5016 319302 : if_info->x = x;
5017 319302 : if_info->a = a;
5018 319302 : if_info->b = b;
5019 :
5020 : /* Try optimizations in some approximation of a useful order. */
5021 : /* ??? Should first look to see if X is live incoming at all. If it
5022 : isn't, we don't need anything but an unconditional set. */
5023 :
5024 : /* Look and see if A and B are really the same. Avoid creating silly
5025 : cmove constructs that no one will fix up later. */
5026 319302 : if (noce_simple_bbs (if_info)
5027 296991 : && rtx_interchangeable_p (a, b))
5028 : {
5029 : /* If we have an INSN_B, we don't have to create any new rtl. Just
5030 : move the instruction that we already have. If we don't have an
5031 : INSN_B, that means that A == X, and we've got a noop move. In
5032 : that case don't do anything and let the code below delete INSN_A. */
5033 381 : if (insn_b && else_bb)
5034 : {
5035 372 : rtx note;
5036 :
5037 372 : if (insn_b == BB_END (else_bb))
5038 261 : BB_END (else_bb) = PREV_INSN (insn_b);
5039 372 : reorder_insns (insn_b, insn_b, PREV_INSN (jump));
5040 :
5041 : /* If there was a REG_EQUAL note, delete it since it may have been
5042 : true due to this insn being after a jump. */
5043 372 : if ((note = find_reg_note (insn_b, REG_EQUAL, NULL_RTX)) != 0)
5044 0 : remove_note (insn_b, note);
5045 :
5046 381 : insn_b = NULL;
5047 : }
5048 : /* If we have "x = b; if (...) x = a;", and x has side-effects, then
5049 : x must be executed twice. */
5050 9 : else if (insn_b && side_effects_p (orig_x))
5051 : return false;
5052 :
5053 381 : x = orig_x;
5054 381 : goto success;
5055 : }
5056 :
5057 318921 : if (!set_b && MEM_P (orig_x))
5058 : /* We want to avoid store speculation to avoid cases like
5059 : if (pthread_mutex_trylock(mutex))
5060 : ++global_variable;
5061 : Rather than go to much effort here, we rely on the SSA optimizers,
5062 : which do a good enough job these days. */
5063 : return false;
5064 :
5065 252720 : if (noce_try_move (if_info))
5066 0 : goto success;
5067 252720 : if (noce_try_ifelse_collapse (if_info))
5068 17798 : goto success;
5069 234922 : if (noce_try_store_flag (if_info))
5070 26001 : goto success;
5071 208921 : if (noce_try_bitop (if_info))
5072 0 : goto success;
5073 208921 : if (noce_try_minmax (if_info))
5074 60 : goto success;
5075 208861 : if (noce_try_abs (if_info))
5076 24 : goto success;
5077 208837 : if (noce_try_inverse_constants (if_info))
5078 0 : goto success;
5079 208837 : if (!targetm.have_conditional_execution ()
5080 208837 : && noce_try_store_flag_constants (if_info))
5081 3161 : goto success;
5082 205676 : if (!targetm.have_conditional_execution ()
5083 205676 : && noce_try_shifted_store_flag (if_info))
5084 5401 : goto success;
5085 200275 : if (noce_try_sign_bit_splat (if_info))
5086 178 : goto success;
5087 200097 : if (!targetm.have_conditional_execution ()
5088 200097 : && noce_try_store_flag_logical (if_info))
5089 0 : goto success;
5090 200097 : if (HAVE_conditional_move
5091 200097 : && noce_try_cmove (if_info))
5092 42588 : goto success;
5093 157509 : if (! targetm.have_conditional_execution ())
5094 : {
5095 157509 : if (noce_try_addcc (if_info))
5096 903 : goto success;
5097 156606 : if (noce_try_store_flag_mask (if_info))
5098 9 : goto success;
5099 156597 : if (HAVE_conditional_move
5100 156597 : && noce_try_cond_arith (if_info))
5101 10182 : goto success;
5102 146415 : if (HAVE_conditional_move
5103 146415 : && noce_try_cmove_arith (if_info))
5104 34943 : goto success;
5105 111472 : if (noce_try_sign_mask (if_info))
5106 0 : goto success;
5107 : }
5108 :
5109 111472 : if (!else_bb && set_b)
5110 : {
5111 27009 : insn_b = NULL;
5112 27009 : set_b = NULL_RTX;
5113 27009 : b = orig_x;
5114 27009 : goto retry;
5115 : }
5116 :
5117 : return false;
5118 :
5119 141629 : success:
5120 141629 : if (dump_file && if_info->transform_name)
5121 7 : fprintf (dump_file, "if-conversion succeeded through %s\n",
5122 : if_info->transform_name);
5123 :
5124 : /* If we used a temporary, fix it up now. */
5125 141629 : if (orig_x != x)
5126 : {
5127 675 : rtx_insn *seq;
5128 :
5129 675 : start_sequence ();
5130 675 : noce_emit_move_insn (orig_x, x);
5131 675 : seq = get_insns ();
5132 675 : set_used_flags (orig_x);
5133 675 : unshare_all_rtl_in_chain (seq);
5134 675 : end_sequence ();
5135 :
5136 675 : emit_insn_before_setloc (seq, BB_END (test_bb), INSN_LOCATION (insn_a));
5137 : }
5138 :
5139 : /* The original THEN and ELSE blocks may now be removed and the test block
5140 : redirected to the join block. */
5141 141629 : noce_finish_if_conversion (if_info);
5142 :
5143 141629 : return true;
5144 1910998 : }
5145 :
5146 : /* Check whether a block is suitable for conditional move conversion.
5147 : Every insn must be a simple set of a register to a constant or a
5148 : register. For each assignment, store the value in the pointer map
5149 : VALS, keyed by register pointer, then store the register pointer in
5150 : REGS. COND is the condition we will test. */
5151 :
5152 : static bool
5153 1766024 : check_cond_move_block (basic_block bb,
5154 : hash_map<rtx, rtx> *vals,
5155 : vec<rtx> *regs,
5156 : rtx cond)
5157 : {
5158 1766024 : rtx_insn *insn;
5159 1766024 : rtx cc = cc_in_cond (cond);
5160 :
5161 : /* We can only handle simple jumps at the end of the basic block.
5162 : It is almost impossible to update the CFG otherwise. */
5163 1766024 : insn = BB_END (bb);
5164 1766024 : if (JUMP_P (insn) && !onlyjump_p (insn))
5165 : return false;
5166 :
5167 10511451 : FOR_BB_INSNS (bb, insn)
5168 : {
5169 10449542 : rtx set, dest, src;
5170 :
5171 10449542 : if (!NONDEBUG_INSN_P (insn) || JUMP_P (insn))
5172 8611265 : continue;
5173 1838277 : set = single_set (insn);
5174 1838277 : if (!set)
5175 1704062 : return false;
5176 :
5177 1764595 : dest = SET_DEST (set);
5178 1764595 : src = SET_SRC (set);
5179 1764595 : if (!REG_P (dest)
5180 1764595 : || (HARD_REGISTER_P (dest)
5181 313353 : && targetm.small_register_classes_for_mode_p (GET_MODE (dest))))
5182 : return false;
5183 :
5184 1062375 : if (!noce_simple_cmove_operand_p (src))
5185 : return false;
5186 :
5187 156635 : if (side_effects_p (src) || side_effects_p (dest))
5188 : return false;
5189 :
5190 156635 : if (may_trap_p (src) || may_trap_p (dest))
5191 : return false;
5192 :
5193 : /* Don't try to handle this if the source register was
5194 : modified earlier in the block. */
5195 156635 : if ((REG_P (src)
5196 51402 : && vals->get (src))
5197 207776 : || (GET_CODE (src) == SUBREG && REG_P (SUBREG_REG (src))
5198 5259 : && vals->get (SUBREG_REG (src))))
5199 : return false;
5200 :
5201 : /* Don't try to handle this if the destination register was
5202 : modified earlier in the block. */
5203 156320 : if (vals->get (dest))
5204 : return false;
5205 :
5206 : /* Don't try to handle this if the condition uses the
5207 : destination register. */
5208 156320 : if (reg_overlap_mentioned_p (dest, cond))
5209 : return false;
5210 :
5211 : /* Don't try to handle this if the source register is modified
5212 : later in the block. */
5213 137439 : if (!CONSTANT_P (src)
5214 137439 : && modified_between_p (src, insn, NEXT_INSN (BB_END (bb))))
5215 : return false;
5216 :
5217 : /* Skip it if the instruction to be moved might clobber CC. */
5218 134215 : if (cc && set_of (cc, insn))
5219 : return false;
5220 :
5221 134215 : vals->put (dest, src);
5222 :
5223 134215 : regs->safe_push (dest);
5224 : }
5225 :
5226 : return true;
5227 : }
5228 :
5229 : /* Given a basic block BB suitable for conditional move conversion,
5230 : a condition COND, and pointer maps THEN_VALS and ELSE_VALS containing
5231 : the register values depending on COND, emit the insns in the block as
5232 : conditional moves. If ELSE_BLOCK is true, THEN_BB was already
5233 : processed. The caller has started a sequence for the conversion.
5234 : Return true if successful, false if something goes wrong. */
5235 :
5236 : static bool
5237 36785 : cond_move_convert_if_block (noce_if_info *if_infop,
5238 : basic_block bb, rtx cond,
5239 : hash_map<rtx, rtx> *then_vals,
5240 : hash_map<rtx, rtx> *else_vals,
5241 : bool else_block_p)
5242 : {
5243 36785 : enum rtx_code code;
5244 36785 : rtx_insn *insn;
5245 36785 : rtx cond_arg0, cond_arg1;
5246 :
5247 36785 : code = GET_CODE (cond);
5248 36785 : cond_arg0 = XEXP (cond, 0);
5249 36785 : cond_arg1 = XEXP (cond, 1);
5250 :
5251 126752 : FOR_BB_INSNS (bb, insn)
5252 : {
5253 104335 : rtx set, target, dest, t, e;
5254 :
5255 : /* ??? Maybe emit conditional debug insn? */
5256 104335 : if (!NONDEBUG_INSN_P (insn) || JUMP_P (insn))
5257 69046 : continue;
5258 46417 : set = single_set (insn);
5259 46417 : gcc_assert (set && REG_P (SET_DEST (set)));
5260 :
5261 46417 : dest = SET_DEST (set);
5262 :
5263 46417 : rtx *then_slot = then_vals->get (dest);
5264 46417 : rtx *else_slot = else_vals->get (dest);
5265 46417 : t = then_slot ? *then_slot : NULL_RTX;
5266 46417 : e = else_slot ? *else_slot : NULL_RTX;
5267 :
5268 46417 : if (else_block_p)
5269 : {
5270 : /* If this register was set in the then block, we already
5271 : handled this case there. */
5272 12400 : if (t)
5273 11128 : continue;
5274 1272 : t = dest;
5275 1272 : gcc_assert (e);
5276 : }
5277 : else
5278 : {
5279 34017 : gcc_assert (t);
5280 34017 : if (!e)
5281 22191 : e = dest;
5282 : }
5283 :
5284 35289 : if (if_infop->cond_inverted)
5285 0 : std::swap (t, e);
5286 :
5287 35289 : target = noce_emit_cmove (if_infop, dest, code, cond_arg0, cond_arg1,
5288 : t, e);
5289 35289 : if (!target)
5290 14368 : return false;
5291 :
5292 20921 : if (target != dest)
5293 0 : noce_emit_move_insn (dest, target);
5294 : }
5295 :
5296 : return true;
5297 : }
5298 :
5299 : /* Given a simple IF-THEN-JOIN or IF-THEN-ELSE-JOIN block, attempt to convert
5300 : it using only conditional moves. Return TRUE if we were successful at
5301 : converting the block. */
5302 :
5303 : static bool
5304 1736255 : cond_move_process_if_block (noce_if_info *if_info)
5305 : {
5306 1736255 : basic_block then_bb = if_info->then_bb;
5307 1736255 : basic_block else_bb = if_info->else_bb;
5308 1736255 : rtx_insn *jump = if_info->jump;
5309 1736255 : rtx cond = if_info->cond;
5310 1736255 : rtx_insn *seq, *loc_insn;
5311 1736255 : int c;
5312 1736255 : auto_vec<rtx> then_regs;
5313 1736255 : auto_vec<rtx> else_regs;
5314 1736255 : int limit = param_max_rtl_if_conversion_insns;
5315 :
5316 : /* Build a mapping for each block to the value used for each
5317 : register. */
5318 1736255 : hash_map<rtx, rtx> then_vals;
5319 1736255 : hash_map<rtx, rtx> else_vals;
5320 :
5321 : /* Make sure the blocks are suitable. */
5322 1736255 : if (!check_cond_move_block (then_bb, &then_vals, &then_regs, cond)
5323 1736255 : || (else_bb
5324 29769 : && !check_cond_move_block (else_bb, &else_vals, &else_regs, cond)))
5325 : return false;
5326 :
5327 : /* Make sure the blocks can be used together. If the same register
5328 : is set in both blocks, and is not set to a constant in both
5329 : cases, then both blocks must set it to the same register. We
5330 : have already verified that if it is set to a register, that the
5331 : source register does not change after the assignment. Also count
5332 : the number of registers set in only one of the blocks. */
5333 32140 : c = 0;
5334 131179 : for (rtx reg : then_regs)
5335 : {
5336 38175 : rtx *then_slot = then_vals.get (reg);
5337 38175 : rtx *else_slot = else_vals.get (reg);
5338 :
5339 38175 : gcc_checking_assert (then_slot);
5340 38175 : if (!else_slot)
5341 22712 : ++c;
5342 : else
5343 : {
5344 15463 : rtx then_val = *then_slot;
5345 15463 : rtx else_val = *else_slot;
5346 4561 : if (!CONSTANT_P (then_val) && !CONSTANT_P (else_val)
5347 19340 : && !rtx_equal_p (then_val, else_val))
5348 3020 : return false;
5349 : }
5350 : }
5351 :
5352 : /* Finish off c for MAX_CONDITIONAL_EXECUTE. */
5353 59529 : for (rtx reg : else_regs)
5354 : {
5355 13673 : gcc_checking_assert (else_vals.get (reg));
5356 13673 : if (!then_vals.get (reg))
5357 1381 : ++c;
5358 : }
5359 :
5360 : /* Make sure it is reasonable to convert this block. What matters
5361 : is the number of assignments currently made in only one of the
5362 : branches, since if we convert we are going to always execute
5363 : them. */
5364 29120 : if (c > MAX_CONDITIONAL_EXECUTE
5365 29120 : || c > limit)
5366 : return false;
5367 :
5368 : /* Try to emit the conditional moves. First do the then block,
5369 : then do anything left in the else blocks. */
5370 29106 : start_sequence ();
5371 29106 : if (!cond_move_convert_if_block (if_info, then_bb, cond,
5372 : &then_vals, &else_vals, false)
5373 29106 : || (else_bb
5374 7679 : && !cond_move_convert_if_block (if_info, else_bb, cond,
5375 : &then_vals, &else_vals, true)))
5376 : {
5377 14368 : end_sequence ();
5378 14368 : return false;
5379 : }
5380 14738 : seq = end_ifcvt_sequence (if_info);
5381 14738 : if (!seq || !targetm.noce_conversion_profitable_p (seq, if_info))
5382 : return false;
5383 :
5384 3369 : loc_insn = first_active_insn (then_bb);
5385 3369 : if (!loc_insn)
5386 : {
5387 0 : loc_insn = first_active_insn (else_bb);
5388 0 : gcc_assert (loc_insn);
5389 : }
5390 3369 : emit_insn_before_setloc (seq, jump, INSN_LOCATION (loc_insn));
5391 :
5392 3369 : noce_finish_if_conversion (if_info);
5393 :
5394 3369 : return true;
5395 1736255 : }
5396 :
5397 :
5398 : /* Determine if a given basic block heads a simple IF-THEN-JOIN or an
5399 : IF-THEN-ELSE-JOIN block.
5400 :
5401 : If so, we'll try to convert the insns to not require the branch,
5402 : using only transformations that do not require conditional execution.
5403 :
5404 : Return TRUE if we were successful at converting the block. */
5405 :
5406 : static bool
5407 9935554 : noce_find_if_block (basic_block test_bb, edge then_edge, edge else_edge,
5408 : int pass)
5409 : {
5410 9935554 : basic_block then_bb, else_bb, join_bb;
5411 9935554 : bool then_else_reversed = false;
5412 9935554 : rtx_insn *jump;
5413 9935554 : rtx_insn *cond_earliest;
5414 9935554 : noce_if_info if_info = {};
5415 9935554 : bool speed_p = optimize_bb_for_speed_p (test_bb);
5416 :
5417 : /* We only ever should get here before reload. */
5418 9935554 : gcc_assert (!reload_completed);
5419 :
5420 : /* Recognize an IF-THEN-ELSE-JOIN block. */
5421 9935554 : if (single_pred_p (then_edge->dest)
5422 12605501 : && single_succ_p (then_edge->dest)
5423 3559397 : && single_pred_p (else_edge->dest)
5424 1854831 : && single_succ_p (else_edge->dest)
5425 11100750 : && single_succ (then_edge->dest) == single_succ (else_edge->dest))
5426 : {
5427 : then_bb = then_edge->dest;
5428 : else_bb = else_edge->dest;
5429 : join_bb = single_succ (then_bb);
5430 : }
5431 : /* Recognize an IF-THEN-JOIN block. */
5432 17134437 : else if (single_pred_p (then_edge->dest)
5433 7273442 : && single_succ_p (then_edge->dest)
5434 11716051 : && single_succ (then_edge->dest) == else_edge->dest)
5435 : {
5436 : then_bb = then_edge->dest;
5437 : else_bb = NULL_BLOCK;
5438 : join_bb = else_edge->dest;
5439 : }
5440 : /* Recognize an IF-ELSE-JOIN block. We can have those because the order
5441 : of basic blocks in cfglayout mode does not matter, so the fallthrough
5442 : edge can go to any basic block (and not just to bb->next_bb, like in
5443 : cfgrtl mode). */
5444 8088333 : else if (single_pred_p (else_edge->dest)
5445 3858092 : && single_succ_p (else_edge->dest)
5446 9497751 : && single_succ (else_edge->dest) == then_edge->dest)
5447 : {
5448 : /* The noce transformations do not apply to IF-ELSE-JOIN blocks.
5449 : To make this work, we have to invert the THEN and ELSE blocks
5450 : and reverse the jump condition. */
5451 : then_bb = else_edge->dest;
5452 : else_bb = NULL_BLOCK;
5453 : join_bb = single_succ (then_bb);
5454 : then_else_reversed = true;
5455 : }
5456 : else
5457 : /* Not a form we can handle. */
5458 : return false;
5459 :
5460 : /* The edges of the THEN and ELSE blocks cannot have complex edges. */
5461 1980603 : if (single_succ_edge (then_bb)->flags & EDGE_COMPLEX)
5462 : return false;
5463 1925111 : if (else_bb
5464 1925111 : && single_succ_edge (else_bb)->flags & EDGE_COMPLEX)
5465 : return false;
5466 :
5467 1915103 : num_possible_if_blocks++;
5468 :
5469 1915103 : if (dump_file)
5470 : {
5471 93 : fprintf (dump_file,
5472 : "\nIF-THEN%s-JOIN block found, pass %d, test %d, then %d",
5473 : (else_bb) ? "-ELSE" : "",
5474 : pass, test_bb->index, then_bb->index);
5475 :
5476 56 : if (else_bb)
5477 19 : fprintf (dump_file, ", else %d", else_bb->index);
5478 :
5479 56 : fprintf (dump_file, ", join %d\n", join_bb->index);
5480 : }
5481 :
5482 : /* If the conditional jump is more than just a conditional
5483 : jump, then we cannot do if-conversion on this block. */
5484 1915103 : jump = BB_END (test_bb);
5485 1915103 : if (! onlyjump_p (jump))
5486 : return false;
5487 :
5488 : /* Initialize an IF_INFO struct to pass around. */
5489 1914842 : if_info.test_bb = test_bb;
5490 1914842 : if_info.then_bb = then_bb;
5491 1914842 : if_info.else_bb = else_bb;
5492 1914842 : if_info.join_bb = join_bb;
5493 1914842 : if_info.cond = noce_get_condition (jump, &cond_earliest,
5494 : then_else_reversed);
5495 1914842 : rtx_insn *rev_cond_earliest;
5496 1914842 : if_info.rev_cond = noce_get_condition (jump, &rev_cond_earliest,
5497 : !then_else_reversed);
5498 1914842 : if (!if_info.cond && !if_info.rev_cond)
5499 : return false;
5500 1910998 : if (!if_info.cond)
5501 : {
5502 0 : std::swap (if_info.cond, if_info.rev_cond);
5503 0 : std::swap (cond_earliest, rev_cond_earliest);
5504 0 : if_info.cond_inverted = true;
5505 : }
5506 : /* We must be comparing objects whose modes imply the size. */
5507 1910998 : if (GET_MODE (XEXP (if_info.cond, 0)) == BLKmode)
5508 : return false;
5509 1910998 : gcc_assert (if_info.rev_cond == NULL_RTX
5510 : || rev_cond_earliest == cond_earliest);
5511 1910998 : if_info.cond_earliest = cond_earliest;
5512 1910998 : if_info.jump = jump;
5513 1910998 : if_info.then_else_reversed = then_else_reversed;
5514 1910998 : if_info.speed_p = speed_p;
5515 1910998 : if_info.max_seq_cost
5516 1910998 : = targetm.max_noce_ifcvt_seq_cost (then_edge);
5517 : /* We'll add in the cost of THEN_BB and ELSE_BB later, when we check
5518 : that they are valid to transform. We can't easily get back to the insn
5519 : for COND (and it may not exist if we had to canonicalize to get COND).
5520 : It is assumed that the costs of a jump insn are dependent on the
5521 : branch costs. */
5522 1910998 : if_info.original_cost += insn_cost (if_info.jump, if_info.speed_p);
5523 :
5524 : /* Do the real work. */
5525 :
5526 : /* ??? noce_process_if_block has not yet been updated to handle
5527 : inverted conditions. */
5528 1910998 : if (!if_info.cond_inverted && noce_process_if_block (&if_info))
5529 : return true;
5530 :
5531 1736255 : if (HAVE_conditional_move
5532 1736255 : && cond_move_process_if_block (&if_info))
5533 : return true;
5534 :
5535 : return false;
5536 : }
5537 :
5538 :
5539 : /* Merge BB into COMBO_BB. BB has no successor edges left, so if COMBO_BB
5540 : still has another successor the BARRIER that follows BB is no longer needed
5541 : and it is in fact incorrect to leave it in the insn stream. */
5542 :
5543 : static void
5544 0 : merge_block_into_combo (basic_block combo_bb, basic_block bb)
5545 : {
5546 0 : if (EDGE_COUNT (bb->succs) == 0 && EDGE_COUNT (combo_bb->succs) > 1)
5547 : {
5548 0 : rtx_insn *end = NEXT_INSN (BB_END (bb));
5549 0 : while (end && NOTE_P (end) && !NOTE_INSN_BASIC_BLOCK_P (end))
5550 0 : end = NEXT_INSN (end);
5551 :
5552 0 : if (end && BARRIER_P (end))
5553 0 : delete_insn (end);
5554 : }
5555 :
5556 0 : merge_blocks (combo_bb, bb);
5557 0 : num_true_changes++;
5558 0 : }
5559 :
5560 : /* Merge the blocks and mark for local life update. */
5561 :
5562 : static void
5563 0 : merge_if_block (ce_if_block *ce_info)
5564 : {
5565 0 : basic_block test_bb = ce_info->test_bb; /* last test block */
5566 0 : basic_block then_bb = ce_info->then_bb; /* THEN */
5567 0 : basic_block else_bb = ce_info->else_bb; /* ELSE or NULL */
5568 0 : basic_block join_bb = ce_info->join_bb; /* join block */
5569 0 : basic_block combo_bb;
5570 :
5571 : /* All block merging is done into the lower block numbers. */
5572 :
5573 0 : combo_bb = test_bb;
5574 0 : df_set_bb_dirty (test_bb);
5575 :
5576 : /* Merge any basic blocks to handle && and || subtests. Each of
5577 : the blocks are on the fallthru path from the predecessor block. */
5578 0 : if (ce_info->num_multiple_test_blocks > 0)
5579 : {
5580 0 : basic_block bb = test_bb;
5581 0 : basic_block last_test_bb = ce_info->last_test_bb;
5582 0 : basic_block fallthru = block_fallthru (bb);
5583 :
5584 0 : do
5585 : {
5586 0 : bb = fallthru;
5587 0 : fallthru = block_fallthru (bb);
5588 0 : merge_blocks (combo_bb, bb);
5589 0 : num_true_changes++;
5590 : }
5591 0 : while (bb != last_test_bb);
5592 : }
5593 :
5594 : /* Merge TEST block into THEN block. Normally the THEN block won't have a
5595 : label, but it might if there were || tests. That label's count should be
5596 : zero, and it normally should be removed. */
5597 :
5598 0 : if (then_bb)
5599 0 : merge_block_into_combo (combo_bb, then_bb);
5600 :
5601 : /* The ELSE block, if it existed, had a label. That label count
5602 : will almost always be zero, but odd things can happen when labels
5603 : get their addresses taken. */
5604 0 : if (else_bb)
5605 0 : merge_block_into_combo (combo_bb, else_bb);
5606 :
5607 : /* If there was no join block reported, that means it was not adjacent
5608 : to the others, and so we cannot merge them. */
5609 :
5610 0 : if (! join_bb)
5611 : {
5612 0 : rtx_insn *last = BB_END (combo_bb);
5613 :
5614 : /* The outgoing edge for the current COMBO block should already
5615 : be correct. Verify this. */
5616 0 : if (EDGE_COUNT (combo_bb->succs) == 0)
5617 0 : gcc_assert (find_reg_note (last, REG_NORETURN, NULL)
5618 : || (NONJUMP_INSN_P (last)
5619 : && GET_CODE (PATTERN (last)) == TRAP_IF
5620 : && (TRAP_CONDITION (PATTERN (last))
5621 : == const_true_rtx)));
5622 :
5623 : else
5624 : /* There should still be something at the end of the THEN or ELSE
5625 : blocks taking us to our final destination. */
5626 0 : gcc_assert (JUMP_P (last)
5627 : || (EDGE_SUCC (combo_bb, 0)->dest
5628 : == EXIT_BLOCK_PTR_FOR_FN (cfun)
5629 : && CALL_P (last)
5630 : && SIBLING_CALL_P (last))
5631 : || ((EDGE_SUCC (combo_bb, 0)->flags & EDGE_EH)
5632 : && can_throw_internal (last)));
5633 : }
5634 :
5635 : /* The JOIN block may have had quite a number of other predecessors too.
5636 : Since we've already merged the TEST, THEN and ELSE blocks, we should
5637 : have only one remaining edge from our if-then-else diamond. If there
5638 : is more than one remaining edge, it must come from elsewhere. There
5639 : may be zero incoming edges if the THEN block didn't actually join
5640 : back up (as with a call to a non-return function). */
5641 0 : else if (EDGE_COUNT (join_bb->preds) < 2
5642 0 : && join_bb != EXIT_BLOCK_PTR_FOR_FN (cfun))
5643 : {
5644 : /* We can merge the JOIN cleanly and update the dataflow try
5645 : again on this pass.*/
5646 0 : merge_blocks (combo_bb, join_bb);
5647 0 : num_true_changes++;
5648 : }
5649 : else
5650 : {
5651 : /* We cannot merge the JOIN. */
5652 :
5653 : /* The outgoing edge for the current COMBO block should already
5654 : be correct. Verify this. */
5655 0 : gcc_assert (single_succ_p (combo_bb)
5656 : && single_succ (combo_bb) == join_bb);
5657 :
5658 : /* Remove the jump and cruft from the end of the COMBO block. */
5659 0 : if (join_bb != EXIT_BLOCK_PTR_FOR_FN (cfun))
5660 0 : tidy_fallthru_edge (single_succ_edge (combo_bb));
5661 : }
5662 :
5663 0 : num_updated_if_blocks++;
5664 0 : }
5665 :
5666 : /* Find a block ending in a simple IF condition and try to transform it
5667 : in some way. When converting a multi-block condition, put the new code
5668 : in the first such block and delete the rest. Return a pointer to this
5669 : first block if some transformation was done. Return NULL otherwise. */
5670 :
5671 : static basic_block
5672 39927116 : find_if_header (basic_block test_bb, int pass)
5673 : {
5674 39927116 : ce_if_block ce_info;
5675 39927116 : edge then_edge;
5676 39927116 : edge else_edge;
5677 :
5678 : /* The kind of block we're looking for has exactly two successors. */
5679 39927116 : if (EDGE_COUNT (test_bb->succs) != 2)
5680 : return NULL;
5681 :
5682 20561052 : then_edge = EDGE_SUCC (test_bb, 0);
5683 20561052 : else_edge = EDGE_SUCC (test_bb, 1);
5684 :
5685 20561052 : if (df_get_bb_dirty (then_edge->dest))
5686 : return NULL;
5687 20539274 : if (df_get_bb_dirty (else_edge->dest))
5688 : return NULL;
5689 :
5690 : /* Neither edge should be abnormal. */
5691 20503845 : if ((then_edge->flags & EDGE_COMPLEX)
5692 18744210 : || (else_edge->flags & EDGE_COMPLEX))
5693 : return NULL;
5694 :
5695 : /* Nor exit the loop. */
5696 18350465 : if ((then_edge->flags & EDGE_LOOP_EXIT)
5697 16871128 : || (else_edge->flags & EDGE_LOOP_EXIT))
5698 : return NULL;
5699 :
5700 : /* The THEN edge is canonically the one that falls through. */
5701 14587007 : if (then_edge->flags & EDGE_FALLTHRU)
5702 : ;
5703 7074430 : else if (else_edge->flags & EDGE_FALLTHRU)
5704 : std::swap (then_edge, else_edge);
5705 : else
5706 : /* Otherwise this must be a multiway branch of some sort. */
5707 : return NULL;
5708 :
5709 14586667 : memset (&ce_info, 0, sizeof (ce_info));
5710 14586667 : ce_info.test_bb = test_bb;
5711 14586667 : ce_info.then_bb = then_edge->dest;
5712 14586667 : ce_info.else_bb = else_edge->dest;
5713 14586667 : ce_info.pass = pass;
5714 :
5715 : #ifdef IFCVT_MACHDEP_INIT
5716 : IFCVT_MACHDEP_INIT (&ce_info);
5717 : #endif
5718 :
5719 14586667 : if (!reload_completed
5720 14586667 : && noce_find_if_block (test_bb, then_edge, else_edge, pass))
5721 178112 : goto success;
5722 :
5723 14408555 : if (reload_completed
5724 4651113 : && targetm.have_conditional_execution ()
5725 14408555 : && cond_exec_find_if_block (&ce_info))
5726 0 : goto success;
5727 :
5728 9757442 : if (!reload_completed && targetm.have_trap ()
5729 9757442 : && optab_handler (ctrap_optab, word_mode) != CODE_FOR_nothing
5730 14408555 : && find_cond_trap (test_bb, then_edge, else_edge))
5731 0 : goto success;
5732 :
5733 14408555 : if (dom_info_state (CDI_POST_DOMINATORS) >= DOM_NO_FAST_QUERY
5734 14408555 : && (reload_completed || !targetm.have_conditional_execution ()))
5735 : {
5736 14408555 : if (find_if_case_1 (test_bb, then_edge, else_edge))
5737 20708 : goto success;
5738 14387847 : if (find_if_case_2 (test_bb, then_edge, else_edge))
5739 125685 : goto success;
5740 : }
5741 :
5742 : return NULL;
5743 :
5744 324505 : success:
5745 324505 : if (dump_file)
5746 22 : fprintf (dump_file, "Conversion succeeded on pass %d.\n", pass);
5747 : /* Set this so we continue looking. */
5748 324505 : ifcvt_changed_p = true;
5749 324505 : return ce_info.test_bb;
5750 : }
5751 :
5752 : /* CUR_BB has two edges, one falling through to the next block and one
5753 : jumping to TARGET_BB, so it can be part of an && test or an || test.
5754 : Return the number of non-note, non-jump, non-USE/CLOBBER insns in it, or
5755 : -1 if CUR_BB is not of that form. */
5756 :
5757 : static int
5758 0 : block_jumps_and_fallthru (basic_block cur_bb, basic_block target_bb)
5759 : {
5760 0 : edge cur_edge;
5761 0 : bool fallthru_p = false;
5762 0 : bool jump_p = false;
5763 0 : rtx_insn *insn;
5764 0 : rtx_insn *end;
5765 0 : int n_insns = 0;
5766 0 : edge_iterator ei;
5767 :
5768 0 : if (!cur_bb || !target_bb)
5769 : return -1;
5770 :
5771 : /* If no edges, obviously it doesn't jump or fallthru. */
5772 0 : if (EDGE_COUNT (cur_bb->succs) == 0)
5773 : return 0;
5774 :
5775 0 : FOR_EACH_EDGE (cur_edge, ei, cur_bb->succs)
5776 : {
5777 0 : if (cur_edge->flags & EDGE_COMPLEX)
5778 : /* Anything complex isn't what we want. */
5779 : return -1;
5780 :
5781 0 : else if (cur_edge->flags & EDGE_FALLTHRU)
5782 : fallthru_p = true;
5783 :
5784 0 : else if (cur_edge->dest == target_bb)
5785 : jump_p = true;
5786 :
5787 : else
5788 : return -1;
5789 : }
5790 :
5791 0 : if (!jump_p || !fallthru_p)
5792 : return -1;
5793 :
5794 : /* Don't allow calls in the block, since this is used to group && and ||
5795 : together for conditional execution support. ??? we should support
5796 : conditional execution support across calls for IA-64 some day, but
5797 : for now it makes the code simpler. */
5798 0 : end = BB_END (cur_bb);
5799 0 : insn = BB_HEAD (cur_bb);
5800 :
5801 0 : while (insn)
5802 : {
5803 0 : if (CALL_P (insn))
5804 : return -1;
5805 :
5806 0 : if (INSN_P (insn)
5807 0 : && !JUMP_P (insn)
5808 0 : && !DEBUG_INSN_P (insn)
5809 0 : && GET_CODE (PATTERN (insn)) != USE
5810 0 : && GET_CODE (PATTERN (insn)) != CLOBBER)
5811 0 : n_insns++;
5812 :
5813 0 : if (insn == end)
5814 : break;
5815 :
5816 0 : insn = NEXT_INSN (insn);
5817 : }
5818 :
5819 : return n_insns;
5820 : }
5821 :
5822 : /* Determine if a given basic block heads a simple IF-THEN or IF-THEN-ELSE
5823 : block. If so, we'll try to convert the insns to not require the branch.
5824 : Return TRUE if we were successful at converting the block. */
5825 :
5826 : static bool
5827 0 : cond_exec_find_if_block (ce_if_block *ce_info)
5828 : {
5829 0 : basic_block test_bb = ce_info->test_bb;
5830 0 : basic_block then_bb = ce_info->then_bb;
5831 0 : basic_block else_bb = ce_info->else_bb;
5832 0 : basic_block join_bb = NULL_BLOCK;
5833 0 : edge cur_edge;
5834 0 : basic_block next;
5835 0 : edge_iterator ei;
5836 :
5837 0 : ce_info->last_test_bb = test_bb;
5838 :
5839 : /* We only ever should get here after reload,
5840 : and if we have conditional execution. */
5841 0 : gcc_assert (reload_completed && targetm.have_conditional_execution ());
5842 :
5843 : /* Discover if any fall through predecessors of the current test basic block
5844 : were && tests (which jump to the else block) or || tests (which jump to
5845 : the then block). */
5846 0 : if (single_pred_p (test_bb)
5847 0 : && single_pred_edge (test_bb)->flags == EDGE_FALLTHRU)
5848 : {
5849 0 : basic_block bb = single_pred (test_bb);
5850 0 : basic_block target_bb;
5851 0 : int max_insns = MAX_CONDITIONAL_EXECUTE;
5852 0 : int n_insns;
5853 :
5854 : /* Determine if the preceding block is an && or || block. */
5855 0 : if ((n_insns = block_jumps_and_fallthru (bb, else_bb)) >= 0)
5856 : {
5857 0 : ce_info->and_and_p = true;
5858 0 : target_bb = else_bb;
5859 : }
5860 0 : else if ((n_insns = block_jumps_and_fallthru (bb, then_bb)) >= 0)
5861 : {
5862 0 : ce_info->and_and_p = false;
5863 0 : target_bb = then_bb;
5864 : }
5865 : else
5866 : target_bb = NULL_BLOCK;
5867 :
5868 0 : if (target_bb && n_insns <= max_insns)
5869 : {
5870 : int total_insns = 0;
5871 : int blocks = 0;
5872 :
5873 : /* Found at least one && or || block, look for more. */
5874 0 : do
5875 : {
5876 0 : ce_info->test_bb = test_bb = bb;
5877 0 : total_insns += n_insns;
5878 0 : blocks++;
5879 :
5880 0 : if (!single_pred_p (bb))
5881 : break;
5882 :
5883 0 : bb = single_pred (bb);
5884 0 : n_insns = block_jumps_and_fallthru (bb, target_bb);
5885 : }
5886 0 : while (n_insns >= 0 && (total_insns + n_insns) <= max_insns);
5887 :
5888 0 : ce_info->num_multiple_test_blocks = blocks;
5889 0 : ce_info->num_multiple_test_insns = total_insns;
5890 :
5891 0 : if (ce_info->and_and_p)
5892 0 : ce_info->num_and_and_blocks = blocks;
5893 : else
5894 0 : ce_info->num_or_or_blocks = blocks;
5895 : }
5896 : }
5897 :
5898 : /* The THEN block of an IF-THEN combo must have exactly one predecessor,
5899 : other than any || blocks which jump to the THEN block. */
5900 0 : if ((EDGE_COUNT (then_bb->preds) - ce_info->num_or_or_blocks) != 1)
5901 : return false;
5902 :
5903 : /* The edges of the THEN and ELSE blocks cannot have complex edges. */
5904 0 : FOR_EACH_EDGE (cur_edge, ei, then_bb->preds)
5905 : {
5906 0 : if (cur_edge->flags & EDGE_COMPLEX)
5907 : return false;
5908 : }
5909 :
5910 0 : FOR_EACH_EDGE (cur_edge, ei, else_bb->preds)
5911 : {
5912 0 : if (cur_edge->flags & EDGE_COMPLEX)
5913 : return false;
5914 : }
5915 :
5916 : /* The THEN block of an IF-THEN combo must have zero or one successors. */
5917 0 : if (EDGE_COUNT (then_bb->succs) > 0
5918 0 : && (!single_succ_p (then_bb)
5919 0 : || (single_succ_edge (then_bb)->flags & EDGE_COMPLEX)
5920 0 : || (epilogue_completed
5921 0 : && tablejump_p (BB_END (then_bb), NULL, NULL))))
5922 : return false;
5923 :
5924 : /* If the THEN block has no successors, conditional execution can still
5925 : make a conditional call. Don't do this unless the ELSE block has
5926 : only one incoming edge -- the CFG manipulation is too ugly otherwise.
5927 : Check for the last insn of the THEN block being an indirect jump, which
5928 : is listed as not having any successors, but confuses the rest of the CE
5929 : code processing. ??? we should fix this in the future. */
5930 0 : if (EDGE_COUNT (then_bb->succs) == 0)
5931 : {
5932 0 : if (single_pred_p (else_bb) && else_bb != EXIT_BLOCK_PTR_FOR_FN (cfun))
5933 : {
5934 0 : rtx_insn *last_insn = BB_END (then_bb);
5935 :
5936 0 : while (last_insn
5937 0 : && NOTE_P (last_insn)
5938 0 : && last_insn != BB_HEAD (then_bb))
5939 0 : last_insn = PREV_INSN (last_insn);
5940 :
5941 0 : if (last_insn
5942 0 : && JUMP_P (last_insn)
5943 0 : && ! simplejump_p (last_insn))
5944 : return false;
5945 :
5946 : join_bb = else_bb;
5947 : else_bb = NULL_BLOCK;
5948 : }
5949 : else
5950 : return false;
5951 : }
5952 :
5953 : /* If the THEN block's successor is the other edge out of the TEST block,
5954 : then we have an IF-THEN combo without an ELSE. */
5955 0 : else if (single_succ (then_bb) == else_bb)
5956 : {
5957 : join_bb = else_bb;
5958 : else_bb = NULL_BLOCK;
5959 : }
5960 :
5961 : /* If the THEN and ELSE block meet in a subsequent block, and the ELSE
5962 : has exactly one predecessor and one successor, and the outgoing edge
5963 : is not complex, then we have an IF-THEN-ELSE combo. */
5964 0 : else if (single_succ_p (else_bb)
5965 0 : && single_succ (then_bb) == single_succ (else_bb)
5966 0 : && single_pred_p (else_bb)
5967 0 : && !(single_succ_edge (else_bb)->flags & EDGE_COMPLEX)
5968 0 : && !(epilogue_completed
5969 0 : && tablejump_p (BB_END (else_bb), NULL, NULL)))
5970 0 : join_bb = single_succ (else_bb);
5971 :
5972 : /* Otherwise it is not an IF-THEN or IF-THEN-ELSE combination. */
5973 : else
5974 : return false;
5975 :
5976 0 : num_possible_if_blocks++;
5977 :
5978 0 : if (dump_file)
5979 : {
5980 0 : fprintf (dump_file,
5981 : "\nIF-THEN%s block found, pass %d, start block %d "
5982 : "[insn %d], then %d [%d]",
5983 : (else_bb) ? "-ELSE" : "",
5984 : ce_info->pass,
5985 : test_bb->index,
5986 0 : BB_HEAD (test_bb) ? (int)INSN_UID (BB_HEAD (test_bb)) : -1,
5987 : then_bb->index,
5988 0 : BB_HEAD (then_bb) ? (int)INSN_UID (BB_HEAD (then_bb)) : -1);
5989 :
5990 0 : if (else_bb)
5991 0 : fprintf (dump_file, ", else %d [%d]",
5992 : else_bb->index,
5993 0 : BB_HEAD (else_bb) ? (int)INSN_UID (BB_HEAD (else_bb)) : -1);
5994 :
5995 0 : fprintf (dump_file, ", join %d [%d]",
5996 : join_bb->index,
5997 0 : BB_HEAD (join_bb) ? (int)INSN_UID (BB_HEAD (join_bb)) : -1);
5998 :
5999 0 : if (ce_info->num_multiple_test_blocks > 0)
6000 0 : fprintf (dump_file, ", %d %s block%s last test %d [%d]",
6001 : ce_info->num_multiple_test_blocks,
6002 0 : (ce_info->and_and_p) ? "&&" : "||",
6003 : (ce_info->num_multiple_test_blocks == 1) ? "" : "s",
6004 : ce_info->last_test_bb->index,
6005 0 : ((BB_HEAD (ce_info->last_test_bb))
6006 0 : ? (int)INSN_UID (BB_HEAD (ce_info->last_test_bb))
6007 : : -1));
6008 :
6009 0 : fputc ('\n', dump_file);
6010 : }
6011 :
6012 : /* Make sure IF, THEN, and ELSE, blocks are adjacent. Actually, we get the
6013 : first condition for free, since we've already asserted that there's a
6014 : fallthru edge from IF to THEN. Likewise for the && and || blocks, since
6015 : we checked the FALLTHRU flag, those are already adjacent to the last IF
6016 : block. */
6017 : /* ??? As an enhancement, move the ELSE block. Have to deal with
6018 : BLOCK notes, if by no other means than backing out the merge if they
6019 : exist. Sticky enough I don't want to think about it now. */
6020 0 : next = then_bb;
6021 0 : if (else_bb && (next = next->next_bb) != else_bb)
6022 : return false;
6023 0 : if ((next = next->next_bb) != join_bb
6024 0 : && join_bb != EXIT_BLOCK_PTR_FOR_FN (cfun))
6025 : {
6026 0 : if (else_bb)
6027 : join_bb = NULL;
6028 : else
6029 : return false;
6030 : }
6031 :
6032 : /* Do the real work. */
6033 :
6034 0 : ce_info->else_bb = else_bb;
6035 0 : ce_info->join_bb = join_bb;
6036 :
6037 : /* If we have && and || tests, try to first handle combining the && and ||
6038 : tests into the conditional code, and if that fails, go back and handle
6039 : it without the && and ||, which at present handles the && case if there
6040 : was no ELSE block. */
6041 0 : if (cond_exec_process_if_block (ce_info, true))
6042 : return true;
6043 :
6044 0 : if (ce_info->num_multiple_test_blocks)
6045 : {
6046 0 : cancel_changes (0);
6047 :
6048 0 : if (cond_exec_process_if_block (ce_info, false))
6049 : return true;
6050 : }
6051 :
6052 : return false;
6053 : }
6054 :
6055 : /* Convert a branch over a trap, or a branch
6056 : to a trap, into a conditional trap. */
6057 :
6058 : static bool
6059 0 : find_cond_trap (basic_block test_bb, edge then_edge, edge else_edge)
6060 : {
6061 0 : basic_block then_bb = then_edge->dest;
6062 0 : basic_block else_bb = else_edge->dest;
6063 0 : basic_block other_bb, trap_bb;
6064 0 : rtx_insn *trap, *jump;
6065 0 : rtx cond;
6066 0 : rtx_insn *cond_earliest;
6067 :
6068 : /* Locate the block with the trap instruction. */
6069 : /* ??? While we look for no successors, we really ought to allow
6070 : EH successors. Need to fix merge_if_block for that to work. */
6071 0 : if ((trap = block_has_only_trap (then_bb)) != NULL)
6072 : trap_bb = then_bb, other_bb = else_bb;
6073 0 : else if ((trap = block_has_only_trap (else_bb)) != NULL)
6074 : trap_bb = else_bb, other_bb = then_bb;
6075 : else
6076 : return false;
6077 :
6078 0 : if (dump_file)
6079 : {
6080 0 : fprintf (dump_file, "\nTRAP-IF block found, start %d, trap %d\n",
6081 : test_bb->index, trap_bb->index);
6082 : }
6083 :
6084 : /* If this is not a standard conditional jump, we can't parse it. */
6085 0 : jump = BB_END (test_bb);
6086 0 : cond = noce_get_condition (jump, &cond_earliest, then_bb == trap_bb);
6087 0 : if (! cond)
6088 : return false;
6089 :
6090 : /* If the conditional jump is more than just a conditional jump, then
6091 : we cannot do if-conversion on this block. Give up for returnjump_p,
6092 : changing a conditional return followed by unconditional trap for
6093 : conditional trap followed by unconditional return is likely not
6094 : beneficial and harder to handle. */
6095 0 : if (! onlyjump_p (jump) || returnjump_p (jump))
6096 : return false;
6097 :
6098 : /* We must be comparing objects whose modes imply the size. */
6099 0 : if (GET_MODE (XEXP (cond, 0)) == BLKmode)
6100 : return false;
6101 :
6102 : /* Attempt to generate the conditional trap. */
6103 0 : rtx_insn *seq = gen_cond_trap (GET_CODE (cond), copy_rtx (XEXP (cond, 0)),
6104 : copy_rtx (XEXP (cond, 1)),
6105 0 : TRAP_CODE (PATTERN (trap)));
6106 0 : if (seq == NULL)
6107 : return false;
6108 :
6109 : /* If that results in an invalid insn, back out. */
6110 0 : for (rtx_insn *x = seq; x; x = NEXT_INSN (x))
6111 0 : if (reload_completed
6112 0 : ? !valid_insn_p (x)
6113 0 : : recog_memoized (x) < 0)
6114 : return false;
6115 :
6116 : /* Emit the new insns before cond_earliest. */
6117 0 : emit_insn_before_setloc (seq, cond_earliest, INSN_LOCATION (trap));
6118 :
6119 : /* Delete the trap block if possible. */
6120 0 : remove_edge (trap_bb == then_bb ? then_edge : else_edge);
6121 0 : df_set_bb_dirty (test_bb);
6122 0 : df_set_bb_dirty (then_bb);
6123 0 : df_set_bb_dirty (else_bb);
6124 :
6125 0 : if (EDGE_COUNT (trap_bb->preds) == 0)
6126 : {
6127 0 : delete_basic_block (trap_bb);
6128 0 : num_true_changes++;
6129 : }
6130 :
6131 : /* Wire together the blocks again. */
6132 0 : if (current_ir_type () == IR_RTL_CFGLAYOUT)
6133 0 : single_succ_edge (test_bb)->flags |= EDGE_FALLTHRU;
6134 0 : else if (trap_bb == then_bb)
6135 : {
6136 0 : rtx lab = JUMP_LABEL (jump);
6137 0 : rtx_insn *seq = targetm.gen_jump (lab);
6138 0 : rtx_jump_insn *newjump = emit_jump_insn_after (seq, jump);
6139 0 : LABEL_NUSES (lab) += 1;
6140 0 : JUMP_LABEL (newjump) = lab;
6141 0 : emit_barrier_after (newjump);
6142 : }
6143 0 : delete_insn (jump);
6144 :
6145 0 : if (can_merge_blocks_p (test_bb, other_bb))
6146 : {
6147 0 : merge_blocks (test_bb, other_bb);
6148 0 : num_true_changes++;
6149 : }
6150 :
6151 0 : num_updated_if_blocks++;
6152 0 : return true;
6153 : }
6154 :
6155 : /* Subroutine of find_cond_trap: if BB contains only a trap insn,
6156 : return it. */
6157 :
6158 : static rtx_insn *
6159 0 : block_has_only_trap (basic_block bb)
6160 : {
6161 0 : rtx_insn *trap;
6162 :
6163 : /* We're not the exit block. */
6164 0 : if (bb == EXIT_BLOCK_PTR_FOR_FN (cfun))
6165 : return NULL;
6166 :
6167 : /* The block must have no successors. */
6168 0 : if (EDGE_COUNT (bb->succs) > 0)
6169 : return NULL;
6170 :
6171 : /* The only instruction in the THEN block must be the trap. */
6172 0 : trap = first_active_insn (bb);
6173 0 : if (! (trap == BB_END (bb)
6174 0 : && GET_CODE (PATTERN (trap)) == TRAP_IF
6175 0 : && TRAP_CONDITION (PATTERN (trap)) == const_true_rtx))
6176 0 : return NULL;
6177 :
6178 : return trap;
6179 : }
6180 :
6181 : /* Look for IF-THEN-ELSE cases in which one of THEN or ELSE is
6182 : transformable, but not necessarily the other. There need be no
6183 : JOIN block.
6184 :
6185 : Return TRUE if we were successful at converting the block.
6186 :
6187 : Cases we'd like to look at:
6188 :
6189 : (1)
6190 : if (test) goto over; // x not live
6191 : x = a;
6192 : goto label;
6193 : over:
6194 :
6195 : becomes
6196 :
6197 : x = a;
6198 : if (! test) goto label;
6199 :
6200 : (2)
6201 : if (test) goto E; // x not live
6202 : x = big();
6203 : goto L;
6204 : E:
6205 : x = b;
6206 : goto M;
6207 :
6208 : becomes
6209 :
6210 : x = b;
6211 : if (test) goto M;
6212 : x = big();
6213 : goto L;
6214 :
6215 : (3) // This one's really only interesting for targets that can do
6216 : // multiway branching, e.g. IA-64 BBB bundles. For other targets
6217 : // it results in multiple branches on a cache line, which often
6218 : // does not sit well with predictors.
6219 :
6220 : if (test1) goto E; // predicted not taken
6221 : x = a;
6222 : if (test2) goto F;
6223 : ...
6224 : E:
6225 : x = b;
6226 : J:
6227 :
6228 : becomes
6229 :
6230 : x = a;
6231 : if (test1) goto E;
6232 : if (test2) goto F;
6233 :
6234 : Notes:
6235 :
6236 : (A) Don't do (2) if the branch is predicted against the block we're
6237 : eliminating. Do it anyway if we can eliminate a branch; this requires
6238 : that the sole successor of the eliminated block postdominate the other
6239 : side of the if.
6240 :
6241 : (B) With CE, on (3) we can steal from both sides of the if, creating
6242 :
6243 : if (test1) x = a;
6244 : if (!test1) x = b;
6245 : if (test1) goto J;
6246 : if (test2) goto F;
6247 : ...
6248 : J:
6249 :
6250 : Again, this is most useful if J postdominates.
6251 :
6252 : (C) CE substitutes for helpful life information.
6253 :
6254 : (D) These heuristics need a lot of work. */
6255 :
6256 : /* Return true if the if-case formed by TEST_BB, THEN_BB and ELSE_BB is one we
6257 : may convert at all.
6258 :
6259 : If we are partitioning hot/cold basic blocks, we don't want to mess up
6260 : unconditional or indirect jumps that cross between hot and cold sections.
6261 : Basic block partitioning may result in some jumps that appear to be
6262 : optimizable (or blocks that appear to be mergeable), but which really must
6263 : be left untouched (they are required to make it safely across partition
6264 : boundaries). See the comments at the top of
6265 : bb-reorder.cc:partition_hot_cold_basic_blocks for complete details.
6266 :
6267 : TEST_BB must also end in a conditional jump with no other side-effects. */
6268 :
6269 : static bool
6270 28643784 : if_case_blocks_ok_p (basic_block test_bb, basic_block then_bb,
6271 : basic_block else_bb)
6272 : {
6273 28643784 : if ((BB_END (then_bb)
6274 28643784 : && JUMP_P (BB_END (then_bb))
6275 14957922 : && CROSSING_JUMP_P (BB_END (then_bb)))
6276 28167214 : || (JUMP_P (BB_END (test_bb))
6277 28167214 : && CROSSING_JUMP_P (BB_END (test_bb)))
6278 56596126 : || (BB_END (else_bb)
6279 27952342 : && JUMP_P (BB_END (else_bb))
6280 14082273 : && CROSSING_JUMP_P (BB_END (else_bb))))
6281 : return false;
6282 :
6283 27905254 : return onlyjump_p (BB_END (test_bb));
6284 : }
6285 :
6286 : /* Tests for case 1 above. */
6287 :
6288 : static bool
6289 14408555 : find_if_case_1 (basic_block test_bb, edge then_edge, edge else_edge)
6290 : {
6291 14408555 : basic_block then_bb = then_edge->dest;
6292 14408555 : basic_block else_bb = else_edge->dest;
6293 14408555 : basic_block new_bb;
6294 14408555 : int then_bb_index;
6295 14408555 : profile_probability then_prob;
6296 14408555 : rtx else_target = NULL_RTX;
6297 :
6298 14408555 : if (!if_case_blocks_ok_p (test_bb, then_bb, else_bb))
6299 : return false;
6300 :
6301 : /* THEN has one successor. */
6302 14038618 : if (!single_succ_p (then_bb))
6303 : return false;
6304 :
6305 : /* THEN does not fall through, but is not strange either. */
6306 6350270 : if (single_succ_edge (then_bb)->flags & (EDGE_COMPLEX | EDGE_FALLTHRU))
6307 : return false;
6308 :
6309 : /* THEN has one predecessor. */
6310 1247171 : if (!single_pred_p (then_bb))
6311 : return false;
6312 :
6313 : /* THEN must do something. */
6314 1123709 : if (forwarder_block_p (then_bb))
6315 : return false;
6316 :
6317 711456 : num_possible_if_blocks++;
6318 711456 : if (dump_file)
6319 8 : fprintf (dump_file,
6320 : "\nIF-CASE-1 found, start %d, then %d\n",
6321 : test_bb->index, then_bb->index);
6322 :
6323 711456 : then_prob = then_edge->probability.invert ();
6324 :
6325 : /* We're speculating from the THEN path, we want to make sure the cost
6326 : of speculation is within reason. */
6327 1345145 : if (! cheap_bb_rtx_cost_p (then_bb, then_prob,
6328 1345145 : COSTS_N_INSNS (BRANCH_COST (optimize_bb_for_speed_p (then_edge->src),
6329 : predictable_edge_p (then_edge)))))
6330 : return false;
6331 :
6332 139082 : if (else_bb == EXIT_BLOCK_PTR_FOR_FN (cfun))
6333 : {
6334 0 : rtx_insn *jump = BB_END (else_edge->src);
6335 0 : gcc_assert (JUMP_P (jump));
6336 0 : else_target = JUMP_LABEL (jump);
6337 : }
6338 :
6339 : /* Registers set are dead, or are predicable. */
6340 139082 : if (! dead_or_predicable (test_bb, then_bb, else_bb,
6341 : single_succ_edge (then_bb), true))
6342 : return false;
6343 :
6344 : /* Conversion went ok, including moving the insns and fixing up the
6345 : jump. Adjust the CFG to match. */
6346 :
6347 : /* We can avoid creating a new basic block if then_bb is immediately
6348 : followed by else_bb, i.e. deleting then_bb allows test_bb to fall
6349 : through to else_bb. */
6350 :
6351 20708 : if (then_bb->next_bb == else_bb
6352 9361 : && then_bb->prev_bb == test_bb
6353 9361 : && else_bb != EXIT_BLOCK_PTR_FOR_FN (cfun))
6354 : {
6355 9361 : redirect_edge_succ (FALLTHRU_EDGE (test_bb), else_bb);
6356 9361 : new_bb = 0;
6357 : }
6358 11347 : else if (else_bb == EXIT_BLOCK_PTR_FOR_FN (cfun))
6359 0 : new_bb = force_nonfallthru_and_redirect (FALLTHRU_EDGE (test_bb),
6360 : else_bb, else_target);
6361 : else
6362 11347 : new_bb = redirect_edge_and_branch_force (FALLTHRU_EDGE (test_bb),
6363 : else_bb);
6364 :
6365 20708 : df_set_bb_dirty (test_bb);
6366 20708 : df_set_bb_dirty (else_bb);
6367 :
6368 20708 : then_bb_index = then_bb->index;
6369 20708 : delete_basic_block (then_bb);
6370 :
6371 : /* Make rest of code believe that the newly created block is the THEN_BB
6372 : block we removed. */
6373 20708 : if (new_bb)
6374 : {
6375 11347 : df_bb_replace (then_bb_index, new_bb);
6376 : /* This should have been done above via force_nonfallthru_and_redirect
6377 : (possibly called from redirect_edge_and_branch_force). */
6378 11347 : gcc_checking_assert (BB_PARTITION (new_bb) == BB_PARTITION (test_bb));
6379 : }
6380 :
6381 20708 : num_true_changes++;
6382 20708 : num_updated_if_blocks++;
6383 20708 : return true;
6384 : }
6385 :
6386 : /* Test for case 2 above. */
6387 :
6388 : static bool
6389 14387847 : find_if_case_2 (basic_block test_bb, edge then_edge, edge else_edge)
6390 : {
6391 14387847 : basic_block then_bb = then_edge->dest;
6392 14387847 : basic_block else_bb = else_edge->dest;
6393 14387847 : edge else_succ;
6394 14387847 : profile_probability then_prob, else_prob;
6395 :
6396 : /* We do not want to speculate (empty) loop latches. */
6397 14387847 : if (current_loops
6398 5623943 : && else_bb->loop_father->latch == else_bb)
6399 : return false;
6400 :
6401 14235229 : if (!if_case_blocks_ok_p (test_bb, then_bb, else_bb))
6402 : return false;
6403 :
6404 : /* ELSE has one successor. */
6405 13865293 : if (!single_succ_p (else_bb))
6406 : return false;
6407 : else
6408 5848102 : else_succ = single_succ_edge (else_bb);
6409 :
6410 : /* ELSE outgoing edge is not complex. */
6411 5848102 : if (else_succ->flags & EDGE_COMPLEX)
6412 : return false;
6413 :
6414 : /* ELSE has one predecessor. */
6415 5689433 : if (!single_pred_p (else_bb))
6416 : return false;
6417 :
6418 : /* THEN is not EXIT. */
6419 2972081 : if (then_bb->index < NUM_FIXED_BLOCKS)
6420 : return false;
6421 :
6422 2972081 : else_prob = else_edge->probability;
6423 2972081 : then_prob = else_prob.invert ();
6424 :
6425 : /* ELSE is predicted or SUCC(ELSE) postdominates THEN. */
6426 2972081 : if (else_prob > then_prob)
6427 : ;
6428 2000459 : else if (else_succ->dest->index < NUM_FIXED_BLOCKS
6429 2000459 : || dominated_by_p (CDI_POST_DOMINATORS, then_bb,
6430 : else_succ->dest))
6431 : ;
6432 : else
6433 : return false;
6434 :
6435 2348467 : num_possible_if_blocks++;
6436 2348467 : if (dump_file)
6437 44 : fprintf (dump_file,
6438 : "\nIF-CASE-2 found, start %d, else %d\n",
6439 : test_bb->index, else_bb->index);
6440 :
6441 : /* We're speculating from the ELSE path, we want to make sure the cost
6442 : of speculation is within reason. */
6443 4525339 : if (! cheap_bb_rtx_cost_p (else_bb, else_prob,
6444 4525339 : COSTS_N_INSNS (BRANCH_COST (optimize_bb_for_speed_p (else_edge->src),
6445 : predictable_edge_p (else_edge)))))
6446 : return false;
6447 :
6448 : /* Registers set are dead, or are predicable. */
6449 449273 : if (! dead_or_predicable (test_bb, else_bb, then_bb, else_succ, false))
6450 : return false;
6451 :
6452 : /* Conversion went ok, including moving the insns and fixing up the
6453 : jump. Adjust the CFG to match. */
6454 :
6455 125685 : df_set_bb_dirty (test_bb);
6456 125685 : df_set_bb_dirty (then_bb);
6457 125685 : delete_basic_block (else_bb);
6458 :
6459 125685 : num_true_changes++;
6460 125685 : num_updated_if_blocks++;
6461 :
6462 : /* ??? We may now fallthru from one of THEN's successors into a join
6463 : block. Rerun cleanup_cfg? Examine things manually? Wait? */
6464 :
6465 125685 : return true;
6466 : }
6467 :
6468 : /* Used by the code above to perform the actual rtl transformations.
6469 : Return TRUE if successful.
6470 :
6471 : TEST_BB is the block containing the conditional branch. MERGE_BB is the
6472 : block containing the code to manipulate. OTHER_BB is the other successor
6473 : of TEST_BB, the one the code is being moved past. DEST_EDGE is an edge
6474 : representing a jump to the join block; after the conversion, TEST_BB should
6475 : be branching to its destination. REVERSEP is true if the sense of the
6476 : branch should be reversed. */
6477 :
6478 : static bool
6479 588355 : dead_or_predicable (basic_block test_bb, basic_block merge_bb,
6480 : basic_block other_bb, edge dest_edge, bool reversep)
6481 : {
6482 588355 : basic_block new_dest = dest_edge->dest;
6483 588355 : rtx_insn *head, *end, *jump;
6484 588355 : rtx_insn *earliest = NULL;
6485 588355 : rtx old_dest;
6486 588355 : auto_bitmap merge_set (®_obstack);
6487 : /* Number of pending changes. */
6488 588355 : int n_validated_changes = 0;
6489 588355 : rtx new_dest_label = NULL_RTX;
6490 :
6491 588355 : jump = BB_END (test_bb);
6492 :
6493 : /* Find the extent of the real code in the merge block. */
6494 588355 : head = BB_HEAD (merge_bb);
6495 588355 : end = BB_END (merge_bb);
6496 :
6497 769326 : while (DEBUG_INSN_P (end) && end != head)
6498 180971 : end = PREV_INSN (end);
6499 :
6500 : /* If merge_bb ends with a tablejump, predicating/moving insn's
6501 : into test_bb and then deleting merge_bb will result in the jumptable
6502 : that follows merge_bb being removed along with merge_bb and then we
6503 : get an unresolved reference to the jumptable. */
6504 588355 : if (tablejump_p (end, NULL, NULL))
6505 : return false;
6506 :
6507 588355 : if (LABEL_P (head))
6508 449343 : head = NEXT_INSN (head);
6509 588355 : while (DEBUG_INSN_P (head) && head != end)
6510 0 : head = NEXT_INSN (head);
6511 588355 : if (NOTE_P (head))
6512 : {
6513 588355 : if (head == end)
6514 : {
6515 103978 : head = end = NULL;
6516 103978 : goto no_body;
6517 : }
6518 484377 : head = NEXT_INSN (head);
6519 1401866 : while (DEBUG_INSN_P (head) && head != end)
6520 433112 : head = NEXT_INSN (head);
6521 : }
6522 :
6523 484377 : if (JUMP_P (end))
6524 : {
6525 201242 : if (!onlyjump_p (end))
6526 : return false;
6527 159977 : if (head == end)
6528 : {
6529 6 : head = end = NULL;
6530 6 : goto no_body;
6531 : }
6532 159971 : end = PREV_INSN (end);
6533 429037 : while (DEBUG_INSN_P (end) && end != head)
6534 109095 : end = PREV_INSN (end);
6535 : }
6536 :
6537 : /* Don't move frame-related insn across the conditional branch. This
6538 : can lead to one of the paths of the branch having wrong unwind info. */
6539 443106 : if (epilogue_completed)
6540 : {
6541 : rtx_insn *insn = head;
6542 82397 : while (1)
6543 : {
6544 282531 : if (INSN_P (insn) && RTX_FRAME_RELATED_P (insn))
6545 : return false;
6546 275912 : if (insn == end)
6547 : break;
6548 82397 : insn = NEXT_INSN (insn);
6549 82397 : }
6550 : }
6551 :
6552 : /* Disable handling dead code by conditional execution if the machine needs
6553 : to do anything funny with the tests, etc. */
6554 : #ifndef IFCVT_MODIFY_TESTS
6555 436487 : if (targetm.have_conditional_execution ())
6556 : {
6557 : /* In the conditional execution case, we have things easy. We know
6558 : the condition is reversible. We don't have to check life info
6559 : because we're going to conditionally execute the code anyway.
6560 : All that's left is making sure the insns involved can actually
6561 : be predicated. */
6562 :
6563 0 : rtx cond;
6564 :
6565 : /* If the conditional jump is more than just a conditional jump,
6566 : then we cannot do conditional execution conversion on this block. */
6567 0 : if (!onlyjump_p (jump))
6568 0 : goto nce;
6569 :
6570 0 : cond = cond_exec_get_condition (jump);
6571 0 : if (! cond)
6572 0 : goto nce;
6573 :
6574 0 : rtx note = find_reg_note (jump, REG_BR_PROB, NULL_RTX);
6575 0 : profile_probability prob_val
6576 0 : = (note ? profile_probability::from_reg_br_prob_note (XINT (note, 0))
6577 : : profile_probability::uninitialized ());
6578 :
6579 0 : if (reversep)
6580 : {
6581 0 : enum rtx_code rev = reversed_comparison_code (cond, jump);
6582 0 : if (rev == UNKNOWN)
6583 0 : return false;
6584 0 : cond = gen_rtx_fmt_ee (rev, GET_MODE (cond), XEXP (cond, 0),
6585 : XEXP (cond, 1));
6586 0 : prob_val = prob_val.invert ();
6587 : }
6588 :
6589 0 : if (cond_exec_process_insns (NULL, head, end, cond, prob_val, false)
6590 0 : && verify_changes (0))
6591 0 : n_validated_changes = num_validated_changes ();
6592 : else
6593 0 : cancel_changes (0);
6594 :
6595 0 : earliest = jump;
6596 : }
6597 436487 : nce:
6598 : #endif
6599 :
6600 : /* If we allocated new pseudos (e.g. in the conditional move
6601 : expander called from noce_emit_cmove), we must resize the
6602 : array first. */
6603 436487 : if (max_regno < max_reg_num ())
6604 84491 : max_regno = max_reg_num ();
6605 :
6606 : /* Try the NCE path if the CE path did not result in any changes. */
6607 436487 : if (n_validated_changes == 0)
6608 : {
6609 436487 : rtx cond;
6610 436487 : rtx_insn *insn;
6611 436487 : bool success;
6612 :
6613 : /* In the non-conditional execution case, we have to verify that there
6614 : are no trapping operations, no calls, no references to memory, and
6615 : that any registers modified are dead at the branch site. */
6616 :
6617 436487 : if (!any_condjump_p (jump))
6618 293179 : return false;
6619 :
6620 : /* Find the extent of the conditional. */
6621 436487 : cond = noce_get_condition (jump, &earliest, false);
6622 436487 : if (!cond)
6623 : return false;
6624 :
6625 435681 : auto_bitmap live (®_obstack);
6626 435681 : simulate_backwards_to_point (merge_bb, live, end);
6627 435681 : success = can_move_insns_across (head, end, earliest, jump,
6628 : merge_bb, live,
6629 : df_get_live_in (other_bb), NULL);
6630 435681 : if (!success)
6631 : return false;
6632 :
6633 : /* Collect the set of registers set in MERGE_BB. */
6634 720229 : FOR_BB_INSNS (merge_bb, insn)
6635 576384 : if (NONDEBUG_INSN_P (insn))
6636 187027 : df_simulate_find_defs (insn, merge_set);
6637 :
6638 : /* If shrink-wrapping, disable this optimization when test_bb is
6639 : the first basic block and merge_bb exits. The idea is to not
6640 : move code setting up a return register as that may clobber a
6641 : register used to pass function parameters, which then must be
6642 : saved in caller-saved regs. A caller-saved reg requires the
6643 : prologue, killing a shrink-wrap opportunity. */
6644 143844 : if ((SHRINK_WRAPPING_ENABLED && !epilogue_completed)
6645 114004 : && ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb == test_bb
6646 157301 : && single_succ_p (new_dest)
6647 13993 : && single_succ (new_dest) == EXIT_BLOCK_PTR_FOR_FN (cfun)
6648 156828 : && bitmap_intersect_p (df_get_live_in (new_dest), merge_set))
6649 : {
6650 12983 : unsigned int i;
6651 :
6652 12983 : auto_bitmap return_regs (®_obstack);
6653 :
6654 : /* Start off with the intersection of regs used to pass
6655 : params and regs used to return values. */
6656 1233385 : for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
6657 1220402 : if (FUNCTION_ARG_REGNO_P (i)
6658 1220402 : && targetm.calls.function_value_regno_p (i))
6659 50754 : bitmap_set_bit (return_regs, INCOMING_REGNO (i));
6660 :
6661 12983 : bitmap_and_into (return_regs,
6662 12983 : df_get_live_out (ENTRY_BLOCK_PTR_FOR_FN (cfun)));
6663 12983 : bitmap_and_into (return_regs,
6664 12983 : df_get_live_in (EXIT_BLOCK_PTR_FOR_FN (cfun)));
6665 12983 : if (!bitmap_empty_p (return_regs))
6666 : {
6667 4888 : FOR_BB_INSNS_REVERSE (new_dest, insn)
6668 4333 : if (NONDEBUG_INSN_P (insn))
6669 : {
6670 2207 : df_ref def;
6671 :
6672 : /* If this insn sets any reg in return_regs, add all
6673 : reg uses to the set of regs we're interested in. */
6674 2796 : FOR_EACH_INSN_DEF (def, insn)
6675 1706 : if (bitmap_bit_p (return_regs, DF_REF_REGNO (def)))
6676 : {
6677 1117 : df_simulate_uses (insn, return_regs);
6678 1117 : break;
6679 : }
6680 : }
6681 555 : if (bitmap_intersect_p (merge_set, return_regs))
6682 537 : return false;
6683 : }
6684 12983 : }
6685 435681 : }
6686 :
6687 0 : no_body:
6688 : /* We don't want to use normal invert_jump or redirect_jump because
6689 : we don't want to delete_insn called. Also, we want to do our own
6690 : change group management. */
6691 :
6692 247292 : old_dest = JUMP_LABEL (jump);
6693 247292 : if (other_bb != new_dest)
6694 : {
6695 247277 : if (!any_condjump_p (jump))
6696 0 : goto cancel;
6697 :
6698 247277 : if (JUMP_P (BB_END (dest_edge->src)))
6699 21778 : new_dest_label = JUMP_LABEL (BB_END (dest_edge->src));
6700 225499 : else if (new_dest == EXIT_BLOCK_PTR_FOR_FN (cfun))
6701 100899 : new_dest_label = ret_rtx;
6702 : else
6703 124600 : new_dest_label = block_label (new_dest);
6704 :
6705 247277 : rtx_jump_insn *jump_insn = as_a <rtx_jump_insn *> (jump);
6706 247277 : if (reversep
6707 247277 : ? ! invert_jump_1 (jump_insn, new_dest_label)
6708 226569 : : ! redirect_jump_1 (jump_insn, new_dest_label))
6709 0 : goto cancel;
6710 : }
6711 :
6712 247292 : if (verify_changes (n_validated_changes))
6713 146393 : confirm_change_group ();
6714 : else
6715 100899 : goto cancel;
6716 :
6717 146393 : if (other_bb != new_dest)
6718 : {
6719 146378 : redirect_jump_2 (as_a <rtx_jump_insn *> (jump), old_dest, new_dest_label,
6720 : 0, reversep);
6721 :
6722 146378 : redirect_edge_succ (BRANCH_EDGE (test_bb), new_dest);
6723 146378 : if (reversep)
6724 : {
6725 20708 : std::swap (BRANCH_EDGE (test_bb)->probability,
6726 20708 : FALLTHRU_EDGE (test_bb)->probability);
6727 20708 : update_br_prob_note (test_bb);
6728 : }
6729 : }
6730 :
6731 : /* Move the insns out of MERGE_BB to before the branch. */
6732 146393 : if (head != NULL)
6733 : {
6734 143308 : rtx_insn *insn;
6735 :
6736 143308 : if (end == BB_END (merge_bb))
6737 110364 : BB_END (merge_bb) = PREV_INSN (head);
6738 :
6739 : /* PR 21767: when moving insns above a conditional branch, the REG_EQUAL
6740 : notes being moved might become invalid. */
6741 143308 : insn = head;
6742 171625 : do
6743 : {
6744 171625 : rtx note;
6745 :
6746 171625 : if (! INSN_P (insn))
6747 3099 : continue;
6748 168526 : note = find_reg_note (insn, REG_EQUAL, NULL_RTX);
6749 168526 : if (! note)
6750 157510 : continue;
6751 11016 : remove_note (insn, note);
6752 199942 : } while (insn != end && (insn = NEXT_INSN (insn)));
6753 :
6754 : /* PR46315: when moving insns above a conditional branch, the REG_EQUAL
6755 : notes referring to the registers being set might become invalid.
6756 : MERGE_SET is empty on the conditional-execution path, which does not
6757 : move anything. */
6758 143308 : unsigned i;
6759 143308 : bitmap_iterator bi;
6760 322776 : EXECUTE_IF_SET_IN_BITMAP (merge_set, 0, i, bi)
6761 179468 : remove_reg_equal_equiv_notes_for_regno (i);
6762 :
6763 143308 : reorder_insns (head, end, PREV_INSN (earliest));
6764 : }
6765 :
6766 : /* Remove the jump and edge if we can. */
6767 146393 : if (other_bb == new_dest)
6768 : {
6769 15 : delete_insn (jump);
6770 15 : remove_edge (BRANCH_EDGE (test_bb));
6771 : /* ??? Can't merge blocks here, as then_bb is still in use.
6772 : At minimum, the merge will get done just before bb-reorder. */
6773 : }
6774 :
6775 : return true;
6776 :
6777 100899 : cancel:
6778 100899 : cancel_changes (0);
6779 :
6780 100899 : return false;
6781 588355 : }
6782 :
6783 : /* Main entry point for all if-conversion. PHASE selects the ce1, ce2 or ce3
6784 : run: before combine, after combine, or after reload. */
6785 :
6786 : static void
6787 3185827 : if_convert (ifcvt_phase phase)
6788 : {
6789 3185827 : basic_block bb;
6790 3185827 : int pass;
6791 :
6792 3185827 : if (optimize == 1)
6793 : {
6794 236611 : df_live_add_problem ();
6795 236611 : df_live_set_all_dirty ();
6796 : }
6797 :
6798 : /* Record which pass is running for the cost model. */
6799 3185827 : ifcvt_pass_phase = phase;
6800 3185827 : have_cbranchcc4 = (direct_optab_handler (cbranch_optab, CCmode)
6801 3185827 : != CODE_FOR_nothing);
6802 3185827 : num_possible_if_blocks = 0;
6803 3185827 : num_updated_if_blocks = 0;
6804 3185827 : num_true_changes = 0;
6805 :
6806 3185827 : loop_optimizer_init (AVOID_CFG_MODIFICATIONS);
6807 3185827 : mark_loop_exit_edges ();
6808 3185827 : loop_optimizer_finalize ();
6809 3185827 : free_dominance_info (CDI_DOMINATORS);
6810 :
6811 : /* Compute postdominators. */
6812 3185827 : calculate_dominance_info (CDI_POST_DOMINATORS);
6813 :
6814 3185827 : df_set_flags (DF_LR_RUN_DCE);
6815 :
6816 : /* Go through each of the basic blocks looking for things to convert. If we
6817 : have conditional execution, we make multiple passes to allow us to handle
6818 : IF-THEN{-ELSE} blocks within other IF-THEN{-ELSE} blocks. */
6819 3185827 : pass = 0;
6820 3352497 : do
6821 : {
6822 3352497 : df_analyze ();
6823 : /* Only need to do dce on the first pass. */
6824 3352497 : df_clear_flags (DF_LR_RUN_DCE);
6825 3352497 : ifcvt_changed_p = false;
6826 3352497 : pass++;
6827 :
6828 3352497 : if (dump_file && pass > 1)
6829 22 : fprintf (dump_file, "\n\n========== Pass %d ==========\n", pass);
6830 :
6831 43443063 : FOR_EACH_BB_FN (bb, cfun)
6832 : {
6833 : basic_block new_bb;
6834 40415071 : while (!df_get_bb_dirty (bb)
6835 80017682 : && (new_bb = find_if_header (bb, pass)) != NULL)
6836 : bb = new_bb;
6837 : }
6838 :
6839 3352497 : if (dump_file && ifcvt_changed_p)
6840 22 : print_rtl_with_bb (dump_file, get_insns (), dump_flags);
6841 : }
6842 : while (ifcvt_changed_p);
6843 :
6844 3185827 : if (dump_file)
6845 88 : fprintf (dump_file, "\n\n========== no more changes\n");
6846 :
6847 3185827 : free_dominance_info (CDI_POST_DOMINATORS);
6848 :
6849 3185827 : if (dump_file)
6850 88 : fflush (dump_file);
6851 :
6852 3185827 : clear_aux_for_blocks ();
6853 :
6854 : /* If we allocated new pseudos, we must resize the array for sched1. */
6855 3185827 : if (max_regno < max_reg_num ())
6856 649165 : max_regno = max_reg_num ();
6857 :
6858 : /* Write the final stats. */
6859 3185827 : if (dump_file && num_possible_if_blocks > 0)
6860 : {
6861 62 : fprintf (dump_file,
6862 : "\n%d possible IF blocks searched.\n",
6863 : num_possible_if_blocks);
6864 62 : fprintf (dump_file,
6865 : "%d IF blocks converted.\n",
6866 : num_updated_if_blocks);
6867 62 : fprintf (dump_file,
6868 : "%d true changes made.\n\n\n",
6869 : num_true_changes);
6870 : }
6871 :
6872 3185827 : if (optimize == 1)
6873 236611 : df_remove_problem (df_live);
6874 :
6875 : /* Some non-cold blocks may now be only reachable from cold blocks.
6876 : Fix that up. */
6877 3185827 : fixup_partitions ();
6878 :
6879 3185827 : checking_verify_flow_info ();
6880 3185827 : }
6881 :
6882 : /* If-conversion and CFG cleanup. */
6883 : static void
6884 1064387 : rest_of_handle_if_conversion (void)
6885 : {
6886 1064387 : int flags = 0;
6887 :
6888 1064387 : if (flag_if_conversion)
6889 : {
6890 1061938 : if (dump_file)
6891 : {
6892 36 : dump_reg_info (dump_file);
6893 36 : dump_flow_info (dump_file, dump_flags);
6894 : }
6895 1061938 : cleanup_cfg (CLEANUP_EXPENSIVE);
6896 1061938 : if_convert (IFCVT_BEFORE_COMBINE);
6897 1061938 : if (num_updated_if_blocks)
6898 : /* Get rid of any dead CC-related instructions. */
6899 1064387 : flags |= CLEANUP_FORCE_FAST_DCE;
6900 : }
6901 :
6902 1064387 : cleanup_cfg (flags);
6903 1064387 : }
6904 :
6905 : namespace {
6906 :
6907 : const pass_data pass_data_rtl_ifcvt =
6908 : {
6909 : RTL_PASS, /* type */
6910 : "ce1", /* name */
6911 : OPTGROUP_NONE, /* optinfo_flags */
6912 : TV_IFCVT, /* tv_id */
6913 : 0, /* properties_required */
6914 : 0, /* properties_provided */
6915 : 0, /* properties_destroyed */
6916 : 0, /* todo_flags_start */
6917 : TODO_df_finish, /* todo_flags_finish */
6918 : };
6919 :
6920 : /* ce2 reruns if-conversion after combine has simplified things enough to
6921 : meet the sequence-length restrictions. */
6922 : const pass_data pass_data_if_after_combine =
6923 : {
6924 : RTL_PASS, /* type */
6925 : "ce2", /* name */
6926 : OPTGROUP_NONE, /* optinfo_flags */
6927 : TV_IFCVT, /* tv_id */
6928 : 0, /* properties_required */
6929 : 0, /* properties_provided */
6930 : 0, /* properties_destroyed */
6931 : 0, /* todo_flags_start */
6932 : TODO_df_finish, /* todo_flags_finish */
6933 : };
6934 :
6935 : /* ce3 reruns if-conversion after reload. */
6936 : const pass_data pass_data_if_after_reload =
6937 : {
6938 : RTL_PASS, /* type */
6939 : "ce3", /* name */
6940 : OPTGROUP_NONE, /* optinfo_flags */
6941 : TV_IFCVT2, /* tv_id */
6942 : 0, /* properties_required */
6943 : 0, /* properties_provided */
6944 : 0, /* properties_destroyed */
6945 : 0, /* todo_flags_start */
6946 : TODO_df_finish, /* todo_flags_finish */
6947 : };
6948 :
6949 : /* The three if-conversion passes (ce1/ce2/ce3) share this class. M_PHASE
6950 : selects the gate condition and the work: ce1 (before combine) also cleans
6951 : up the CFG and is gated only on optimize, while ce2 and ce3 rerun once
6952 : combine and reload have simplified the RTL. */
6953 :
6954 : class pass_rtl_ifcvt : public rtl_opt_pass
6955 : {
6956 : public:
6957 883761 : pass_rtl_ifcvt (gcc::context *ctxt, const pass_data &data, ifcvt_phase phase)
6958 1767522 : : rtl_opt_pass (data, ctxt), m_phase (phase)
6959 : {}
6960 :
6961 : /* opt_pass methods: */
6962 4534176 : bool gate (function *) final override
6963 : {
6964 4534176 : if (optimize == 0)
6965 : return false;
6966 3193164 : switch (m_phase)
6967 : {
6968 1064388 : case IFCVT_BEFORE_COMBINE:
6969 1064388 : return dbg_cnt (if_conversion);
6970 1064388 : case IFCVT_AFTER_COMBINE:
6971 1064388 : return flag_if_conversion && dbg_cnt (if_after_combine);
6972 1064388 : case IFCVT_AFTER_RELOAD:
6973 1064388 : return flag_if_conversion2 && dbg_cnt (if_after_reload);
6974 : }
6975 0 : gcc_unreachable ();
6976 : }
6977 :
6978 3188276 : unsigned int execute (function *) final override
6979 : {
6980 3188276 : if (m_phase == IFCVT_BEFORE_COMBINE)
6981 1064387 : rest_of_handle_if_conversion ();
6982 : else
6983 2123889 : if_convert (m_phase);
6984 3188276 : return 0;
6985 : }
6986 :
6987 : private:
6988 : ifcvt_phase m_phase;
6989 :
6990 : }; // class pass_rtl_ifcvt
6991 :
6992 : } // anon namespace
6993 :
6994 : rtl_opt_pass *
6995 294587 : make_pass_rtl_ifcvt (gcc::context *ctxt)
6996 : {
6997 294587 : return new pass_rtl_ifcvt (ctxt, pass_data_rtl_ifcvt, IFCVT_BEFORE_COMBINE);
6998 : }
6999 :
7000 : rtl_opt_pass *
7001 294587 : make_pass_if_after_combine (gcc::context *ctxt)
7002 : {
7003 294587 : return new pass_rtl_ifcvt (ctxt, pass_data_if_after_combine,
7004 294587 : IFCVT_AFTER_COMBINE);
7005 : }
7006 :
7007 : rtl_opt_pass *
7008 294587 : make_pass_if_after_reload (gcc::context *ctxt)
7009 : {
7010 294587 : return new pass_rtl_ifcvt (ctxt, pass_data_if_after_reload,
7011 294587 : IFCVT_AFTER_RELOAD);
7012 : }
|