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 3095551 : cheap_bb_rtx_cost_p (const_basic_block bb,
137 : profile_probability prob, int max_cost)
138 : {
139 3095551 : int count = 0;
140 3095551 : rtx_insn *insn = BB_HEAD (bb);
141 3095551 : bool speed = optimize_bb_for_speed_p (bb);
142 3095551 : 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 3095551 : 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 3044103 : scale += REG_BR_PROB_BASE / 8;
161 :
162 :
163 3095551 : max_cost *= scale;
164 :
165 13075491 : while (1)
166 : {
167 16171042 : 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 4626971 : if (asm_noperands (PATTERN (insn)) >= 0)
174 : return false;
175 :
176 4624270 : int cost = insn_cost (insn, speed) * REG_BR_PROB_BASE;
177 4624270 : 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 4573961 : {
189 4573961 : rtx set = single_set (insn);
190 4573961 : if (set && STACK_REG_P (SET_DEST (set)))
191 : return false;
192 : }
193 : #endif
194 :
195 4569989 : count += cost;
196 4569989 : if (count >= max_cost)
197 : return false;
198 : }
199 11544071 : else if (CALL_P (insn))
200 : return false;
201 :
202 13681885 : if (insn == BB_END (bb))
203 : break;
204 13075491 : insn = NEXT_INSN (insn);
205 13075491 : }
206 :
207 : return true;
208 : }
209 :
210 : /* Return the first non-jump active insn in the basic block. */
211 :
212 : static rtx_insn *
213 1559273 : first_active_insn (basic_block bb)
214 : {
215 1559273 : rtx_insn *insn = BB_HEAD (bb);
216 :
217 1559273 : if (LABEL_P (insn))
218 : {
219 289169 : if (insn == BB_END (bb))
220 : return NULL;
221 289169 : insn = NEXT_INSN (insn);
222 : }
223 :
224 5199753 : while (NOTE_P (insn) || DEBUG_INSN_P (insn))
225 : {
226 3640480 : if (insn == BB_END (bb))
227 : return NULL;
228 3640480 : insn = NEXT_INSN (insn);
229 : }
230 :
231 1559273 : if (JUMP_P (insn))
232 0 : 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 2608810 : last_active_insn (basic_block bb, bool skip_use_p)
241 : {
242 2608810 : rtx_insn *insn = BB_END (bb);
243 2608810 : rtx_insn *head = BB_HEAD (bb);
244 :
245 2608810 : while (NOTE_P (insn)
246 : || JUMP_P (insn)
247 : || DEBUG_INSN_P (insn)
248 6304529 : || (skip_use_p
249 0 : && NONJUMP_INSN_P (insn)
250 0 : && GET_CODE (PATTERN (insn)) == USE))
251 : {
252 3695953 : if (insn == head)
253 : return NULL;
254 3695719 : insn = PREV_INSN (insn);
255 : }
256 :
257 2608576 : if (LABEL_P (insn))
258 77 : 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 500324 : rtx_interchangeable_p (const_rtx a, const_rtx b)
319 : {
320 500324 : if (!rtx_equal_p (a, b))
321 : return false;
322 :
323 183855 : 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 2326 : 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 118124 : cond_exec_get_condition (rtx_insn *jump, bool get_reversed = false)
440 : {
441 118124 : rtx test_if, cond;
442 :
443 118124 : if (any_condjump_p (jump))
444 118124 : test_if = SET_SRC (pc_set (jump));
445 : else
446 : return NULL_RTX;
447 118124 : cond = XEXP (test_if, 0);
448 :
449 : /* If this branches to JUMP_LABEL when the condition is false,
450 : reverse the condition. */
451 118124 : if (get_reversed
452 118124 : || (GET_CODE (XEXP (test_if, 2)) == LABEL_REF
453 0 : && label_ref_label (XEXP (test_if, 2))
454 0 : == JUMP_LABEL (jump)))
455 : {
456 59062 : enum rtx_code rev = reversed_comparison_code (cond, jump);
457 59062 : if (rev == UNKNOWN)
458 : return NULL_RTX;
459 :
460 59062 : 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_shifted_store_flag (struct noce_if_info *);
785 : static bool noce_try_store_flag_mask (struct noce_if_info *);
786 : static rtx noce_emit_cmove (struct noce_if_info *, rtx, enum rtx_code, rtx,
787 : rtx, rtx, rtx, rtx = NULL, rtx = NULL);
788 : static bool noce_try_cmove (struct noce_if_info *);
789 : static bool noce_try_cmove_arith (struct noce_if_info *);
790 : static rtx noce_get_alt_condition (struct noce_if_info *, rtx, rtx_insn **);
791 : static bool noce_try_minmax (struct noce_if_info *);
792 : static bool noce_try_abs (struct noce_if_info *);
793 : static bool noce_try_sign_mask (struct noce_if_info *);
794 :
795 : /* Return the comparison code for reversed condition for IF_INFO,
796 : or UNKNOWN if reversing the condition is not possible. */
797 :
798 : static inline enum rtx_code
799 105341 : noce_reversed_cond_code (struct noce_if_info *if_info)
800 : {
801 105341 : if (if_info->rev_cond)
802 105341 : return GET_CODE (if_info->rev_cond);
803 0 : return reversed_comparison_code (if_info->cond, if_info->jump);
804 : }
805 :
806 : /* Return true if SEQ is a good candidate as a replacement for the
807 : if-convertible sequence described in IF_INFO.
808 : This is the default implementation that targets can override
809 : through a target hook. */
810 :
811 : bool
812 169367 : default_noce_conversion_profitable_p (rtx_insn *seq,
813 : struct noce_if_info *if_info)
814 : {
815 169367 : bool speed_p = if_info->speed_p;
816 :
817 : /* Cost up the new sequence. */
818 169367 : unsigned int cost = seq_cost (seq, speed_p);
819 :
820 169367 : if (cost <= if_info->original_cost)
821 : return true;
822 :
823 : /* When compiling for size, we can make a reasonably accurately guess
824 : at the size growth. When compiling for speed, use the maximum. */
825 88344 : return speed_p && cost <= if_info->max_seq_cost;
826 : }
827 :
828 : /* Helper function for noce_try_store_flag*. Return NULL_RTX on failure,
829 : including when REVERSEP is requested but the condition cannot be
830 : reversed; callers may rely on this and need not pre-check. */
831 :
832 : static rtx
833 59171 : noce_emit_store_flag (struct noce_if_info *if_info, rtx x, bool reversep,
834 : int normalize)
835 : {
836 59171 : rtx cond = if_info->cond;
837 59171 : bool cond_complex;
838 59171 : enum rtx_code code;
839 :
840 59171 : cond_complex = (! general_operand (XEXP (cond, 0), VOIDmode)
841 59171 : || ! general_operand (XEXP (cond, 1), VOIDmode));
842 :
843 : /* If earliest == jump, or when the condition is complex, try to
844 : build the store_flag insn directly. */
845 :
846 34603 : if (cond_complex)
847 : {
848 24568 : rtx set = pc_set (if_info->jump);
849 24568 : cond = XEXP (SET_SRC (set), 0);
850 24568 : if (GET_CODE (XEXP (SET_SRC (set), 2)) == LABEL_REF
851 24568 : && label_ref_label (XEXP (SET_SRC (set), 2)) == JUMP_LABEL (if_info->jump))
852 0 : reversep = !reversep;
853 24568 : if (if_info->then_else_reversed)
854 21800 : reversep = !reversep;
855 : }
856 34603 : else if (reversep
857 17784 : && if_info->rev_cond
858 17784 : && general_operand (XEXP (if_info->rev_cond, 0), VOIDmode)
859 52387 : && general_operand (XEXP (if_info->rev_cond, 1), VOIDmode))
860 : {
861 17784 : cond = if_info->rev_cond;
862 17784 : reversep = false;
863 : }
864 :
865 59171 : if (reversep)
866 4455 : code = reversed_comparison_code (cond, if_info->jump);
867 : else
868 54716 : code = GET_CODE (cond);
869 :
870 : /* reversed_comparison_code returns UNKNOWN for an unordered code, or a
871 : CC-mode compare it cannot trace; neither path below can use that. */
872 59171 : if (code == UNKNOWN)
873 : return NULL_RTX;
874 :
875 59171 : if ((if_info->cond_earliest == if_info->jump || cond_complex)
876 24568 : && (normalize == 0 || STORE_FLAG_VALUE == normalize))
877 : {
878 18814 : rtx src = gen_rtx_fmt_ee (code, GET_MODE (x), XEXP (cond, 0),
879 : XEXP (cond, 1));
880 18814 : rtx set = gen_rtx_SET (x, src);
881 :
882 18814 : start_sequence ();
883 18814 : rtx_insn *insn = emit_insn (set);
884 :
885 18814 : if (recog_memoized (insn) >= 0)
886 : {
887 8453 : rtx_insn *seq = end_sequence ();
888 8453 : emit_insn (seq);
889 :
890 8453 : if_info->cond_earliest = if_info->jump;
891 :
892 8453 : return x;
893 : }
894 :
895 10361 : end_sequence ();
896 : }
897 :
898 : /* Don't even try if the comparison operands or the mode of X are weird. */
899 50718 : if (cond_complex || !SCALAR_INT_MODE_P (GET_MODE (x)))
900 : return NULL_RTX;
901 :
902 : /* Don't try if mode of X is more than the max fixed mode size. */
903 103779 : if (known_le (MAX_FIXED_MODE_SIZE, GET_MODE_BITSIZE (GET_MODE (x))))
904 : return NULL_RTX;
905 :
906 33261 : return emit_store_flag (x, code, XEXP (cond, 0),
907 : XEXP (cond, 1), VOIDmode,
908 33261 : (code == LTU || code == LEU
909 66522 : || code == GEU || code == GTU), normalize);
910 : }
911 :
912 : /* Return true if X can be safely forced into a register by copy_to_mode_reg
913 : / force_operand. */
914 :
915 : static bool
916 994426 : noce_can_force_operand (rtx x)
917 : {
918 994806 : if (general_operand (x, VOIDmode))
919 : return true;
920 292934 : if (SUBREG_P (x))
921 : {
922 380 : if (!noce_can_force_operand (SUBREG_REG (x)))
923 : return false;
924 : return true;
925 : }
926 292554 : if (ARITHMETIC_P (x))
927 : {
928 247276 : if (!noce_can_force_operand (XEXP (x, 0))
929 247276 : || !noce_can_force_operand (XEXP (x, 1)))
930 : return false;
931 244850 : switch (GET_CODE (x))
932 : {
933 : case MULT:
934 : case MOD:
935 : case UDIV:
936 : case UMOD:
937 : return true;
938 483 : case DIV:
939 483 : if (INTEGRAL_MODE_P (GET_MODE (x)))
940 : return true;
941 : /* FALLTHRU */
942 237865 : default:
943 237865 : auto optab = code_to_optab (GET_CODE (x));
944 237865 : if (!optab)
945 : return false;
946 235016 : return optab_handler (optab, GET_MODE (x));
947 : }
948 : }
949 45278 : if (UNARY_P (x))
950 : {
951 40047 : if (!noce_can_force_operand (XEXP (x, 0)))
952 : return false;
953 40034 : switch (GET_CODE (x))
954 : {
955 : case ZERO_EXTEND:
956 : case SIGN_EXTEND:
957 : case TRUNCATE:
958 : case FLOAT_EXTEND:
959 : case FLOAT_TRUNCATE:
960 : case FIX:
961 : case UNSIGNED_FIX:
962 : case FLOAT:
963 : case UNSIGNED_FLOAT:
964 : return true;
965 5023 : default:
966 5023 : auto optab = code_to_optab (GET_CODE (x));
967 5023 : if (!optab)
968 : return false;
969 5023 : return optab_handler (optab, GET_MODE (x));
970 : }
971 : }
972 : return false;
973 : }
974 :
975 : /* Emit instruction to move an rtx, possibly into STRICT_LOW_PART.
976 : X is the destination/target and Y is the value to copy. */
977 :
978 : static void
979 114242 : noce_emit_move_insn (rtx x, rtx y)
980 : {
981 114242 : machine_mode outmode;
982 114242 : rtx outer, inner;
983 114242 : poly_int64 bitpos;
984 :
985 114242 : if (GET_CODE (x) != STRICT_LOW_PART)
986 : {
987 114242 : rtx_insn *seq, *insn;
988 114242 : rtx target;
989 114242 : optab ot;
990 :
991 114242 : start_sequence ();
992 : /* Check that the SET_SRC is reasonable before calling emit_move_insn,
993 : otherwise construct a suitable SET pattern ourselves. */
994 114322 : insn = (OBJECT_P (y) || CONSTANT_P (y) || GET_CODE (y) == SUBREG)
995 114322 : ? emit_move_insn (x, y)
996 81066 : : emit_insn (gen_rtx_SET (x, y));
997 114242 : seq = end_sequence ();
998 :
999 114242 : if (recog_memoized (insn) <= 0)
1000 : {
1001 46824 : if (GET_CODE (x) == ZERO_EXTRACT)
1002 : {
1003 0 : rtx op = XEXP (x, 0);
1004 0 : unsigned HOST_WIDE_INT size = INTVAL (XEXP (x, 1));
1005 0 : unsigned HOST_WIDE_INT start = INTVAL (XEXP (x, 2));
1006 :
1007 : /* store_bit_field expects START to be relative to
1008 : BYTES_BIG_ENDIAN and adjusts this value for machines with
1009 : BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN. In order to be able to
1010 : invoke store_bit_field again it is necessary to have the START
1011 : value from the first call. */
1012 0 : if (BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN)
1013 : {
1014 : if (MEM_P (op))
1015 : start = BITS_PER_UNIT - start - size;
1016 : else
1017 : {
1018 : gcc_assert (REG_P (op));
1019 : start = BITS_PER_WORD - start - size;
1020 : }
1021 : }
1022 :
1023 0 : gcc_assert (start < (MEM_P (op) ? BITS_PER_UNIT : BITS_PER_WORD));
1024 0 : store_bit_field (op, size, start, 0, 0, GET_MODE (x), y, false,
1025 : false);
1026 0 : return;
1027 : }
1028 :
1029 46824 : switch (GET_RTX_CLASS (GET_CODE (y)))
1030 : {
1031 926 : case RTX_UNARY:
1032 926 : ot = code_to_optab (GET_CODE (y));
1033 926 : if (ot && noce_can_force_operand (XEXP (y, 0)))
1034 : {
1035 732 : start_sequence ();
1036 732 : target = expand_unop (GET_MODE (y), ot, XEXP (y, 0), x, 0);
1037 732 : if (target != NULL_RTX)
1038 : {
1039 732 : if (target != x)
1040 0 : emit_move_insn (x, target);
1041 732 : seq = get_insns ();
1042 : }
1043 732 : end_sequence ();
1044 : }
1045 : break;
1046 :
1047 15107 : case RTX_BIN_ARITH:
1048 15107 : case RTX_COMM_ARITH:
1049 15107 : ot = code_to_optab (GET_CODE (y));
1050 15107 : if (ot
1051 15107 : && noce_can_force_operand (XEXP (y, 0))
1052 30214 : && noce_can_force_operand (XEXP (y, 1)))
1053 : {
1054 15107 : start_sequence ();
1055 15107 : target = expand_binop (GET_MODE (y), ot,
1056 : XEXP (y, 0), XEXP (y, 1),
1057 : x, 0, OPTAB_DIRECT);
1058 15107 : if (target != NULL_RTX)
1059 : {
1060 15107 : if (target != x)
1061 0 : emit_move_insn (x, target);
1062 15107 : seq = get_insns ();
1063 : }
1064 15107 : end_sequence ();
1065 : }
1066 : break;
1067 :
1068 : default:
1069 : break;
1070 : }
1071 : }
1072 :
1073 114242 : emit_insn (seq);
1074 114242 : return;
1075 : }
1076 :
1077 0 : outer = XEXP (x, 0);
1078 0 : inner = XEXP (outer, 0);
1079 0 : outmode = GET_MODE (outer);
1080 0 : bitpos = SUBREG_BYTE (outer) * BITS_PER_UNIT;
1081 0 : store_bit_field (inner, GET_MODE_BITSIZE (outmode), bitpos,
1082 : 0, 0, outmode, y, false, false);
1083 : }
1084 :
1085 : /* Return the CC reg if it is used in COND. */
1086 :
1087 : static rtx
1088 4200409 : cc_in_cond (rtx cond)
1089 : {
1090 4200409 : if (have_cbranchcc4 && cond
1091 4200409 : && GET_MODE_CLASS (GET_MODE (XEXP (cond, 0))) == MODE_CC)
1092 141146 : return XEXP (cond, 0);
1093 :
1094 : return NULL_RTX;
1095 : }
1096 :
1097 : /* Return sequence of instructions generated by if conversion. This
1098 : function calls end_sequence() to end the current stream, ensures
1099 : that the instructions are unshared, recognizable non-jump insns.
1100 : On failure, this function returns a NULL_RTX. */
1101 :
1102 : static rtx_insn *
1103 227239 : end_ifcvt_sequence (struct noce_if_info *if_info)
1104 : {
1105 227239 : rtx_insn *insn;
1106 227239 : rtx_insn *seq = get_insns ();
1107 227239 : rtx cc = cc_in_cond (if_info->cond);
1108 :
1109 227239 : set_used_flags (if_info->x);
1110 227239 : set_used_flags (if_info->cond);
1111 227239 : set_used_flags (if_info->a);
1112 227239 : set_used_flags (if_info->b);
1113 :
1114 1175795 : for (insn = seq; insn; insn = NEXT_INSN (insn))
1115 721317 : set_used_flags (insn);
1116 :
1117 227239 : unshare_all_rtl_in_chain (seq);
1118 227239 : end_sequence ();
1119 :
1120 : /* Make sure that all of the instructions emitted are recognizable,
1121 : and that we haven't introduced a new jump instruction.
1122 : As an exercise for the reader, build a general mechanism that
1123 : allows proper placement of required clobbers. */
1124 1143385 : for (insn = seq; insn; insn = NEXT_INSN (insn))
1125 720812 : if (JUMP_P (insn)
1126 720812 : || recog_memoized (insn) == -1
1127 : /* Make sure new generated code does not clobber CC. */
1128 1409794 : || (cc && set_of (cc, insn)))
1129 : return NULL;
1130 :
1131 : return seq;
1132 : }
1133 :
1134 : /* Return true iff the then and else basic block (if it exists)
1135 : consist of a single simple set instruction. */
1136 :
1137 : static bool
1138 3173589 : noce_simple_bbs (struct noce_if_info *if_info)
1139 : {
1140 0 : if (!if_info->then_simple)
1141 : return false;
1142 :
1143 2941459 : if (if_info->else_bb)
1144 0 : return if_info->else_simple;
1145 :
1146 : return true;
1147 : }
1148 :
1149 : /* Convert "if (a != b) x = a; else x = b" into "x = a" and
1150 : "if (a == b) x = a; else x = b" into "x = b". */
1151 :
1152 : static bool
1153 252809 : noce_try_move (struct noce_if_info *if_info)
1154 : {
1155 252809 : rtx cond = if_info->cond;
1156 252809 : enum rtx_code code = GET_CODE (cond);
1157 252809 : rtx y;
1158 252809 : rtx_insn *seq;
1159 :
1160 252809 : if (code != NE && code != EQ)
1161 : return false;
1162 :
1163 256857 : if (!noce_simple_bbs (if_info))
1164 : return false;
1165 :
1166 : /* This optimization isn't valid if either A or B could be a NaN
1167 : or a signed zero. */
1168 176559 : if (HONOR_NANS (if_info->x)
1169 176559 : || HONOR_SIGNED_ZEROS (if_info->x))
1170 : return false;
1171 :
1172 : /* Check whether the operands of the comparison are A and in
1173 : either order. */
1174 151323 : if ((rtx_equal_p (if_info->a, XEXP (cond, 0))
1175 2320 : && rtx_equal_p (if_info->b, XEXP (cond, 1)))
1176 153631 : || (rtx_equal_p (if_info->a, XEXP (cond, 1))
1177 15618 : && rtx_equal_p (if_info->b, XEXP (cond, 0))))
1178 : {
1179 21 : if (!rtx_interchangeable_p (if_info->a, if_info->b))
1180 : return false;
1181 :
1182 0 : y = (code == EQ) ? if_info->a : if_info->b;
1183 :
1184 : /* Avoid generating the move if the source is the destination. */
1185 0 : if (! rtx_equal_p (if_info->x, y))
1186 : {
1187 0 : start_sequence ();
1188 0 : noce_emit_move_insn (if_info->x, y);
1189 0 : seq = end_ifcvt_sequence (if_info);
1190 0 : if (!seq)
1191 : return false;
1192 :
1193 0 : emit_insn_before_setloc (seq, if_info->jump,
1194 0 : INSN_LOCATION (if_info->insn_a));
1195 : }
1196 0 : if_info->transform_name = "noce_try_move";
1197 0 : return true;
1198 : }
1199 : return false;
1200 : }
1201 :
1202 : /* If a sign bit test is selecting across constants, we may be able
1203 : to generate efficient code utilizing the -1/0 result of a sign
1204 : bit splat idiom.
1205 :
1206 : Do this before trying the generalized conditional move as these
1207 : (when applicable) are hopefully faster than a conditional move. */
1208 :
1209 : static bool
1210 201070 : noce_try_sign_bit_splat (struct noce_if_info *if_info)
1211 : {
1212 201070 : rtx cond = if_info->cond;
1213 201070 : enum rtx_code code = GET_CODE (cond);
1214 :
1215 : /* We're looking for sign bit tests, so only a few cases are
1216 : interesting. LT/GE 0 LE/GT -1. */
1217 201070 : if (((code == LT || code == GE)
1218 10993 : && XEXP (cond, 1) == CONST0_RTX (GET_MODE (cond)))
1219 198741 : || ((code == LE || code == GT)
1220 11350 : && XEXP (cond, 1) == CONSTM1_RTX (GET_MODE (cond))))
1221 : ;
1222 : else
1223 : return false;
1224 :
1225 : /* It would be good if this could be extended since constant synthesis
1226 : on some platforms will result in blocks which fail this test. */
1227 10753 : if (!noce_simple_bbs (if_info))
1228 : return false;
1229 :
1230 : /* Only try this for constants in the true/false arms and a REG
1231 : destination. We could select between 0 and a REG pretty
1232 : easily with a logical AND. */
1233 6050 : if (!CONST_INT_P (if_info->a)
1234 1962 : || !CONST_INT_P (if_info->b)
1235 660 : || !REG_P (if_info->x))
1236 : return false;
1237 :
1238 660 : machine_mode mode = GET_MODE (if_info->x);
1239 :
1240 : /* If the mode of the destination does not match the mode of
1241 : the value we're testing, then this optimization is not valid. */
1242 660 : if (mode != GET_MODE (XEXP (cond, 0)))
1243 : return false;
1244 :
1245 206 : HOST_WIDE_INT val_a = INTVAL (if_info->a);
1246 206 : HOST_WIDE_INT val_b = INTVAL (if_info->b);
1247 :
1248 206 : rtx_insn *seq;
1249 206 : start_sequence ();
1250 :
1251 : /* We're testing the sign bit of this operand. */
1252 206 : rtx condop = XEXP (cond, 0);
1253 :
1254 : /* To splat the sign bit we arithmetically shift the
1255 : input value right by the size of the object - 1 bits.
1256 :
1257 : Note some targets do not have strong shifters, but do have
1258 : alternative ways to generate the sign bit splat. The
1259 : profitability test when we end the sequence should reject
1260 : cases when the branchy sequence is better. */
1261 206 : int splat_count = GET_MODE_BITSIZE (GET_MODE (condop)).to_constant () - 1;
1262 206 : rtx splat = GEN_INT (splat_count);
1263 :
1264 206 : rtx temp;
1265 206 : temp = expand_simple_binop (GET_MODE (XEXP (cond, 0)), ASHIFTRT,
1266 : XEXP (cond, 0), splat, NULL_RTX,
1267 : false, OPTAB_WIDEN);
1268 206 : if (!temp)
1269 0 : goto fail;
1270 :
1271 : /* IOR of anything with -1 still results in -1. So we can
1272 : IOR the other operand to generate a select between -1 and
1273 : an arbitrary constant. */
1274 206 : if (val_a == -1)
1275 : {
1276 47 : if (code == LT || code == LE)
1277 : {
1278 2 : temp = expand_simple_unop (mode, NOT, temp, NULL_RTX, true);
1279 2 : if (!temp)
1280 0 : goto fail;
1281 : }
1282 :
1283 47 : temp = expand_simple_binop (mode, IOR, temp, GEN_INT (val_b),
1284 : if_info->x, false, OPTAB_WIDEN);
1285 : }
1286 : /* AND of anything with 0 is still zero. So we can AND
1287 : with the -1 operand with the a constant to select
1288 : between the constant and zero. */
1289 159 : else if (val_b == 0)
1290 : {
1291 0 : if (code == LT || code == LE)
1292 : {
1293 0 : temp = expand_simple_unop (mode, NOT, temp, NULL_RTX, true);
1294 0 : if (!temp)
1295 0 : goto fail;
1296 : }
1297 :
1298 : /* Since we know the value is currently -1 or 0, some constants may
1299 : be more easily handled by shifting the value again. A right
1300 : logical shift constructs 2^n-1 constants a left shift constructs
1301 : ~(2^n-1) constants. Given some targets don't have efficient
1302 : shifts, generate the obvious RTL for both forms and select the
1303 : one with smaller cost. */
1304 0 : rtx and_form = gen_rtx_AND (mode, temp, GEN_INT (val_a));
1305 0 : rtx shift_left = gen_rtx_ASHIFT (mode, temp, GEN_INT (ctz_hwi (val_a)));
1306 0 : HOST_WIDE_INT rshift_count
1307 0 : = (clz_hwi (val_a) & (GET_MODE_PRECISION (mode).to_constant() - 1));
1308 0 : rtx shift_right = gen_rtx_LSHIFTRT (mode, temp, GEN_INT (rshift_count));
1309 0 : bool speed_p = optimize_insn_for_speed_p ();
1310 0 : if (exact_log2 (val_a + 1) >= 0
1311 0 : && (rtx_cost (shift_right, mode, SET, 1, speed_p)
1312 0 : < rtx_cost (and_form, mode, SET, 1, speed_p)))
1313 0 : temp = expand_simple_binop (mode, LSHIFTRT, temp,
1314 : GEN_INT (rshift_count),
1315 : if_info->x, false, OPTAB_WIDEN);
1316 0 : else if (exact_log2 (~val_a + 1) >= 0
1317 0 : && (rtx_cost (shift_left, mode, SET, 1, speed_p)
1318 0 : < rtx_cost (and_form, mode, SET, 1, speed_p)))
1319 0 : temp = expand_simple_binop (mode, ASHIFT, temp,
1320 0 : GEN_INT (ctz_hwi (val_a)),
1321 : if_info->x, false, OPTAB_WIDEN);
1322 : else
1323 0 : temp = expand_simple_binop (mode, AND, temp, GEN_INT (val_a),
1324 : if_info->x, false, OPTAB_WIDEN);
1325 : }
1326 : /* Same cases, but with the test or arms swapped. These
1327 : can be realized as well, though it typically costs
1328 : an extra instruction. */
1329 159 : else if (val_b == -1)
1330 : {
1331 46 : if (code != LT && code != LE)
1332 : {
1333 2 : temp = expand_simple_unop (mode, NOT, temp, NULL_RTX, true);
1334 2 : if (!temp)
1335 0 : goto fail;
1336 : }
1337 :
1338 46 : temp = expand_simple_binop (mode, IOR, temp, GEN_INT (val_a),
1339 : if_info->x, false, OPTAB_WIDEN);
1340 : }
1341 113 : else if (val_a == 0)
1342 : {
1343 82 : if (code != LT && code != LE)
1344 : {
1345 9 : temp = expand_simple_unop (mode, NOT, temp, NULL_RTX, true);
1346 9 : if (!temp)
1347 0 : goto fail;
1348 : }
1349 :
1350 : /* Since we know the value is currently -1 or 0, some constants may
1351 : be more easily handled by shifting the value again. A right
1352 : logical shift constructs 2^n-1 constants a left shift constructs
1353 : ~(2^n-1) constants. Given some targets don't have efficient
1354 : shifts, generate the obvious RTL for both forms and select the
1355 : one with smaller cost. */
1356 82 : rtx and_form = gen_rtx_AND (mode, temp, GEN_INT (val_b));
1357 82 : rtx shift_left = gen_rtx_ASHIFT (mode, temp, GEN_INT (ctz_hwi (val_b)));
1358 82 : HOST_WIDE_INT rshift_count
1359 82 : = (clz_hwi (val_b) & (GET_MODE_PRECISION (mode).to_constant() - 1));
1360 82 : rtx shift_right = gen_rtx_LSHIFTRT (mode, temp, GEN_INT (rshift_count));
1361 82 : bool speed_p = optimize_insn_for_speed_p ();
1362 82 : if (exact_log2 (val_b + 1) >= 0
1363 50 : && (rtx_cost (shift_right, mode, SET, 1, speed_p)
1364 25 : < rtx_cost (and_form, mode, SET, 1, speed_p)))
1365 3 : temp = expand_simple_binop (mode, LSHIFTRT, temp,
1366 : GEN_INT (rshift_count),
1367 : if_info->x, false, OPTAB_WIDEN);
1368 79 : else if (exact_log2 (~val_b + 1) >= 0
1369 0 : && (rtx_cost (shift_left, mode, SET, 1, speed_p)
1370 0 : < rtx_cost (and_form, mode, SET, 1, speed_p)))
1371 0 : temp = expand_simple_binop (mode, ASHIFT, temp,
1372 0 : GEN_INT (ctz_hwi (val_b)),
1373 : if_info->x, false, OPTAB_WIDEN);
1374 : else
1375 79 : temp = expand_simple_binop (mode, AND, temp, GEN_INT (val_b),
1376 : if_info->x, false, OPTAB_WIDEN);
1377 : }
1378 : /* Nothing worked. */
1379 : else
1380 : temp = NULL_RTX;
1381 :
1382 175 : if (!temp)
1383 31 : goto fail;
1384 :
1385 : /* Move into the final destination if the value wasn't
1386 : constructed there. */
1387 175 : if (if_info->x != temp)
1388 0 : emit_move_insn (if_info->x, temp);
1389 :
1390 : /* This ends the sequence and tests the cost model. */
1391 175 : seq = end_ifcvt_sequence (if_info);
1392 175 : if (!seq || !targetm.noce_conversion_profitable_p (seq, if_info))
1393 : return false;
1394 :
1395 : /* Everything looks good. Install the if-converted sequence. */
1396 175 : emit_insn_before_setloc (seq, if_info->jump,
1397 175 : INSN_LOCATION (if_info->insn_a));
1398 175 : if_info->transform_name = "splat_sign_bit_trivial";
1399 175 : return true;
1400 :
1401 31 : fail:
1402 31 : end_ifcvt_sequence (if_info);
1403 31 : return false;
1404 : }
1405 :
1406 :
1407 : /* Try forming an IF_THEN_ELSE (cond, b, a) and collapsing that
1408 : through simplify_rtx. Sometimes that can eliminate the IF_THEN_ELSE.
1409 : If that is the case, emit the result into x. */
1410 :
1411 : static bool
1412 252809 : noce_try_ifelse_collapse (struct noce_if_info * if_info)
1413 : {
1414 338830 : if (!noce_simple_bbs (if_info))
1415 : return false;
1416 :
1417 234203 : machine_mode mode = GET_MODE (if_info->x);
1418 234203 : rtx if_then_else = simplify_gen_ternary (IF_THEN_ELSE, mode, mode,
1419 : if_info->cond, if_info->b,
1420 : if_info->a);
1421 :
1422 234203 : if (GET_CODE (if_then_else) == IF_THEN_ELSE)
1423 : return false;
1424 :
1425 48582 : rtx_insn *seq;
1426 48582 : start_sequence ();
1427 48582 : noce_emit_move_insn (if_info->x, if_then_else);
1428 48582 : seq = end_ifcvt_sequence (if_info);
1429 48582 : if (!seq)
1430 : return false;
1431 :
1432 17791 : emit_insn_before_setloc (seq, if_info->jump,
1433 17791 : INSN_LOCATION (if_info->insn_a));
1434 :
1435 17791 : if_info->transform_name = "noce_try_ifelse_collapse";
1436 17791 : return true;
1437 : }
1438 :
1439 :
1440 : /* Convert "if (test) x = 1; else x = 0".
1441 :
1442 : Only try 0 and STORE_FLAG_VALUE here. Other combinations will be
1443 : tried in noce_try_store_flag_constants after noce_try_cmove has had
1444 : a go at the conversion. */
1445 :
1446 : static bool
1447 235018 : noce_try_store_flag (struct noce_if_info *if_info)
1448 : {
1449 235018 : bool reversep;
1450 235018 : rtx target;
1451 235018 : rtx_insn *seq;
1452 :
1453 307755 : if (!noce_simple_bbs (if_info))
1454 : return false;
1455 :
1456 216412 : if (CONST_INT_P (if_info->b)
1457 73779 : && INTVAL (if_info->b) == STORE_FLAG_VALUE
1458 13410 : && if_info->a == const0_rtx)
1459 : reversep = false;
1460 205933 : else if (if_info->b == const0_rtx
1461 30391 : && CONST_INT_P (if_info->a)
1462 20752 : && INTVAL (if_info->a) == STORE_FLAG_VALUE)
1463 : reversep = true;
1464 : else
1465 : return false;
1466 :
1467 30792 : start_sequence ();
1468 :
1469 30792 : target = noce_emit_store_flag (if_info, if_info->x, reversep, 0);
1470 30792 : if (target)
1471 : {
1472 25925 : if (target != if_info->x)
1473 2982 : noce_emit_move_insn (if_info->x, target);
1474 :
1475 25925 : seq = end_ifcvt_sequence (if_info);
1476 25925 : if (! seq)
1477 : return false;
1478 :
1479 25925 : emit_insn_before_setloc (seq, if_info->jump,
1480 25925 : INSN_LOCATION (if_info->insn_a));
1481 25925 : if_info->transform_name = "noce_try_store_flag";
1482 25925 : return true;
1483 : }
1484 : else
1485 : {
1486 4867 : end_sequence ();
1487 4867 : return false;
1488 : }
1489 : }
1490 :
1491 :
1492 : /* Convert "if (test) x = -A; else x = A" into
1493 : x = A; if (test) x = -x if the machine can do the
1494 : conditional negate form of this cheaply.
1495 : Try this before noce_try_cmove that will just load the
1496 : immediates into two registers and do a conditional select
1497 : between them. If the target has a conditional negate or
1498 : conditional invert operation we can save a potentially
1499 : expensive constant synthesis. */
1500 :
1501 : static bool
1502 208996 : noce_try_inverse_constants (struct noce_if_info *if_info)
1503 : {
1504 272102 : if (!noce_simple_bbs (if_info))
1505 : return false;
1506 :
1507 190390 : if (!CONST_INT_P (if_info->a)
1508 51739 : || !CONST_INT_P (if_info->b)
1509 21211 : || !REG_P (if_info->x))
1510 : return false;
1511 :
1512 21211 : machine_mode mode = GET_MODE (if_info->x);
1513 :
1514 21211 : HOST_WIDE_INT val_a = INTVAL (if_info->a);
1515 21211 : HOST_WIDE_INT val_b = INTVAL (if_info->b);
1516 :
1517 21211 : rtx cond = if_info->cond;
1518 :
1519 21211 : rtx x = if_info->x;
1520 21211 : rtx target;
1521 :
1522 21211 : start_sequence ();
1523 :
1524 21211 : rtx_code code;
1525 21211 : if (val_b != HOST_WIDE_INT_MIN && val_a == -val_b)
1526 : code = NEG;
1527 19937 : else if (val_a == ~val_b)
1528 : code = NOT;
1529 : else
1530 : {
1531 19869 : end_sequence ();
1532 19869 : return false;
1533 : }
1534 :
1535 1342 : rtx tmp = gen_reg_rtx (mode);
1536 1342 : noce_emit_move_insn (tmp, if_info->a);
1537 :
1538 1342 : target = emit_conditional_neg_or_complement (x, code, mode, cond, tmp, tmp);
1539 :
1540 1342 : if (target)
1541 : {
1542 0 : rtx_insn *seq = get_insns ();
1543 :
1544 0 : if (!seq)
1545 : {
1546 0 : end_sequence ();
1547 0 : return false;
1548 : }
1549 :
1550 0 : if (target != if_info->x)
1551 0 : noce_emit_move_insn (if_info->x, target);
1552 :
1553 0 : seq = end_ifcvt_sequence (if_info);
1554 :
1555 0 : if (!seq)
1556 : return false;
1557 :
1558 0 : emit_insn_before_setloc (seq, if_info->jump,
1559 0 : INSN_LOCATION (if_info->insn_a));
1560 0 : if_info->transform_name = "noce_try_inverse_constants";
1561 0 : return true;
1562 : }
1563 :
1564 1342 : end_sequence ();
1565 1342 : return false;
1566 : }
1567 :
1568 : /* Check if OP is supported by conditional zero based if conversion,
1569 : returning TRUE if satisfied otherwise FALSE.
1570 :
1571 : OP is the operation to check. */
1572 :
1573 : static bool
1574 478670 : noce_cond_zero_binary_op_supported (rtx op)
1575 : {
1576 478670 : enum rtx_code opcode = GET_CODE (op);
1577 :
1578 0 : if (opcode == PLUS || opcode == MINUS || opcode == IOR || opcode == XOR
1579 : || opcode == ASHIFT || opcode == ASHIFTRT || opcode == LSHIFTRT
1580 : || opcode == ROTATE || opcode == ROTATERT || opcode == AND)
1581 0 : return true;
1582 :
1583 : return false;
1584 : }
1585 :
1586 : /* Convert "if (test) x = a; else x = a OP c " where c is 2^n.
1587 :
1588 : We can shift the output of a set flag insn left to generate 2^n
1589 : cheaply, then apply OP unconditionally. This works even if the
1590 : target does not have a conditional zero idiom. On targets such
1591 : as RISC-V this sequence may also encode better.
1592 :
1593 : This is based on noce_try_store_flag_constants. */
1594 :
1595 : static bool
1596 205839 : noce_try_shifted_store_flag (struct noce_if_info *if_info)
1597 : {
1598 205839 : rtx target;
1599 205839 : rtx_insn *seq;
1600 205839 : machine_mode mode = GET_MODE (if_info->x);
1601 205839 : rtx common = NULL_RTX;
1602 205839 : rtx_code code = UNKNOWN;
1603 :
1604 205839 : if (STORE_FLAG_VALUE != 1)
1605 : return false;
1606 :
1607 265862 : if (!noce_simple_bbs (if_info))
1608 : return false;
1609 :
1610 187233 : rtx a = if_info->a;
1611 187233 : rtx b = if_info->b;
1612 :
1613 : /* Most binary operators are allowed, essentially the same set
1614 : as the condzero arithmetic paths, with the exception of AND
1615 : which could be handled if we were inclined. */
1616 187233 : int shiftval;
1617 187233 : bool reversed = false;
1618 187233 : if (noce_cond_zero_binary_op_supported (a)
1619 24493 : && GET_CODE (a) != AND
1620 24284 : && GET_CODE (b) == REG
1621 20552 : && rtx_equal_p (XEXP (a, 0), b)
1622 18575 : && CONST_INT_P (XEXP (a, 1))
1623 9105 : && pow2p_hwi (INTVAL (XEXP (a, 1))))
1624 : {
1625 6633 : code = GET_CODE (a);
1626 6633 : common = XEXP (a, 0);
1627 6633 : shiftval = exact_log2 (INTVAL (XEXP (a, 1)));
1628 :
1629 : /* When the condition is true, we branch around A and thus we want
1630 : the condition reversed from what you might expect. */
1631 : reversed = true;
1632 : }
1633 180600 : else if (noce_cond_zero_binary_op_supported (b)
1634 2348 : && GET_CODE (b) != AND
1635 2317 : && GET_CODE (a) == REG
1636 253 : && rtx_equal_p (XEXP (b, 0), a)
1637 112 : && CONST_INT_P (XEXP (b, 1))
1638 70 : && pow2p_hwi (INTVAL (XEXP (b, 1))))
1639 : {
1640 31 : code = GET_CODE (b);
1641 31 : common = XEXP (b, 0);
1642 31 : shiftval = exact_log2 (INTVAL (XEXP (b, 1)));
1643 : }
1644 :
1645 :
1646 : /* If CODE hasn't been reset, then the basic expression form was wrong and
1647 : we can not optimize. */
1648 6664 : if (code == UNKNOWN)
1649 : return false;
1650 :
1651 6664 : start_sequence ();
1652 :
1653 : /* If X and COMMON are the same, then we're going to need a temporary. */
1654 6664 : if (common && rtx_equal_p (common, if_info->x))
1655 : {
1656 6089 : common = gen_reg_rtx (mode);
1657 6089 : noce_emit_move_insn (common, if_info->x);
1658 : }
1659 :
1660 6664 : target = noce_emit_store_flag (if_info, if_info->x, reversed, 1);
1661 6664 : if (!target)
1662 : {
1663 749 : end_sequence ();
1664 749 : return false;
1665 : }
1666 :
1667 : /* Right now TARGET has the value 1/0. A left shift will produce the
1668 : target value. Unnecessary if the shift value is zero. */
1669 5915 : if (shiftval != 0)
1670 1207 : target = expand_simple_binop (mode, ASHIFT, target,
1671 : GEN_INT (shiftval),
1672 : NULL_RTX, 0, OPTAB_WIDEN);
1673 :
1674 5915 : if (!target)
1675 : {
1676 0 : end_sequence ();
1677 0 : return false;
1678 : }
1679 :
1680 : /* Now we just need to apply the code to COMMON and TARGET. */
1681 5915 : target = expand_simple_binop (mode, code,
1682 : common, target,
1683 : NULL_RTX, 0, OPTAB_WIDEN);
1684 :
1685 5915 : if (!target)
1686 : {
1687 0 : end_sequence ();
1688 0 : return false;
1689 : }
1690 :
1691 : /* If necessary, store the result into the proper destination. */
1692 5915 : if (target != if_info->x)
1693 5915 : noce_emit_move_insn (if_info->x, target);
1694 :
1695 5915 : seq = end_ifcvt_sequence (if_info);
1696 5915 : if (!seq || !targetm.noce_conversion_profitable_p (seq, if_info))
1697 : return false;
1698 :
1699 4769 : emit_insn_before_setloc (seq, if_info->jump,
1700 4769 : INSN_LOCATION (if_info->insn_a));
1701 4769 : if_info->transform_name = "noce_try_shifted_store_flag";
1702 :
1703 4769 : return true;
1704 : }
1705 :
1706 :
1707 : /* Convert "if (test) x = a; else x = b", for A and B constant.
1708 : Also allow A = y + c1, B = y + c2, with a common y between A
1709 : and B. */
1710 :
1711 : static bool
1712 208996 : noce_try_store_flag_constants (struct noce_if_info *if_info)
1713 : {
1714 208996 : rtx target;
1715 208996 : rtx_insn *seq;
1716 208996 : bool reversep;
1717 208996 : HOST_WIDE_INT itrue, ifalse, diff, tmp;
1718 208996 : int normalize;
1719 208996 : bool can_reverse;
1720 208996 : machine_mode mode = GET_MODE (if_info->x);
1721 208996 : rtx common = NULL_RTX;
1722 :
1723 208996 : rtx a = if_info->a;
1724 208996 : rtx b = if_info->b;
1725 :
1726 : /* Handle cases like x := test ? y + 3 : y + 4. */
1727 208996 : if (GET_CODE (a) == PLUS
1728 22535 : && GET_CODE (b) == PLUS
1729 1495 : && CONST_INT_P (XEXP (a, 1))
1730 574 : && CONST_INT_P (XEXP (b, 1))
1731 494 : && rtx_equal_p (XEXP (a, 0), XEXP (b, 0))
1732 : /* Allow expressions that are not using the result or plain
1733 : registers where we handle overlap below. */
1734 209432 : && (REG_P (XEXP (a, 0))
1735 6 : || (noce_operand_ok (XEXP (a, 0))
1736 6 : && ! reg_overlap_mentioned_p (if_info->x, XEXP (a, 0)))))
1737 : {
1738 436 : common = XEXP (a, 0);
1739 436 : a = XEXP (a, 1);
1740 436 : b = XEXP (b, 1);
1741 : }
1742 :
1743 272102 : if (!noce_simple_bbs (if_info))
1744 : return false;
1745 :
1746 190390 : if (CONST_INT_P (a)
1747 52163 : && CONST_INT_P (b))
1748 : {
1749 21635 : ifalse = INTVAL (a);
1750 21635 : itrue = INTVAL (b);
1751 21635 : bool subtract_flag_p = false;
1752 :
1753 21635 : diff = (unsigned HOST_WIDE_INT) itrue - ifalse;
1754 : /* Make sure we can represent the difference between the two values. */
1755 21635 : if ((diff > 0)
1756 21635 : != ((ifalse < 0) != (itrue < 0) ? ifalse < 0 : ifalse < itrue))
1757 : return false;
1758 :
1759 21521 : diff = trunc_int_for_mode (diff, mode);
1760 :
1761 21521 : can_reverse = noce_reversed_cond_code (if_info) != UNKNOWN;
1762 21521 : reversep = false;
1763 21521 : if (diff == STORE_FLAG_VALUE || diff == -STORE_FLAG_VALUE)
1764 : {
1765 12040 : normalize = 0;
1766 : /* We could collapse these cases but it is easier to follow the
1767 : diff/STORE_FLAG_VALUE combinations when they are listed
1768 : explicitly. */
1769 :
1770 : /* test ? 3 : 4
1771 : => 4 + (test != 0). */
1772 12040 : if (diff < 0 && STORE_FLAG_VALUE < 0)
1773 : reversep = false;
1774 : /* test ? 4 : 3
1775 : => can_reverse | 4 + (test == 0)
1776 : !can_reverse | 3 - (test != 0). */
1777 12040 : else if (diff > 0 && STORE_FLAG_VALUE < 0)
1778 : {
1779 : reversep = can_reverse;
1780 : subtract_flag_p = !can_reverse;
1781 : /* If we need to subtract the flag and we have PLUS-immediate
1782 : A and B then it is unlikely to be beneficial to play tricks
1783 : here. */
1784 : if (subtract_flag_p && common)
1785 : return false;
1786 : }
1787 : /* test ? 3 : 4
1788 : => can_reverse | 3 + (test == 0)
1789 : !can_reverse | 4 - (test != 0). */
1790 12040 : else if (diff < 0 && STORE_FLAG_VALUE > 0)
1791 : {
1792 6136 : reversep = can_reverse;
1793 6136 : subtract_flag_p = !can_reverse;
1794 : /* If we need to subtract the flag and we have PLUS-immediate
1795 : A and B then it is unlikely to be beneficial to play tricks
1796 : here. */
1797 6136 : if (subtract_flag_p && common)
1798 : return false;
1799 : }
1800 : /* test ? 4 : 3
1801 : => 4 + (test != 0). */
1802 : else if (diff > 0 && STORE_FLAG_VALUE > 0)
1803 : reversep = false;
1804 : else
1805 : gcc_unreachable ();
1806 : }
1807 : /* Is this (cond) ? 2^n : 0? */
1808 527 : else if (ifalse == 0 && pow2p_hwi (itrue)
1809 9481 : && STORE_FLAG_VALUE == 1)
1810 : normalize = 1;
1811 : /* Is this (cond) ? 0 : 2^n? */
1812 372 : else if (itrue == 0 && pow2p_hwi (ifalse)
1813 9474 : && STORE_FLAG_VALUE == 1)
1814 : {
1815 : normalize = 1;
1816 : reversep = true;
1817 : }
1818 : /* Is this (cond) ? -1 : x? */
1819 : else if (itrue == -1
1820 : && STORE_FLAG_VALUE == -1)
1821 : normalize = -1;
1822 : /* Is this (cond) ? x : -1? */
1823 : else if (ifalse == -1
1824 : && STORE_FLAG_VALUE == -1)
1825 : {
1826 : normalize = -1;
1827 : reversep = true;
1828 : }
1829 : else
1830 : return false;
1831 :
1832 6136 : if (reversep)
1833 : {
1834 6137 : std::swap (itrue, ifalse);
1835 6137 : diff = trunc_int_for_mode (-(unsigned HOST_WIDE_INT) diff, mode);
1836 : }
1837 :
1838 12048 : start_sequence ();
1839 :
1840 : /* If we have x := test ? x + 3 : x + 4 then move the original
1841 : x out of the way while we store flags. */
1842 12048 : if (common && rtx_equal_p (common, if_info->x))
1843 : {
1844 5 : common = gen_reg_rtx (mode);
1845 5 : noce_emit_move_insn (common, if_info->x);
1846 : }
1847 :
1848 12048 : target = noce_emit_store_flag (if_info, if_info->x, reversep, normalize);
1849 12048 : if (! target)
1850 : {
1851 4903 : end_sequence ();
1852 4903 : return false;
1853 : }
1854 :
1855 : /* if (test) x = 3; else x = 4;
1856 : => x = 3 + (test == 0); */
1857 7145 : if (diff == STORE_FLAG_VALUE || diff == -STORE_FLAG_VALUE)
1858 : {
1859 : /* Add the common part now. This may allow combine to merge this
1860 : with the store flag operation earlier into some sort of conditional
1861 : increment/decrement if the target allows it. */
1862 7137 : if (common)
1863 28 : target = expand_simple_binop (mode, PLUS,
1864 : target, common,
1865 : target, 0, OPTAB_WIDEN);
1866 :
1867 : /* Always use ifalse here. It should have been swapped with itrue
1868 : when appropriate when reversep is true. */
1869 14274 : target = expand_simple_binop (mode, subtract_flag_p ? MINUS : PLUS,
1870 7137 : gen_int_mode (ifalse, mode), target,
1871 : if_info->x, 0, OPTAB_WIDEN);
1872 : }
1873 : /* Other cases are not beneficial when the original A and B are PLUS
1874 : expressions. */
1875 8 : else if (common)
1876 : {
1877 0 : end_sequence ();
1878 0 : return false;
1879 : }
1880 : /* if (test) x = 8; else x = 0;
1881 : => x = (test != 0) << 3; */
1882 8 : else if (ifalse == 0 && (tmp = exact_log2 (itrue)) >= 0)
1883 : {
1884 8 : target = expand_simple_binop (mode, ASHIFT,
1885 : target, GEN_INT (tmp), if_info->x, 0,
1886 : OPTAB_WIDEN);
1887 : }
1888 :
1889 : /* if (test) x = -1; else x = b;
1890 : => x = -(test != 0) | b; */
1891 0 : else if (itrue == -1)
1892 : {
1893 0 : target = expand_simple_binop (mode, IOR,
1894 0 : target, gen_int_mode (ifalse, mode),
1895 : if_info->x, 0, OPTAB_WIDEN);
1896 : }
1897 : else
1898 : {
1899 0 : end_sequence ();
1900 0 : return false;
1901 : }
1902 :
1903 7145 : if (! target)
1904 : {
1905 0 : end_sequence ();
1906 0 : return false;
1907 : }
1908 :
1909 7145 : if (target != if_info->x)
1910 0 : noce_emit_move_insn (if_info->x, target);
1911 :
1912 7145 : seq = end_ifcvt_sequence (if_info);
1913 7145 : if (!seq || !targetm.noce_conversion_profitable_p (seq, if_info))
1914 : return false;
1915 :
1916 3157 : emit_insn_before_setloc (seq, if_info->jump,
1917 3157 : INSN_LOCATION (if_info->insn_a));
1918 3157 : if_info->transform_name = "noce_try_store_flag_constants";
1919 :
1920 3157 : return true;
1921 : }
1922 :
1923 : return false;
1924 : }
1925 :
1926 : /* This is trying to capture cases like dest = cond ? a : -1.
1927 :
1928 : The basic idea is to use a store-flag insn to generate a -1/0
1929 : value (directly or indirectly), then IOR that with the other
1930 : input. */
1931 : static bool
1932 200895 : noce_try_store_flag_logical (struct noce_if_info *if_info)
1933 : {
1934 200895 : rtx a = if_info->a;
1935 200895 : rtx b = if_info->b;
1936 200895 : rtx dest = if_info->x;
1937 200895 : machine_mode mode = GET_MODE (dest);
1938 :
1939 200895 : if (STORE_FLAG_VALUE != -1 && STORE_FLAG_VALUE != 1)
1940 : return false;
1941 :
1942 260636 : if (!noce_simple_bbs (if_info))
1943 : return false;
1944 :
1945 182289 : bool swapped = STORE_FLAG_VALUE == -1;
1946 182289 : if (a == CONSTM1_RTX (GET_MODE (dest))
1947 1642 : && if_info->rev_cond)
1948 : {
1949 : std::swap (a, b);
1950 182289 : swapped = !swapped;
1951 : }
1952 :
1953 182289 : if (b != CONSTM1_RTX (GET_MODE (dest)))
1954 : return false;
1955 :
1956 : /* If the other arm is not a REG/SUBREG, then punt. This is primarily to
1957 : let the target handle the constant case, which it can likely do better.
1958 : It also means we don't have to worry about non terminal expressions. */
1959 2497 : if (!REG_P (a) && !SUBREG_P (a))
1960 : return false;
1961 :
1962 : /* At this point we've got dest = cond ? a : -1. Emit the store flag and
1963 : adjust its value (if necessary) to -1/0. */
1964 1000 : start_sequence ();
1965 1000 : rtx temp = gen_reg_rtx (mode);
1966 1000 : rtx target = noce_emit_store_flag (if_info, temp, !swapped, false);
1967 1000 : if (!target)
1968 : {
1969 88 : end_sequence ();
1970 88 : return false;
1971 : }
1972 :
1973 912 : if (STORE_FLAG_VALUE == 1)
1974 : {
1975 912 : rtx x = gen_rtx_PLUS (mode, target, CONSTM1_RTX (mode));
1976 912 : emit_move_insn (target, x);
1977 : }
1978 :
1979 : /* Now we've got -1/0 in TARGET. We can just IOR with A. */
1980 912 : rtx x = gen_rtx_IOR (mode, target, a);
1981 912 : emit_move_insn (dest, x);
1982 :
1983 : /* We've generated all the RTL, make sure it recognizes and is
1984 : profitable. */
1985 912 : rtx_insn *seq = end_ifcvt_sequence (if_info);
1986 912 : if (!seq || !targetm.noce_conversion_profitable_p (seq, if_info))
1987 : return false;
1988 :
1989 0 : emit_insn_before_setloc (seq, if_info->jump,
1990 0 : INSN_LOCATION (if_info->insn_a));
1991 0 : if_info->transform_name = "noce_try_store_flag_logical";
1992 0 : return true;
1993 : }
1994 :
1995 : /* Convert "if (test) foo++" into "foo += (test != 0)", and
1996 : similarly for "foo--". */
1997 :
1998 : static bool
1999 158292 : noce_try_addcc (struct noce_if_info *if_info)
2000 : {
2001 158292 : rtx target;
2002 158292 : rtx_insn *seq;
2003 158292 : bool subtract;
2004 158292 : int normalize;
2005 :
2006 201547 : if (!noce_simple_bbs (if_info))
2007 : return false;
2008 :
2009 139686 : if (GET_CODE (if_info->a) == PLUS
2010 15585 : && rtx_equal_p (XEXP (if_info->a, 0), if_info->b)
2011 151743 : && noce_reversed_cond_code (if_info) != UNKNOWN)
2012 : {
2013 12057 : rtx cond = if_info->rev_cond;
2014 12057 : enum rtx_code code;
2015 :
2016 12057 : if (cond == NULL_RTX)
2017 : {
2018 0 : cond = if_info->cond;
2019 0 : code = reversed_comparison_code (cond, if_info->jump);
2020 : }
2021 : else
2022 12057 : code = GET_CODE (cond);
2023 :
2024 : /* First try to use addcc pattern. */
2025 12057 : if (general_operand (XEXP (cond, 0), VOIDmode)
2026 12057 : && general_operand (XEXP (cond, 1), VOIDmode))
2027 : {
2028 11139 : start_sequence ();
2029 33417 : target = emit_conditional_add (if_info->x, code,
2030 : XEXP (cond, 0),
2031 : XEXP (cond, 1),
2032 : VOIDmode,
2033 : if_info->b,
2034 11139 : XEXP (if_info->a, 1),
2035 11139 : GET_MODE (if_info->x),
2036 11139 : (code == LTU || code == GEU
2037 11139 : || code == LEU || code == GTU));
2038 11139 : if (target)
2039 : {
2040 328 : if (target != if_info->x)
2041 0 : noce_emit_move_insn (if_info->x, target);
2042 :
2043 328 : seq = end_ifcvt_sequence (if_info);
2044 328 : if (!seq || !targetm.noce_conversion_profitable_p (seq, if_info))
2045 : return false;
2046 :
2047 328 : emit_insn_before_setloc (seq, if_info->jump,
2048 328 : INSN_LOCATION (if_info->insn_a));
2049 328 : if_info->transform_name = "noce_try_addcc";
2050 :
2051 328 : return true;
2052 : }
2053 10811 : end_sequence ();
2054 : }
2055 :
2056 : /* If that fails, construct conditional increment or decrement using
2057 : setcc. We're changing a branch and an increment to a comparison and
2058 : an ADD/SUB. */
2059 11729 : if (XEXP (if_info->a, 1) == const1_rtx
2060 10139 : || XEXP (if_info->a, 1) == constm1_rtx)
2061 : {
2062 2145 : start_sequence ();
2063 2145 : if (STORE_FLAG_VALUE == INTVAL (XEXP (if_info->a, 1)))
2064 : subtract = false, normalize = 0;
2065 555 : else if (-STORE_FLAG_VALUE == INTVAL (XEXP (if_info->a, 1)))
2066 : subtract = true, normalize = 0;
2067 : else
2068 0 : subtract = false, normalize = INTVAL (XEXP (if_info->a, 1));
2069 :
2070 :
2071 2145 : target = noce_emit_store_flag (if_info,
2072 2145 : gen_reg_rtx (GET_MODE (if_info->x)),
2073 : true, normalize);
2074 :
2075 2145 : if (target)
2076 2374 : target = expand_simple_binop (GET_MODE (if_info->x),
2077 : subtract ? MINUS : PLUS,
2078 : if_info->b, target, if_info->x,
2079 : 0, OPTAB_WIDEN);
2080 1454 : if (target)
2081 : {
2082 1454 : if (target != if_info->x)
2083 0 : noce_emit_move_insn (if_info->x, target);
2084 :
2085 1454 : seq = end_ifcvt_sequence (if_info);
2086 1454 : if (!seq || !targetm.noce_conversion_profitable_p (seq, if_info))
2087 : return false;
2088 :
2089 1186 : emit_insn_before_setloc (seq, if_info->jump,
2090 1186 : INSN_LOCATION (if_info->insn_a));
2091 1186 : if_info->transform_name = "noce_try_addcc";
2092 1186 : return true;
2093 : }
2094 691 : end_sequence ();
2095 : }
2096 : }
2097 :
2098 : return false;
2099 : }
2100 :
2101 : /* Convert "if (test) x = 0;" to "x &= -(test == 0);" */
2102 :
2103 : static bool
2104 156778 : noce_try_store_flag_mask (struct noce_if_info *if_info)
2105 : {
2106 156778 : rtx target;
2107 156778 : rtx_insn *seq;
2108 156778 : bool reversep;
2109 :
2110 199993 : if (!noce_simple_bbs (if_info))
2111 : return false;
2112 :
2113 138172 : reversep = false;
2114 :
2115 138172 : if ((if_info->a == const0_rtx
2116 2824 : && (REG_P (if_info->b) || rtx_equal_p (if_info->b, if_info->x)))
2117 138172 : || ((reversep = true)
2118 137021 : && if_info->b == const0_rtx
2119 13176 : && (REG_P (if_info->a) || rtx_equal_p (if_info->a, if_info->x))))
2120 : {
2121 1153 : start_sequence ();
2122 1153 : target = noce_emit_store_flag (if_info,
2123 1153 : gen_reg_rtx (GET_MODE (if_info->x)),
2124 : reversep, -1);
2125 1153 : if (target)
2126 303 : target = expand_simple_binop (GET_MODE (if_info->x), AND,
2127 : reversep ? if_info->a : if_info->b,
2128 : target, if_info->x, 0,
2129 : OPTAB_WIDEN);
2130 :
2131 303 : if (target)
2132 : {
2133 303 : if (target != if_info->x)
2134 0 : noce_emit_move_insn (if_info->x, target);
2135 :
2136 303 : seq = end_ifcvt_sequence (if_info);
2137 303 : if (!seq || !targetm.noce_conversion_profitable_p (seq, if_info))
2138 : return false;
2139 :
2140 11 : emit_insn_before_setloc (seq, if_info->jump,
2141 11 : INSN_LOCATION (if_info->insn_a));
2142 11 : if_info->transform_name = "noce_try_store_flag_mask";
2143 :
2144 11 : return true;
2145 : }
2146 :
2147 850 : end_sequence ();
2148 : }
2149 :
2150 : return false;
2151 : }
2152 :
2153 : /* Helper function for noce_try_cmove and noce_try_cmove_arith. */
2154 :
2155 : static rtx
2156 419852 : noce_emit_cmove (struct noce_if_info *if_info, rtx x, enum rtx_code code,
2157 : rtx cmp_a, rtx cmp_b, rtx vfalse, rtx vtrue, rtx cc_cmp,
2158 : rtx rev_cc_cmp)
2159 : {
2160 419852 : rtx target ATTRIBUTE_UNUSED;
2161 419852 : bool unsignedp ATTRIBUTE_UNUSED;
2162 :
2163 : /* If earliest == jump, try to build the cmove insn directly.
2164 : This is helpful when combine has created some complex condition
2165 : (like for alpha's cmovlbs) that we can't hope to regenerate
2166 : through the normal interface. */
2167 :
2168 419852 : if (if_info->cond_earliest == if_info->jump)
2169 : {
2170 4614 : rtx cond = gen_rtx_fmt_ee (code, GET_MODE (if_info->cond), cmp_a, cmp_b);
2171 4614 : rtx if_then_else = gen_rtx_IF_THEN_ELSE (GET_MODE (x),
2172 : cond, vtrue, vfalse);
2173 4614 : rtx set = gen_rtx_SET (x, if_then_else);
2174 :
2175 4614 : start_sequence ();
2176 4614 : rtx_insn *insn = emit_insn (set);
2177 :
2178 4614 : if (recog_memoized (insn) >= 0)
2179 : {
2180 1347 : rtx_insn *seq = end_sequence ();
2181 1347 : emit_insn (seq);
2182 :
2183 1347 : return x;
2184 : }
2185 :
2186 3267 : end_sequence ();
2187 : }
2188 :
2189 837010 : unsignedp = (code == LTU || code == GEU
2190 418505 : || code == LEU || code == GTU);
2191 :
2192 418505 : if (cc_cmp != NULL_RTX && rev_cc_cmp != NULL_RTX)
2193 86964 : target = emit_conditional_move (x, cc_cmp, rev_cc_cmp,
2194 86964 : vtrue, vfalse, GET_MODE (x));
2195 : else
2196 : {
2197 : /* Don't even try if the comparison operands are weird
2198 : except that the target supports cbranchcc4. */
2199 331541 : if (! general_operand (cmp_a, GET_MODE (cmp_a))
2200 331541 : || ! general_operand (cmp_b, GET_MODE (cmp_b)))
2201 : {
2202 25236 : if (!have_cbranchcc4
2203 25236 : || GET_MODE_CLASS (GET_MODE (cmp_a)) != MODE_CC
2204 3015 : || cmp_b != const0_rtx)
2205 : return NULL_RTX;
2206 : }
2207 :
2208 309320 : target = emit_conditional_move (x, { code, cmp_a, cmp_b, VOIDmode },
2209 309320 : vtrue, vfalse, GET_MODE (x),
2210 : unsignedp);
2211 : }
2212 :
2213 396284 : if (target)
2214 : return target;
2215 :
2216 : /* We might be faced with a situation like:
2217 :
2218 : x = (reg:M TARGET)
2219 : vtrue = (subreg:M (reg:N VTRUE) BYTE)
2220 : vfalse = (subreg:M (reg:N VFALSE) BYTE)
2221 :
2222 : We can't do a conditional move in mode M, but it's possible that we
2223 : could do a conditional move in mode N instead and take a subreg of
2224 : the result.
2225 :
2226 : If we can't create new pseudos, though, don't bother. */
2227 43129 : if (reload_completed)
2228 : return NULL_RTX;
2229 :
2230 43129 : if (GET_CODE (vtrue) == SUBREG && GET_CODE (vfalse) == SUBREG)
2231 : {
2232 23 : rtx reg_vtrue = SUBREG_REG (vtrue);
2233 23 : rtx reg_vfalse = SUBREG_REG (vfalse);
2234 23 : poly_uint64 byte_vtrue = SUBREG_BYTE (vtrue);
2235 23 : poly_uint64 byte_vfalse = SUBREG_BYTE (vfalse);
2236 23 : rtx promoted_target;
2237 :
2238 23 : if (GET_MODE (reg_vtrue) != GET_MODE (reg_vfalse)
2239 23 : || maybe_ne (byte_vtrue, byte_vfalse)
2240 23 : || (SUBREG_PROMOTED_VAR_P (vtrue)
2241 23 : != SUBREG_PROMOTED_VAR_P (vfalse))
2242 23 : || (SUBREG_PROMOTED_GET (vtrue)
2243 23 : != SUBREG_PROMOTED_GET (vfalse)))
2244 : return NULL_RTX;
2245 :
2246 23 : promoted_target = gen_reg_rtx (GET_MODE (reg_vtrue));
2247 :
2248 46 : target = emit_conditional_move (promoted_target,
2249 : { code, cmp_a, cmp_b, VOIDmode },
2250 : reg_vtrue, reg_vfalse,
2251 23 : GET_MODE (reg_vtrue), unsignedp);
2252 : /* Nope, couldn't do it in that mode either. */
2253 23 : if (!target)
2254 : return NULL_RTX;
2255 :
2256 6 : target = gen_rtx_SUBREG (GET_MODE (vtrue), promoted_target, byte_vtrue);
2257 6 : SUBREG_PROMOTED_VAR_P (target) = SUBREG_PROMOTED_VAR_P (vtrue);
2258 6 : SUBREG_PROMOTED_SET (target, SUBREG_PROMOTED_GET (vtrue));
2259 6 : emit_move_insn (x, target);
2260 6 : return x;
2261 : }
2262 : else
2263 : return NULL_RTX;
2264 : }
2265 :
2266 : /* Try only simple constants and registers here. More complex cases
2267 : are handled in noce_try_cmove_arith after noce_try_store_flag_arith
2268 : has had a go at it. */
2269 :
2270 : static bool
2271 200895 : noce_try_cmove (struct noce_if_info *if_info)
2272 : {
2273 200895 : enum rtx_code code;
2274 200895 : rtx target;
2275 200895 : rtx_insn *seq;
2276 :
2277 260636 : if (!noce_simple_bbs (if_info))
2278 : return false;
2279 :
2280 124136 : if ((CONSTANT_P (if_info->a) || register_operand (if_info->a, VOIDmode))
2281 213511 : && (CONSTANT_P (if_info->b) || register_operand (if_info->b, VOIDmode)))
2282 : {
2283 82754 : start_sequence ();
2284 :
2285 82754 : code = GET_CODE (if_info->cond);
2286 82754 : target = noce_emit_cmove (if_info, if_info->x, code,
2287 : XEXP (if_info->cond, 0),
2288 : XEXP (if_info->cond, 1),
2289 : if_info->a, if_info->b);
2290 :
2291 82754 : if (target)
2292 : {
2293 56592 : if (target != if_info->x)
2294 0 : noce_emit_move_insn (if_info->x, target);
2295 :
2296 56592 : seq = end_ifcvt_sequence (if_info);
2297 56592 : if (!seq || !targetm.noce_conversion_profitable_p (seq, if_info))
2298 : return false;
2299 :
2300 42567 : emit_insn_before_setloc (seq, if_info->jump,
2301 42567 : INSN_LOCATION (if_info->insn_a));
2302 42567 : if_info->transform_name = "noce_try_cmove";
2303 :
2304 42567 : return true;
2305 : }
2306 : /* If both a and b are constants try a last-ditch transformation:
2307 : if (test) x = a; else x = b;
2308 : => x = (-(test != 0) & (b - a)) + a;
2309 : Try this only if the target-specific expansion above has failed.
2310 : The target-specific expander may want to generate sequences that
2311 : we don't know about, so give them a chance before trying this
2312 : approach. */
2313 26162 : else if (!targetm.have_conditional_execution ()
2314 26162 : && CONST_INT_P (if_info->a) && CONST_INT_P (if_info->b))
2315 : {
2316 5369 : machine_mode mode = GET_MODE (if_info->x);
2317 5369 : HOST_WIDE_INT ifalse = INTVAL (if_info->a);
2318 5369 : HOST_WIDE_INT itrue = INTVAL (if_info->b);
2319 5369 : rtx target = noce_emit_store_flag (if_info, if_info->x, false, -1);
2320 5369 : if (!target)
2321 : {
2322 5309 : end_sequence ();
2323 5309 : return false;
2324 : }
2325 :
2326 60 : HOST_WIDE_INT diff = (unsigned HOST_WIDE_INT) itrue - ifalse;
2327 : /* Make sure we can represent the difference
2328 : between the two values. */
2329 60 : if ((diff > 0)
2330 60 : != ((ifalse < 0) != (itrue < 0) ? ifalse < 0 : ifalse < itrue))
2331 : {
2332 21 : end_sequence ();
2333 21 : return false;
2334 : }
2335 :
2336 39 : diff = trunc_int_for_mode (diff, mode);
2337 39 : target = expand_simple_binop (mode, AND,
2338 39 : target, gen_int_mode (diff, mode),
2339 : if_info->x, 0, OPTAB_WIDEN);
2340 39 : if (target)
2341 39 : target = expand_simple_binop (mode, PLUS,
2342 39 : target, gen_int_mode (ifalse, mode),
2343 : if_info->x, 0, OPTAB_WIDEN);
2344 39 : if (target)
2345 : {
2346 39 : if (target != if_info->x)
2347 0 : noce_emit_move_insn (if_info->x, target);
2348 :
2349 39 : seq = end_ifcvt_sequence (if_info);
2350 39 : if (!seq || !targetm.noce_conversion_profitable_p (seq, if_info))
2351 : return false;
2352 :
2353 36 : emit_insn_before_setloc (seq, if_info->jump,
2354 36 : INSN_LOCATION (if_info->insn_a));
2355 36 : if_info->transform_name = "noce_try_cmove";
2356 36 : return true;
2357 : }
2358 : else
2359 : {
2360 0 : end_sequence ();
2361 0 : return false;
2362 : }
2363 : }
2364 : else
2365 20793 : end_sequence ();
2366 : }
2367 :
2368 : return false;
2369 : }
2370 :
2371 : /* Return true if X contains a conditional code mode rtx. */
2372 :
2373 : static bool
2374 2924856 : contains_ccmode_rtx_p (rtx x)
2375 : {
2376 2924856 : subrtx_iterator::array_type array;
2377 7450007 : FOR_EACH_SUBRTX (iter, array, x, ALL)
2378 4570505 : if (GET_MODE_CLASS (GET_MODE (*iter)) == MODE_CC)
2379 45354 : return true;
2380 :
2381 2879502 : return false;
2382 2924856 : }
2383 :
2384 : /* Helper for bb_valid_for_noce_process_p. Validate that
2385 : the rtx insn INSN is a single set that does not set
2386 : the conditional register CC and is in general valid for
2387 : if-conversion. */
2388 :
2389 : static bool
2390 3674980 : insn_valid_noce_process_p (rtx_insn *insn, rtx cc)
2391 : {
2392 3674980 : if (!insn
2393 3674669 : || !NONJUMP_INSN_P (insn)
2394 6630908 : || (cc && set_of (cc, insn)))
2395 : return false;
2396 :
2397 2944307 : rtx sset = single_set (insn);
2398 :
2399 : /* Currently support only simple single sets in test_bb. */
2400 2944307 : if (!sset
2401 2937939 : || !noce_operand_ok (SET_DEST (sset))
2402 2924856 : || contains_ccmode_rtx_p (SET_DEST (sset))
2403 5823809 : || !noce_operand_ok (SET_SRC (sset)))
2404 130455 : return false;
2405 :
2406 : return true;
2407 : }
2408 :
2409 :
2410 : /* Return true iff the registers that the insns in BB_A set do not get
2411 : used in BB_B. If TO_RENAME is non-NULL then it is a location that will be
2412 : renamed later by the caller and so conflicts on it should be ignored
2413 : in this function. */
2414 :
2415 : static bool
2416 54248 : bbs_ok_for_cmove_arith (basic_block bb_a, basic_block bb_b, rtx to_rename)
2417 : {
2418 54248 : rtx_insn *a_insn;
2419 54248 : bitmap bba_sets = BITMAP_ALLOC (®_obstack);
2420 :
2421 54248 : df_ref def;
2422 54248 : df_ref use;
2423 :
2424 284792 : FOR_BB_INSNS (bb_a, a_insn)
2425 : {
2426 230544 : if (!active_insn_p (a_insn))
2427 153564 : continue;
2428 :
2429 76980 : rtx sset_a = single_set (a_insn);
2430 :
2431 76980 : if (!sset_a)
2432 : {
2433 0 : BITMAP_FREE (bba_sets);
2434 0 : return false;
2435 : }
2436 : /* Record all registers that BB_A sets. */
2437 187984 : FOR_EACH_INSN_DEF (def, a_insn)
2438 111004 : if (!(to_rename && DF_REF_REG (def) == to_rename))
2439 57885 : bitmap_set_bit (bba_sets, DF_REF_REGNO (def));
2440 : }
2441 :
2442 54248 : rtx_insn *b_insn;
2443 :
2444 284856 : FOR_BB_INSNS (bb_b, b_insn)
2445 : {
2446 230708 : if (!active_insn_p (b_insn))
2447 153735 : continue;
2448 :
2449 76973 : rtx sset_b = single_set (b_insn);
2450 :
2451 76973 : if (!sset_b)
2452 : {
2453 0 : BITMAP_FREE (bba_sets);
2454 0 : return false;
2455 : }
2456 :
2457 : /* Make sure this is a REG and not some instance
2458 : of ZERO_EXTRACT or non-paradoxical SUBREG or other dangerous stuff.
2459 : If we have a memory destination then we have a pair of simple
2460 : basic blocks performing an operation of the form [addr] = c ? a : b.
2461 : bb_valid_for_noce_process_p will have ensured that these are
2462 : the only stores present. In that case [addr] should be the location
2463 : to be renamed. Assert that the callers set this up properly. */
2464 76973 : if (MEM_P (SET_DEST (sset_b)))
2465 1116 : gcc_assert (rtx_equal_p (SET_DEST (sset_b), to_rename));
2466 75857 : else if (!REG_P (SET_DEST (sset_b))
2467 75857 : && !paradoxical_subreg_p (SET_DEST (sset_b)))
2468 : {
2469 43 : BITMAP_FREE (bba_sets);
2470 43 : return false;
2471 : }
2472 :
2473 : /* If the insn uses a reg set in BB_A return false. */
2474 150254 : FOR_EACH_INSN_USE (use, b_insn)
2475 : {
2476 73381 : if (bitmap_bit_p (bba_sets, DF_REF_REGNO (use)))
2477 : {
2478 57 : BITMAP_FREE (bba_sets);
2479 57 : return false;
2480 : }
2481 : }
2482 :
2483 : }
2484 :
2485 54148 : BITMAP_FREE (bba_sets);
2486 54148 : return true;
2487 : }
2488 :
2489 : /* Emit copies of all the active instructions in BB except the last.
2490 : This is a helper for noce_try_cmove_arith. */
2491 :
2492 : static void
2493 14095 : noce_emit_all_but_last (basic_block bb)
2494 : {
2495 14095 : rtx_insn *last = last_active_insn (bb, false);
2496 14095 : rtx_insn *insn;
2497 145074 : FOR_BB_INSNS (bb, insn)
2498 : {
2499 116884 : if (insn != last && active_insn_p (insn))
2500 : {
2501 37711 : rtx_insn *to_emit = as_a <rtx_insn *> (copy_rtx (insn));
2502 :
2503 37711 : emit_insn (PATTERN (to_emit));
2504 : }
2505 : }
2506 14095 : }
2507 :
2508 : /* Helper for noce_try_cmove_arith. Emit the pattern TO_EMIT and return
2509 : the resulting insn or NULL if it's not a valid insn. */
2510 :
2511 : static rtx_insn *
2512 141074 : noce_emit_insn (rtx to_emit)
2513 : {
2514 141074 : gcc_assert (to_emit);
2515 141074 : rtx_insn *insn = emit_insn (to_emit);
2516 :
2517 141074 : if (recog_memoized (insn) < 0)
2518 193 : return NULL;
2519 :
2520 : return insn;
2521 : }
2522 :
2523 : /* Helper for noce_try_cmove_arith. Emit a copy of the insns up to
2524 : and including the penultimate one in BB if it is not simple
2525 : (as indicated by SIMPLE). Then emit LAST_INSN as the last
2526 : insn in the block. The reason for that is that LAST_INSN may
2527 : have been modified by the preparation in noce_try_cmove_arith. */
2528 :
2529 : static bool
2530 143326 : noce_emit_bb (rtx last_insn, basic_block bb, bool simple)
2531 : {
2532 143326 : if (bb && !simple)
2533 14095 : noce_emit_all_but_last (bb);
2534 :
2535 143326 : if (last_insn && !noce_emit_insn (last_insn))
2536 193 : return false;
2537 :
2538 : return true;
2539 : }
2540 :
2541 : /* Try more complex cases involving conditional_move. */
2542 :
2543 : static bool
2544 146385 : noce_try_cmove_arith (struct noce_if_info *if_info)
2545 : {
2546 146385 : rtx a = if_info->a;
2547 146385 : rtx b = if_info->b;
2548 146385 : rtx x = if_info->x;
2549 146385 : rtx orig_a, orig_b;
2550 146385 : rtx_insn *insn_a, *insn_b;
2551 146385 : bool a_simple = if_info->then_simple;
2552 146385 : bool b_simple = if_info->else_simple;
2553 146385 : basic_block then_bb = if_info->then_bb;
2554 146385 : basic_block else_bb = if_info->else_bb;
2555 146385 : rtx target;
2556 146385 : bool is_mem = false;
2557 146385 : enum rtx_code code;
2558 146385 : rtx cond = if_info->cond;
2559 146385 : rtx_insn *ifcvt_seq;
2560 :
2561 : /* A conditional move from two memory sources is equivalent to a
2562 : conditional on their addresses followed by a load. Don't do this
2563 : early because it'll screw alias analysis. Note that we've
2564 : already checked for no side effects. */
2565 146385 : if (cse_not_expected
2566 47820 : && MEM_P (a) && MEM_P (b)
2567 149044 : && MEM_ADDR_SPACE (a) == MEM_ADDR_SPACE (b))
2568 : {
2569 2658 : machine_mode address_mode = get_address_mode (a);
2570 :
2571 2658 : a = XEXP (a, 0);
2572 2658 : b = XEXP (b, 0);
2573 2658 : x = gen_reg_rtx (address_mode);
2574 2658 : is_mem = true;
2575 : }
2576 :
2577 : /* ??? We could handle this if we knew that a load from A or B could
2578 : not trap or fault. This is also true if we've already loaded
2579 : from the address along the path from ENTRY. */
2580 143727 : else if (may_trap_or_fault_p (a) || may_trap_or_fault_p (b))
2581 : return false;
2582 :
2583 : /* if (test) x = a + b; else x = c - d;
2584 : => y = a + b;
2585 : x = c - d;
2586 : if (test)
2587 : x = y;
2588 : */
2589 :
2590 92165 : code = GET_CODE (cond);
2591 92165 : insn_a = if_info->insn_a;
2592 92165 : insn_b = if_info->insn_b;
2593 :
2594 92165 : machine_mode x_mode = GET_MODE (x);
2595 :
2596 92165 : if (!can_conditionally_move_p (x_mode))
2597 : return false;
2598 :
2599 : /* Possibly rearrange operands to make things come out more natural. */
2600 71763 : if (noce_reversed_cond_code (if_info) != UNKNOWN)
2601 : {
2602 71763 : bool reversep = false;
2603 71763 : if (rtx_equal_p (b, x))
2604 : reversep = true;
2605 45766 : else if (general_operand (b, GET_MODE (b)))
2606 : reversep = true;
2607 :
2608 : if (reversep)
2609 : {
2610 63668 : if (if_info->rev_cond)
2611 : {
2612 63668 : cond = if_info->rev_cond;
2613 63668 : code = GET_CODE (cond);
2614 : }
2615 : else
2616 0 : code = reversed_comparison_code (cond, if_info->jump);
2617 : std::swap (a, b);
2618 : std::swap (insn_a, insn_b);
2619 : std::swap (a_simple, b_simple);
2620 : std::swap (then_bb, else_bb);
2621 : }
2622 : }
2623 :
2624 27943 : if (then_bb && else_bb
2625 98937 : && (!bbs_ok_for_cmove_arith (then_bb, else_bb, if_info->orig_x)
2626 27074 : || !bbs_ok_for_cmove_arith (else_bb, then_bb, if_info->orig_x)))
2627 : return false;
2628 :
2629 71663 : start_sequence ();
2630 :
2631 : /* If one of the blocks is empty then the corresponding B or A value
2632 : came from the test block. The non-empty complex block that we will
2633 : emit might clobber the register used by B or A, so move it to a pseudo
2634 : first. */
2635 :
2636 71663 : rtx tmp_a = NULL_RTX;
2637 71663 : rtx tmp_b = NULL_RTX;
2638 :
2639 71663 : if (b_simple || !else_bb)
2640 59652 : tmp_b = gen_reg_rtx (x_mode);
2641 :
2642 71663 : if (a_simple || !then_bb)
2643 69579 : tmp_a = gen_reg_rtx (x_mode);
2644 :
2645 71663 : orig_a = a;
2646 71663 : orig_b = b;
2647 :
2648 71663 : rtx emit_a = NULL_RTX;
2649 71663 : rtx emit_b = NULL_RTX;
2650 71663 : rtx_insn *tmp_insn = NULL;
2651 71663 : bool modified_in_a = false;
2652 71663 : bool modified_in_b = false;
2653 : /* If either operand is complex, load it into a register first.
2654 : The best way to do this is to copy the original insn. In this
2655 : way we preserve any clobbers etc that the insn may have had.
2656 : This is of course not possible in the IS_MEM case. */
2657 :
2658 71663 : if (! general_operand (a, GET_MODE (a)) || tmp_a)
2659 : {
2660 :
2661 71013 : if (is_mem)
2662 : {
2663 2657 : rtx reg = gen_reg_rtx (GET_MODE (a));
2664 2657 : emit_a = gen_rtx_SET (reg, a);
2665 : }
2666 : else
2667 : {
2668 68356 : if (insn_a)
2669 : {
2670 42300 : a = tmp_a ? tmp_a : gen_reg_rtx (GET_MODE (a));
2671 :
2672 42300 : rtx_insn *copy_of_a = as_a <rtx_insn *> (copy_rtx (insn_a));
2673 42300 : rtx set = single_set (copy_of_a);
2674 42300 : SET_DEST (set) = a;
2675 :
2676 42300 : emit_a = PATTERN (copy_of_a);
2677 : }
2678 : else
2679 : {
2680 26056 : rtx tmp_reg = tmp_a ? tmp_a : gen_reg_rtx (GET_MODE (a));
2681 26056 : emit_a = gen_rtx_SET (tmp_reg, a);
2682 26056 : a = tmp_reg;
2683 : }
2684 : }
2685 : }
2686 :
2687 71663 : if (! general_operand (b, GET_MODE (b)) || tmp_b)
2688 : {
2689 70061 : if (is_mem)
2690 : {
2691 2657 : rtx reg = gen_reg_rtx (GET_MODE (b));
2692 2657 : emit_b = gen_rtx_SET (reg, b);
2693 : }
2694 : else
2695 : {
2696 67404 : if (insn_b)
2697 : {
2698 67214 : b = tmp_b ? tmp_b : gen_reg_rtx (GET_MODE (b));
2699 67214 : rtx_insn *copy_of_b = as_a <rtx_insn *> (copy_rtx (insn_b));
2700 67214 : rtx set = single_set (copy_of_b);
2701 :
2702 67214 : SET_DEST (set) = b;
2703 67214 : emit_b = PATTERN (copy_of_b);
2704 : }
2705 : else
2706 : {
2707 190 : rtx tmp_reg = tmp_b ? tmp_b : gen_reg_rtx (GET_MODE (b));
2708 190 : emit_b = gen_rtx_SET (tmp_reg, b);
2709 190 : b = tmp_reg;
2710 : }
2711 : }
2712 : }
2713 :
2714 71663 : modified_in_a = emit_a != NULL_RTX && modified_in_p (orig_b, emit_a);
2715 71663 : if (tmp_b && then_bb)
2716 : {
2717 77083 : FOR_BB_INSNS (then_bb, tmp_insn)
2718 : /* Don't check inside insn_a. We will have changed it to emit_a
2719 : with a destination that doesn't conflict. */
2720 58155 : if (!(insn_a && tmp_insn == insn_a)
2721 97382 : && modified_in_p (orig_b, tmp_insn))
2722 : {
2723 : modified_in_a = true;
2724 : break;
2725 : }
2726 :
2727 : }
2728 :
2729 71663 : modified_in_b = emit_b != NULL_RTX && modified_in_p (orig_a, emit_b);
2730 71663 : if (tmp_a && else_bb)
2731 : {
2732 332060 : FOR_BB_INSNS (else_bb, tmp_insn)
2733 : /* Don't check inside insn_b. We will have changed it to emit_b
2734 : with a destination that doesn't conflict. */
2735 263226 : if (!(insn_b && tmp_insn == insn_b)
2736 457618 : && modified_in_p (orig_a, tmp_insn))
2737 : {
2738 : modified_in_b = true;
2739 : break;
2740 : }
2741 : }
2742 :
2743 : /* If insn to set up A clobbers any registers B depends on, try to
2744 : swap insn that sets up A with the one that sets up B. If even
2745 : that doesn't help, punt. */
2746 71663 : if (modified_in_a && !modified_in_b)
2747 : {
2748 0 : if (!noce_emit_bb (emit_b, else_bb, b_simple))
2749 0 : goto end_seq_and_fail;
2750 :
2751 0 : if (!noce_emit_bb (emit_a, then_bb, a_simple))
2752 0 : goto end_seq_and_fail;
2753 : }
2754 71663 : else if (!modified_in_a)
2755 : {
2756 71663 : if (!noce_emit_bb (emit_a, then_bb, a_simple))
2757 0 : goto end_seq_and_fail;
2758 :
2759 71663 : if (!noce_emit_bb (emit_b, else_bb, b_simple))
2760 193 : goto end_seq_and_fail;
2761 : }
2762 : else
2763 0 : goto end_seq_and_fail;
2764 :
2765 71470 : target = noce_emit_cmove (if_info, x, code, XEXP (cond, 0), XEXP (cond, 1),
2766 : a, b);
2767 :
2768 71470 : if (! target)
2769 17499 : goto end_seq_and_fail;
2770 :
2771 : /* If we're handling a memory for above, emit the load now. */
2772 53971 : if (is_mem)
2773 : {
2774 2266 : rtx mem = gen_rtx_MEM (GET_MODE (if_info->x), target);
2775 :
2776 : /* Copy over flags as appropriate. */
2777 2266 : if (MEM_VOLATILE_P (if_info->a) || MEM_VOLATILE_P (if_info->b))
2778 0 : MEM_VOLATILE_P (mem) = 1;
2779 2266 : if (MEM_ALIAS_SET (if_info->a) == MEM_ALIAS_SET (if_info->b))
2780 2070 : set_mem_alias_set (mem, MEM_ALIAS_SET (if_info->a));
2781 4532 : set_mem_align (mem,
2782 2266 : MIN (MEM_ALIGN (if_info->a), MEM_ALIGN (if_info->b)));
2783 :
2784 2266 : gcc_assert (MEM_ADDR_SPACE (if_info->a) == MEM_ADDR_SPACE (if_info->b));
2785 2266 : set_mem_addr_space (mem, MEM_ADDR_SPACE (if_info->a));
2786 :
2787 2266 : noce_emit_move_insn (if_info->x, mem);
2788 : }
2789 51705 : else if (target != x)
2790 0 : noce_emit_move_insn (x, target);
2791 :
2792 53971 : ifcvt_seq = end_ifcvt_sequence (if_info);
2793 53971 : if (!ifcvt_seq || !targetm.noce_conversion_profitable_p (ifcvt_seq, if_info))
2794 : return false;
2795 :
2796 35085 : emit_insn_before_setloc (ifcvt_seq, if_info->jump,
2797 35085 : INSN_LOCATION (if_info->insn_a));
2798 35085 : if_info->transform_name = "noce_try_cmove_arith";
2799 35085 : return true;
2800 :
2801 17692 : end_seq_and_fail:
2802 17692 : end_sequence ();
2803 17692 : return false;
2804 : }
2805 :
2806 : /* For most cases, the simplified condition we found is the best
2807 : choice, but this is not the case for the min/max/abs transforms.
2808 : For these we wish to know that it is A or B in the condition. */
2809 :
2810 : static rtx
2811 161558 : noce_get_alt_condition (struct noce_if_info *if_info, rtx target,
2812 : rtx_insn **earliest)
2813 : {
2814 161558 : rtx cond, set;
2815 161558 : rtx_insn *insn;
2816 161558 : bool reverse;
2817 :
2818 : /* If target is already mentioned in the known condition, return it. */
2819 161558 : if (reg_mentioned_p (target, if_info->cond))
2820 : {
2821 8258 : *earliest = if_info->cond_earliest;
2822 8258 : return if_info->cond;
2823 : }
2824 :
2825 153300 : set = pc_set (if_info->jump);
2826 153300 : cond = XEXP (SET_SRC (set), 0);
2827 153300 : reverse
2828 306600 : = GET_CODE (XEXP (SET_SRC (set), 2)) == LABEL_REF
2829 153300 : && label_ref_label (XEXP (SET_SRC (set), 2)) == JUMP_LABEL (if_info->jump);
2830 153300 : if (if_info->then_else_reversed)
2831 23819 : reverse = !reverse;
2832 :
2833 : /* If we're looking for a constant, try to make the conditional
2834 : have that constant in it. There are two reasons why it may
2835 : not have the constant we want:
2836 :
2837 : 1. GCC may have needed to put the constant in a register, because
2838 : the target can't compare directly against that constant. For
2839 : this case, we look for a SET immediately before the comparison
2840 : that puts a constant in that register.
2841 :
2842 : 2. GCC may have canonicalized the conditional, for example
2843 : replacing "if x < 4" with "if x <= 3". We can undo that (or
2844 : make equivalent types of changes) to get the constants we need
2845 : if they're off by one in the right direction. */
2846 :
2847 153300 : if (CONST_INT_P (target))
2848 : {
2849 46839 : enum rtx_code code = GET_CODE (if_info->cond);
2850 46839 : rtx op_a = XEXP (if_info->cond, 0);
2851 46839 : rtx op_b = XEXP (if_info->cond, 1);
2852 46839 : rtx_insn *prev_insn;
2853 :
2854 : /* First, look to see if we put a constant in a register. */
2855 46839 : prev_insn = prev_nonnote_nondebug_insn (if_info->cond_earliest);
2856 46839 : if (prev_insn
2857 46728 : && BLOCK_FOR_INSN (prev_insn)
2858 46728 : == BLOCK_FOR_INSN (if_info->cond_earliest)
2859 37324 : && INSN_P (prev_insn)
2860 80016 : && GET_CODE (PATTERN (prev_insn)) == SET)
2861 : {
2862 25764 : rtx src = find_reg_equal_equiv_note (prev_insn);
2863 25764 : if (!src)
2864 25598 : src = SET_SRC (PATTERN (prev_insn));
2865 25764 : if (CONST_INT_P (src))
2866 : {
2867 15258 : if (rtx_equal_p (op_a, SET_DEST (PATTERN (prev_insn))))
2868 : op_a = src;
2869 14716 : else if (rtx_equal_p (op_b, SET_DEST (PATTERN (prev_insn))))
2870 1073 : op_b = src;
2871 :
2872 15258 : if (CONST_INT_P (op_a))
2873 : {
2874 542 : std::swap (op_a, op_b);
2875 542 : code = swap_condition (code);
2876 : }
2877 : }
2878 : }
2879 :
2880 : /* Now, look to see if we can get the right constant by
2881 : adjusting the conditional. */
2882 46839 : if (CONST_INT_P (op_b))
2883 : {
2884 24323 : HOST_WIDE_INT desired_val = INTVAL (target);
2885 24323 : HOST_WIDE_INT actual_val = INTVAL (op_b);
2886 :
2887 24323 : switch (code)
2888 : {
2889 1177 : case LT:
2890 1177 : if (desired_val != HOST_WIDE_INT_MAX
2891 1162 : && actual_val == desired_val + 1)
2892 : {
2893 173 : code = LE;
2894 173 : op_b = GEN_INT (desired_val);
2895 : }
2896 : break;
2897 3 : case LE:
2898 3 : if (desired_val != HOST_WIDE_INT_MIN
2899 3 : && actual_val == desired_val - 1)
2900 : {
2901 0 : code = LT;
2902 0 : op_b = GEN_INT (desired_val);
2903 : }
2904 : break;
2905 1683 : case GT:
2906 1683 : if (desired_val != HOST_WIDE_INT_MIN
2907 1683 : && actual_val == desired_val - 1)
2908 : {
2909 235 : code = GE;
2910 235 : op_b = GEN_INT (desired_val);
2911 : }
2912 : break;
2913 40 : case GE:
2914 40 : if (desired_val != HOST_WIDE_INT_MAX
2915 25 : && actual_val == desired_val + 1)
2916 : {
2917 3 : code = GT;
2918 3 : op_b = GEN_INT (desired_val);
2919 : }
2920 : break;
2921 : default:
2922 : break;
2923 : }
2924 : }
2925 :
2926 : /* If we made any changes, generate a new conditional that is
2927 : equivalent to what we started with, but has the right
2928 : constants in it. */
2929 46839 : if (code != GET_CODE (if_info->cond)
2930 45887 : || op_a != XEXP (if_info->cond, 0)
2931 45886 : || op_b != XEXP (if_info->cond, 1))
2932 : {
2933 2026 : cond = gen_rtx_fmt_ee (code, GET_MODE (cond), op_a, op_b);
2934 2026 : *earliest = if_info->cond_earliest;
2935 2026 : return cond;
2936 : }
2937 : }
2938 :
2939 151274 : cond = canonicalize_condition (if_info->jump, cond, reverse,
2940 : earliest, target, have_cbranchcc4, true);
2941 151274 : if (! cond || ! reg_mentioned_p (target, cond))
2942 : return NULL;
2943 :
2944 : /* We almost certainly searched back to a different place.
2945 : Need to re-verify correct lifetimes. */
2946 :
2947 : /* X may not be mentioned in the range (cond_earliest, jump]. */
2948 0 : for (insn = if_info->jump; insn != *earliest; insn = PREV_INSN (insn))
2949 0 : if (INSN_P (insn) && reg_overlap_mentioned_p (if_info->x, PATTERN (insn)))
2950 : return NULL;
2951 :
2952 : /* A and B may not be modified in the range [cond_earliest, jump). */
2953 0 : for (insn = *earliest; insn != if_info->jump; insn = NEXT_INSN (insn))
2954 0 : if (INSN_P (insn)
2955 0 : && (modified_in_p (if_info->a, insn)
2956 0 : || modified_in_p (if_info->b, insn)))
2957 : return NULL;
2958 :
2959 : return cond;
2960 : }
2961 :
2962 : /* Convert "if (a < b) x = a; else x = b;" to "x = min(a, b);", etc. */
2963 :
2964 : static bool
2965 209093 : noce_try_minmax (struct noce_if_info *if_info)
2966 : {
2967 209093 : rtx cond, target;
2968 209093 : rtx_insn *earliest, *seq;
2969 209093 : enum rtx_code code, op;
2970 209093 : bool unsignedp;
2971 :
2972 272226 : if (!noce_simple_bbs (if_info))
2973 : return false;
2974 :
2975 : /* ??? Reject modes with NaNs or signed zeros since we don't know how
2976 : they will be resolved with an SMIN/SMAX. It wouldn't be too hard
2977 : to get the target to tell us... */
2978 190487 : if (HONOR_SIGNED_ZEROS (if_info->x)
2979 190487 : || HONOR_NANS (if_info->x))
2980 : return false;
2981 :
2982 160568 : cond = noce_get_alt_condition (if_info, if_info->a, &earliest);
2983 160568 : if (!cond)
2984 : return false;
2985 :
2986 : /* Verify the condition is of the form we expect, and canonicalize
2987 : the comparison code. */
2988 10259 : code = GET_CODE (cond);
2989 10259 : if (rtx_equal_p (XEXP (cond, 0), if_info->a))
2990 : {
2991 2575 : if (! rtx_equal_p (XEXP (cond, 1), if_info->b))
2992 : return false;
2993 : }
2994 7684 : else if (rtx_equal_p (XEXP (cond, 1), if_info->a))
2995 : {
2996 4681 : if (! rtx_equal_p (XEXP (cond, 0), if_info->b))
2997 : return false;
2998 54 : code = swap_condition (code);
2999 : }
3000 : else
3001 : return false;
3002 :
3003 : /* Determine what sort of operation this is. Note that the code is for
3004 : a taken branch, so the code->operation mapping appears backwards. */
3005 73 : switch (code)
3006 : {
3007 : case LT:
3008 : case LE:
3009 : case UNLT:
3010 : case UNLE:
3011 : op = SMAX;
3012 : unsignedp = false;
3013 : break;
3014 21 : case GT:
3015 21 : case GE:
3016 21 : case UNGT:
3017 21 : case UNGE:
3018 21 : op = SMIN;
3019 21 : unsignedp = false;
3020 21 : break;
3021 3 : case LTU:
3022 3 : case LEU:
3023 3 : op = UMAX;
3024 3 : unsignedp = true;
3025 3 : break;
3026 21 : case GTU:
3027 21 : case GEU:
3028 21 : op = UMIN;
3029 21 : unsignedp = true;
3030 21 : break;
3031 : default:
3032 : return false;
3033 : }
3034 :
3035 73 : start_sequence ();
3036 :
3037 73 : target = expand_simple_binop (GET_MODE (if_info->x), op,
3038 : if_info->a, if_info->b,
3039 : if_info->x, unsignedp, OPTAB_WIDEN);
3040 73 : if (! target)
3041 : {
3042 0 : end_sequence ();
3043 0 : return false;
3044 : }
3045 73 : if (target != if_info->x)
3046 0 : noce_emit_move_insn (if_info->x, target);
3047 :
3048 73 : seq = end_ifcvt_sequence (if_info);
3049 73 : if (!seq)
3050 : return false;
3051 :
3052 73 : emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATION (if_info->insn_a));
3053 73 : if_info->cond = cond;
3054 73 : if_info->cond_earliest = earliest;
3055 73 : if_info->rev_cond = NULL_RTX;
3056 73 : if_info->transform_name = "noce_try_minmax";
3057 :
3058 73 : return true;
3059 : }
3060 :
3061 : /* Convert "if (a < 0) x = -a; else x = a;" to "x = abs(a);",
3062 : "if (a < 0) x = ~a; else x = a;" to "x = one_cmpl_abs(a);",
3063 : etc. */
3064 :
3065 : static bool
3066 209020 : noce_try_abs (struct noce_if_info *if_info)
3067 : {
3068 209020 : rtx cond, target, a, b, c;
3069 209020 : rtx_insn *earliest, *seq;
3070 209020 : bool negate;
3071 209020 : bool one_cmpl = false;
3072 :
3073 272144 : if (!noce_simple_bbs (if_info))
3074 : return false;
3075 :
3076 : /* Reject modes with signed zeros. */
3077 190414 : if (HONOR_SIGNED_ZEROS (if_info->x))
3078 : return false;
3079 :
3080 : /* Recognize A and B as constituting an ABS or NABS. The canonical
3081 : form is a branch around the negation, taken when the object is the
3082 : first operand of a comparison against 0 that evaluates to true. */
3083 160503 : a = if_info->a;
3084 160503 : b = if_info->b;
3085 160503 : if (GET_CODE (a) == NEG && rtx_equal_p (XEXP (a, 0), b))
3086 : negate = false;
3087 159543 : else if (GET_CODE (b) == NEG && rtx_equal_p (XEXP (b, 0), a))
3088 : {
3089 : std::swap (a, b);
3090 : negate = true;
3091 : }
3092 159513 : else if (GET_CODE (a) == NOT && rtx_equal_p (XEXP (a, 0), b))
3093 : {
3094 : negate = false;
3095 : one_cmpl = true;
3096 : }
3097 159513 : else if (GET_CODE (b) == NOT && rtx_equal_p (XEXP (b, 0), a))
3098 : {
3099 : std::swap (a, b);
3100 : negate = true;
3101 : one_cmpl = true;
3102 : }
3103 : else
3104 : return false;
3105 :
3106 990 : cond = noce_get_alt_condition (if_info, b, &earliest);
3107 990 : if (!cond)
3108 : return false;
3109 :
3110 : /* Verify the condition is of the form we expect. */
3111 25 : if (rtx_equal_p (XEXP (cond, 0), b))
3112 25 : c = XEXP (cond, 1);
3113 0 : else if (rtx_equal_p (XEXP (cond, 1), b))
3114 : {
3115 0 : c = XEXP (cond, 0);
3116 0 : negate = !negate;
3117 : }
3118 : else
3119 : return false;
3120 :
3121 : /* Verify that C is zero. Search one step backward for a
3122 : REG_EQUAL note or a simple source if necessary. */
3123 25 : if (REG_P (c))
3124 : {
3125 0 : rtx set;
3126 0 : rtx_insn *insn = prev_nonnote_nondebug_insn (earliest);
3127 0 : if (insn
3128 0 : && BLOCK_FOR_INSN (insn) == BLOCK_FOR_INSN (earliest)
3129 0 : && (set = single_set (insn))
3130 0 : && rtx_equal_p (SET_DEST (set), c))
3131 : {
3132 0 : rtx note = find_reg_equal_equiv_note (insn);
3133 0 : if (note)
3134 0 : c = XEXP (note, 0);
3135 : else
3136 0 : c = SET_SRC (set);
3137 : }
3138 : else
3139 : return false;
3140 : }
3141 25 : if (MEM_P (c)
3142 0 : && GET_CODE (XEXP (c, 0)) == SYMBOL_REF
3143 25 : && CONSTANT_POOL_ADDRESS_P (XEXP (c, 0)))
3144 0 : c = get_pool_constant (XEXP (c, 0));
3145 :
3146 : /* Work around funny ideas get_condition has wrt canonicalization.
3147 : Note that these rtx constants are known to be CONST_INT, and
3148 : therefore imply integer comparisons.
3149 : The one_cmpl case is more complicated, as we want to handle
3150 : only x < 0 ? ~x : x or x >= 0 ? x : ~x to one_cmpl_abs (x)
3151 : and x < 0 ? x : ~x or x >= 0 ? ~x : x to ~one_cmpl_abs (x),
3152 : but not other cases (x > -1 is equivalent of x >= 0). */
3153 25 : if (c == constm1_rtx && GET_CODE (cond) == GT)
3154 : ;
3155 1 : else if (c == const1_rtx && GET_CODE (cond) == LT)
3156 : {
3157 0 : if (one_cmpl)
3158 : return false;
3159 : }
3160 1 : else if (c == CONST0_RTX (GET_MODE (b)))
3161 : {
3162 0 : if (one_cmpl
3163 0 : && GET_CODE (cond) != GE
3164 0 : && GET_CODE (cond) != LT)
3165 : return false;
3166 : }
3167 : else
3168 : return false;
3169 :
3170 : /* Determine what sort of operation this is. */
3171 24 : switch (GET_CODE (cond))
3172 : {
3173 0 : case LT:
3174 0 : case LE:
3175 0 : case UNLT:
3176 0 : case UNLE:
3177 0 : negate = !negate;
3178 0 : break;
3179 : case GT:
3180 : case GE:
3181 : case UNGT:
3182 : case UNGE:
3183 : break;
3184 : default:
3185 : return false;
3186 : }
3187 :
3188 24 : start_sequence ();
3189 24 : if (one_cmpl)
3190 0 : target = expand_one_cmpl_abs_nojump (GET_MODE (if_info->x), b,
3191 : if_info->x);
3192 : else
3193 24 : target = expand_abs_nojump (GET_MODE (if_info->x), b, if_info->x, 1);
3194 :
3195 : /* ??? It's a quandary whether cmove would be better here, especially
3196 : for integers. Perhaps combine will clean things up. */
3197 24 : if (target && negate)
3198 : {
3199 0 : if (one_cmpl)
3200 0 : target = expand_simple_unop (GET_MODE (target), NOT, target,
3201 : if_info->x, 0);
3202 : else
3203 0 : target = expand_simple_unop (GET_MODE (target), NEG, target,
3204 : if_info->x, 0);
3205 : }
3206 :
3207 24 : if (! target)
3208 : {
3209 0 : end_sequence ();
3210 0 : return false;
3211 : }
3212 :
3213 24 : if (target != if_info->x)
3214 0 : noce_emit_move_insn (if_info->x, target);
3215 :
3216 24 : seq = end_ifcvt_sequence (if_info);
3217 24 : if (!seq)
3218 : return false;
3219 :
3220 24 : emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATION (if_info->insn_a));
3221 24 : if_info->cond = cond;
3222 24 : if_info->cond_earliest = earliest;
3223 24 : if_info->rev_cond = NULL_RTX;
3224 24 : if_info->transform_name = "noce_try_abs";
3225 :
3226 24 : return true;
3227 : }
3228 :
3229 : /* Convert "if (m < 0) x = b; else x = 0;" to "x = (m >> C) & b;". */
3230 :
3231 : static bool
3232 111300 : noce_try_sign_mask (struct noce_if_info *if_info)
3233 : {
3234 111300 : rtx cond, t, m, c;
3235 111300 : rtx_insn *seq;
3236 111300 : machine_mode mode;
3237 111300 : enum rtx_code code;
3238 111300 : bool t_unconditional;
3239 :
3240 136912 : if (!noce_simple_bbs (if_info))
3241 : return false;
3242 :
3243 99832 : cond = if_info->cond;
3244 99832 : code = GET_CODE (cond);
3245 99832 : m = XEXP (cond, 0);
3246 99832 : c = XEXP (cond, 1);
3247 :
3248 99832 : t = NULL_RTX;
3249 99832 : if (if_info->a == const0_rtx)
3250 : {
3251 2636 : if ((code == LT && c == const0_rtx)
3252 2607 : || (code == LE && c == constm1_rtx))
3253 29 : t = if_info->b;
3254 : }
3255 97196 : else if (if_info->b == const0_rtx)
3256 : {
3257 10922 : if ((code == GE && c == const0_rtx)
3258 10922 : || (code == GT && c == constm1_rtx))
3259 : t = if_info->a;
3260 : }
3261 :
3262 95 : if (! t || side_effects_p (t))
3263 : return false;
3264 :
3265 : /* We currently don't handle different modes. */
3266 95 : mode = GET_MODE (t);
3267 95 : if (GET_MODE (m) != mode)
3268 : return false;
3269 :
3270 : /* This is only profitable if T is unconditionally executed/evaluated in the
3271 : original insn sequence or T is cheap and can't trap or fault. The former
3272 : happens if B is the non-zero (T) value and if INSN_B was taken from
3273 : TEST_BB, or there was no INSN_B which can happen for e.g. conditional
3274 : stores to memory. For the cost computation use the block TEST_BB where
3275 : the evaluation will end up after the transformation. */
3276 43 : t_unconditional
3277 86 : = (t == if_info->b
3278 43 : && (if_info->insn_b == NULL_RTX
3279 0 : || BLOCK_FOR_INSN (if_info->insn_b) == if_info->test_bb));
3280 86 : if (!(t_unconditional
3281 43 : || ((set_src_cost (t, mode, if_info->speed_p)
3282 : < COSTS_N_INSNS (2))
3283 37 : && !may_trap_or_fault_p (t))))
3284 : return false;
3285 :
3286 0 : if (!noce_can_force_operand (t))
3287 : return false;
3288 :
3289 0 : start_sequence ();
3290 : /* Use emit_store_flag to generate "m < 0 ? -1 : 0" instead of expanding
3291 : "(signed) m >> 31" directly. This benefits targets with specialized
3292 : insns to obtain the signmask, but still uses ashr_optab otherwise. */
3293 0 : m = emit_store_flag (gen_reg_rtx (mode), LT, m, const0_rtx, mode, 0, -1);
3294 0 : t = m ? expand_binop (mode, and_optab, m, t, NULL_RTX, 0, OPTAB_DIRECT)
3295 : : NULL_RTX;
3296 :
3297 0 : if (!t)
3298 : {
3299 0 : end_sequence ();
3300 0 : return false;
3301 : }
3302 :
3303 0 : noce_emit_move_insn (if_info->x, t);
3304 :
3305 0 : seq = end_ifcvt_sequence (if_info);
3306 0 : if (!seq)
3307 : return false;
3308 :
3309 0 : emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATION (if_info->insn_a));
3310 0 : if_info->transform_name = "noce_try_sign_mask";
3311 :
3312 0 : return true;
3313 : }
3314 :
3315 : /* Helper function to return REG itself,
3316 : otherwise NULL_RTX for other RTX_CODE. */
3317 :
3318 : static rtx
3319 28654 : get_base_reg_or_constant (rtx exp)
3320 : {
3321 0 : if (REG_P (exp))
3322 : return exp;
3323 5294 : else if (SUBREG_P (exp))
3324 323 : return SUBREG_REG (exp);
3325 4971 : else if (CONST_INT_P (exp))
3326 0 : return exp;
3327 : return NULL_RTX;
3328 : }
3329 :
3330 : /* Try to covert if-then-else with conditional zero,
3331 : returning TURE on success or FALSE on failure.
3332 : IF_INFO describes the if-conversion scenario under consideration.
3333 :
3334 : It verifies the branch structure on left and transforms it into branchless
3335 : sequence on the right, with a backend provided conditional zero or orig for
3336 : operand z. If true, tmp is z, 0 otherwise (y op 0 is same as y for most op).
3337 :
3338 : if (cond) | tmp = cond ? z : 0
3339 : x = y op z | x = y op tmp
3340 : else |
3341 : x = y |
3342 :
3343 : AND is special as it needs to be handled differently.
3344 :
3345 : tmp = !cond ? y : 0
3346 : x = (y & z) | tmp
3347 : Also for AND try:
3348 : tmp = cond ? z : -1
3349 : x = y op tmp
3350 : To see if it is cheaper to produce `!cond ? y : 0`
3351 : or `cond ? z : -1`.
3352 : */
3353 :
3354 : static int
3355 156767 : noce_try_cond_arith (struct noce_if_info *if_info)
3356 : {
3357 156767 : rtx target, a, b, a_op0, a_op1;
3358 156767 : rtx cond = if_info->cond;
3359 156767 : rtx_code code = GET_CODE (cond);
3360 156767 : rtx_insn *seq;
3361 156767 : rtx_code op;
3362 156767 : machine_mode mode = GET_MODE (if_info->x);
3363 :
3364 : /* Scalar integral modes are only supported here.
3365 : Could support scalar floating point but that
3366 : would be only with -ffast-math and might
3367 : be worse than a branch. */
3368 156767 : if (!SCALAR_INT_MODE_P (mode))
3369 : return false;
3370 :
3371 166058 : if (!noce_simple_bbs (if_info))
3372 : return false;
3373 :
3374 109692 : a = copy_rtx (if_info->a);
3375 109692 : b = copy_rtx (if_info->b);
3376 :
3377 : /* Canonicalize x = y : (y op z) to x = (y op z) : y. */
3378 109692 : if (REG_P (a) && noce_cond_zero_binary_op_supported (b))
3379 : {
3380 227 : if (if_info->rev_cond)
3381 : {
3382 227 : cond = if_info->rev_cond;
3383 227 : code = GET_CODE (cond);
3384 : }
3385 : else
3386 0 : code = reversed_comparison_code (cond, if_info->jump);
3387 : std::swap (a, b);
3388 : }
3389 :
3390 : /* Check if x = (y op z) : y is supported by czero based ifcvt. */
3391 109465 : else if (!(noce_cond_zero_binary_op_supported (a) && REG_P (b)))
3392 95036 : goto fail;
3393 :
3394 14656 : if (code == UNKNOWN)
3395 0 : goto fail;
3396 :
3397 14656 : op = GET_CODE (a);
3398 :
3399 : /* Canonicalize x = (z op y) : y to x = (y op z) : y */
3400 14656 : a_op1 = get_base_reg_or_constant (XEXP (a, 1));
3401 13995 : if (a_op1 && rtx_equal_p (a_op1, b) && COMMUTATIVE_ARITH_P (a))
3402 : {
3403 10 : std::swap (XEXP (a, 0), XEXP (a, 1));
3404 10 : a_op1 = get_base_reg_or_constant (XEXP (a, 1));
3405 : }
3406 :
3407 14646 : if (a_op1 == NULL_RTX)
3408 668 : goto fail;
3409 :
3410 : /* Ensure the cond is of form: x = (y op z) : y */
3411 13988 : a_op0 = get_base_reg_or_constant (XEXP (a, 0));
3412 13983 : if (!(a_op0 && rtx_equal_p (a_op0, b)))
3413 1987 : goto fail;
3414 :
3415 12001 : start_sequence ();
3416 :
3417 12001 : if (CONST_INT_P (XEXP (a, 1)))
3418 3038 : target = gen_reg_rtx (GET_MODE (XEXP (a, 0)));
3419 : else
3420 8963 : target = gen_reg_rtx (GET_MODE (XEXP (a, op != AND)));
3421 :
3422 : /* AND requires !cond, instead we swap ops around. */
3423 12001 : target = noce_emit_cmove (if_info, target, code,
3424 : XEXP (cond, 0), XEXP (cond, 1),
3425 : op != AND ? XEXP (a, 1) : const0_rtx,
3426 : op != AND ? const0_rtx : XEXP (a, 0));
3427 12001 : if (!target)
3428 : {
3429 1223 : end_sequence ();
3430 1223 : rtx tmp = XEXP (a, op != AND);
3431 : /* If the cmove fails and this was a lowpart subreg,
3432 : then try the reg part and then putting back the lowpart
3433 : afterwards. */
3434 1223 : if (GET_CODE (tmp) != SUBREG || !subreg_lowpart_p (tmp))
3435 : return false;
3436 0 : tmp = SUBREG_REG (tmp);
3437 : /* Only handle integer scalar modes for the inner mode of
3438 : the subreg. */
3439 0 : if (!SCALAR_INT_MODE_P (GET_MODE (tmp)))
3440 : return false;
3441 :
3442 0 : start_sequence ();
3443 0 : target = gen_reg_rtx (GET_MODE (tmp));
3444 0 : target = noce_emit_cmove (if_info, target, code,
3445 : XEXP (cond, 0), XEXP (cond, 1),
3446 : op != AND ? tmp : const0_rtx,
3447 : op != AND ? const0_rtx : tmp);
3448 0 : if (!target)
3449 0 : goto end_seq_n_fail;
3450 0 : target = rtl_hooks.gen_lowpart_no_emit (GET_MODE (XEXP (a, op != AND)), target);
3451 0 : gcc_assert (target);
3452 : }
3453 :
3454 : /* For AND, try `cond ? z : -1` to see if that is cheaper or the same cost.
3455 : In some cases it will be cheaper to produce the -1 rather than the 0 case. */
3456 10778 : if (op == AND)
3457 : {
3458 85 : rtx_insn *seq0 = end_sequence ();
3459 85 : unsigned cost0 = seq_cost (seq0, if_info->speed_p);
3460 85 : if (!target)
3461 : cost0 = -1u;
3462 :
3463 : /* Produce `cond ? z : -1`. */
3464 85 : rtx targetm1;
3465 85 : start_sequence ();
3466 85 : targetm1 = gen_reg_rtx (GET_MODE (XEXP (a, 1)));
3467 85 : targetm1 = noce_emit_cmove (if_info, targetm1, code,
3468 : XEXP (cond, 0), XEXP (cond, 1),
3469 : XEXP (a, 1), constm1_rtx);
3470 85 : rtx_insn *seqm1 = end_sequence ();
3471 85 : unsigned costm1 = seq_cost (seqm1, if_info->speed_p);
3472 85 : if (!targetm1)
3473 79 : costm1 = -1u;
3474 : /* If both fails, then there is no costing to be done. */
3475 85 : if (!targetm1 && !target)
3476 : return false;
3477 :
3478 : /* If -1 is cheaper or the same cost to producing 0, then use that. */
3479 85 : if (costm1 <= cost0)
3480 : {
3481 6 : push_to_sequence (seqm1);
3482 6 : targetm1 = expand_simple_binop (mode, op, a_op0, targetm1,
3483 : if_info->x, 0, OPTAB_WIDEN);
3484 6 : if (targetm1)
3485 : {
3486 6 : target = targetm1;
3487 6 : goto success;
3488 : }
3489 0 : end_sequence ();
3490 : }
3491 79 : if (!target)
3492 : return false;
3493 : /* For 0 the produce sequence is:
3494 : tmp = !cond ? y : 0
3495 : x = (y & z) | tmp */
3496 79 : push_to_sequence (seq0);
3497 79 : rtx a_bin = gen_reg_rtx (mode);
3498 79 : noce_emit_move_insn (a_bin, a);
3499 :
3500 79 : target = expand_simple_binop (mode, IOR, a_bin, target, if_info->x, 0,
3501 : OPTAB_WIDEN);
3502 79 : if (!target)
3503 0 : goto end_seq_n_fail;
3504 79 : goto success;
3505 : }
3506 10693 : if (!target)
3507 : goto end_seq_n_fail;
3508 :
3509 10693 : target = expand_simple_binop (mode, op, a_op0, target, if_info->x, 0,
3510 : OPTAB_WIDEN);
3511 :
3512 10693 : if (!target)
3513 0 : goto end_seq_n_fail;
3514 :
3515 10693 : success:
3516 10778 : if (target != if_info->x)
3517 0 : noce_emit_move_insn (if_info->x, target);
3518 :
3519 10778 : seq = end_ifcvt_sequence (if_info);
3520 10778 : if (!seq || !targetm.noce_conversion_profitable_p (seq, if_info))
3521 396 : goto fail;
3522 :
3523 10382 : emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATION (if_info->insn_a));
3524 10382 : if_info->transform_name = "noce_try_cond_arith";
3525 10382 : return true;
3526 :
3527 0 : end_seq_n_fail:
3528 0 : end_sequence ();
3529 :
3530 156767 : fail:
3531 :
3532 : return false;
3533 : }
3534 :
3535 : /* Optimize away "if (x & C) x |= C" and similar bit manipulation
3536 : transformations. */
3537 :
3538 : static bool
3539 209093 : noce_try_bitop (struct noce_if_info *if_info)
3540 : {
3541 209093 : rtx cond, x, a, result;
3542 209093 : rtx_insn *seq;
3543 209093 : scalar_int_mode mode;
3544 209093 : enum rtx_code code;
3545 209093 : int bitnum;
3546 :
3547 209093 : x = if_info->x;
3548 209093 : cond = if_info->cond;
3549 209093 : code = GET_CODE (cond);
3550 :
3551 : /* Check for an integer operation. */
3552 209093 : if (!is_a <scalar_int_mode> (GET_MODE (x), &mode))
3553 : return false;
3554 :
3555 235202 : if (!noce_simple_bbs (if_info))
3556 : return false;
3557 :
3558 : /* Check for no else condition. */
3559 159179 : if (! rtx_equal_p (x, if_info->b))
3560 : return false;
3561 :
3562 : /* Check for a suitable condition. */
3563 84174 : if (code != NE && code != EQ)
3564 : return false;
3565 59840 : if (XEXP (cond, 1) != const0_rtx)
3566 : return false;
3567 41573 : cond = XEXP (cond, 0);
3568 :
3569 : /* ??? We could also handle AND here. */
3570 41573 : if (GET_CODE (cond) == ZERO_EXTRACT)
3571 : {
3572 230 : if (XEXP (cond, 1) != const1_rtx
3573 114 : || !CONST_INT_P (XEXP (cond, 2))
3574 344 : || ! rtx_equal_p (x, XEXP (cond, 0)))
3575 : return false;
3576 4 : bitnum = INTVAL (XEXP (cond, 2));
3577 4 : if (BITS_BIG_ENDIAN)
3578 : bitnum = GET_MODE_BITSIZE (mode) - 1 - bitnum;
3579 4 : if (bitnum < 0 || bitnum >= HOST_BITS_PER_WIDE_INT)
3580 : return false;
3581 : }
3582 : else
3583 : return false;
3584 :
3585 4 : a = if_info->a;
3586 4 : if (GET_CODE (a) == IOR || GET_CODE (a) == XOR)
3587 : {
3588 : /* Check for "if (X & C) x = x op C". */
3589 0 : if (! rtx_equal_p (x, XEXP (a, 0))
3590 0 : || !CONST_INT_P (XEXP (a, 1))
3591 0 : || (INTVAL (XEXP (a, 1)) & GET_MODE_MASK (mode))
3592 0 : != HOST_WIDE_INT_1U << bitnum)
3593 : return false;
3594 :
3595 : /* if ((x & C) == 0) x |= C; is transformed to x |= C. */
3596 : /* if ((x & C) != 0) x |= C; is transformed to nothing. */
3597 0 : if (GET_CODE (a) == IOR)
3598 0 : result = (code == NE) ? a : NULL_RTX;
3599 0 : else if (code == NE)
3600 : {
3601 : /* if ((x & C) == 0) x ^= C; is transformed to x |= C. */
3602 0 : result = gen_int_mode (HOST_WIDE_INT_1 << bitnum, mode);
3603 0 : result = simplify_gen_binary (IOR, mode, x, result);
3604 : }
3605 : else
3606 : {
3607 : /* if ((x & C) != 0) x ^= C; is transformed to x &= ~C. */
3608 0 : result = gen_int_mode (~(HOST_WIDE_INT_1 << bitnum), mode);
3609 0 : result = simplify_gen_binary (AND, mode, x, result);
3610 : }
3611 : }
3612 4 : else if (GET_CODE (a) == AND)
3613 : {
3614 : /* Check for "if (X & C) x &= ~C". */
3615 0 : if (! rtx_equal_p (x, XEXP (a, 0))
3616 0 : || !CONST_INT_P (XEXP (a, 1))
3617 0 : || (INTVAL (XEXP (a, 1)) & GET_MODE_MASK (mode))
3618 0 : != (~(HOST_WIDE_INT_1 << bitnum) & GET_MODE_MASK (mode)))
3619 : return false;
3620 :
3621 : /* if ((x & C) == 0) x &= ~C; is transformed to nothing. */
3622 : /* if ((x & C) != 0) x &= ~C; is transformed to x &= ~C. */
3623 0 : result = (code == EQ) ? a : NULL_RTX;
3624 : }
3625 : else
3626 : return false;
3627 :
3628 0 : if (result)
3629 : {
3630 0 : start_sequence ();
3631 0 : noce_emit_move_insn (x, result);
3632 0 : seq = end_ifcvt_sequence (if_info);
3633 0 : if (!seq)
3634 : return false;
3635 :
3636 0 : emit_insn_before_setloc (seq, if_info->jump,
3637 0 : INSN_LOCATION (if_info->insn_a));
3638 : }
3639 0 : if_info->transform_name = "noce_try_bitop";
3640 0 : return true;
3641 : }
3642 :
3643 :
3644 : /* Similar to get_condition, only the resulting condition must be
3645 : valid at JUMP, instead of at EARLIEST.
3646 :
3647 : If THEN_ELSE_REVERSED is true, the fallthrough does not go to the
3648 : THEN block of the caller, and we have to reverse the condition. */
3649 :
3650 : static rtx
3651 4395850 : noce_get_condition (rtx_insn *jump, rtx_insn **earliest,
3652 : bool then_else_reversed)
3653 : {
3654 4395850 : rtx cond, set, tmp;
3655 4395850 : bool reverse;
3656 :
3657 4395850 : if (! any_condjump_p (jump))
3658 : return NULL_RTX;
3659 :
3660 4395850 : set = pc_set (jump);
3661 :
3662 : /* If this branches to JUMP_LABEL when the condition is false,
3663 : reverse the condition. */
3664 8791700 : reverse = (GET_CODE (XEXP (SET_SRC (set), 2)) == LABEL_REF
3665 4395850 : && label_ref_label (XEXP (SET_SRC (set), 2)) == JUMP_LABEL (jump));
3666 :
3667 : /* We may have to reverse because the caller's if block is not canonical,
3668 : i.e. the THEN block isn't the fallthrough block for the TEST block
3669 : (see find_if_header). */
3670 4395850 : if (then_else_reversed)
3671 1926312 : reverse = !reverse;
3672 :
3673 : /* If the condition variable is a register and is MODE_INT, accept it. */
3674 :
3675 4395850 : cond = XEXP (SET_SRC (set), 0);
3676 4395850 : tmp = XEXP (cond, 0);
3677 4395109 : if (REG_P (tmp) && GET_MODE_CLASS (GET_MODE (tmp)) == MODE_INT
3678 4395890 : && (GET_MODE (tmp) != BImode
3679 0 : || !targetm.small_register_classes_for_mode_p (BImode)))
3680 : {
3681 40 : *earliest = jump;
3682 :
3683 40 : if (reverse)
3684 17 : cond = gen_rtx_fmt_ee (reverse_condition (GET_CODE (cond)),
3685 : GET_MODE (cond), tmp, XEXP (cond, 1));
3686 : return cond;
3687 : }
3688 :
3689 : /* Otherwise, fall back on canonicalize_condition to do the dirty
3690 : work of manipulating MODE_CC values and COMPARE rtx codes. */
3691 4395810 : tmp = canonicalize_condition (jump, cond, reverse, earliest,
3692 : NULL_RTX, have_cbranchcc4, true);
3693 :
3694 : /* We don't handle side-effects in the condition, like handling
3695 : REG_INC notes and making sure no duplicate conditions are emitted. */
3696 4395810 : if (tmp != NULL_RTX && side_effects_p (tmp))
3697 8380 : return NULL_RTX;
3698 :
3699 : return tmp;
3700 : }
3701 :
3702 : /* Return true if OP is ok for if-then-else processing. */
3703 :
3704 : static bool
3705 7895779 : noce_operand_ok (const_rtx op)
3706 : {
3707 7895779 : if (side_effects_p (op))
3708 : return false;
3709 :
3710 : /* We special-case memories, so handle any of them with
3711 : no address side effects. */
3712 7875056 : if (MEM_P (op))
3713 1588606 : return ! side_effects_p (XEXP (op, 0));
3714 :
3715 6286450 : return ! may_trap_p (op);
3716 : }
3717 :
3718 : /* Return true iff basic block TEST_BB is valid for noce if-conversion.
3719 : The condition used in this if-conversion is in COND.
3720 : In practice, check that TEST_BB ends with a single set
3721 : x := a and all previous computations
3722 : in TEST_BB don't produce any values that are live after TEST_BB.
3723 : In other words, all the insns in TEST_BB are there only
3724 : to compute a value for x. Add the rtx cost of the insns
3725 : in TEST_BB to COST. Record whether TEST_BB is a single simple
3726 : set instruction in SIMPLE_P. */
3727 :
3728 : static bool
3729 2187692 : bb_valid_for_noce_process_p (basic_block test_bb, rtx cond,
3730 : unsigned int *cost, bool *simple_p)
3731 : {
3732 2187692 : if (!test_bb)
3733 : return false;
3734 :
3735 2187692 : rtx_insn *last_insn = last_active_insn (test_bb, false);
3736 2187692 : rtx last_set = NULL_RTX;
3737 :
3738 2187692 : rtx cc = cc_in_cond (cond);
3739 :
3740 2187692 : if (!insn_valid_noce_process_p (last_insn, cc))
3741 : return false;
3742 :
3743 : /* Punt on blocks ending with asm goto or jumps with other side-effects,
3744 : last_active_insn ignores JUMP_INSNs. */
3745 1556121 : if (JUMP_P (BB_END (test_bb)) && !onlyjump_p (BB_END (test_bb)))
3746 : return false;
3747 :
3748 1556119 : last_set = single_set (last_insn);
3749 :
3750 1556119 : rtx x = SET_DEST (last_set);
3751 1556119 : rtx_insn *first_insn = first_active_insn (test_bb);
3752 1556119 : rtx first_set = single_set (first_insn);
3753 :
3754 1556119 : if (!first_set)
3755 : return false;
3756 :
3757 : /* We have a single simple set, that's okay. */
3758 1542131 : bool speed_p = optimize_bb_for_speed_p (test_bb);
3759 :
3760 1542131 : if (first_insn == last_insn)
3761 : {
3762 562452 : *simple_p = noce_operand_ok (SET_DEST (first_set));
3763 562452 : *cost += pattern_cost (first_set, speed_p);
3764 562452 : return *simple_p;
3765 : }
3766 :
3767 979679 : rtx_insn *prev_last_insn = PREV_INSN (last_insn);
3768 979679 : gcc_assert (prev_last_insn);
3769 :
3770 : /* For now, disallow setting x multiple times in test_bb. */
3771 979679 : if (REG_P (x) && reg_set_between_p (x, first_insn, prev_last_insn))
3772 : return false;
3773 :
3774 832556 : bitmap test_bb_temps = BITMAP_ALLOC (®_obstack);
3775 :
3776 : /* The regs that are live out of test_bb. */
3777 832556 : bitmap test_bb_live_out = df_get_live_out (test_bb);
3778 :
3779 832556 : int potential_cost = pattern_cost (last_set, speed_p);
3780 832556 : rtx_insn *insn;
3781 4582842 : FOR_BB_INSNS (test_bb, insn)
3782 : {
3783 4489559 : if (insn != last_insn)
3784 : {
3785 4396276 : if (!active_insn_p (insn))
3786 2908988 : continue;
3787 :
3788 1487288 : if (!insn_valid_noce_process_p (insn, cc))
3789 229557 : goto free_bitmap_and_fail;
3790 :
3791 1257731 : rtx sset = single_set (insn);
3792 1257731 : gcc_assert (sset);
3793 1257731 : rtx dest = SET_DEST (sset);
3794 1257731 : if (SUBREG_P (dest))
3795 18537 : dest = SUBREG_REG (dest);
3796 :
3797 1257731 : if (contains_mem_rtx_p (SET_SRC (sset))
3798 887959 : || !REG_P (dest)
3799 2017156 : || reg_overlap_mentioned_p (dest, cond))
3800 509716 : goto free_bitmap_and_fail;
3801 :
3802 748015 : potential_cost += pattern_cost (sset, speed_p);
3803 748015 : bitmap_set_bit (test_bb_temps, REGNO (dest));
3804 : }
3805 : }
3806 :
3807 : /* If any of the intermediate results in test_bb are live after test_bb
3808 : then fail. */
3809 93283 : if (bitmap_intersect_p (test_bb_live_out, test_bb_temps))
3810 62594 : goto free_bitmap_and_fail;
3811 :
3812 30689 : BITMAP_FREE (test_bb_temps);
3813 30689 : *cost += potential_cost;
3814 30689 : *simple_p = false;
3815 30689 : return true;
3816 :
3817 801867 : free_bitmap_and_fail:
3818 801867 : BITMAP_FREE (test_bb_temps);
3819 801867 : return false;
3820 : }
3821 :
3822 : /* Helper function to emit a cmov sequence encapsulated in
3823 : start_sequence () and end_sequence (). If NEED_CMOV is true
3824 : we call noce_emit_cmove to create a cmove sequence. Otherwise emit
3825 : a simple move. If successful, store the first instruction of the
3826 : sequence in TEMP_DEST and the sequence costs in SEQ_COST. */
3827 :
3828 : static rtx_insn*
3829 260676 : try_emit_cmove_seq (struct noce_if_info *if_info, rtx temp,
3830 : rtx cond, rtx new_val, rtx old_val, bool need_cmov,
3831 : unsigned *cost, rtx *temp_dest,
3832 : rtx cc_cmp = NULL, rtx rev_cc_cmp = NULL)
3833 : {
3834 260676 : rtx_insn *seq = NULL;
3835 260676 : *cost = 0;
3836 :
3837 260676 : rtx x = XEXP (cond, 0);
3838 260676 : rtx y = XEXP (cond, 1);
3839 260676 : rtx_code cond_code = GET_CODE (cond);
3840 :
3841 260676 : start_sequence ();
3842 :
3843 260676 : if (need_cmov)
3844 217111 : *temp_dest = noce_emit_cmove (if_info, temp, cond_code,
3845 : x, y, new_val, old_val, cc_cmp, rev_cc_cmp);
3846 : else
3847 : {
3848 43565 : *temp_dest = temp;
3849 43565 : if (if_info->then_else_reversed)
3850 1948 : noce_emit_move_insn (temp, old_val);
3851 : else
3852 41617 : noce_emit_move_insn (temp, new_val);
3853 : }
3854 :
3855 260676 : if (*temp_dest != NULL_RTX)
3856 : {
3857 254686 : seq = get_insns ();
3858 254686 : *cost = seq_cost (seq, if_info->speed_p);
3859 : }
3860 :
3861 260676 : end_sequence ();
3862 :
3863 260676 : return seq;
3864 : }
3865 :
3866 : /* We have something like:
3867 :
3868 : if (x > y)
3869 : { i = EXPR_A; j = EXPR_B; k = EXPR_C; }
3870 :
3871 : Make it:
3872 :
3873 : tmp_i = (x > y) ? EXPR_A : i;
3874 : tmp_j = (x > y) ? EXPR_B : j;
3875 : tmp_k = (x > y) ? EXPR_C : k;
3876 : i = tmp_i;
3877 : j = tmp_j;
3878 : k = tmp_k;
3879 :
3880 : Subsequent passes are expected to clean up the extra moves.
3881 :
3882 : Look for special cases such as writes to one register which are
3883 : read back in another SET, as might occur in a swap idiom or
3884 : similar.
3885 :
3886 : These look like:
3887 :
3888 : if (x > y)
3889 : i = a;
3890 : j = i;
3891 :
3892 : Which we want to rewrite to:
3893 :
3894 : tmp_i = (x > y) ? a : i;
3895 : tmp_j = (x > y) ? tmp_i : j;
3896 : i = tmp_i;
3897 : j = tmp_j;
3898 :
3899 : We can catch these when looking at (SET x y) by keeping a list of the
3900 : registers we would have targeted before if-conversion and looking back
3901 : through it for an overlap with Y. If we find one, we rewire the
3902 : conditional set to use the temporary we introduced earlier.
3903 :
3904 : IF_INFO contains the useful information about the block structure and
3905 : jump instructions. */
3906 :
3907 : static bool
3908 30029 : noce_convert_multiple_sets (struct noce_if_info *if_info)
3909 : {
3910 30029 : basic_block test_bb = if_info->test_bb;
3911 30029 : basic_block then_bb = if_info->then_bb;
3912 30029 : basic_block join_bb = if_info->join_bb;
3913 30029 : rtx_insn *jump = if_info->jump;
3914 30029 : rtx_insn *cond_earliest;
3915 30029 : rtx_insn *insn;
3916 :
3917 30029 : start_sequence ();
3918 :
3919 : /* Decompose the condition attached to the jump. */
3920 30029 : rtx cond = noce_get_condition (jump, &cond_earliest, false);
3921 30029 : rtx x = XEXP (cond, 0);
3922 30029 : rtx y = XEXP (cond, 1);
3923 :
3924 30029 : auto_delete_vec<noce_multiple_sets_info> insn_info;
3925 30029 : init_noce_multiple_sets_info (then_bb, insn_info);
3926 :
3927 30029 : int last_needs_comparison = -1;
3928 :
3929 30029 : bool use_cond_earliest = false;
3930 :
3931 30029 : bool ok = noce_convert_multiple_sets_1
3932 30029 : (if_info, insn_info, &last_needs_comparison, &use_cond_earliest);
3933 30029 : if (!ok)
3934 : return false;
3935 :
3936 : /* Always perform a second attempt that uses information gathered in the
3937 : first. At least we can omit creating temporaries until we definitely
3938 : need them. The sequence created in the second attempt is never worse
3939 : than the first. */
3940 :
3941 29033 : end_sequence ();
3942 29033 : start_sequence ();
3943 29033 : ok = noce_convert_multiple_sets_1
3944 29033 : (if_info, insn_info, &last_needs_comparison, &use_cond_earliest);
3945 :
3946 : /* Actually we should not fail anymore if we reached here,
3947 : but better still check. */
3948 29033 : if (!ok)
3949 : return false;
3950 :
3951 : /* We must have seen some sort of insn to insert, otherwise we were
3952 : given an empty BB to convert, and we can't handle that. */
3953 29033 : gcc_assert (!insn_info.is_empty ());
3954 :
3955 : /* Now fixup the assignments.
3956 : PR116405: Iterate in reverse order and keep track of the targets so that
3957 : a move does not overwrite a subsequent value when multiple instructions
3958 : have the same target. */
3959 29033 : unsigned i;
3960 29033 : noce_multiple_sets_info *info;
3961 29033 : bitmap set_targets = BITMAP_ALLOC (®_obstack);
3962 105059 : FOR_EACH_VEC_ELT_REVERSE (insn_info, i, info)
3963 : {
3964 76026 : gcc_checking_assert (REG_P (info->target));
3965 :
3966 76026 : if (info->target != info->temporary
3967 76026 : && !bitmap_bit_p (set_targets, REGNO (info->target)))
3968 2718 : noce_emit_move_insn (info->target, info->temporary);
3969 :
3970 76026 : bitmap_set_bit (set_targets, REGNO (info->target));
3971 : }
3972 29033 : BITMAP_FREE (set_targets);
3973 :
3974 : /* Actually emit the sequence if it isn't too expensive. */
3975 29033 : rtx_insn *seq = get_insns ();
3976 :
3977 : /* If the created sequence does not use cond_earliest (but the jump
3978 : does) add its cost to the original_cost before comparing costs. */
3979 29033 : unsigned int original_cost = if_info->original_cost;
3980 29033 : if (if_info->jump != if_info->cond_earliest && !use_cond_earliest)
3981 17822 : if_info->original_cost += insn_cost (if_info->cond_earliest,
3982 : if_info->speed_p);
3983 :
3984 29033 : if (!targetm.noce_conversion_profitable_p (seq, if_info))
3985 : {
3986 3602 : end_sequence ();
3987 3602 : return false;
3988 : }
3989 :
3990 : /* Restore the original cost in case we do not succeed below. */
3991 25431 : if_info->original_cost = original_cost;
3992 :
3993 146938 : for (insn = seq; insn; insn = NEXT_INSN (insn))
3994 121507 : set_used_flags (insn);
3995 :
3996 : /* Mark all our temporaries and targets as used. */
3997 87460 : for (unsigned i = 0; i < insn_info.length (); i++)
3998 : {
3999 62029 : set_used_flags (insn_info[i]->temporary);
4000 62029 : set_used_flags (insn_info[i]->target);
4001 : }
4002 :
4003 25431 : set_used_flags (cond);
4004 25431 : set_used_flags (x);
4005 25431 : set_used_flags (y);
4006 :
4007 25431 : unshare_all_rtl_in_chain (seq);
4008 25431 : end_sequence ();
4009 :
4010 25431 : if (!seq)
4011 : return false;
4012 :
4013 146751 : for (insn = seq; insn; insn = NEXT_INSN (insn))
4014 121367 : if (JUMP_P (insn) || CALL_P (insn)
4015 121367 : || recog_memoized (insn) == -1)
4016 : return false;
4017 :
4018 25384 : emit_insn_before_setloc (seq, if_info->jump,
4019 25384 : INSN_LOCATION (insn_info.last ()->unmodified_insn));
4020 :
4021 : /* Clean up THEN_BB and the edges in and out of it. */
4022 25384 : remove_edge (find_edge (test_bb, join_bb));
4023 25384 : remove_edge (find_edge (then_bb, join_bb));
4024 25384 : redirect_edge_and_branch_force (single_succ_edge (test_bb), join_bb);
4025 25384 : delete_basic_block (then_bb);
4026 25384 : num_true_changes++;
4027 :
4028 : /* Maybe merge blocks now the jump is simple enough. */
4029 25384 : if (can_merge_blocks_p (test_bb, join_bb))
4030 : {
4031 16713 : merge_blocks (test_bb, join_bb);
4032 16713 : num_true_changes++;
4033 : }
4034 :
4035 25384 : num_updated_if_blocks++;
4036 25384 : if_info->transform_name = "noce_convert_multiple_sets";
4037 25384 : return true;
4038 30029 : }
4039 :
4040 : /* This goes through all relevant insns of IF_INFO->then_bb and tries to create
4041 : conditional moves. Information for the insns is kept in INSN_INFO. */
4042 :
4043 : static bool
4044 59062 : noce_convert_multiple_sets_1 (struct noce_if_info *if_info,
4045 : auto_delete_vec<noce_multiple_sets_info> &insn_info,
4046 : int *last_needs_comparison,
4047 : bool *use_cond_earliest)
4048 : {
4049 59062 : basic_block then_bb = if_info->then_bb;
4050 59062 : rtx_insn *jump = if_info->jump;
4051 59062 : rtx_insn *cond_earliest;
4052 :
4053 : /* Decompose the condition attached to the jump. */
4054 59062 : rtx cond = noce_get_condition (jump, &cond_earliest, false);
4055 :
4056 59062 : rtx cc_cmp = cond_exec_get_condition (jump);
4057 59062 : if (cc_cmp)
4058 59062 : cc_cmp = copy_rtx (cc_cmp);
4059 59062 : rtx rev_cc_cmp = cond_exec_get_condition (jump, /* get_reversed */ true);
4060 59062 : if (rev_cc_cmp)
4061 59062 : rev_cc_cmp = copy_rtx (rev_cc_cmp);
4062 :
4063 59062 : rtx_insn *insn;
4064 59062 : int count = 0;
4065 59062 : bool second_try = *last_needs_comparison != -1;
4066 59062 : *use_cond_earliest = false;
4067 :
4068 349763 : FOR_BB_INSNS (then_bb, insn)
4069 : {
4070 : /* Skip over non-insns. */
4071 291697 : if (!active_insn_p (insn))
4072 137200 : continue;
4073 :
4074 154497 : noce_multiple_sets_info *info = insn_info[count];
4075 :
4076 154497 : rtx set = single_set (insn);
4077 154497 : gcc_checking_assert (set);
4078 :
4079 154497 : rtx target = SET_DEST (set);
4080 154497 : rtx temp;
4081 :
4082 154497 : rtx new_val = SET_SRC (set);
4083 :
4084 154497 : int i, ii;
4085 184400 : FOR_EACH_VEC_ELT (info->rewired_src, i, ii)
4086 29903 : new_val = simplify_replace_rtx (new_val, insn_info[ii]->target,
4087 29903 : insn_info[ii]->temporary);
4088 :
4089 154497 : rtx old_val = target;
4090 :
4091 : /* As we are transforming
4092 : if (x > y)
4093 : {
4094 : a = b;
4095 : c = d;
4096 : }
4097 : into
4098 : a = (x > y) ...
4099 : c = (x > y) ...
4100 :
4101 : we potentially check x > y before every set.
4102 : Even though the check might be removed by subsequent passes, this means
4103 : that we cannot transform
4104 : if (x > y)
4105 : {
4106 : x = y;
4107 : ...
4108 : }
4109 : into
4110 : x = (x > y) ...
4111 : ...
4112 : since this would invalidate x and the following to-be-removed checks.
4113 : Therefore we introduce a temporary every time we are about to
4114 : overwrite a variable used in the check. Costing of a sequence with
4115 : these is going to be inaccurate so only use temporaries when
4116 : needed.
4117 :
4118 : If performing a second try, we know how many insns require a
4119 : temporary. For the last of these, we can omit creating one. */
4120 154497 : if (reg_overlap_mentioned_p (target, cond)
4121 154497 : && (!second_try || count < *last_needs_comparison))
4122 20722 : temp = gen_reg_rtx (GET_MODE (target));
4123 : else
4124 : temp = target;
4125 :
4126 : /* We have identified swap-style idioms before. A normal
4127 : set will need to be a cmov while the first instruction of a swap-style
4128 : idiom can be a regular move. This helps with costing. */
4129 154497 : bool need_cmov = info->need_cmov;
4130 :
4131 : /* If we had a non-canonical conditional jump (i.e. one where
4132 : the fallthrough is to the "else" case) we need to reverse
4133 : the conditional select. */
4134 154497 : if (if_info->then_else_reversed)
4135 51636 : std::swap (old_val, new_val);
4136 :
4137 : /* Try emitting a conditional move passing the backend the
4138 : canonicalized comparison. The backend is then able to
4139 : recognize expressions like
4140 :
4141 : if (x > y)
4142 : y = x;
4143 :
4144 : as min/max and emit an insn, accordingly. */
4145 154497 : unsigned cost1 = 0, cost2 = 0;
4146 154497 : rtx_insn *seq, *seq1, *seq2 = NULL;
4147 154497 : rtx temp_dest = NULL_RTX, temp_dest1 = NULL_RTX, temp_dest2 = NULL_RTX;
4148 154497 : bool read_comparison = false;
4149 :
4150 154497 : seq1 = try_emit_cmove_seq (if_info, temp, cond,
4151 : new_val, old_val, need_cmov,
4152 : &cost1, &temp_dest1);
4153 :
4154 : /* Here, we try to pass the backend a non-canonicalized cc comparison
4155 : as well. This allows the backend to emit a cmov directly without
4156 : creating an additional compare for each. If successful, costing
4157 : is easier and this sequence is usually preferred. */
4158 154497 : if (cc_cmp)
4159 : {
4160 106179 : seq2 = try_emit_cmove_seq (if_info, temp, cond,
4161 : new_val, old_val, need_cmov,
4162 : &cost2, &temp_dest2, cc_cmp, rev_cc_cmp);
4163 :
4164 : /* The if_then_else in SEQ2 may be affected when cc_cmp/rev_cc_cmp is
4165 : clobbered. We can't safely use the sequence in this case. */
4166 293492 : for (rtx_insn *iter = seq2; iter; iter = NEXT_INSN (iter))
4167 118597 : if (modified_in_p (cc_cmp, iter)
4168 118597 : || (rev_cc_cmp && modified_in_p (rev_cc_cmp, iter)))
4169 : {
4170 : seq2 = NULL;
4171 : break;
4172 : }
4173 : }
4174 :
4175 : /* The backend might have created a sequence that uses the
4176 : condition as a value. Check this. */
4177 :
4178 : /* We cannot handle anything more complex than a reg or constant. */
4179 154497 : if (!REG_P (XEXP (cond, 0)) && !CONSTANT_P (XEXP (cond, 0)))
4180 154497 : read_comparison = true;
4181 :
4182 154497 : if (!REG_P (XEXP (cond, 1)) && !CONSTANT_P (XEXP (cond, 1)))
4183 154497 : read_comparison = true;
4184 :
4185 154497 : rtx_insn *walk = seq2;
4186 154497 : int if_then_else_count = 0;
4187 232018 : while (walk && !read_comparison)
4188 : {
4189 77521 : rtx exprs_to_check[2];
4190 77521 : unsigned int exprs_count = 0;
4191 :
4192 77521 : rtx set = single_set (walk);
4193 77521 : if (set && XEXP (set, 1)
4194 77521 : && GET_CODE (XEXP (set, 1)) == IF_THEN_ELSE)
4195 : {
4196 : /* We assume that this is the cmove created by the backend that
4197 : naturally uses the condition. */
4198 49860 : exprs_to_check[exprs_count++] = XEXP (XEXP (set, 1), 1);
4199 49860 : exprs_to_check[exprs_count++] = XEXP (XEXP (set, 1), 2);
4200 49860 : if_then_else_count++;
4201 : }
4202 27661 : else if (NONDEBUG_INSN_P (walk))
4203 27661 : exprs_to_check[exprs_count++] = PATTERN (walk);
4204 :
4205 : /* Bail if we get more than one if_then_else because the assumption
4206 : above may be incorrect. */
4207 77521 : if (if_then_else_count > 1)
4208 : {
4209 0 : read_comparison = true;
4210 0 : break;
4211 : }
4212 :
4213 204902 : for (unsigned int i = 0; i < exprs_count; i++)
4214 : {
4215 127381 : subrtx_iterator::array_type array;
4216 281380 : FOR_EACH_SUBRTX (iter, array, exprs_to_check[i], NONCONST)
4217 184242 : if (*iter != NULL_RTX
4218 184242 : && (reg_overlap_mentioned_p (XEXP (cond, 0), *iter)
4219 166683 : || reg_overlap_mentioned_p (XEXP (cond, 1), *iter)))
4220 : {
4221 : read_comparison = true;
4222 : break;
4223 : }
4224 127381 : }
4225 :
4226 77521 : walk = NEXT_INSN (walk);
4227 : }
4228 :
4229 : /* Check which version is less expensive. */
4230 154497 : if (seq1 != NULL_RTX && (cost1 <= cost2 || seq2 == NULL_RTX))
4231 : {
4232 102503 : seq = seq1;
4233 102503 : temp_dest = temp_dest1;
4234 102503 : if (!second_try)
4235 52024 : *last_needs_comparison = count;
4236 : }
4237 1077 : else if (seq2 != NULL_RTX)
4238 : {
4239 51125 : seq = seq2;
4240 51125 : temp_dest = temp_dest2;
4241 51125 : if (!second_try && read_comparison)
4242 8452 : *last_needs_comparison = count;
4243 51125 : *use_cond_earliest = true;
4244 : }
4245 : else
4246 : {
4247 : /* Nothing worked, bail out. */
4248 869 : end_sequence ();
4249 996 : return false;
4250 : }
4251 :
4252 : /* Although we use temporaries if there is register overlap of COND and
4253 : TARGET, it is possible that SEQ modifies COND anyway. For example,
4254 : COND may use the flags register and if INSN clobbers flags then
4255 : we may be unable to emit a valid sequence (e.g. in x86 that would
4256 : require saving and restoring the flags register). */
4257 103149 : if (!second_try)
4258 233501 : for (rtx_insn *iter = seq; iter; iter = NEXT_INSN (iter))
4259 156026 : if (modified_in_p (cond, iter))
4260 : {
4261 127 : end_sequence ();
4262 127 : return false;
4263 : }
4264 :
4265 153501 : if (cc_cmp && seq == seq1)
4266 : {
4267 : /* Check if SEQ can clobber registers mentioned in cc_cmp/rev_cc_cmp.
4268 : If yes, we need to use only SEQ1 from that point on.
4269 : Only check when we use SEQ1 since we have already tested SEQ2. */
4270 74879 : for (rtx_insn *iter = seq; iter; iter = NEXT_INSN (iter))
4271 57435 : if (modified_in_p (cc_cmp, iter)
4272 57435 : || (rev_cc_cmp && modified_in_p (rev_cc_cmp, iter)))
4273 : {
4274 : cc_cmp = NULL_RTX;
4275 : rev_cc_cmp = NULL_RTX;
4276 : break;
4277 : }
4278 : }
4279 :
4280 : /* End the sub sequence and emit to the main sequence. */
4281 153501 : emit_insn (seq);
4282 :
4283 : /* Bookkeeping. */
4284 153501 : count++;
4285 :
4286 153501 : info->target = target;
4287 153501 : info->temporary = temp_dest;
4288 153501 : info->unmodified_insn = insn;
4289 : }
4290 :
4291 : /* Even if we did not actually need the comparison, we want to make sure
4292 : to try a second time in order to get rid of the temporaries. */
4293 58066 : if (*last_needs_comparison == -1)
4294 979 : *last_needs_comparison = 0;
4295 :
4296 : return true;
4297 : }
4298 :
4299 : /* Find local swap-style idioms in BB and mark the first insn (1)
4300 : that is only a temporary as not needing a conditional move as
4301 : it is going to be dead afterwards anyway.
4302 :
4303 : (1) int tmp = a;
4304 : a = b;
4305 : b = tmp;
4306 :
4307 : ifcvt
4308 : -->
4309 :
4310 : tmp = a;
4311 : a = cond ? b : a_old;
4312 : b = cond ? tmp : b_old;
4313 :
4314 : Additionally, store the index of insns like (2) when a subsequent
4315 : SET reads from their destination.
4316 :
4317 : (2) int c = a;
4318 : int d = c;
4319 :
4320 : ifcvt
4321 : -->
4322 :
4323 : c = cond ? a : c_old;
4324 : d = cond ? d : c; // Need to use c rather than c_old here.
4325 : */
4326 :
4327 : static void
4328 30029 : init_noce_multiple_sets_info (basic_block bb,
4329 : auto_delete_vec<noce_multiple_sets_info> &insn_info)
4330 : {
4331 30029 : rtx_insn *insn;
4332 30029 : int count = 0;
4333 30029 : auto_vec<rtx> dests;
4334 30029 : bitmap bb_live_out = df_get_live_out (bb);
4335 :
4336 : /* Iterate over all SETs, storing the destinations in DEST.
4337 : - If we encounter a previously changed register,
4338 : rewire the read to the original source.
4339 : - If we encounter a SET that writes to a destination
4340 : that is not live after this block then the register
4341 : does not need to be moved conditionally. */
4342 180879 : FOR_BB_INSNS (bb, insn)
4343 : {
4344 150850 : if (!active_insn_p (insn))
4345 71980 : continue;
4346 :
4347 78870 : noce_multiple_sets_info *info = new noce_multiple_sets_info;
4348 78870 : info->target = NULL_RTX;
4349 78870 : info->temporary = NULL_RTX;
4350 78870 : info->unmodified_insn = NULL;
4351 78870 : insn_info.safe_push (info);
4352 :
4353 78870 : rtx set = single_set (insn);
4354 78870 : gcc_checking_assert (set);
4355 :
4356 78870 : rtx src = SET_SRC (set);
4357 78870 : rtx dest = SET_DEST (set);
4358 :
4359 78870 : gcc_checking_assert (REG_P (dest) && !HARD_REGISTER_P (dest));
4360 78870 : info->need_cmov = bitmap_bit_p (bb_live_out, REGNO (dest));
4361 :
4362 : /* Check if the current SET's source mentions any previously seen
4363 : destination. Keep only the newest definition of each pseudo register.
4364 : This is quadratic but the number of insns in BB
4365 : is bounded by PARAM_MAX_RTL_IF_CONVERSION_INSNS. */
4366 78870 : auto_bitmap rewired_regs;
4367 159176 : for (int i = count - 1; i >= 0; --i)
4368 80306 : if (reg_mentioned_p (dests[i], src)
4369 80306 : && bitmap_set_bit (rewired_regs, REGNO (dests[i])))
4370 15718 : insn_info[count]->rewired_src.safe_push (i);
4371 :
4372 78870 : dests.safe_push (dest);
4373 78870 : count++;
4374 78870 : }
4375 30029 : }
4376 :
4377 : /* Return true iff basic block TEST_BB is suitable for conversion to a
4378 : series of conditional moves. Also check that we have more than one
4379 : set (other routines can handle a single set better than we would),
4380 : and fewer than PARAM_MAX_RTL_IF_CONVERSION_INSNS sets. While going
4381 : through the insns store the sum of their potential costs in COST. */
4382 :
4383 : static bool
4384 1088090 : bb_ok_for_noce_convert_multiple_sets (basic_block test_bb, unsigned *cost)
4385 : {
4386 1088090 : rtx_insn *insn;
4387 1088090 : unsigned count = 0;
4388 1088090 : unsigned param = param_max_rtl_if_conversion_insns;
4389 1088090 : bool speed_p = optimize_bb_for_speed_p (test_bb);
4390 1088090 : unsigned potential_cost = 0;
4391 :
4392 8458743 : FOR_BB_INSNS (test_bb, insn)
4393 : {
4394 : /* Skip over notes etc. */
4395 8341322 : if (!active_insn_p (insn))
4396 6975323 : continue;
4397 :
4398 : /* We only handle SET insns. */
4399 1365999 : rtx set = single_set (insn);
4400 1365999 : if (set == NULL_RTX)
4401 : return false;
4402 :
4403 1302970 : rtx dest = SET_DEST (set);
4404 1302970 : rtx src = SET_SRC (set);
4405 :
4406 : /* Dependency rewiring is keyed by register number, so restrict
4407 : destinations to pseudos. Hard-register definitions can overlap
4408 : without having the same mode. Do not handle anything involving
4409 : memory loads/stores since it might violate data-race-freedom
4410 : guarantees. Make sure we can force SRC to a register as that may
4411 : be needed in try_emit_cmove_seq. */
4412 1138748 : if (!REG_P (dest) || HARD_REGISTER_P (dest)
4413 814470 : || contains_mem_rtx_p (src)
4414 1733303 : || !noce_can_force_operand (src))
4415 : return false;
4416 :
4417 : /* Destination and source must be appropriate. */
4418 422128 : if (!noce_operand_ok (dest) || !noce_operand_ok (src))
4419 : return false;
4420 :
4421 : /* We must be able to conditionally move in this mode. */
4422 416040 : if (!can_conditionally_move_p (GET_MODE (dest)))
4423 : return false;
4424 :
4425 395330 : potential_cost += insn_cost (insn, speed_p);
4426 :
4427 395330 : count++;
4428 : }
4429 :
4430 117421 : *cost += potential_cost;
4431 :
4432 : /* If we would only put out one conditional move, the other strategies
4433 : this pass tries are better optimized and will be more appropriate.
4434 : Some targets want to strictly limit the number of conditional moves
4435 : that are emitted, they set this through PARAM, we need to respect
4436 : that. */
4437 117421 : return count > 1 && count <= param;
4438 : }
4439 :
4440 : /* Compute average of two given costs weighted by relative probabilities
4441 : of respective basic blocks in an IF-THEN-ELSE. E is the IF-THEN edge.
4442 : With P as the probability to take the IF-THEN branch, return
4443 : P * THEN_COST + (1 - P) * ELSE_COST. Evaluate this as
4444 : ELSE_COST + P * (THEN_COST - ELSE_COST) when THEN_COST >= ELSE_COST, and
4445 : THEN_COST + (1 - P) * (ELSE_COST - THEN_COST) otherwise. Both forms pass
4446 : a nonnegative value to profile_probability::apply and make its rounding
4447 : independent of the CFG arm order. */
4448 : static unsigned
4449 259934 : average_cost (unsigned then_cost, unsigned else_cost, edge e)
4450 : {
4451 259934 : if (then_cost < else_cost)
4452 6651 : return then_cost
4453 6651 : + e->probability.invert ().apply ((gcov_type) else_cost - then_cost);
4454 :
4455 253283 : return else_cost
4456 253283 : + e->probability.apply ((gcov_type) then_cost - else_cost);
4457 : }
4458 :
4459 : /* Given a simple IF-THEN-JOIN or IF-THEN-ELSE-JOIN block, attempt to convert
4460 : it without using conditional execution. Return TRUE if we were successful
4461 : at converting the block. */
4462 :
4463 : static bool
4464 1922514 : noce_process_if_block (struct noce_if_info *if_info)
4465 : {
4466 1922514 : basic_block test_bb = if_info->test_bb; /* test block */
4467 1922514 : basic_block then_bb = if_info->then_bb; /* THEN */
4468 1922514 : basic_block else_bb = if_info->else_bb; /* ELSE or NULL */
4469 1922514 : basic_block join_bb = if_info->join_bb; /* JOIN */
4470 1922514 : rtx_insn *jump = if_info->jump;
4471 1922514 : rtx cond = if_info->cond;
4472 1922514 : rtx_insn *insn_a, *insn_b;
4473 1922514 : rtx set_a, set_b;
4474 1922514 : rtx orig_x, x, a, b;
4475 :
4476 : /* We're looking for patterns of the form
4477 :
4478 : (1) if (...) x = a; else x = b;
4479 : (2) x = b; if (...) x = a;
4480 : (3) if (...) x = a; // as if with an initial x = x.
4481 : (4) if (...) { x = a; y = b; z = c; } // Like 3, for multiple SETS.
4482 : The later patterns require jumps to be more expensive.
4483 : For the if (...) x = a; else x = b; case we allow multiple insns
4484 : inside the then and else blocks as long as their only effect is
4485 : to calculate a value for x.
4486 : ??? For future expansion, further expand the "multiple X" rules. */
4487 :
4488 : /* First look for multiple SETS.
4489 : The original costs already include costs for the jump insn as well
4490 : as for a CC comparison if there is any.
4491 : If a target re-uses the existing CC comparison we keep track of that
4492 : and add the costs before default noce_conversion_profitable_p. */
4493 :
4494 1922514 : unsigned potential_cost = if_info->original_cost;
4495 1922514 : unsigned old_cost = if_info->original_cost;
4496 1922514 : if (!else_bb
4497 : && HAVE_conditional_move
4498 1922514 : && bb_ok_for_noce_convert_multiple_sets (then_bb, &potential_cost))
4499 : {
4500 : /* Temporarily set the original costs to what we estimated so
4501 : we can determine if the transformation is worth it. */
4502 30029 : if_info->original_cost = potential_cost;
4503 30029 : if (noce_convert_multiple_sets (if_info))
4504 : {
4505 25384 : if (dump_file && if_info->transform_name)
4506 1 : fprintf (dump_file, "if-conversion succeeded through %s\n",
4507 : if_info->transform_name);
4508 : return true;
4509 : }
4510 :
4511 : /* Restore the original costs. */
4512 4645 : if_info->original_cost = old_cost;
4513 : }
4514 :
4515 1897130 : bool speed_p = optimize_bb_for_speed_p (test_bb);
4516 1897130 : unsigned int then_cost = 0, else_cost = 0;
4517 1897130 : if (!bb_valid_for_noce_process_p (then_bb, cond, &then_cost,
4518 : &if_info->then_simple))
4519 : return false;
4520 :
4521 488697 : if (else_bb
4522 488697 : && !bb_valid_for_noce_process_p (else_bb, cond, &else_cost,
4523 : &if_info->else_simple))
4524 : return false;
4525 :
4526 302579 : if (speed_p)
4527 259934 : if_info->original_cost += average_cost (then_cost, else_cost,
4528 : find_edge (test_bb, then_bb));
4529 : else
4530 42645 : if_info->original_cost += then_cost + else_cost;
4531 :
4532 302579 : insn_a = last_active_insn (then_bb, false);
4533 302579 : set_a = single_set (insn_a);
4534 302579 : gcc_assert (set_a);
4535 :
4536 302579 : x = SET_DEST (set_a);
4537 302579 : a = SET_SRC (set_a);
4538 :
4539 : /* Look for the other potential set. Make sure we've got equivalent
4540 : destinations. */
4541 : /* ??? This is overconservative. Storing to two different mems is
4542 : as easy as conditionally computing the address. Storing to a
4543 : single mem merely requires a scratch memory to use as one of the
4544 : destination addresses; often the memory immediately below the
4545 : stack pointer is available for this. */
4546 302579 : set_b = NULL_RTX;
4547 302579 : if (else_bb)
4548 : {
4549 104444 : insn_b = last_active_insn (else_bb, false);
4550 104444 : set_b = single_set (insn_b);
4551 104444 : gcc_assert (set_b);
4552 :
4553 104444 : if (!rtx_interchangeable_p (x, SET_DEST (set_b)))
4554 : return false;
4555 : }
4556 : else
4557 : {
4558 198135 : insn_b = if_info->cond_earliest;
4559 536691 : do
4560 536691 : insn_b = prev_nonnote_nondebug_insn (insn_b);
4561 : while (insn_b
4562 533991 : && (BLOCK_FOR_INSN (insn_b)
4563 533991 : == BLOCK_FOR_INSN (if_info->cond_earliest))
4564 1183675 : && !modified_in_p (x, insn_b));
4565 :
4566 : /* We're going to be moving the evaluation of B down from above
4567 : COND_EARLIEST to JUMP. Make sure the relevant data is still
4568 : intact. */
4569 198135 : if (! insn_b
4570 195435 : || BLOCK_FOR_INSN (insn_b) != BLOCK_FOR_INSN (if_info->cond_earliest)
4571 110293 : || !NONJUMP_INSN_P (insn_b)
4572 105099 : || (set_b = single_set (insn_b)) == NULL_RTX
4573 103657 : || ! rtx_interchangeable_p (x, SET_DEST (set_b))
4574 89254 : || ! noce_operand_ok (SET_SRC (set_b))
4575 87279 : || reg_overlap_mentioned_p (x, SET_SRC (set_b))
4576 85533 : || modified_between_p (SET_SRC (set_b), insn_b, jump)
4577 : /* Avoid extending the lifetime of hard registers on small
4578 : register class machines. */
4579 83318 : || (REG_P (SET_SRC (set_b))
4580 20194 : && HARD_REGISTER_P (SET_SRC (set_b))
4581 3656 : && targetm.small_register_classes_for_mode_p
4582 3656 : (GET_MODE (SET_SRC (set_b))))
4583 : /* Likewise with X. In particular this can happen when
4584 : noce_get_condition looks farther back in the instruction
4585 : stream than one might expect. */
4586 79662 : || reg_overlap_mentioned_p (x, cond)
4587 66043 : || reg_overlap_mentioned_p (x, a)
4588 258512 : || modified_between_p (x, insn_b, jump))
4589 : {
4590 : insn_b = NULL;
4591 : set_b = NULL_RTX;
4592 : }
4593 : }
4594 :
4595 : /* If x has side effects then only the if-then-else form is safe to
4596 : convert. But even in that case we would need to restore any notes
4597 : (such as REG_INC) at then end. That can be tricky if
4598 : noce_emit_move_insn expands to more than one insn, so disable the
4599 : optimization entirely for now if there are side effects. */
4600 291424 : if (side_effects_p (x))
4601 : return false;
4602 :
4603 291424 : b = (set_b ? SET_SRC (set_b) : x);
4604 :
4605 : /* Only operate on register destinations, and even then avoid extending
4606 : the lifetime of hard registers on small register class machines. */
4607 291424 : orig_x = x;
4608 291424 : if_info->orig_x = orig_x;
4609 291424 : if (!REG_P (x)
4610 291424 : || (HARD_REGISTER_P (x)
4611 2 : && targetm.small_register_classes_for_mode_p (GET_MODE (x))))
4612 : {
4613 66775 : if (GET_MODE (x) == BLKmode)
4614 : return false;
4615 :
4616 66536 : if (GET_CODE (x) == ZERO_EXTRACT
4617 1 : && (!CONST_INT_P (XEXP (x, 1))
4618 1 : || !CONST_INT_P (XEXP (x, 2))))
4619 : return false;
4620 :
4621 66536 : x = gen_reg_rtx (GET_MODE (GET_CODE (x) == STRICT_LOW_PART
4622 : ? XEXP (x, 0) : x));
4623 : }
4624 :
4625 : /* Don't operate on sources that may trap or are volatile. */
4626 291185 : if (! noce_operand_ok (a) || ! noce_operand_ok (b))
4627 : return false;
4628 :
4629 318078 : retry:
4630 : /* Set up the info block for our subroutines. */
4631 318078 : if_info->insn_a = insn_a;
4632 318078 : if_info->insn_b = insn_b;
4633 318078 : if_info->x = x;
4634 318078 : if_info->a = a;
4635 318078 : if_info->b = b;
4636 :
4637 : /* Try optimizations in some approximation of a useful order. */
4638 : /* ??? Should first look to see if X is live incoming at all. If it
4639 : isn't, we don't need anything but an unconditional set. */
4640 :
4641 : /* Look and see if A and B are really the same. Avoid creating silly
4642 : cmove constructs that no one will fix up later. */
4643 318078 : if (noce_simple_bbs (if_info)
4644 295983 : && rtx_interchangeable_p (a, b))
4645 : {
4646 : /* If we have an INSN_B, we don't have to create any new rtl. Just
4647 : move the instruction that we already have. If we don't have an
4648 : INSN_B, that means that A == X, and we've got a noop move. In
4649 : that case don't do anything and let the code below delete INSN_A. */
4650 377 : if (insn_b && else_bb)
4651 : {
4652 368 : rtx note;
4653 :
4654 368 : if (else_bb && insn_b == BB_END (else_bb))
4655 257 : BB_END (else_bb) = PREV_INSN (insn_b);
4656 368 : reorder_insns (insn_b, insn_b, PREV_INSN (jump));
4657 :
4658 : /* If there was a REG_EQUAL note, delete it since it may have been
4659 : true due to this insn being after a jump. */
4660 368 : if ((note = find_reg_note (insn_b, REG_EQUAL, NULL_RTX)) != 0)
4661 0 : remove_note (insn_b, note);
4662 :
4663 377 : insn_b = NULL;
4664 : }
4665 : /* If we have "x = b; if (...) x = a;", and x has side-effects, then
4666 : x must be executed twice. */
4667 9 : else if (insn_b && side_effects_p (orig_x))
4668 : return false;
4669 :
4670 377 : x = orig_x;
4671 377 : goto success;
4672 : }
4673 :
4674 317701 : if (!set_b && MEM_P (orig_x))
4675 : /* We want to avoid store speculation to avoid cases like
4676 : if (pthread_mutex_trylock(mutex))
4677 : ++global_variable;
4678 : Rather than go to much effort here, we rely on the SSA optimizers,
4679 : which do a good enough job these days. */
4680 : return false;
4681 :
4682 252809 : if (noce_try_move (if_info))
4683 0 : goto success;
4684 252809 : if (noce_try_ifelse_collapse (if_info))
4685 17791 : goto success;
4686 235018 : if (noce_try_store_flag (if_info))
4687 25925 : goto success;
4688 209093 : if (noce_try_bitop (if_info))
4689 0 : goto success;
4690 209093 : if (noce_try_minmax (if_info))
4691 73 : goto success;
4692 209020 : if (noce_try_abs (if_info))
4693 24 : goto success;
4694 208996 : if (noce_try_inverse_constants (if_info))
4695 0 : goto success;
4696 208996 : if (!targetm.have_conditional_execution ()
4697 208996 : && noce_try_store_flag_constants (if_info))
4698 3157 : goto success;
4699 205839 : if (!targetm.have_conditional_execution ()
4700 205839 : && noce_try_shifted_store_flag (if_info))
4701 4769 : goto success;
4702 201070 : if (noce_try_sign_bit_splat (if_info))
4703 175 : goto success;
4704 200895 : if (!targetm.have_conditional_execution ()
4705 200895 : && noce_try_store_flag_logical (if_info))
4706 0 : goto success;
4707 200895 : if (HAVE_conditional_move
4708 200895 : && noce_try_cmove (if_info))
4709 42603 : goto success;
4710 158292 : if (! targetm.have_conditional_execution ())
4711 : {
4712 158292 : if (noce_try_addcc (if_info))
4713 1514 : goto success;
4714 156778 : if (noce_try_store_flag_mask (if_info))
4715 11 : goto success;
4716 156767 : if (HAVE_conditional_move
4717 156767 : && noce_try_cond_arith (if_info))
4718 10382 : goto success;
4719 146385 : if (HAVE_conditional_move
4720 146385 : && noce_try_cmove_arith (if_info))
4721 35085 : goto success;
4722 111300 : if (noce_try_sign_mask (if_info))
4723 0 : goto success;
4724 : }
4725 :
4726 111300 : if (!else_bb && set_b)
4727 : {
4728 26893 : insn_b = NULL;
4729 26893 : set_b = NULL_RTX;
4730 26893 : b = orig_x;
4731 26893 : goto retry;
4732 : }
4733 :
4734 : return false;
4735 :
4736 141886 : success:
4737 141886 : if (dump_file && if_info->transform_name)
4738 7 : fprintf (dump_file, "if-conversion succeeded through %s\n",
4739 : if_info->transform_name);
4740 :
4741 : /* If we used a temporary, fix it up now. */
4742 141886 : if (orig_x != x)
4743 : {
4744 699 : rtx_insn *seq;
4745 :
4746 699 : start_sequence ();
4747 699 : noce_emit_move_insn (orig_x, x);
4748 699 : seq = get_insns ();
4749 699 : set_used_flags (orig_x);
4750 699 : unshare_all_rtl_in_chain (seq);
4751 699 : end_sequence ();
4752 :
4753 699 : emit_insn_before_setloc (seq, BB_END (test_bb), INSN_LOCATION (insn_a));
4754 : }
4755 :
4756 : /* The original THEN and ELSE blocks may now be removed. The test block
4757 : must now jump to the join block. If the test block and the join block
4758 : can be merged, do so. */
4759 141886 : if (else_bb)
4760 : {
4761 64690 : delete_basic_block (else_bb);
4762 64690 : num_true_changes++;
4763 : }
4764 : else
4765 77196 : remove_edge (find_edge (test_bb, join_bb));
4766 :
4767 141886 : remove_edge (find_edge (then_bb, join_bb));
4768 141886 : redirect_edge_and_branch_force (single_succ_edge (test_bb), join_bb);
4769 141886 : delete_basic_block (then_bb);
4770 141886 : num_true_changes++;
4771 :
4772 141886 : if (can_merge_blocks_p (test_bb, join_bb))
4773 : {
4774 111723 : merge_blocks (test_bb, join_bb);
4775 111723 : num_true_changes++;
4776 : }
4777 :
4778 141886 : num_updated_if_blocks++;
4779 141886 : return true;
4780 : }
4781 :
4782 : /* Check whether a block is suitable for conditional move conversion.
4783 : Every insn must be a simple set of a register to a constant or a
4784 : register. For each assignment, store the value in the pointer map
4785 : VALS, keyed indexed by register pointer, then store the register
4786 : pointer in REGS. COND is the condition we will test. */
4787 :
4788 : static bool
4789 1785478 : check_cond_move_block (basic_block bb,
4790 : hash_map<rtx, rtx> *vals,
4791 : vec<rtx> *regs,
4792 : rtx cond)
4793 : {
4794 1785478 : rtx_insn *insn;
4795 1785478 : rtx cc = cc_in_cond (cond);
4796 :
4797 : /* We can only handle simple jumps at the end of the basic block.
4798 : It is almost impossible to update the CFG otherwise. */
4799 1785478 : insn = BB_END (bb);
4800 1785478 : if (JUMP_P (insn) && !onlyjump_p (insn))
4801 : return false;
4802 :
4803 10574529 : FOR_BB_INSNS (bb, insn)
4804 : {
4805 10511828 : rtx set, dest, src;
4806 :
4807 10511828 : if (!NONDEBUG_INSN_P (insn) || JUMP_P (insn))
4808 8653256 : continue;
4809 1858572 : set = single_set (insn);
4810 1858572 : if (!set)
4811 1722724 : return false;
4812 :
4813 1784922 : dest = SET_DEST (set);
4814 1784922 : src = SET_SRC (set);
4815 1784922 : if (!REG_P (dest)
4816 1784922 : || (HARD_REGISTER_P (dest)
4817 312529 : && targetm.small_register_classes_for_mode_p (GET_MODE (dest))))
4818 : return false;
4819 :
4820 1083873 : if (!CONSTANT_P (src) && !register_operand (src, VOIDmode))
4821 : return false;
4822 :
4823 158373 : if (side_effects_p (src) || side_effects_p (dest))
4824 : return false;
4825 :
4826 158373 : if (may_trap_p (src) || may_trap_p (dest))
4827 : return false;
4828 :
4829 : /* Don't try to handle this if the source register was
4830 : modified earlier in the block. */
4831 158373 : if ((REG_P (src)
4832 51833 : && vals->get (src))
4833 209953 : || (GET_CODE (src) == SUBREG && REG_P (SUBREG_REG (src))
4834 5343 : && vals->get (SUBREG_REG (src))))
4835 : return false;
4836 :
4837 : /* Don't try to handle this if the destination register was
4838 : modified earlier in the block. */
4839 158066 : if (vals->get (dest))
4840 : return false;
4841 :
4842 : /* Don't try to handle this if the condition uses the
4843 : destination register. */
4844 158066 : if (reg_overlap_mentioned_p (dest, cond))
4845 : return false;
4846 :
4847 : /* Don't try to handle this if the source register is modified
4848 : later in the block. */
4849 139123 : if (!CONSTANT_P (src)
4850 139123 : && modified_between_p (src, insn, NEXT_INSN (BB_END (bb))))
4851 : return false;
4852 :
4853 : /* Skip it if the instruction to be moved might clobber CC. */
4854 135848 : if (cc && set_of (cc, insn))
4855 : return false;
4856 :
4857 135848 : vals->put (dest, src);
4858 :
4859 135848 : regs->safe_push (dest);
4860 : }
4861 :
4862 : return true;
4863 : }
4864 :
4865 : /* Given a basic block BB suitable for conditional move conversion,
4866 : a condition COND, and pointer maps THEN_VALS and ELSE_VALS containing
4867 : the register values depending on COND, emit the insns in the block as
4868 : conditional moves. If ELSE_BLOCK is true, THEN_BB was already
4869 : processed. The caller has started a sequence for the conversion.
4870 : Return true if successful, false if something goes wrong. */
4871 :
4872 : static bool
4873 37326 : cond_move_convert_if_block (struct noce_if_info *if_infop,
4874 : basic_block bb, rtx cond,
4875 : hash_map<rtx, rtx> *then_vals,
4876 : hash_map<rtx, rtx> *else_vals,
4877 : bool else_block_p)
4878 : {
4879 37326 : enum rtx_code code;
4880 37326 : rtx_insn *insn;
4881 37326 : rtx cond_arg0, cond_arg1;
4882 :
4883 37326 : code = GET_CODE (cond);
4884 37326 : cond_arg0 = XEXP (cond, 0);
4885 37326 : cond_arg1 = XEXP (cond, 1);
4886 :
4887 129789 : FOR_BB_INSNS (bb, insn)
4888 : {
4889 106854 : rtx set, target, dest, t, e;
4890 :
4891 : /* ??? Maybe emit conditional debug insn? */
4892 106854 : if (!NONDEBUG_INSN_P (insn) || JUMP_P (insn))
4893 70423 : continue;
4894 48323 : set = single_set (insn);
4895 48323 : gcc_assert (set && REG_P (SET_DEST (set)));
4896 :
4897 48323 : dest = SET_DEST (set);
4898 :
4899 48323 : rtx *then_slot = then_vals->get (dest);
4900 48323 : rtx *else_slot = else_vals->get (dest);
4901 48323 : t = then_slot ? *then_slot : NULL_RTX;
4902 48323 : e = else_slot ? *else_slot : NULL_RTX;
4903 :
4904 48323 : if (else_block_p)
4905 : {
4906 : /* If this register was set in the then block, we already
4907 : handled this case there. */
4908 13347 : if (t)
4909 11892 : continue;
4910 1455 : t = dest;
4911 1455 : gcc_assert (e);
4912 : }
4913 : else
4914 : {
4915 34976 : gcc_assert (t);
4916 34976 : if (!e)
4917 22415 : e = dest;
4918 : }
4919 :
4920 36431 : if (if_infop->cond_inverted)
4921 0 : std::swap (t, e);
4922 :
4923 36431 : target = noce_emit_cmove (if_infop, dest, code, cond_arg0, cond_arg1,
4924 : t, e);
4925 36431 : if (!target)
4926 14391 : return false;
4927 :
4928 22040 : if (target != dest)
4929 0 : noce_emit_move_insn (dest, target);
4930 : }
4931 :
4932 : return true;
4933 : }
4934 :
4935 : /* Given a simple IF-THEN-JOIN or IF-THEN-ELSE-JOIN block, attempt to convert
4936 : it using only conditional moves. Return TRUE if we were successful at
4937 : converting the block. */
4938 :
4939 : static bool
4940 1755244 : cond_move_process_if_block (struct noce_if_info *if_info)
4941 : {
4942 1755244 : basic_block test_bb = if_info->test_bb;
4943 1755244 : basic_block then_bb = if_info->then_bb;
4944 1755244 : basic_block else_bb = if_info->else_bb;
4945 1755244 : basic_block join_bb = if_info->join_bb;
4946 1755244 : rtx_insn *jump = if_info->jump;
4947 1755244 : rtx cond = if_info->cond;
4948 1755244 : rtx_insn *seq, *loc_insn;
4949 1755244 : int c;
4950 1755244 : vec<rtx> then_regs = vNULL;
4951 1755244 : vec<rtx> else_regs = vNULL;
4952 1755244 : bool success_p = false;
4953 1755244 : int limit = param_max_rtl_if_conversion_insns;
4954 :
4955 : /* Build a mapping for each block to the value used for each
4956 : register. */
4957 1755244 : hash_map<rtx, rtx> then_vals;
4958 1755244 : hash_map<rtx, rtx> else_vals;
4959 :
4960 : /* Make sure the blocks are suitable. */
4961 1755244 : if (!check_cond_move_block (then_bb, &then_vals, &then_regs, cond)
4962 1755244 : || (else_bb
4963 30234 : && !check_cond_move_block (else_bb, &else_vals, &else_regs, cond)))
4964 1722777 : goto done;
4965 :
4966 : /* Make sure the blocks can be used together. If the same register
4967 : is set in both blocks, and is not set to a constant in both
4968 : cases, then both blocks must set it to the same register. We
4969 : have already verified that if it is set to a register, that the
4970 : source register does not change after the assignment. Also count
4971 : the number of registers set in only one of the blocks. */
4972 32467 : c = 0;
4973 133305 : for (rtx reg : then_regs)
4974 : {
4975 39344 : rtx *then_slot = then_vals.get (reg);
4976 39344 : rtx *else_slot = else_vals.get (reg);
4977 :
4978 39344 : gcc_checking_assert (then_slot);
4979 39344 : if (!else_slot)
4980 23092 : ++c;
4981 : else
4982 : {
4983 16252 : rtx then_val = *then_slot;
4984 16252 : rtx else_val = *else_slot;
4985 4602 : if (!CONSTANT_P (then_val) && !CONSTANT_P (else_val)
4986 20203 : && !rtx_equal_p (then_val, else_val))
4987 3046 : goto done;
4988 : }
4989 : }
4990 :
4991 : /* Finish off c for MAX_CONDITIONAL_EXECUTE. */
4992 61317 : for (rtx reg : else_regs)
4993 : {
4994 14642 : gcc_checking_assert (else_vals.get (reg));
4995 14642 : if (!then_vals.get (reg))
4996 1587 : ++c;
4997 : }
4998 :
4999 : /* Make sure it is reasonable to convert this block. What matters
5000 : is the number of assignments currently made in only one of the
5001 : branches, since if we convert we are going to always execute
5002 : them. */
5003 29421 : if (c > MAX_CONDITIONAL_EXECUTE
5004 29421 : || c > limit)
5005 38 : goto done;
5006 :
5007 : /* Try to emit the conditional moves. First do the then block,
5008 : then do anything left in the else blocks. */
5009 29383 : start_sequence ();
5010 29383 : if (!cond_move_convert_if_block (if_info, then_bb, cond,
5011 : &then_vals, &else_vals, false)
5012 29383 : || (else_bb
5013 7943 : && !cond_move_convert_if_block (if_info, else_bb, cond,
5014 : &then_vals, &else_vals, true)))
5015 : {
5016 14391 : end_sequence ();
5017 14391 : goto done;
5018 : }
5019 14992 : seq = end_ifcvt_sequence (if_info);
5020 14992 : if (!seq || !targetm.noce_conversion_profitable_p (seq, if_info))
5021 11838 : goto done;
5022 :
5023 3154 : loc_insn = first_active_insn (then_bb);
5024 3154 : if (!loc_insn)
5025 : {
5026 0 : loc_insn = first_active_insn (else_bb);
5027 0 : gcc_assert (loc_insn);
5028 : }
5029 3154 : emit_insn_before_setloc (seq, jump, INSN_LOCATION (loc_insn));
5030 :
5031 3154 : if (else_bb)
5032 : {
5033 3154 : delete_basic_block (else_bb);
5034 3154 : num_true_changes++;
5035 : }
5036 : else
5037 0 : remove_edge (find_edge (test_bb, join_bb));
5038 :
5039 3154 : remove_edge (find_edge (then_bb, join_bb));
5040 3154 : redirect_edge_and_branch_force (single_succ_edge (test_bb), join_bb);
5041 3154 : delete_basic_block (then_bb);
5042 3154 : num_true_changes++;
5043 :
5044 3154 : if (can_merge_blocks_p (test_bb, join_bb))
5045 : {
5046 1256 : merge_blocks (test_bb, join_bb);
5047 1256 : num_true_changes++;
5048 : }
5049 :
5050 3154 : num_updated_if_blocks++;
5051 3154 : success_p = true;
5052 :
5053 1755244 : done:
5054 1755244 : then_regs.release ();
5055 1755244 : else_regs.release ();
5056 1755244 : return success_p;
5057 1755244 : }
5058 :
5059 :
5060 : /* Determine if a given basic block heads a simple IF-THEN-JOIN or an
5061 : IF-THEN-ELSE-JOIN block.
5062 :
5063 : If so, we'll try to convert the insns to not require the branch,
5064 : using only transformations that do not require conditional execution.
5065 :
5066 : Return TRUE if we were successful at converting the block. */
5067 :
5068 : static bool
5069 9929941 : noce_find_if_block (basic_block test_bb, edge then_edge, edge else_edge,
5070 : int pass)
5071 : {
5072 9929941 : basic_block then_bb, else_bb, join_bb;
5073 9929941 : bool then_else_reversed = false;
5074 9929941 : rtx_insn *jump;
5075 9929941 : rtx_insn *cond_earliest;
5076 9929941 : struct noce_if_info if_info;
5077 9929941 : bool speed_p = optimize_bb_for_speed_p (test_bb);
5078 :
5079 : /* We only ever should get here before reload. */
5080 9929941 : gcc_assert (!reload_completed);
5081 :
5082 : /* Recognize an IF-THEN-ELSE-JOIN block. */
5083 9929941 : if (single_pred_p (then_edge->dest)
5084 12604187 : && single_succ_p (then_edge->dest)
5085 3574540 : && single_pred_p (else_edge->dest)
5086 1872187 : && single_succ_p (else_edge->dest)
5087 11103406 : && single_succ (then_edge->dest) == single_succ (else_edge->dest))
5088 : {
5089 : then_bb = then_edge->dest;
5090 : else_bb = else_edge->dest;
5091 : join_bb = single_succ (then_bb);
5092 : }
5093 : /* Recognize an IF-THEN-JOIN block. */
5094 17100381 : else if (single_pred_p (then_edge->dest)
5095 7268379 : && single_succ_p (then_edge->dest)
5096 11703893 : && single_succ (then_edge->dest) == else_edge->dest)
5097 : {
5098 : then_bb = then_edge->dest;
5099 : else_bb = NULL_BLOCK;
5100 : join_bb = else_edge->dest;
5101 : }
5102 : /* Recognize an IF-ELSE-JOIN block. We can have those because the order
5103 : of basic blocks in cfglayout mode does not matter, so the fallthrough
5104 : edge can go to any basic block (and not just to bb->next_bb, like in
5105 : cfgrtl mode). */
5106 8070734 : else if (single_pred_p (else_edge->dest)
5107 3856886 : && single_succ_p (else_edge->dest)
5108 9474736 : && single_succ (else_edge->dest) == then_edge->dest)
5109 : {
5110 : /* The noce transformations do not apply to IF-ELSE-JOIN blocks.
5111 : To make this work, we have to invert the THEN and ELSE blocks
5112 : and reverse the jump condition. */
5113 : then_bb = else_edge->dest;
5114 : else_bb = NULL_BLOCK;
5115 : join_bb = single_succ (then_bb);
5116 : then_else_reversed = true;
5117 : }
5118 : else
5119 : /* Not a form we can handle. */
5120 : return false;
5121 :
5122 : /* The edges of the THEN and ELSE blocks cannot have complex edges. */
5123 1992090 : if (single_succ_edge (then_bb)->flags & EDGE_COMPLEX)
5124 : return false;
5125 1936579 : if (else_bb
5126 1936579 : && single_succ_edge (else_bb)->flags & EDGE_COMPLEX)
5127 : return false;
5128 :
5129 1926573 : num_possible_if_blocks++;
5130 :
5131 1926573 : if (dump_file)
5132 : {
5133 92 : fprintf (dump_file,
5134 : "\nIF-THEN%s-JOIN block found, pass %d, test %d, then %d",
5135 : (else_bb) ? "-ELSE" : "",
5136 : pass, test_bb->index, then_bb->index);
5137 :
5138 55 : if (else_bb)
5139 18 : fprintf (dump_file, ", else %d", else_bb->index);
5140 :
5141 55 : fprintf (dump_file, ", join %d\n", join_bb->index);
5142 : }
5143 :
5144 : /* If the conditional jump is more than just a conditional
5145 : jump, then we cannot do if-conversion on this block. */
5146 1926573 : jump = BB_END (test_bb);
5147 1926573 : if (! onlyjump_p (jump))
5148 : return false;
5149 :
5150 : /* Initialize an IF_INFO struct to pass around. */
5151 1926312 : memset (&if_info, 0, sizeof if_info);
5152 1926312 : if_info.test_bb = test_bb;
5153 1926312 : if_info.then_bb = then_bb;
5154 1926312 : if_info.else_bb = else_bb;
5155 1926312 : if_info.join_bb = join_bb;
5156 1926312 : if_info.cond = noce_get_condition (jump, &cond_earliest,
5157 : then_else_reversed);
5158 1926312 : rtx_insn *rev_cond_earliest;
5159 1926312 : if_info.rev_cond = noce_get_condition (jump, &rev_cond_earliest,
5160 : !then_else_reversed);
5161 1926312 : if (!if_info.cond && !if_info.rev_cond)
5162 : return false;
5163 1922514 : if (!if_info.cond)
5164 : {
5165 0 : std::swap (if_info.cond, if_info.rev_cond);
5166 0 : std::swap (cond_earliest, rev_cond_earliest);
5167 0 : if_info.cond_inverted = true;
5168 : }
5169 : /* We must be comparing objects whose modes imply the size. */
5170 1922514 : if (GET_MODE (XEXP (if_info.cond, 0)) == BLKmode)
5171 : return false;
5172 1922514 : gcc_assert (if_info.rev_cond == NULL_RTX
5173 : || rev_cond_earliest == cond_earliest);
5174 1922514 : if_info.cond_earliest = cond_earliest;
5175 1922514 : if_info.jump = jump;
5176 1922514 : if_info.then_else_reversed = then_else_reversed;
5177 1922514 : if_info.speed_p = speed_p;
5178 1922514 : if_info.max_seq_cost
5179 1922514 : = targetm.max_noce_ifcvt_seq_cost (then_edge);
5180 : /* We'll add in the cost of THEN_BB and ELSE_BB later, when we check
5181 : that they are valid to transform. We can't easily get back to the insn
5182 : for COND (and it may not exist if we had to canonicalize to get COND).
5183 : It is assumed that the costs of a jump insn are dependent on the
5184 : branch costs. */
5185 1922514 : if_info.original_cost += insn_cost (if_info.jump, if_info.speed_p);
5186 :
5187 : /* Do the real work. */
5188 :
5189 : /* ??? noce_process_if_block has not yet been updated to handle
5190 : inverted conditions. */
5191 1922514 : if (!if_info.cond_inverted && noce_process_if_block (&if_info))
5192 : return true;
5193 :
5194 1755244 : if (HAVE_conditional_move
5195 1755244 : && cond_move_process_if_block (&if_info))
5196 : return true;
5197 :
5198 : return false;
5199 : }
5200 :
5201 :
5202 : /* Merge the blocks and mark for local life update. */
5203 :
5204 : static void
5205 0 : merge_if_block (struct ce_if_block * ce_info)
5206 : {
5207 0 : basic_block test_bb = ce_info->test_bb; /* last test block */
5208 0 : basic_block then_bb = ce_info->then_bb; /* THEN */
5209 0 : basic_block else_bb = ce_info->else_bb; /* ELSE or NULL */
5210 0 : basic_block join_bb = ce_info->join_bb; /* join block */
5211 0 : basic_block combo_bb;
5212 :
5213 : /* All block merging is done into the lower block numbers. */
5214 :
5215 0 : combo_bb = test_bb;
5216 0 : df_set_bb_dirty (test_bb);
5217 :
5218 : /* Merge any basic blocks to handle && and || subtests. Each of
5219 : the blocks are on the fallthru path from the predecessor block. */
5220 0 : if (ce_info->num_multiple_test_blocks > 0)
5221 : {
5222 0 : basic_block bb = test_bb;
5223 0 : basic_block last_test_bb = ce_info->last_test_bb;
5224 0 : basic_block fallthru = block_fallthru (bb);
5225 :
5226 0 : do
5227 : {
5228 0 : bb = fallthru;
5229 0 : fallthru = block_fallthru (bb);
5230 0 : merge_blocks (combo_bb, bb);
5231 0 : num_true_changes++;
5232 : }
5233 0 : while (bb != last_test_bb);
5234 : }
5235 :
5236 : /* Merge TEST block into THEN block. Normally the THEN block won't have a
5237 : label, but it might if there were || tests. That label's count should be
5238 : zero, and it normally should be removed. */
5239 :
5240 0 : if (then_bb)
5241 : {
5242 : /* If THEN_BB has no successors, then there's a BARRIER after it.
5243 : If COMBO_BB has more than one successor (THEN_BB), then that BARRIER
5244 : is no longer needed, and in fact it is incorrect to leave it in
5245 : the insn stream. */
5246 0 : if (EDGE_COUNT (then_bb->succs) == 0
5247 0 : && EDGE_COUNT (combo_bb->succs) > 1)
5248 : {
5249 0 : rtx_insn *end = NEXT_INSN (BB_END (then_bb));
5250 0 : while (end && NOTE_P (end) && !NOTE_INSN_BASIC_BLOCK_P (end))
5251 0 : end = NEXT_INSN (end);
5252 :
5253 0 : if (end && BARRIER_P (end))
5254 0 : delete_insn (end);
5255 : }
5256 0 : merge_blocks (combo_bb, then_bb);
5257 0 : num_true_changes++;
5258 : }
5259 :
5260 : /* The ELSE block, if it existed, had a label. That label count
5261 : will almost always be zero, but odd things can happen when labels
5262 : get their addresses taken. */
5263 0 : if (else_bb)
5264 : {
5265 : /* If ELSE_BB has no successors, then there's a BARRIER after it.
5266 : If COMBO_BB has more than one successor (ELSE_BB), then that BARRIER
5267 : is no longer needed, and in fact it is incorrect to leave it in
5268 : the insn stream. */
5269 0 : if (EDGE_COUNT (else_bb->succs) == 0
5270 0 : && EDGE_COUNT (combo_bb->succs) > 1)
5271 : {
5272 0 : rtx_insn *end = NEXT_INSN (BB_END (else_bb));
5273 0 : while (end && NOTE_P (end) && !NOTE_INSN_BASIC_BLOCK_P (end))
5274 0 : end = NEXT_INSN (end);
5275 :
5276 0 : if (end && BARRIER_P (end))
5277 0 : delete_insn (end);
5278 : }
5279 0 : merge_blocks (combo_bb, else_bb);
5280 0 : num_true_changes++;
5281 : }
5282 :
5283 : /* If there was no join block reported, that means it was not adjacent
5284 : to the others, and so we cannot merge them. */
5285 :
5286 0 : if (! join_bb)
5287 : {
5288 0 : rtx_insn *last = BB_END (combo_bb);
5289 :
5290 : /* The outgoing edge for the current COMBO block should already
5291 : be correct. Verify this. */
5292 0 : if (EDGE_COUNT (combo_bb->succs) == 0)
5293 0 : gcc_assert (find_reg_note (last, REG_NORETURN, NULL)
5294 : || (NONJUMP_INSN_P (last)
5295 : && GET_CODE (PATTERN (last)) == TRAP_IF
5296 : && (TRAP_CONDITION (PATTERN (last))
5297 : == const_true_rtx)));
5298 :
5299 : else
5300 : /* There should still be something at the end of the THEN or ELSE
5301 : blocks taking us to our final destination. */
5302 0 : gcc_assert (JUMP_P (last)
5303 : || (EDGE_SUCC (combo_bb, 0)->dest
5304 : == EXIT_BLOCK_PTR_FOR_FN (cfun)
5305 : && CALL_P (last)
5306 : && SIBLING_CALL_P (last))
5307 : || ((EDGE_SUCC (combo_bb, 0)->flags & EDGE_EH)
5308 : && can_throw_internal (last)));
5309 : }
5310 :
5311 : /* The JOIN block may have had quite a number of other predecessors too.
5312 : Since we've already merged the TEST, THEN and ELSE blocks, we should
5313 : have only one remaining edge from our if-then-else diamond. If there
5314 : is more than one remaining edge, it must come from elsewhere. There
5315 : may be zero incoming edges if the THEN block didn't actually join
5316 : back up (as with a call to a non-return function). */
5317 0 : else if (EDGE_COUNT (join_bb->preds) < 2
5318 0 : && join_bb != EXIT_BLOCK_PTR_FOR_FN (cfun))
5319 : {
5320 : /* We can merge the JOIN cleanly and update the dataflow try
5321 : again on this pass.*/
5322 0 : merge_blocks (combo_bb, join_bb);
5323 0 : num_true_changes++;
5324 : }
5325 : else
5326 : {
5327 : /* We cannot merge the JOIN. */
5328 :
5329 : /* The outgoing edge for the current COMBO block should already
5330 : be correct. Verify this. */
5331 0 : gcc_assert (single_succ_p (combo_bb)
5332 : && single_succ (combo_bb) == join_bb);
5333 :
5334 : /* Remove the jump and cruft from the end of the COMBO block. */
5335 0 : if (join_bb != EXIT_BLOCK_PTR_FOR_FN (cfun))
5336 0 : tidy_fallthru_edge (single_succ_edge (combo_bb));
5337 : }
5338 :
5339 0 : num_updated_if_blocks++;
5340 0 : }
5341 :
5342 : /* Find a block ending in a simple IF condition and try to transform it
5343 : in some way. When converting a multi-block condition, put the new code
5344 : in the first such block and delete the rest. Return a pointer to this
5345 : first block if some transformation was done. Return NULL otherwise. */
5346 :
5347 : static basic_block
5348 40126121 : find_if_header (basic_block test_bb, int pass)
5349 : {
5350 40126121 : ce_if_block ce_info;
5351 40126121 : edge then_edge;
5352 40126121 : edge else_edge;
5353 :
5354 : /* The kind of block we're looking for has exactly two successors. */
5355 40126121 : if (EDGE_COUNT (test_bb->succs) != 2)
5356 : return NULL;
5357 :
5358 20647113 : then_edge = EDGE_SUCC (test_bb, 0);
5359 20647113 : else_edge = EDGE_SUCC (test_bb, 1);
5360 :
5361 20647113 : if (df_get_bb_dirty (then_edge->dest))
5362 : return NULL;
5363 20625718 : if (df_get_bb_dirty (else_edge->dest))
5364 : return NULL;
5365 :
5366 : /* Neither edge should be abnormal. */
5367 20589008 : if ((then_edge->flags & EDGE_COMPLEX)
5368 18816494 : || (else_edge->flags & EDGE_COMPLEX))
5369 : return NULL;
5370 :
5371 : /* Nor exit the loop. */
5372 18415184 : if ((then_edge->flags & EDGE_LOOP_EXIT)
5373 16929239 : || (else_edge->flags & EDGE_LOOP_EXIT))
5374 : return NULL;
5375 :
5376 : /* The THEN edge is canonically the one that falls through. */
5377 14645058 : if (then_edge->flags & EDGE_FALLTHRU)
5378 : ;
5379 7103597 : else if (else_edge->flags & EDGE_FALLTHRU)
5380 : std::swap (then_edge, else_edge);
5381 : else
5382 : /* Otherwise this must be a multiway branch of some sort. */
5383 : return NULL;
5384 :
5385 14644718 : memset (&ce_info, 0, sizeof (ce_info));
5386 14644718 : ce_info.test_bb = test_bb;
5387 14644718 : ce_info.then_bb = then_edge->dest;
5388 14644718 : ce_info.else_bb = else_edge->dest;
5389 14644718 : ce_info.pass = pass;
5390 :
5391 : #ifdef IFCVT_MACHDEP_INIT
5392 : IFCVT_MACHDEP_INIT (&ce_info);
5393 : #endif
5394 :
5395 14644718 : if (!reload_completed
5396 14644718 : && noce_find_if_block (test_bb, then_edge, else_edge, pass))
5397 170424 : goto success;
5398 :
5399 14474294 : if (reload_completed
5400 4714777 : && targetm.have_conditional_execution ()
5401 14474294 : && cond_exec_find_if_block (&ce_info))
5402 0 : goto success;
5403 :
5404 9759517 : if (!reload_completed && targetm.have_trap ()
5405 9759517 : && optab_handler (ctrap_optab, word_mode) != CODE_FOR_nothing
5406 14474294 : && find_cond_trap (test_bb, then_edge, else_edge))
5407 0 : goto success;
5408 :
5409 14474294 : if (dom_info_state (CDI_POST_DOMINATORS) >= DOM_NO_FAST_QUERY
5410 14474294 : && (reload_completed || !targetm.have_conditional_execution ()))
5411 : {
5412 14474294 : if (find_if_case_1 (test_bb, then_edge, else_edge))
5413 21836 : goto success;
5414 14452458 : if (find_if_case_2 (test_bb, then_edge, else_edge))
5415 127431 : goto success;
5416 : }
5417 :
5418 : return NULL;
5419 :
5420 319691 : success:
5421 319691 : if (dump_file)
5422 21 : fprintf (dump_file, "Conversion succeeded on pass %d.\n", pass);
5423 : /* Set this so we continue looking. */
5424 319691 : cond_exec_changed_p = true;
5425 319691 : return ce_info.test_bb;
5426 : }
5427 :
5428 : /* Return true if a block has two edges, one of which falls through to the next
5429 : block, and the other jumps to a specific block, so that we can tell if the
5430 : block is part of an && test or an || test. Returns either -1 or the number
5431 : of non-note, non-jump, non-USE/CLOBBER insns in the block. */
5432 :
5433 : static int
5434 0 : block_jumps_and_fallthru (basic_block cur_bb, basic_block target_bb)
5435 : {
5436 0 : edge cur_edge;
5437 0 : bool fallthru_p = false;
5438 0 : bool jump_p = false;
5439 0 : rtx_insn *insn;
5440 0 : rtx_insn *end;
5441 0 : int n_insns = 0;
5442 0 : edge_iterator ei;
5443 :
5444 0 : if (!cur_bb || !target_bb)
5445 : return -1;
5446 :
5447 : /* If no edges, obviously it doesn't jump or fallthru. */
5448 0 : if (EDGE_COUNT (cur_bb->succs) == 0)
5449 : return 0;
5450 :
5451 0 : FOR_EACH_EDGE (cur_edge, ei, cur_bb->succs)
5452 : {
5453 0 : if (cur_edge->flags & EDGE_COMPLEX)
5454 : /* Anything complex isn't what we want. */
5455 : return -1;
5456 :
5457 0 : else if (cur_edge->flags & EDGE_FALLTHRU)
5458 : fallthru_p = true;
5459 :
5460 0 : else if (cur_edge->dest == target_bb)
5461 : jump_p = true;
5462 :
5463 : else
5464 : return -1;
5465 : }
5466 :
5467 0 : if ((jump_p & fallthru_p) == 0)
5468 : return -1;
5469 :
5470 : /* Don't allow calls in the block, since this is used to group && and ||
5471 : together for conditional execution support. ??? we should support
5472 : conditional execution support across calls for IA-64 some day, but
5473 : for now it makes the code simpler. */
5474 0 : end = BB_END (cur_bb);
5475 0 : insn = BB_HEAD (cur_bb);
5476 :
5477 0 : while (insn != NULL_RTX)
5478 : {
5479 0 : if (CALL_P (insn))
5480 : return -1;
5481 :
5482 0 : if (INSN_P (insn)
5483 0 : && !JUMP_P (insn)
5484 0 : && !DEBUG_INSN_P (insn)
5485 0 : && GET_CODE (PATTERN (insn)) != USE
5486 0 : && GET_CODE (PATTERN (insn)) != CLOBBER)
5487 0 : n_insns++;
5488 :
5489 0 : if (insn == end)
5490 : break;
5491 :
5492 0 : insn = NEXT_INSN (insn);
5493 : }
5494 :
5495 : return n_insns;
5496 : }
5497 :
5498 : /* Determine if a given basic block heads a simple IF-THEN or IF-THEN-ELSE
5499 : block. If so, we'll try to convert the insns to not require the branch.
5500 : Return TRUE if we were successful at converting the block. */
5501 :
5502 : static bool
5503 0 : cond_exec_find_if_block (struct ce_if_block * ce_info)
5504 : {
5505 0 : basic_block test_bb = ce_info->test_bb;
5506 0 : basic_block then_bb = ce_info->then_bb;
5507 0 : basic_block else_bb = ce_info->else_bb;
5508 0 : basic_block join_bb = NULL_BLOCK;
5509 0 : edge cur_edge;
5510 0 : basic_block next;
5511 0 : edge_iterator ei;
5512 :
5513 0 : ce_info->last_test_bb = test_bb;
5514 :
5515 : /* We only ever should get here after reload,
5516 : and if we have conditional execution. */
5517 0 : gcc_assert (reload_completed && targetm.have_conditional_execution ());
5518 :
5519 : /* Discover if any fall through predecessors of the current test basic block
5520 : were && tests (which jump to the else block) or || tests (which jump to
5521 : the then block). */
5522 0 : if (single_pred_p (test_bb)
5523 0 : && single_pred_edge (test_bb)->flags == EDGE_FALLTHRU)
5524 : {
5525 0 : basic_block bb = single_pred (test_bb);
5526 0 : basic_block target_bb;
5527 0 : int max_insns = MAX_CONDITIONAL_EXECUTE;
5528 0 : int n_insns;
5529 :
5530 : /* Determine if the preceding block is an && or || block. */
5531 0 : if ((n_insns = block_jumps_and_fallthru (bb, else_bb)) >= 0)
5532 : {
5533 0 : ce_info->and_and_p = true;
5534 0 : target_bb = else_bb;
5535 : }
5536 0 : else if ((n_insns = block_jumps_and_fallthru (bb, then_bb)) >= 0)
5537 : {
5538 0 : ce_info->and_and_p = false;
5539 0 : target_bb = then_bb;
5540 : }
5541 : else
5542 : target_bb = NULL_BLOCK;
5543 :
5544 0 : if (target_bb && n_insns <= max_insns)
5545 : {
5546 0 : int total_insns = 0;
5547 0 : int blocks = 0;
5548 :
5549 0 : ce_info->last_test_bb = test_bb;
5550 :
5551 : /* Found at least one && or || block, look for more. */
5552 0 : do
5553 : {
5554 0 : ce_info->test_bb = test_bb = bb;
5555 0 : total_insns += n_insns;
5556 0 : blocks++;
5557 :
5558 0 : if (!single_pred_p (bb))
5559 : break;
5560 :
5561 0 : bb = single_pred (bb);
5562 0 : n_insns = block_jumps_and_fallthru (bb, target_bb);
5563 : }
5564 0 : while (n_insns >= 0 && (total_insns + n_insns) <= max_insns);
5565 :
5566 0 : ce_info->num_multiple_test_blocks = blocks;
5567 0 : ce_info->num_multiple_test_insns = total_insns;
5568 :
5569 0 : if (ce_info->and_and_p)
5570 0 : ce_info->num_and_and_blocks = blocks;
5571 : else
5572 0 : ce_info->num_or_or_blocks = blocks;
5573 : }
5574 : }
5575 :
5576 : /* The THEN block of an IF-THEN combo must have exactly one predecessor,
5577 : other than any || blocks which jump to the THEN block. */
5578 0 : if ((EDGE_COUNT (then_bb->preds) - ce_info->num_or_or_blocks) != 1)
5579 : return false;
5580 :
5581 : /* The edges of the THEN and ELSE blocks cannot have complex edges. */
5582 0 : FOR_EACH_EDGE (cur_edge, ei, then_bb->preds)
5583 : {
5584 0 : if (cur_edge->flags & EDGE_COMPLEX)
5585 : return false;
5586 : }
5587 :
5588 0 : FOR_EACH_EDGE (cur_edge, ei, else_bb->preds)
5589 : {
5590 0 : if (cur_edge->flags & EDGE_COMPLEX)
5591 : return false;
5592 : }
5593 :
5594 : /* The THEN block of an IF-THEN combo must have zero or one successors. */
5595 0 : if (EDGE_COUNT (then_bb->succs) > 0
5596 0 : && (!single_succ_p (then_bb)
5597 0 : || (single_succ_edge (then_bb)->flags & EDGE_COMPLEX)
5598 0 : || (epilogue_completed
5599 0 : && tablejump_p (BB_END (then_bb), NULL, NULL))))
5600 : return false;
5601 :
5602 : /* If the THEN block has no successors, conditional execution can still
5603 : make a conditional call. Don't do this unless the ELSE block has
5604 : only one incoming edge -- the CFG manipulation is too ugly otherwise.
5605 : Check for the last insn of the THEN block being an indirect jump, which
5606 : is listed as not having any successors, but confuses the rest of the CE
5607 : code processing. ??? we should fix this in the future. */
5608 0 : if (EDGE_COUNT (then_bb->succs) == 0)
5609 : {
5610 0 : if (single_pred_p (else_bb) && else_bb != EXIT_BLOCK_PTR_FOR_FN (cfun))
5611 : {
5612 0 : rtx_insn *last_insn = BB_END (then_bb);
5613 :
5614 0 : while (last_insn
5615 0 : && NOTE_P (last_insn)
5616 0 : && last_insn != BB_HEAD (then_bb))
5617 0 : last_insn = PREV_INSN (last_insn);
5618 :
5619 0 : if (last_insn
5620 0 : && JUMP_P (last_insn)
5621 0 : && ! simplejump_p (last_insn))
5622 : return false;
5623 :
5624 : join_bb = else_bb;
5625 : else_bb = NULL_BLOCK;
5626 : }
5627 : else
5628 : return false;
5629 : }
5630 :
5631 : /* If the THEN block's successor is the other edge out of the TEST block,
5632 : then we have an IF-THEN combo without an ELSE. */
5633 0 : else if (single_succ (then_bb) == else_bb)
5634 : {
5635 : join_bb = else_bb;
5636 : else_bb = NULL_BLOCK;
5637 : }
5638 :
5639 : /* If the THEN and ELSE block meet in a subsequent block, and the ELSE
5640 : has exactly one predecessor and one successor, and the outgoing edge
5641 : is not complex, then we have an IF-THEN-ELSE combo. */
5642 0 : else if (single_succ_p (else_bb)
5643 0 : && single_succ (then_bb) == single_succ (else_bb)
5644 0 : && single_pred_p (else_bb)
5645 0 : && !(single_succ_edge (else_bb)->flags & EDGE_COMPLEX)
5646 0 : && !(epilogue_completed
5647 0 : && tablejump_p (BB_END (else_bb), NULL, NULL)))
5648 0 : join_bb = single_succ (else_bb);
5649 :
5650 : /* Otherwise it is not an IF-THEN or IF-THEN-ELSE combination. */
5651 : else
5652 : return false;
5653 :
5654 0 : num_possible_if_blocks++;
5655 :
5656 0 : if (dump_file)
5657 : {
5658 0 : fprintf (dump_file,
5659 : "\nIF-THEN%s block found, pass %d, start block %d "
5660 : "[insn %d], then %d [%d]",
5661 : (else_bb) ? "-ELSE" : "",
5662 : ce_info->pass,
5663 : test_bb->index,
5664 0 : BB_HEAD (test_bb) ? (int)INSN_UID (BB_HEAD (test_bb)) : -1,
5665 : then_bb->index,
5666 0 : BB_HEAD (then_bb) ? (int)INSN_UID (BB_HEAD (then_bb)) : -1);
5667 :
5668 0 : if (else_bb)
5669 0 : fprintf (dump_file, ", else %d [%d]",
5670 : else_bb->index,
5671 0 : BB_HEAD (else_bb) ? (int)INSN_UID (BB_HEAD (else_bb)) : -1);
5672 :
5673 0 : fprintf (dump_file, ", join %d [%d]",
5674 : join_bb->index,
5675 0 : BB_HEAD (join_bb) ? (int)INSN_UID (BB_HEAD (join_bb)) : -1);
5676 :
5677 0 : if (ce_info->num_multiple_test_blocks > 0)
5678 0 : fprintf (dump_file, ", %d %s block%s last test %d [%d]",
5679 : ce_info->num_multiple_test_blocks,
5680 0 : (ce_info->and_and_p) ? "&&" : "||",
5681 : (ce_info->num_multiple_test_blocks == 1) ? "" : "s",
5682 : ce_info->last_test_bb->index,
5683 0 : ((BB_HEAD (ce_info->last_test_bb))
5684 0 : ? (int)INSN_UID (BB_HEAD (ce_info->last_test_bb))
5685 : : -1));
5686 :
5687 0 : fputc ('\n', dump_file);
5688 : }
5689 :
5690 : /* Make sure IF, THEN, and ELSE, blocks are adjacent. Actually, we get the
5691 : first condition for free, since we've already asserted that there's a
5692 : fallthru edge from IF to THEN. Likewise for the && and || blocks, since
5693 : we checked the FALLTHRU flag, those are already adjacent to the last IF
5694 : block. */
5695 : /* ??? As an enhancement, move the ELSE block. Have to deal with
5696 : BLOCK notes, if by no other means than backing out the merge if they
5697 : exist. Sticky enough I don't want to think about it now. */
5698 0 : next = then_bb;
5699 0 : if (else_bb && (next = next->next_bb) != else_bb)
5700 : return false;
5701 0 : if ((next = next->next_bb) != join_bb
5702 0 : && join_bb != EXIT_BLOCK_PTR_FOR_FN (cfun))
5703 : {
5704 0 : if (else_bb)
5705 : join_bb = NULL;
5706 : else
5707 : return false;
5708 : }
5709 :
5710 : /* Do the real work. */
5711 :
5712 0 : ce_info->else_bb = else_bb;
5713 0 : ce_info->join_bb = join_bb;
5714 :
5715 : /* If we have && and || tests, try to first handle combining the && and ||
5716 : tests into the conditional code, and if that fails, go back and handle
5717 : it without the && and ||, which at present handles the && case if there
5718 : was no ELSE block. */
5719 0 : if (cond_exec_process_if_block (ce_info, true))
5720 : return true;
5721 :
5722 0 : if (ce_info->num_multiple_test_blocks)
5723 : {
5724 0 : cancel_changes (0);
5725 :
5726 0 : if (cond_exec_process_if_block (ce_info, false))
5727 : return true;
5728 : }
5729 :
5730 : return false;
5731 : }
5732 :
5733 : /* Convert a branch over a trap, or a branch
5734 : to a trap, into a conditional trap. */
5735 :
5736 : static bool
5737 0 : find_cond_trap (basic_block test_bb, edge then_edge, edge else_edge)
5738 : {
5739 0 : basic_block then_bb = then_edge->dest;
5740 0 : basic_block else_bb = else_edge->dest;
5741 0 : basic_block other_bb, trap_bb;
5742 0 : rtx_insn *trap, *jump;
5743 0 : rtx cond;
5744 0 : rtx_insn *cond_earliest;
5745 :
5746 : /* Locate the block with the trap instruction. */
5747 : /* ??? While we look for no successors, we really ought to allow
5748 : EH successors. Need to fix merge_if_block for that to work. */
5749 0 : if ((trap = block_has_only_trap (then_bb)) != NULL)
5750 : trap_bb = then_bb, other_bb = else_bb;
5751 0 : else if ((trap = block_has_only_trap (else_bb)) != NULL)
5752 : trap_bb = else_bb, other_bb = then_bb;
5753 : else
5754 : return false;
5755 :
5756 0 : if (dump_file)
5757 : {
5758 0 : fprintf (dump_file, "\nTRAP-IF block found, start %d, trap %d\n",
5759 : test_bb->index, trap_bb->index);
5760 : }
5761 :
5762 : /* If this is not a standard conditional jump, we can't parse it. */
5763 0 : jump = BB_END (test_bb);
5764 0 : cond = noce_get_condition (jump, &cond_earliest, then_bb == trap_bb);
5765 0 : if (! cond)
5766 : return false;
5767 :
5768 : /* If the conditional jump is more than just a conditional jump, then
5769 : we cannot do if-conversion on this block. Give up for returnjump_p,
5770 : changing a conditional return followed by unconditional trap for
5771 : conditional trap followed by unconditional return is likely not
5772 : beneficial and harder to handle. */
5773 0 : if (! onlyjump_p (jump) || returnjump_p (jump))
5774 : return false;
5775 :
5776 : /* We must be comparing objects whose modes imply the size. */
5777 0 : if (GET_MODE (XEXP (cond, 0)) == BLKmode)
5778 : return false;
5779 :
5780 : /* Attempt to generate the conditional trap. */
5781 0 : rtx_insn *seq = gen_cond_trap (GET_CODE (cond), copy_rtx (XEXP (cond, 0)),
5782 : copy_rtx (XEXP (cond, 1)),
5783 0 : TRAP_CODE (PATTERN (trap)));
5784 0 : if (seq == NULL)
5785 : return false;
5786 :
5787 : /* If that results in an invalid insn, back out. */
5788 0 : for (rtx_insn *x = seq; x; x = NEXT_INSN (x))
5789 0 : if (reload_completed
5790 0 : ? !valid_insn_p (x)
5791 0 : : recog_memoized (x) < 0)
5792 : return false;
5793 :
5794 : /* Emit the new insns before cond_earliest. */
5795 0 : emit_insn_before_setloc (seq, cond_earliest, INSN_LOCATION (trap));
5796 :
5797 : /* Delete the trap block if possible. */
5798 0 : remove_edge (trap_bb == then_bb ? then_edge : else_edge);
5799 0 : df_set_bb_dirty (test_bb);
5800 0 : df_set_bb_dirty (then_bb);
5801 0 : df_set_bb_dirty (else_bb);
5802 :
5803 0 : if (EDGE_COUNT (trap_bb->preds) == 0)
5804 : {
5805 0 : delete_basic_block (trap_bb);
5806 0 : num_true_changes++;
5807 : }
5808 :
5809 : /* Wire together the blocks again. */
5810 0 : if (current_ir_type () == IR_RTL_CFGLAYOUT)
5811 0 : single_succ_edge (test_bb)->flags |= EDGE_FALLTHRU;
5812 0 : else if (trap_bb == then_bb)
5813 : {
5814 0 : rtx lab = JUMP_LABEL (jump);
5815 0 : rtx_insn *seq = targetm.gen_jump (lab);
5816 0 : rtx_jump_insn *newjump = emit_jump_insn_after (seq, jump);
5817 0 : LABEL_NUSES (lab) += 1;
5818 0 : JUMP_LABEL (newjump) = lab;
5819 0 : emit_barrier_after (newjump);
5820 : }
5821 0 : delete_insn (jump);
5822 :
5823 0 : if (can_merge_blocks_p (test_bb, other_bb))
5824 : {
5825 0 : merge_blocks (test_bb, other_bb);
5826 0 : num_true_changes++;
5827 : }
5828 :
5829 0 : num_updated_if_blocks++;
5830 0 : return true;
5831 : }
5832 :
5833 : /* Subroutine of find_cond_trap: if BB contains only a trap insn,
5834 : return it. */
5835 :
5836 : static rtx_insn *
5837 0 : block_has_only_trap (basic_block bb)
5838 : {
5839 0 : rtx_insn *trap;
5840 :
5841 : /* We're not the exit block. */
5842 0 : if (bb == EXIT_BLOCK_PTR_FOR_FN (cfun))
5843 : return NULL;
5844 :
5845 : /* The block must have no successors. */
5846 0 : if (EDGE_COUNT (bb->succs) > 0)
5847 : return NULL;
5848 :
5849 : /* The only instruction in the THEN block must be the trap. */
5850 0 : trap = first_active_insn (bb);
5851 0 : if (! (trap == BB_END (bb)
5852 0 : && GET_CODE (PATTERN (trap)) == TRAP_IF
5853 0 : && TRAP_CONDITION (PATTERN (trap)) == const_true_rtx))
5854 0 : return NULL;
5855 :
5856 : return trap;
5857 : }
5858 :
5859 : /* Look for IF-THEN-ELSE cases in which one of THEN or ELSE is
5860 : transformable, but not necessarily the other. There need be no
5861 : JOIN block.
5862 :
5863 : Return TRUE if we were successful at converting the block.
5864 :
5865 : Cases we'd like to look at:
5866 :
5867 : (1)
5868 : if (test) goto over; // x not live
5869 : x = a;
5870 : goto label;
5871 : over:
5872 :
5873 : becomes
5874 :
5875 : x = a;
5876 : if (! test) goto label;
5877 :
5878 : (2)
5879 : if (test) goto E; // x not live
5880 : x = big();
5881 : goto L;
5882 : E:
5883 : x = b;
5884 : goto M;
5885 :
5886 : becomes
5887 :
5888 : x = b;
5889 : if (test) goto M;
5890 : x = big();
5891 : goto L;
5892 :
5893 : (3) // This one's really only interesting for targets that can do
5894 : // multiway branching, e.g. IA-64 BBB bundles. For other targets
5895 : // it results in multiple branches on a cache line, which often
5896 : // does not sit well with predictors.
5897 :
5898 : if (test1) goto E; // predicted not taken
5899 : x = a;
5900 : if (test2) goto F;
5901 : ...
5902 : E:
5903 : x = b;
5904 : J:
5905 :
5906 : becomes
5907 :
5908 : x = a;
5909 : if (test1) goto E;
5910 : if (test2) goto F;
5911 :
5912 : Notes:
5913 :
5914 : (A) Don't do (2) if the branch is predicted against the block we're
5915 : eliminating. Do it anyway if we can eliminate a branch; this requires
5916 : that the sole successor of the eliminated block postdominate the other
5917 : side of the if.
5918 :
5919 : (B) With CE, on (3) we can steal from both sides of the if, creating
5920 :
5921 : if (test1) x = a;
5922 : if (!test1) x = b;
5923 : if (test1) goto J;
5924 : if (test2) goto F;
5925 : ...
5926 : J:
5927 :
5928 : Again, this is most useful if J postdominates.
5929 :
5930 : (C) CE substitutes for helpful life information.
5931 :
5932 : (D) These heuristics need a lot of work. */
5933 :
5934 : /* Tests for case 1 above. */
5935 :
5936 : static bool
5937 14474294 : find_if_case_1 (basic_block test_bb, edge then_edge, edge else_edge)
5938 : {
5939 14474294 : basic_block then_bb = then_edge->dest;
5940 14474294 : basic_block else_bb = else_edge->dest;
5941 14474294 : basic_block new_bb;
5942 14474294 : int then_bb_index;
5943 14474294 : profile_probability then_prob;
5944 14474294 : rtx else_target = NULL_RTX;
5945 :
5946 : /* If we are partitioning hot/cold basic blocks, we don't want to
5947 : mess up unconditional or indirect jumps that cross between hot
5948 : and cold sections.
5949 :
5950 : Basic block partitioning may result in some jumps that appear to
5951 : be optimizable (or blocks that appear to be mergeable), but which really
5952 : must be left untouched (they are required to make it safely across
5953 : partition boundaries). See the comments at the top of
5954 : bb-reorder.cc:partition_hot_cold_basic_blocks for complete details. */
5955 :
5956 14474294 : if ((BB_END (then_bb)
5957 14474294 : && JUMP_P (BB_END (then_bb))
5958 7545595 : && CROSSING_JUMP_P (BB_END (then_bb)))
5959 14235669 : || (JUMP_P (BB_END (test_bb))
5960 14235669 : && CROSSING_JUMP_P (BB_END (test_bb)))
5961 28600178 : || (BB_END (else_bb)
5962 14125884 : && JUMP_P (BB_END (else_bb))
5963 7144070 : && CROSSING_JUMP_P (BB_END (else_bb))))
5964 : return false;
5965 :
5966 : /* Verify test_bb ends in a conditional jump with no other side-effects. */
5967 14102008 : if (!onlyjump_p (BB_END (test_bb)))
5968 : return false;
5969 :
5970 : /* THEN has one successor. */
5971 14101337 : if (!single_succ_p (then_bb))
5972 : return false;
5973 :
5974 : /* THEN does not fall through, but is not strange either. */
5975 6407999 : if (single_succ_edge (then_bb)->flags & (EDGE_COMPLEX | EDGE_FALLTHRU))
5976 : return false;
5977 :
5978 : /* THEN has one predecessor. */
5979 1268211 : if (!single_pred_p (then_bb))
5980 : return false;
5981 :
5982 : /* THEN must do something. */
5983 1144351 : if (forwarder_block_p (then_bb))
5984 : return false;
5985 :
5986 723133 : num_possible_if_blocks++;
5987 723133 : if (dump_file)
5988 8 : fprintf (dump_file,
5989 : "\nIF-CASE-1 found, start %d, then %d\n",
5990 : test_bb->index, then_bb->index);
5991 :
5992 723133 : then_prob = then_edge->probability.invert ();
5993 :
5994 : /* We're speculating from the THEN path, we want to make sure the cost
5995 : of speculation is within reason. */
5996 1368148 : if (! cheap_bb_rtx_cost_p (then_bb, then_prob,
5997 1368148 : COSTS_N_INSNS (BRANCH_COST (optimize_bb_for_speed_p (then_edge->src),
5998 : predictable_edge_p (then_edge)))))
5999 : return false;
6000 :
6001 144527 : if (else_bb == EXIT_BLOCK_PTR_FOR_FN (cfun))
6002 : {
6003 0 : rtx_insn *jump = BB_END (else_edge->src);
6004 0 : gcc_assert (JUMP_P (jump));
6005 0 : else_target = JUMP_LABEL (jump);
6006 : }
6007 :
6008 : /* Registers set are dead, or are predicable. */
6009 144527 : if (! dead_or_predicable (test_bb, then_bb, else_bb,
6010 : single_succ_edge (then_bb), true))
6011 : return false;
6012 :
6013 : /* Conversion went ok, including moving the insns and fixing up the
6014 : jump. Adjust the CFG to match. */
6015 :
6016 : /* We can avoid creating a new basic block if then_bb is immediately
6017 : followed by else_bb, i.e. deleting then_bb allows test_bb to fall
6018 : through to else_bb. */
6019 :
6020 21836 : if (then_bb->next_bb == else_bb
6021 10241 : && then_bb->prev_bb == test_bb
6022 10241 : && else_bb != EXIT_BLOCK_PTR_FOR_FN (cfun))
6023 : {
6024 10241 : redirect_edge_succ (FALLTHRU_EDGE (test_bb), else_bb);
6025 10241 : new_bb = 0;
6026 : }
6027 11595 : else if (else_bb == EXIT_BLOCK_PTR_FOR_FN (cfun))
6028 0 : new_bb = force_nonfallthru_and_redirect (FALLTHRU_EDGE (test_bb),
6029 : else_bb, else_target);
6030 : else
6031 11595 : new_bb = redirect_edge_and_branch_force (FALLTHRU_EDGE (test_bb),
6032 : else_bb);
6033 :
6034 21836 : df_set_bb_dirty (test_bb);
6035 21836 : df_set_bb_dirty (else_bb);
6036 :
6037 21836 : then_bb_index = then_bb->index;
6038 21836 : delete_basic_block (then_bb);
6039 :
6040 : /* Make rest of code believe that the newly created block is the THEN_BB
6041 : block we removed. */
6042 21836 : if (new_bb)
6043 : {
6044 11595 : df_bb_replace (then_bb_index, new_bb);
6045 : /* This should have been done above via force_nonfallthru_and_redirect
6046 : (possibly called from redirect_edge_and_branch_force). */
6047 11595 : gcc_checking_assert (BB_PARTITION (new_bb) == BB_PARTITION (test_bb));
6048 : }
6049 :
6050 21836 : num_true_changes++;
6051 21836 : num_updated_if_blocks++;
6052 21836 : return true;
6053 : }
6054 :
6055 : /* Test for case 2 above. */
6056 :
6057 : static bool
6058 14452458 : find_if_case_2 (basic_block test_bb, edge then_edge, edge else_edge)
6059 : {
6060 14452458 : basic_block then_bb = then_edge->dest;
6061 14452458 : basic_block else_bb = else_edge->dest;
6062 14452458 : edge else_succ;
6063 14452458 : profile_probability then_prob, else_prob;
6064 :
6065 : /* We do not want to speculate (empty) loop latches. */
6066 14452458 : if (current_loops
6067 5630184 : && else_bb->loop_father->latch == else_bb)
6068 : return false;
6069 :
6070 : /* If we are partitioning hot/cold basic blocks, we don't want to
6071 : mess up unconditional or indirect jumps that cross between hot
6072 : and cold sections.
6073 :
6074 : Basic block partitioning may result in some jumps that appear to
6075 : be optimizable (or blocks that appear to be mergeable), but which really
6076 : must be left untouched (they are required to make it safely across
6077 : partition boundaries). See the comments at the top of
6078 : bb-reorder.cc:partition_hot_cold_basic_blocks for complete details. */
6079 :
6080 14299472 : if ((BB_END (then_bb)
6081 14299472 : && JUMP_P (BB_END (then_bb))
6082 7449210 : && CROSSING_JUMP_P (BB_END (then_bb)))
6083 14060847 : || (JUMP_P (BB_END (test_bb))
6084 14060847 : && CROSSING_JUMP_P (BB_END (test_bb)))
6085 28250534 : || (BB_END (else_bb)
6086 13951062 : && JUMP_P (BB_END (else_bb))
6087 7002965 : && CROSSING_JUMP_P (BB_END (else_bb))))
6088 : return false;
6089 :
6090 : /* Verify test_bb ends in a conditional jump with no other side-effects. */
6091 13927186 : if (!onlyjump_p (BB_END (test_bb)))
6092 : return false;
6093 :
6094 : /* ELSE has one successor. */
6095 13926516 : if (!single_succ_p (else_bb))
6096 : return false;
6097 : else
6098 5876321 : else_succ = single_succ_edge (else_bb);
6099 :
6100 : /* ELSE outgoing edge is not complex. */
6101 5876321 : if (else_succ->flags & EDGE_COMPLEX)
6102 : return false;
6103 :
6104 : /* ELSE has one predecessor. */
6105 5718177 : if (!single_pred_p (else_bb))
6106 : return false;
6107 :
6108 : /* THEN is not EXIT. */
6109 2995839 : if (then_bb->index < NUM_FIXED_BLOCKS)
6110 : return false;
6111 :
6112 2995839 : else_prob = else_edge->probability;
6113 2995839 : then_prob = else_prob.invert ();
6114 :
6115 : /* ELSE is predicted or SUCC(ELSE) postdominates THEN. */
6116 2995839 : if (else_prob > then_prob)
6117 : ;
6118 2018181 : else if (else_succ->dest->index < NUM_FIXED_BLOCKS
6119 2018181 : || dominated_by_p (CDI_POST_DOMINATORS, then_bb,
6120 : else_succ->dest))
6121 : ;
6122 : else
6123 : return false;
6124 :
6125 2372418 : num_possible_if_blocks++;
6126 2372418 : if (dump_file)
6127 44 : fprintf (dump_file,
6128 : "\nIF-CASE-2 found, start %d, else %d\n",
6129 : test_bb->index, else_bb->index);
6130 :
6131 : /* We're speculating from the ELSE path, we want to make sure the cost
6132 : of speculation is within reason. */
6133 4571579 : if (! cheap_bb_rtx_cost_p (else_bb, else_prob,
6134 4571579 : COSTS_N_INSNS (BRANCH_COST (optimize_bb_for_speed_p (else_edge->src),
6135 : predictable_edge_p (else_edge)))))
6136 : return false;
6137 :
6138 : /* Registers set are dead, or are predicable. */
6139 461867 : if (! dead_or_predicable (test_bb, else_bb, then_bb, else_succ, false))
6140 : return false;
6141 :
6142 : /* Conversion went ok, including moving the insns and fixing up the
6143 : jump. Adjust the CFG to match. */
6144 :
6145 127431 : df_set_bb_dirty (test_bb);
6146 127431 : df_set_bb_dirty (then_bb);
6147 127431 : delete_basic_block (else_bb);
6148 :
6149 127431 : num_true_changes++;
6150 127431 : num_updated_if_blocks++;
6151 :
6152 : /* ??? We may now fallthru from one of THEN's successors into a join
6153 : block. Rerun cleanup_cfg? Examine things manually? Wait? */
6154 :
6155 127431 : return true;
6156 : }
6157 :
6158 : /* Used by the code above to perform the actual rtl transformations.
6159 : Return TRUE if successful.
6160 :
6161 : TEST_BB is the block containing the conditional branch. MERGE_BB
6162 : is the block containing the code to manipulate. DEST_EDGE is an
6163 : edge representing a jump to the join block; after the conversion,
6164 : TEST_BB should be branching to its destination.
6165 : REVERSEP is true if the sense of the branch should be reversed. */
6166 :
6167 : static bool
6168 606394 : dead_or_predicable (basic_block test_bb, basic_block merge_bb,
6169 : basic_block other_bb, edge dest_edge, bool reversep)
6170 : {
6171 606394 : basic_block new_dest = dest_edge->dest;
6172 606394 : rtx_insn *head, *end, *jump;
6173 606394 : rtx_insn *earliest = NULL;
6174 606394 : rtx old_dest;
6175 606394 : bitmap merge_set = NULL;
6176 : /* Number of pending changes. */
6177 606394 : int n_validated_changes = 0;
6178 606394 : rtx new_dest_label = NULL_RTX;
6179 :
6180 606394 : jump = BB_END (test_bb);
6181 :
6182 : /* Find the extent of the real code in the merge block. */
6183 606394 : head = BB_HEAD (merge_bb);
6184 606394 : end = BB_END (merge_bb);
6185 :
6186 790693 : while (DEBUG_INSN_P (end) && end != head)
6187 184299 : end = PREV_INSN (end);
6188 :
6189 : /* If merge_bb ends with a tablejump, predicating/moving insn's
6190 : into test_bb and then deleting merge_bb will result in the jumptable
6191 : that follows merge_bb being removed along with merge_bb and then we
6192 : get an unresolved reference to the jumptable. */
6193 606394 : if (tablejump_p (end, NULL, NULL))
6194 : return false;
6195 :
6196 606394 : if (LABEL_P (head))
6197 461930 : head = NEXT_INSN (head);
6198 606394 : while (DEBUG_INSN_P (head) && head != end)
6199 0 : head = NEXT_INSN (head);
6200 606394 : if (NOTE_P (head))
6201 : {
6202 606394 : if (head == end)
6203 : {
6204 104220 : head = end = NULL;
6205 104220 : goto no_body;
6206 : }
6207 502174 : head = NEXT_INSN (head);
6208 1452996 : while (DEBUG_INSN_P (head) && head != end)
6209 448648 : head = NEXT_INSN (head);
6210 : }
6211 :
6212 502174 : if (JUMP_P (end))
6213 : {
6214 207150 : if (!onlyjump_p (end))
6215 : return false;
6216 165904 : if (head == end)
6217 : {
6218 6 : head = end = NULL;
6219 6 : goto no_body;
6220 : }
6221 165898 : end = PREV_INSN (end);
6222 440687 : while (DEBUG_INSN_P (end) && end != head)
6223 108891 : end = PREV_INSN (end);
6224 : }
6225 :
6226 : /* Don't move frame-related insn across the conditional branch. This
6227 : can lead to one of the paths of the branch having wrong unwind info. */
6228 460922 : if (epilogue_completed)
6229 : {
6230 : rtx_insn *insn = head;
6231 85030 : while (1)
6232 : {
6233 293473 : if (INSN_P (insn) && RTX_FRAME_RELATED_P (insn))
6234 : return false;
6235 286686 : if (insn == end)
6236 : break;
6237 85030 : insn = NEXT_INSN (insn);
6238 85030 : }
6239 : }
6240 :
6241 : /* Disable handling dead code by conditional execution if the machine needs
6242 : to do anything funny with the tests, etc. */
6243 : #ifndef IFCVT_MODIFY_TESTS
6244 454135 : if (targetm.have_conditional_execution ())
6245 : {
6246 : /* In the conditional execution case, we have things easy. We know
6247 : the condition is reversible. We don't have to check life info
6248 : because we're going to conditionally execute the code anyway.
6249 : All that's left is making sure the insns involved can actually
6250 : be predicated. */
6251 :
6252 0 : rtx cond;
6253 :
6254 : /* If the conditional jump is more than just a conditional jump,
6255 : then we cannot do conditional execution conversion on this block. */
6256 0 : if (!onlyjump_p (jump))
6257 0 : goto nce;
6258 :
6259 0 : cond = cond_exec_get_condition (jump);
6260 0 : if (! cond)
6261 0 : goto nce;
6262 :
6263 0 : rtx note = find_reg_note (jump, REG_BR_PROB, NULL_RTX);
6264 0 : profile_probability prob_val
6265 0 : = (note ? profile_probability::from_reg_br_prob_note (XINT (note, 0))
6266 : : profile_probability::uninitialized ());
6267 :
6268 0 : if (reversep)
6269 : {
6270 0 : enum rtx_code rev = reversed_comparison_code (cond, jump);
6271 0 : if (rev == UNKNOWN)
6272 0 : return false;
6273 0 : cond = gen_rtx_fmt_ee (rev, GET_MODE (cond), XEXP (cond, 0),
6274 : XEXP (cond, 1));
6275 0 : prob_val = prob_val.invert ();
6276 : }
6277 :
6278 0 : if (cond_exec_process_insns (NULL, head, end, cond, prob_val, false)
6279 0 : && verify_changes (0))
6280 0 : n_validated_changes = num_validated_changes ();
6281 : else
6282 0 : cancel_changes (0);
6283 :
6284 0 : earliest = jump;
6285 : }
6286 454135 : nce:
6287 : #endif
6288 :
6289 : /* If we allocated new pseudos (e.g. in the conditional move
6290 : expander called from noce_emit_cmove), we must resize the
6291 : array first. */
6292 454135 : if (max_regno < max_reg_num ())
6293 81555 : max_regno = max_reg_num ();
6294 :
6295 : /* Try the NCE path if the CE path did not result in any changes. */
6296 454135 : if (n_validated_changes == 0)
6297 : {
6298 454135 : rtx cond;
6299 454135 : rtx_insn *insn;
6300 454135 : regset live;
6301 454135 : bool success;
6302 :
6303 : /* In the non-conditional execution case, we have to verify that there
6304 : are no trapping operations, no calls, no references to memory, and
6305 : that any registers modified are dead at the branch site. */
6306 :
6307 454135 : if (!any_condjump_p (jump))
6308 : return false;
6309 :
6310 : /* Find the extent of the conditional. */
6311 454135 : cond = noce_get_condition (jump, &earliest, false);
6312 454135 : if (!cond)
6313 : return false;
6314 :
6315 453351 : live = BITMAP_ALLOC (®_obstack);
6316 453351 : simulate_backwards_to_point (merge_bb, live, end);
6317 453351 : success = can_move_insns_across (head, end, earliest, jump,
6318 : merge_bb, live,
6319 : df_get_live_in (other_bb), NULL);
6320 453351 : BITMAP_FREE (live);
6321 453351 : if (!success)
6322 : return false;
6323 :
6324 : /* Collect the set of registers set in MERGE_BB. */
6325 146715 : merge_set = BITMAP_ALLOC (®_obstack);
6326 :
6327 733527 : FOR_BB_INSNS (merge_bb, insn)
6328 586812 : if (NONDEBUG_INSN_P (insn))
6329 192930 : df_simulate_find_defs (insn, merge_set);
6330 :
6331 : /* If shrink-wrapping, disable this optimization when test_bb is
6332 : the first basic block and merge_bb exits. The idea is to not
6333 : move code setting up a return register as that may clobber a
6334 : register used to pass function parameters, which then must be
6335 : saved in caller-saved regs. A caller-saved reg requires the
6336 : prologue, killing a shrink-wrap opportunity. */
6337 146714 : if ((SHRINK_WRAPPING_ENABLED && !epilogue_completed)
6338 115574 : && ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb == test_bb
6339 19030 : && single_succ_p (new_dest)
6340 14043 : && single_succ (new_dest) == EXIT_BLOCK_PTR_FOR_FN (cfun)
6341 159735 : && bitmap_intersect_p (df_get_live_in (new_dest), merge_set))
6342 : {
6343 13020 : regset return_regs;
6344 13020 : unsigned int i;
6345 :
6346 13020 : return_regs = BITMAP_ALLOC (®_obstack);
6347 :
6348 : /* Start off with the intersection of regs used to pass
6349 : params and regs used to return values. */
6350 1223880 : for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
6351 1197840 : if (FUNCTION_ARG_REGNO_P (i)
6352 1197840 : && targetm.calls.function_value_regno_p (i))
6353 50910 : bitmap_set_bit (return_regs, INCOMING_REGNO (i));
6354 :
6355 13020 : bitmap_and_into (return_regs,
6356 13020 : df_get_live_out (ENTRY_BLOCK_PTR_FOR_FN (cfun)));
6357 13020 : bitmap_and_into (return_regs,
6358 13020 : df_get_live_in (EXIT_BLOCK_PTR_FOR_FN (cfun)));
6359 13020 : if (!bitmap_empty_p (return_regs))
6360 : {
6361 4786 : FOR_BB_INSNS_REVERSE (new_dest, insn)
6362 4239 : if (NONDEBUG_INSN_P (insn))
6363 : {
6364 2157 : df_ref def;
6365 :
6366 : /* If this insn sets any reg in return_regs, add all
6367 : reg uses to the set of regs we're interested in. */
6368 2734 : FOR_EACH_INSN_DEF (def, insn)
6369 1676 : if (bitmap_bit_p (return_regs, DF_REF_REGNO (def)))
6370 : {
6371 1099 : df_simulate_uses (insn, return_regs);
6372 1099 : break;
6373 : }
6374 : }
6375 547 : if (bitmap_intersect_p (merge_set, return_regs))
6376 : {
6377 529 : BITMAP_FREE (return_regs);
6378 529 : BITMAP_FREE (merge_set);
6379 529 : return false;
6380 : }
6381 : }
6382 12491 : BITMAP_FREE (return_regs);
6383 : }
6384 : }
6385 :
6386 250412 : no_body:
6387 : /* We don't want to use normal invert_jump or redirect_jump because
6388 : we don't want to delete_insn called. Also, we want to do our own
6389 : change group management. */
6390 :
6391 250412 : old_dest = JUMP_LABEL (jump);
6392 250412 : if (other_bb != new_dest)
6393 : {
6394 250397 : if (!any_condjump_p (jump))
6395 0 : goto cancel;
6396 :
6397 250397 : if (JUMP_P (BB_END (dest_edge->src)))
6398 22962 : new_dest_label = JUMP_LABEL (BB_END (dest_edge->src));
6399 227435 : else if (new_dest == EXIT_BLOCK_PTR_FOR_FN (cfun))
6400 101145 : new_dest_label = ret_rtx;
6401 : else
6402 126290 : new_dest_label = block_label (new_dest);
6403 :
6404 250397 : rtx_jump_insn *jump_insn = as_a <rtx_jump_insn *> (jump);
6405 250397 : if (reversep
6406 250397 : ? ! invert_jump_1 (jump_insn, new_dest_label)
6407 228561 : : ! redirect_jump_1 (jump_insn, new_dest_label))
6408 0 : goto cancel;
6409 : }
6410 :
6411 250412 : if (verify_changes (n_validated_changes))
6412 149267 : confirm_change_group ();
6413 : else
6414 101145 : goto cancel;
6415 :
6416 149267 : if (other_bb != new_dest)
6417 : {
6418 149252 : redirect_jump_2 (as_a <rtx_jump_insn *> (jump), old_dest, new_dest_label,
6419 : 0, reversep);
6420 :
6421 149252 : redirect_edge_succ (BRANCH_EDGE (test_bb), new_dest);
6422 149252 : if (reversep)
6423 : {
6424 21836 : std::swap (BRANCH_EDGE (test_bb)->probability,
6425 21836 : FALLTHRU_EDGE (test_bb)->probability);
6426 21836 : update_br_prob_note (test_bb);
6427 : }
6428 : }
6429 :
6430 : /* Move the insns out of MERGE_BB to before the branch. */
6431 149267 : if (head != NULL)
6432 : {
6433 146186 : rtx_insn *insn;
6434 :
6435 146186 : if (end == BB_END (merge_bb))
6436 112065 : BB_END (merge_bb) = PREV_INSN (head);
6437 :
6438 : /* PR 21767: when moving insns above a conditional branch, the REG_EQUAL
6439 : notes being moved might become invalid. */
6440 146186 : insn = head;
6441 176624 : do
6442 : {
6443 176624 : rtx note;
6444 :
6445 176624 : if (! INSN_P (insn))
6446 3208 : continue;
6447 173416 : note = find_reg_note (insn, REG_EQUAL, NULL_RTX);
6448 173416 : if (! note)
6449 161802 : continue;
6450 11614 : remove_note (insn, note);
6451 207062 : } while (insn != end && (insn = NEXT_INSN (insn)));
6452 :
6453 : /* PR46315: when moving insns above a conditional branch, the REG_EQUAL
6454 : notes referring to the registers being set might become invalid. */
6455 146186 : if (merge_set)
6456 : {
6457 146186 : unsigned i;
6458 146186 : bitmap_iterator bi;
6459 :
6460 330790 : EXECUTE_IF_SET_IN_BITMAP (merge_set, 0, i, bi)
6461 184604 : remove_reg_equal_equiv_notes_for_regno (i);
6462 :
6463 146186 : BITMAP_FREE (merge_set);
6464 : }
6465 :
6466 146186 : reorder_insns (head, end, PREV_INSN (earliest));
6467 : }
6468 :
6469 : /* Remove the jump and edge if we can. */
6470 149267 : if (other_bb == new_dest)
6471 : {
6472 15 : delete_insn (jump);
6473 15 : remove_edge (BRANCH_EDGE (test_bb));
6474 : /* ??? Can't merge blocks here, as then_bb is still in use.
6475 : At minimum, the merge will get done just before bb-reorder. */
6476 : }
6477 :
6478 : return true;
6479 :
6480 101145 : cancel:
6481 101145 : cancel_changes (0);
6482 :
6483 101145 : if (merge_set)
6484 0 : BITMAP_FREE (merge_set);
6485 :
6486 : return false;
6487 : }
6488 :
6489 : /* Main entry point for all if-conversion. AFTER_COMBINE is true if
6490 : we are after combine pass. */
6491 :
6492 : static void
6493 3179761 : if_convert (bool after_combine)
6494 : {
6495 3179761 : basic_block bb;
6496 3179761 : int pass;
6497 :
6498 3179761 : if (optimize == 1)
6499 : {
6500 235906 : df_live_add_problem ();
6501 235906 : df_live_set_all_dirty ();
6502 : }
6503 :
6504 : /* Record whether we are after combine pass. */
6505 3179761 : ifcvt_after_combine = after_combine;
6506 3179761 : have_cbranchcc4 = (direct_optab_handler (cbranch_optab, CCmode)
6507 3179761 : != CODE_FOR_nothing);
6508 3179761 : num_possible_if_blocks = 0;
6509 3179761 : num_updated_if_blocks = 0;
6510 3179761 : num_true_changes = 0;
6511 :
6512 3179761 : loop_optimizer_init (AVOID_CFG_MODIFICATIONS);
6513 3179761 : mark_loop_exit_edges ();
6514 3179761 : loop_optimizer_finalize ();
6515 3179761 : free_dominance_info (CDI_DOMINATORS);
6516 :
6517 : /* Compute postdominators. */
6518 3179761 : calculate_dominance_info (CDI_POST_DOMINATORS);
6519 :
6520 3179761 : df_set_flags (DF_LR_RUN_DCE);
6521 :
6522 : /* Go through each of the basic blocks looking for things to convert. If we
6523 : have conditional execution, we make multiple passes to allow us to handle
6524 : IF-THEN{-ELSE} blocks within other IF-THEN{-ELSE} blocks. */
6525 3179761 : pass = 0;
6526 3345270 : do
6527 : {
6528 3345270 : df_analyze ();
6529 : /* Only need to do dce on the first pass. */
6530 3345270 : df_clear_flags (DF_LR_RUN_DCE);
6531 3345270 : cond_exec_changed_p = false;
6532 3345270 : pass++;
6533 :
6534 : #ifdef IFCVT_MULTIPLE_DUMPS
6535 3345270 : if (dump_file && pass > 1)
6536 21 : fprintf (dump_file, "\n\n========== Pass %d ==========\n", pass);
6537 : #endif
6538 :
6539 43637812 : FOR_EACH_BB_FN (bb, cfun)
6540 : {
6541 : basic_block new_bb;
6542 40612233 : while (!df_get_bb_dirty (bb)
6543 80418663 : && (new_bb = find_if_header (bb, pass)) != NULL)
6544 : bb = new_bb;
6545 : }
6546 :
6547 : #ifdef IFCVT_MULTIPLE_DUMPS
6548 3345270 : if (dump_file && cond_exec_changed_p)
6549 21 : print_rtl_with_bb (dump_file, get_insns (), dump_flags);
6550 : #endif
6551 : }
6552 : while (cond_exec_changed_p);
6553 :
6554 : #ifdef IFCVT_MULTIPLE_DUMPS
6555 3179761 : if (dump_file)
6556 87 : fprintf (dump_file, "\n\n========== no more changes\n");
6557 : #endif
6558 :
6559 3179761 : free_dominance_info (CDI_POST_DOMINATORS);
6560 :
6561 3179761 : if (dump_file)
6562 87 : fflush (dump_file);
6563 :
6564 3179761 : clear_aux_for_blocks ();
6565 :
6566 : /* If we allocated new pseudos, we must resize the array for sched1. */
6567 3179761 : if (max_regno < max_reg_num ())
6568 647616 : max_regno = max_reg_num ();
6569 :
6570 : /* Write the final stats. */
6571 3179761 : if (dump_file && num_possible_if_blocks > 0)
6572 : {
6573 61 : fprintf (dump_file,
6574 : "\n%d possible IF blocks searched.\n",
6575 : num_possible_if_blocks);
6576 61 : fprintf (dump_file,
6577 : "%d IF blocks converted.\n",
6578 : num_updated_if_blocks);
6579 61 : fprintf (dump_file,
6580 : "%d true changes made.\n\n\n",
6581 : num_true_changes);
6582 : }
6583 :
6584 3179761 : if (optimize == 1)
6585 235906 : df_remove_problem (df_live);
6586 :
6587 : /* Some non-cold blocks may now be only reachable from cold blocks.
6588 : Fix that up. */
6589 3179761 : fixup_partitions ();
6590 :
6591 3179761 : checking_verify_flow_info ();
6592 3179761 : }
6593 :
6594 : /* If-conversion and CFG cleanup. */
6595 : static void
6596 1062343 : rest_of_handle_if_conversion (void)
6597 : {
6598 1062343 : int flags = 0;
6599 :
6600 1062343 : if (flag_if_conversion)
6601 : {
6602 1059916 : if (dump_file)
6603 : {
6604 35 : dump_reg_info (dump_file);
6605 35 : dump_flow_info (dump_file, dump_flags);
6606 : }
6607 1059916 : cleanup_cfg (CLEANUP_EXPENSIVE);
6608 1059916 : if_convert (false);
6609 1059916 : if (num_updated_if_blocks)
6610 : /* Get rid of any dead CC-related instructions. */
6611 1062343 : flags |= CLEANUP_FORCE_FAST_DCE;
6612 : }
6613 :
6614 1062343 : cleanup_cfg (flags);
6615 1062343 : }
6616 :
6617 : namespace {
6618 :
6619 : const pass_data pass_data_rtl_ifcvt =
6620 : {
6621 : RTL_PASS, /* type */
6622 : "ce1", /* name */
6623 : OPTGROUP_NONE, /* optinfo_flags */
6624 : TV_IFCVT, /* tv_id */
6625 : 0, /* properties_required */
6626 : 0, /* properties_provided */
6627 : 0, /* properties_destroyed */
6628 : 0, /* todo_flags_start */
6629 : TODO_df_finish, /* todo_flags_finish */
6630 : };
6631 :
6632 : class pass_rtl_ifcvt : public rtl_opt_pass
6633 : {
6634 : public:
6635 294196 : pass_rtl_ifcvt (gcc::context *ctxt)
6636 588392 : : rtl_opt_pass (pass_data_rtl_ifcvt, ctxt)
6637 : {}
6638 :
6639 : /* opt_pass methods: */
6640 1515129 : bool gate (function *) final override
6641 : {
6642 1515129 : return (optimize > 0) && dbg_cnt (if_conversion);
6643 : }
6644 :
6645 1062343 : unsigned int execute (function *) final override
6646 : {
6647 1062343 : rest_of_handle_if_conversion ();
6648 1062343 : return 0;
6649 : }
6650 :
6651 : }; // class pass_rtl_ifcvt
6652 :
6653 : } // anon namespace
6654 :
6655 : rtl_opt_pass *
6656 294196 : make_pass_rtl_ifcvt (gcc::context *ctxt)
6657 : {
6658 294196 : return new pass_rtl_ifcvt (ctxt);
6659 : }
6660 :
6661 :
6662 : /* Rerun if-conversion, as combine may have simplified things enough
6663 : to now meet sequence length restrictions. */
6664 :
6665 : namespace {
6666 :
6667 : const pass_data pass_data_if_after_combine =
6668 : {
6669 : RTL_PASS, /* type */
6670 : "ce2", /* name */
6671 : OPTGROUP_NONE, /* optinfo_flags */
6672 : TV_IFCVT, /* tv_id */
6673 : 0, /* properties_required */
6674 : 0, /* properties_provided */
6675 : 0, /* properties_destroyed */
6676 : 0, /* todo_flags_start */
6677 : TODO_df_finish, /* todo_flags_finish */
6678 : };
6679 :
6680 : class pass_if_after_combine : public rtl_opt_pass
6681 : {
6682 : public:
6683 294196 : pass_if_after_combine (gcc::context *ctxt)
6684 588392 : : rtl_opt_pass (pass_data_if_after_combine, ctxt)
6685 : {}
6686 :
6687 : /* opt_pass methods: */
6688 1515129 : bool gate (function *) final override
6689 : {
6690 1062344 : return optimize > 0 && flag_if_conversion
6691 2575046 : && dbg_cnt (if_after_combine);
6692 : }
6693 :
6694 1059916 : unsigned int execute (function *) final override
6695 : {
6696 1059916 : if_convert (true);
6697 1059916 : return 0;
6698 : }
6699 :
6700 : }; // class pass_if_after_combine
6701 :
6702 : } // anon namespace
6703 :
6704 : rtl_opt_pass *
6705 294196 : make_pass_if_after_combine (gcc::context *ctxt)
6706 : {
6707 294196 : return new pass_if_after_combine (ctxt);
6708 : }
6709 :
6710 :
6711 : namespace {
6712 :
6713 : const pass_data pass_data_if_after_reload =
6714 : {
6715 : RTL_PASS, /* type */
6716 : "ce3", /* name */
6717 : OPTGROUP_NONE, /* optinfo_flags */
6718 : TV_IFCVT2, /* tv_id */
6719 : 0, /* properties_required */
6720 : 0, /* properties_provided */
6721 : 0, /* properties_destroyed */
6722 : 0, /* todo_flags_start */
6723 : TODO_df_finish, /* todo_flags_finish */
6724 : };
6725 :
6726 : class pass_if_after_reload : public rtl_opt_pass
6727 : {
6728 : public:
6729 294196 : pass_if_after_reload (gcc::context *ctxt)
6730 588392 : : rtl_opt_pass (pass_data_if_after_reload, ctxt)
6731 : {}
6732 :
6733 : /* opt_pass methods: */
6734 1515129 : bool gate (function *) final override
6735 : {
6736 1062344 : return optimize > 0 && flag_if_conversion2
6737 2575059 : && dbg_cnt (if_after_reload);
6738 : }
6739 :
6740 1059929 : unsigned int execute (function *) final override
6741 : {
6742 1059929 : if_convert (true);
6743 1059929 : return 0;
6744 : }
6745 :
6746 : }; // class pass_if_after_reload
6747 :
6748 : } // anon namespace
6749 :
6750 : rtl_opt_pass *
6751 294196 : make_pass_if_after_reload (gcc::context *ctxt)
6752 : {
6753 294196 : return new pass_if_after_reload (ctxt);
6754 : }
|