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