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