source: trunk/src/gcc/gcc/ifcvt.c@ 1392

Last change on this file since 1392 was 1392, checked in by bird, 21 years ago

This commit was generated by cvs2svn to compensate for changes in r1391,
which included commits to RCS files with non-trunk default branches.

  • Property cvs2svn:cvs-rev set to 1.1.1.2
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 87.6 KB
Line 
1/* If-conversion support.
2 Copyright (C) 2000, 2001, 2002 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 2, 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 COPYING. If not, write to the Free
18 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19 02111-1307, USA. */
20
21#include "config.h"
22#include "system.h"
23
24#include "rtl.h"
25#include "regs.h"
26#include "function.h"
27#include "flags.h"
28#include "insn-config.h"
29#include "recog.h"
30#include "except.h"
31#include "hard-reg-set.h"
32#include "basic-block.h"
33#include "expr.h"
34#include "real.h"
35#include "output.h"
36#include "toplev.h"
37#include "tm_p.h"
38
39
40#ifndef HAVE_conditional_execution
41#define HAVE_conditional_execution 0
42#endif
43#ifndef HAVE_conditional_move
44#define HAVE_conditional_move 0
45#endif
46#ifndef HAVE_incscc
47#define HAVE_incscc 0
48#endif
49#ifndef HAVE_decscc
50#define HAVE_decscc 0
51#endif
52#ifndef HAVE_trap
53#define HAVE_trap 0
54#endif
55#ifndef HAVE_conditional_trap
56#define HAVE_conditional_trap 0
57#endif
58
59#ifndef MAX_CONDITIONAL_EXECUTE
60#define MAX_CONDITIONAL_EXECUTE (BRANCH_COST + 1)
61#endif
62
63#define NULL_EDGE ((struct edge_def *)NULL)
64#define NULL_BLOCK ((struct basic_block_def *)NULL)
65
66/* # of IF-THEN or IF-THEN-ELSE blocks we looked at */
67static int num_possible_if_blocks;
68
69/* # of IF-THEN or IF-THEN-ELSE blocks were converted to conditional
70 execution. */
71static int num_updated_if_blocks;
72
73/* # of basic blocks that were removed. */
74static int num_removed_blocks;
75
76/* Whether conditional execution changes were made. */
77static int cond_exec_changed_p;
78
79/* True if life data ok at present. */
80static bool life_data_ok;
81
82/* The post-dominator relation on the original block numbers. */
83static dominance_info post_dominators;
84
85/* Forward references. */
86static int count_bb_insns PARAMS ((basic_block));
87static rtx first_active_insn PARAMS ((basic_block));
88static rtx last_active_insn PARAMS ((basic_block, int));
89static int seq_contains_jump PARAMS ((rtx));
90static basic_block block_fallthru PARAMS ((basic_block));
91static int cond_exec_process_insns PARAMS ((ce_if_block_t *,
92 rtx, rtx, rtx, rtx, int));
93static rtx cond_exec_get_condition PARAMS ((rtx));
94static int cond_exec_process_if_block PARAMS ((ce_if_block_t *, int));
95static rtx noce_get_condition PARAMS ((rtx, rtx *));
96static int noce_operand_ok PARAMS ((rtx));
97static int noce_process_if_block PARAMS ((ce_if_block_t *));
98static int process_if_block PARAMS ((ce_if_block_t *));
99static void merge_if_block PARAMS ((ce_if_block_t *));
100static int find_cond_trap PARAMS ((basic_block, edge, edge));
101static basic_block find_if_header PARAMS ((basic_block, int));
102static int block_jumps_and_fallthru_p PARAMS ((basic_block, basic_block));
103static int find_if_block PARAMS ((ce_if_block_t *));
104static int find_if_case_1 PARAMS ((basic_block, edge, edge));
105static int find_if_case_2 PARAMS ((basic_block, edge, edge));
106static int find_memory PARAMS ((rtx *, void *));
107static int dead_or_predicable PARAMS ((basic_block, basic_block,
108 basic_block, basic_block, int));
109static void noce_emit_move_insn PARAMS ((rtx, rtx));
110static rtx block_has_only_trap PARAMS ((basic_block));
111
112
113/* Count the number of non-jump active insns in BB. */
114
115static int
116count_bb_insns (bb)
117 basic_block bb;
118{
119 int count = 0;
120 rtx insn = bb->head;
121
122 while (1)
123 {
124 if (GET_CODE (insn) == CALL_INSN || GET_CODE (insn) == INSN)
125 count++;
126
127 if (insn == bb->end)
128 break;
129 insn = NEXT_INSN (insn);
130 }
131
132 return count;
133}
134
135/* Return the first non-jump active insn in the basic block. */
136
137static rtx
138first_active_insn (bb)
139 basic_block bb;
140{
141 rtx insn = bb->head;
142
143 if (GET_CODE (insn) == CODE_LABEL)
144 {
145 if (insn == bb->end)
146 return NULL_RTX;
147 insn = NEXT_INSN (insn);
148 }
149
150 while (GET_CODE (insn) == NOTE)
151 {
152 if (insn == bb->end)
153 return NULL_RTX;
154 insn = NEXT_INSN (insn);
155 }
156
157 if (GET_CODE (insn) == JUMP_INSN)
158 return NULL_RTX;
159
160 return insn;
161}
162
163/* Return the last non-jump active (non-jump) insn in the basic block. */
164
165static rtx
166last_active_insn (bb, skip_use_p)
167 basic_block bb;
168 int skip_use_p;
169{
170 rtx insn = bb->end;
171 rtx head = bb->head;
172
173 while (GET_CODE (insn) == NOTE
174 || GET_CODE (insn) == JUMP_INSN
175 || (skip_use_p
176 && GET_CODE (insn) == INSN
177 && GET_CODE (PATTERN (insn)) == USE))
178 {
179 if (insn == head)
180 return NULL_RTX;
181 insn = PREV_INSN (insn);
182 }
183
184 if (GET_CODE (insn) == CODE_LABEL)
185 return NULL_RTX;
186
187 return insn;
188}
189
190/* It is possible, especially when having dealt with multi-word
191 arithmetic, for the expanders to have emitted jumps. Search
192 through the sequence and return TRUE if a jump exists so that
193 we can abort the conversion. */
194
195static int
196seq_contains_jump (insn)
197 rtx insn;
198{
199 while (insn)
200 {
201 if (GET_CODE (insn) == JUMP_INSN)
202 return 1;
203 insn = NEXT_INSN (insn);
204 }
205 return 0;
206}
207
208static basic_block
209block_fallthru (bb)
210 basic_block bb;
211{
212 edge e;
213
214 for (e = bb->succ;
215 e != NULL_EDGE && (e->flags & EDGE_FALLTHRU) == 0;
216 e = e->succ_next)
217 ;
218
219 return (e) ? e->dest : NULL_BLOCK;
220}
221
222
223/* Go through a bunch of insns, converting them to conditional
224 execution format if possible. Return TRUE if all of the non-note
225 insns were processed. */
226
227static int
228cond_exec_process_insns (ce_info, start, end, test, prob_val, mod_ok)
229 ce_if_block_t *ce_info ATTRIBUTE_UNUSED; /* if block information */
230 rtx start; /* first insn to look at */
231 rtx end; /* last insn to look at */
232 rtx test; /* conditional execution test */
233 rtx prob_val; /* probability of branch taken. */
234 int mod_ok; /* true if modifications ok last insn. */
235{
236 int must_be_last = FALSE;
237 rtx insn;
238 rtx xtest;
239 rtx pattern;
240
241 if (!start || !end)
242 return FALSE;
243
244 for (insn = start; ; insn = NEXT_INSN (insn))
245 {
246 if (GET_CODE (insn) == NOTE)
247 goto insn_done;
248
249 if (GET_CODE (insn) != INSN && GET_CODE (insn) != CALL_INSN)
250 abort ();
251
252 /* Remove USE insns that get in the way. */
253 if (reload_completed && GET_CODE (PATTERN (insn)) == USE)
254 {
255 /* ??? Ug. Actually unlinking the thing is problematic,
256 given what we'd have to coordinate with our callers. */
257 PUT_CODE (insn, NOTE);
258 NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
259 NOTE_SOURCE_FILE (insn) = 0;
260 goto insn_done;
261 }
262
263 /* Last insn wasn't last? */
264 if (must_be_last)
265 return FALSE;
266
267 if (modified_in_p (test, insn))
268 {
269 if (!mod_ok)
270 return FALSE;
271 must_be_last = TRUE;
272 }
273
274 /* Now build the conditional form of the instruction. */
275 pattern = PATTERN (insn);
276 xtest = copy_rtx (test);
277
278 /* If this is already a COND_EXEC, rewrite the test to be an AND of the
279 two conditions. */
280 if (GET_CODE (pattern) == COND_EXEC)
281 {
282 if (GET_MODE (xtest) != GET_MODE (COND_EXEC_TEST (pattern)))
283 return FALSE;
284
285 xtest = gen_rtx_AND (GET_MODE (xtest), xtest,
286 COND_EXEC_TEST (pattern));
287 pattern = COND_EXEC_CODE (pattern);
288 }
289
290 pattern = gen_rtx_COND_EXEC (VOIDmode, xtest, pattern);
291
292 /* If the machine needs to modify the insn being conditionally executed,
293 say for example to force a constant integer operand into a temp
294 register, do so here. */
295#ifdef IFCVT_MODIFY_INSN
296 IFCVT_MODIFY_INSN (ce_info, pattern, insn);
297 if (! pattern)
298 return FALSE;
299#endif
300
301 validate_change (insn, &PATTERN (insn), pattern, 1);
302
303 if (GET_CODE (insn) == CALL_INSN && prob_val)
304 validate_change (insn, &REG_NOTES (insn),
305 alloc_EXPR_LIST (REG_BR_PROB, prob_val,
306 REG_NOTES (insn)), 1);
307
308 insn_done:
309 if (insn == end)
310 break;
311 }
312
313 return TRUE;
314}
315
316/* Return the condition for a jump. Do not do any special processing. */
317
318static rtx
319cond_exec_get_condition (jump)
320 rtx jump;
321{
322 rtx test_if, cond;
323
324 if (any_condjump_p (jump))
325 test_if = SET_SRC (pc_set (jump));
326 else
327 return NULL_RTX;
328 cond = XEXP (test_if, 0);
329
330 /* If this branches to JUMP_LABEL when the condition is false,
331 reverse the condition. */
332 if (GET_CODE (XEXP (test_if, 2)) == LABEL_REF
333 && XEXP (XEXP (test_if, 2), 0) == JUMP_LABEL (jump))
334 {
335 enum rtx_code rev = reversed_comparison_code (cond, jump);
336 if (rev == UNKNOWN)
337 return NULL_RTX;
338
339 cond = gen_rtx_fmt_ee (rev, GET_MODE (cond), XEXP (cond, 0),
340 XEXP (cond, 1));
341 }
342
343 return cond;
344}
345
346/* Given a simple IF-THEN or IF-THEN-ELSE block, attempt to convert it
347 to conditional execution. Return TRUE if we were successful at
348 converting the block. */
349
350static int
351cond_exec_process_if_block (ce_info, do_multiple_p)
352 ce_if_block_t * ce_info; /* if block information */
353 int do_multiple_p; /* != 0 if we should handle && and || blocks */
354{
355 basic_block test_bb = ce_info->test_bb; /* last test block */
356 basic_block then_bb = ce_info->then_bb; /* THEN */
357 basic_block else_bb = ce_info->else_bb; /* ELSE or NULL */
358 rtx test_expr; /* expression in IF_THEN_ELSE that is tested */
359 rtx then_start; /* first insn in THEN block */
360 rtx then_end; /* last insn + 1 in THEN block */
361 rtx else_start = NULL_RTX; /* first insn in ELSE block or NULL */
362 rtx else_end = NULL_RTX; /* last insn + 1 in ELSE block */
363 int max; /* max # of insns to convert. */
364 int then_mod_ok; /* whether conditional mods are ok in THEN */
365 rtx true_expr; /* test for else block insns */
366 rtx false_expr; /* test for then block insns */
367 rtx true_prob_val; /* probability of else block */
368 rtx false_prob_val; /* probability of then block */
369 int n_insns;
370 enum rtx_code false_code;
371
372 /* If test is comprised of && or || elements, and we've failed at handling
373 all of them together, just use the last test if it is the special case of
374 && elements without an ELSE block. */
375 if (!do_multiple_p && ce_info->num_multiple_test_blocks)
376 {
377 if (else_bb || ! ce_info->and_and_p)
378 return FALSE;
379
380 ce_info->test_bb = test_bb = ce_info->last_test_bb;
381 ce_info->num_multiple_test_blocks = 0;
382 ce_info->num_and_and_blocks = 0;
383 ce_info->num_or_or_blocks = 0;
384 }
385
386 /* Find the conditional jump to the ELSE or JOIN part, and isolate
387 the test. */
388 test_expr = cond_exec_get_condition (test_bb->end);
389 if (! test_expr)
390 return FALSE;
391
392 /* If the conditional jump is more than just a conditional jump,
393 then we can not do conditional execution conversion on this block. */
394 if (! onlyjump_p (test_bb->end))
395 return FALSE;
396
397 /* Collect the bounds of where we're to search, skipping any labels, jumps
398 and notes at the beginning and end of the block. Then count the total
399 number of insns and see if it is small enough to convert. */
400 then_start = first_active_insn (then_bb);
401 then_end = last_active_insn (then_bb, TRUE);
402 n_insns = ce_info->num_then_insns = count_bb_insns (then_bb);
403 max = MAX_CONDITIONAL_EXECUTE;
404
405 if (else_bb)
406 {
407 max *= 2;
408 else_start = first_active_insn (else_bb);
409 else_end = last_active_insn (else_bb, TRUE);
410 n_insns += ce_info->num_else_insns = count_bb_insns (else_bb);
411 }
412
413 if (n_insns > max)
414 return FALSE;
415
416 /* Map test_expr/test_jump into the appropriate MD tests to use on
417 the conditionally executed code. */
418
419 true_expr = test_expr;
420
421 false_code = reversed_comparison_code (true_expr, test_bb->end);
422 if (false_code != UNKNOWN)
423 false_expr = gen_rtx_fmt_ee (false_code, GET_MODE (true_expr),
424 XEXP (true_expr, 0), XEXP (true_expr, 1));
425 else
426 false_expr = NULL_RTX;
427
428#ifdef IFCVT_MODIFY_TESTS
429 /* If the machine description needs to modify the tests, such as setting a
430 conditional execution register from a comparison, it can do so here. */
431 IFCVT_MODIFY_TESTS (ce_info, true_expr, false_expr);
432
433 /* See if the conversion failed */
434 if (!true_expr || !false_expr)
435 goto fail;
436#endif
437
438 true_prob_val = find_reg_note (test_bb->end, REG_BR_PROB, NULL_RTX);
439 if (true_prob_val)
440 {
441 true_prob_val = XEXP (true_prob_val, 0);
442 false_prob_val = GEN_INT (REG_BR_PROB_BASE - INTVAL (true_prob_val));
443 }
444 else
445 false_prob_val = NULL_RTX;
446
447 /* If we have && or || tests, do them here. These tests are in the adjacent
448 blocks after the first block containing the test. */
449 if (ce_info->num_multiple_test_blocks > 0)
450 {
451 basic_block bb = test_bb;
452 basic_block last_test_bb = ce_info->last_test_bb;
453
454 if (! false_expr)
455 goto fail;
456
457 do
458 {
459 rtx start, end;
460 rtx t, f;
461
462 bb = block_fallthru (bb);
463 start = first_active_insn (bb);
464 end = last_active_insn (bb, TRUE);
465 if (start
466 && ! cond_exec_process_insns (ce_info, start, end, false_expr,
467 false_prob_val, FALSE))
468 goto fail;
469
470 /* If the conditional jump is more than just a conditional jump, then
471 we can not do conditional execution conversion on this block. */
472 if (! onlyjump_p (bb->end))
473 goto fail;
474
475 /* Find the conditional jump and isolate the test. */
476 t = cond_exec_get_condition (bb->end);
477 if (! t)
478 goto fail;
479
480 f = gen_rtx_fmt_ee (reverse_condition (GET_CODE (t)),
481 GET_MODE (t),
482 XEXP (t, 0),
483 XEXP (t, 1));
484
485 if (ce_info->and_and_p)
486 {
487 t = gen_rtx_AND (GET_MODE (t), true_expr, t);
488 f = gen_rtx_IOR (GET_MODE (t), false_expr, f);
489 }
490 else
491 {
492 t = gen_rtx_IOR (GET_MODE (t), true_expr, t);
493 f = gen_rtx_AND (GET_MODE (t), false_expr, f);
494 }
495
496 /* If the machine description needs to modify the tests, such as
497 setting a conditional execution register from a comparison, it can
498 do so here. */
499#ifdef IFCVT_MODIFY_MULTIPLE_TESTS
500 IFCVT_MODIFY_MULTIPLE_TESTS (ce_info, bb, t, f);
501
502 /* See if the conversion failed */
503 if (!t || !f)
504 goto fail;
505#endif
506
507 true_expr = t;
508 false_expr = f;
509 }
510 while (bb != last_test_bb);
511 }
512
513 /* For IF-THEN-ELSE blocks, we don't allow modifications of the test
514 on then THEN block. */
515 then_mod_ok = (else_bb == NULL_BLOCK);
516
517 /* Go through the THEN and ELSE blocks converting the insns if possible
518 to conditional execution. */
519
520 if (then_end
521 && (! false_expr
522 || ! cond_exec_process_insns (ce_info, then_start, then_end,
523 false_expr, false_prob_val,
524 then_mod_ok)))
525 goto fail;
526
527 if (else_bb && else_end
528 && ! cond_exec_process_insns (ce_info, else_start, else_end,
529 true_expr, true_prob_val, TRUE))
530 goto fail;
531
532 /* If we cannot apply the changes, fail. Do not go through the normal fail
533 processing, since apply_change_group will call cancel_changes. */
534 if (! apply_change_group ())
535 {
536#ifdef IFCVT_MODIFY_CANCEL
537 /* Cancel any machine dependent changes. */
538 IFCVT_MODIFY_CANCEL (ce_info);
539#endif
540 return FALSE;
541 }
542
543#ifdef IFCVT_MODIFY_FINAL
544 /* Do any machine dependent final modifications */
545 IFCVT_MODIFY_FINAL (ce_info);
546#endif
547
548 /* Conversion succeeded. */
549 if (rtl_dump_file)
550 fprintf (rtl_dump_file, "%d insn%s converted to conditional execution.\n",
551 n_insns, (n_insns == 1) ? " was" : "s were");
552
553 /* Merge the blocks! */
554 merge_if_block (ce_info);
555 cond_exec_changed_p = TRUE;
556 return TRUE;
557
558 fail:
559#ifdef IFCVT_MODIFY_CANCEL
560 /* Cancel any machine dependent changes. */
561 IFCVT_MODIFY_CANCEL (ce_info);
562#endif
563
564 cancel_changes (0);
565 return FALSE;
566}
567
568
569/* Used by noce_process_if_block to communicate with its subroutines.
570
571 The subroutines know that A and B may be evaluated freely. They
572 know that X is a register. They should insert new instructions
573 before cond_earliest. */
574
575struct noce_if_info
576{
577 basic_block test_bb;
578 rtx insn_a, insn_b;
579 rtx x, a, b;
580 rtx jump, cond, cond_earliest;
581};
582
583static rtx noce_emit_store_flag PARAMS ((struct noce_if_info *,
584 rtx, int, int));
585static int noce_try_store_flag PARAMS ((struct noce_if_info *));
586static int noce_try_store_flag_inc PARAMS ((struct noce_if_info *));
587static int noce_try_store_flag_constants PARAMS ((struct noce_if_info *));
588static int noce_try_store_flag_mask PARAMS ((struct noce_if_info *));
589static rtx noce_emit_cmove PARAMS ((struct noce_if_info *,
590 rtx, enum rtx_code, rtx,
591 rtx, rtx, rtx));
592static int noce_try_cmove PARAMS ((struct noce_if_info *));
593static int noce_try_cmove_arith PARAMS ((struct noce_if_info *));
594static rtx noce_get_alt_condition PARAMS ((struct noce_if_info *,
595 rtx, rtx *));
596static int noce_try_minmax PARAMS ((struct noce_if_info *));
597static int noce_try_abs PARAMS ((struct noce_if_info *));
598
599/* Helper function for noce_try_store_flag*. */
600
601static rtx
602noce_emit_store_flag (if_info, x, reversep, normalize)
603 struct noce_if_info *if_info;
604 rtx x;
605 int reversep, normalize;
606{
607 rtx cond = if_info->cond;
608 int cond_complex;
609 enum rtx_code code;
610
611 cond_complex = (! general_operand (XEXP (cond, 0), VOIDmode)
612 || ! general_operand (XEXP (cond, 1), VOIDmode));
613
614 /* If earliest == jump, or when the condition is complex, try to
615 build the store_flag insn directly. */
616
617 if (cond_complex)
618 cond = XEXP (SET_SRC (pc_set (if_info->jump)), 0);
619
620 if (reversep)
621 code = reversed_comparison_code (cond, if_info->jump);
622 else
623 code = GET_CODE (cond);
624
625 if ((if_info->cond_earliest == if_info->jump || cond_complex)
626 && (normalize == 0 || STORE_FLAG_VALUE == normalize))
627 {
628 rtx tmp;
629
630 tmp = gen_rtx_fmt_ee (code, GET_MODE (x), XEXP (cond, 0),
631 XEXP (cond, 1));
632 tmp = gen_rtx_SET (VOIDmode, x, tmp);
633
634 start_sequence ();
635 tmp = emit_insn (tmp);
636
637 if (recog_memoized (tmp) >= 0)
638 {
639 tmp = get_insns ();
640 end_sequence ();
641 emit_insn (tmp);
642
643 if_info->cond_earliest = if_info->jump;
644
645 return x;
646 }
647
648 end_sequence ();
649 }
650
651 /* Don't even try if the comparison operands or the mode of X are weird. */
652 if (cond_complex || !SCALAR_INT_MODE_P (GET_MODE (x)))
653 return NULL_RTX;
654
655 return emit_store_flag (x, code, XEXP (cond, 0),
656 XEXP (cond, 1), VOIDmode,
657 (code == LTU || code == LEU
658 || code == GEU || code == GTU), normalize);
659}
660
661/* Emit instruction to move an rtx into STRICT_LOW_PART. */
662static void
663noce_emit_move_insn (x, y)
664 rtx x, y;
665{
666 enum machine_mode outmode, inmode;
667 rtx outer, inner;
668 int bitpos;
669
670 if (GET_CODE (x) != STRICT_LOW_PART)
671 {
672 emit_move_insn (x, y);
673 return;
674 }
675
676 outer = XEXP (x, 0);
677 inner = XEXP (outer, 0);
678 outmode = GET_MODE (outer);
679 inmode = GET_MODE (inner);
680 bitpos = SUBREG_BYTE (outer) * BITS_PER_UNIT;
681 store_bit_field (inner, GET_MODE_BITSIZE (outmode), bitpos, outmode, y,
682 GET_MODE_BITSIZE (inmode));
683}
684
685/* Convert "if (test) x = 1; else x = 0".
686
687 Only try 0 and STORE_FLAG_VALUE here. Other combinations will be
688 tried in noce_try_store_flag_constants after noce_try_cmove has had
689 a go at the conversion. */
690
691static int
692noce_try_store_flag (if_info)
693 struct noce_if_info *if_info;
694{
695 int reversep;
696 rtx target, seq;
697
698 if (GET_CODE (if_info->b) == CONST_INT
699 && INTVAL (if_info->b) == STORE_FLAG_VALUE
700 && if_info->a == const0_rtx)
701 reversep = 0;
702 else if (if_info->b == const0_rtx
703 && GET_CODE (if_info->a) == CONST_INT
704 && INTVAL (if_info->a) == STORE_FLAG_VALUE
705 && (reversed_comparison_code (if_info->cond, if_info->jump)
706 != UNKNOWN))
707 reversep = 1;
708 else
709 return FALSE;
710
711 start_sequence ();
712
713 target = noce_emit_store_flag (if_info, if_info->x, reversep, 0);
714 if (target)
715 {
716 if (target != if_info->x)
717 noce_emit_move_insn (if_info->x, target);
718
719 seq = get_insns ();
720 end_sequence ();
721 emit_insn_before_scope (seq, if_info->jump, INSN_SCOPE (if_info->insn_a));
722
723 return TRUE;
724 }
725 else
726 {
727 end_sequence ();
728 return FALSE;
729 }
730}
731
732/* Convert "if (test) x = a; else x = b", for A and B constant. */
733
734static int
735noce_try_store_flag_constants (if_info)
736 struct noce_if_info *if_info;
737{
738 rtx target, seq;
739 int reversep;
740 HOST_WIDE_INT itrue, ifalse, diff, tmp;
741 int normalize, can_reverse;
742 enum machine_mode mode;
743
744 if (! no_new_pseudos
745 && GET_CODE (if_info->a) == CONST_INT
746 && GET_CODE (if_info->b) == CONST_INT)
747 {
748 mode = GET_MODE (if_info->x);
749 ifalse = INTVAL (if_info->a);
750 itrue = INTVAL (if_info->b);
751
752 /* Make sure we can represent the difference between the two values. */
753 if ((itrue - ifalse > 0)
754 != ((ifalse < 0) != (itrue < 0) ? ifalse < 0 : ifalse < itrue))
755 return FALSE;
756
757 diff = trunc_int_for_mode (itrue - ifalse, mode);
758
759 can_reverse = (reversed_comparison_code (if_info->cond, if_info->jump)
760 != UNKNOWN);
761
762 reversep = 0;
763 if (diff == STORE_FLAG_VALUE || diff == -STORE_FLAG_VALUE)
764 normalize = 0;
765 else if (ifalse == 0 && exact_log2 (itrue) >= 0
766 && (STORE_FLAG_VALUE == 1
767 || BRANCH_COST >= 2))
768 normalize = 1;
769 else if (itrue == 0 && exact_log2 (ifalse) >= 0 && can_reverse
770 && (STORE_FLAG_VALUE == 1 || BRANCH_COST >= 2))
771 normalize = 1, reversep = 1;
772 else if (itrue == -1
773 && (STORE_FLAG_VALUE == -1
774 || BRANCH_COST >= 2))
775 normalize = -1;
776 else if (ifalse == -1 && can_reverse
777 && (STORE_FLAG_VALUE == -1 || BRANCH_COST >= 2))
778 normalize = -1, reversep = 1;
779 else if ((BRANCH_COST >= 2 && STORE_FLAG_VALUE == -1)
780 || BRANCH_COST >= 3)
781 normalize = -1;
782 else
783 return FALSE;
784
785 if (reversep)
786 {
787 tmp = itrue; itrue = ifalse; ifalse = tmp;
788 diff = trunc_int_for_mode (-diff, mode);
789 }
790
791 start_sequence ();
792 target = noce_emit_store_flag (if_info, if_info->x, reversep, normalize);
793 if (! target)
794 {
795 end_sequence ();
796 return FALSE;
797 }
798
799 /* if (test) x = 3; else x = 4;
800 => x = 3 + (test == 0); */
801 if (diff == STORE_FLAG_VALUE || diff == -STORE_FLAG_VALUE)
802 {
803 target = expand_simple_binop (mode,
804 (diff == STORE_FLAG_VALUE
805 ? PLUS : MINUS),
806 GEN_INT (ifalse), target, if_info->x, 0,
807 OPTAB_WIDEN);
808 }
809
810 /* if (test) x = 8; else x = 0;
811 => x = (test != 0) << 3; */
812 else if (ifalse == 0 && (tmp = exact_log2 (itrue)) >= 0)
813 {
814 target = expand_simple_binop (mode, ASHIFT,
815 target, GEN_INT (tmp), if_info->x, 0,
816 OPTAB_WIDEN);
817 }
818
819 /* if (test) x = -1; else x = b;
820 => x = -(test != 0) | b; */
821 else if (itrue == -1)
822 {
823 target = expand_simple_binop (mode, IOR,
824 target, GEN_INT (ifalse), if_info->x, 0,
825 OPTAB_WIDEN);
826 }
827
828 /* if (test) x = a; else x = b;
829 => x = (-(test != 0) & (b - a)) + a; */
830 else
831 {
832 target = expand_simple_binop (mode, AND,
833 target, GEN_INT (diff), if_info->x, 0,
834 OPTAB_WIDEN);
835 if (target)
836 target = expand_simple_binop (mode, PLUS,
837 target, GEN_INT (ifalse),
838 if_info->x, 0, OPTAB_WIDEN);
839 }
840
841 if (! target)
842 {
843 end_sequence ();
844 return FALSE;
845 }
846
847 if (target != if_info->x)
848 noce_emit_move_insn (if_info->x, target);
849
850 seq = get_insns ();
851 end_sequence ();
852
853 if (seq_contains_jump (seq))
854 return FALSE;
855
856 emit_insn_before_scope (seq, if_info->jump, INSN_SCOPE (if_info->insn_a));
857
858 return TRUE;
859 }
860
861 return FALSE;
862}
863
864/* Convert "if (test) foo++" into "foo += (test != 0)", and
865 similarly for "foo--". */
866
867static int
868noce_try_store_flag_inc (if_info)
869 struct noce_if_info *if_info;
870{
871 rtx target, seq;
872 int subtract, normalize;
873
874 if (! no_new_pseudos
875 && (BRANCH_COST >= 2
876 || HAVE_incscc
877 || HAVE_decscc)
878 /* Should be no `else' case to worry about. */
879 && if_info->b == if_info->x
880 && GET_CODE (if_info->a) == PLUS
881 && (XEXP (if_info->a, 1) == const1_rtx
882 || XEXP (if_info->a, 1) == constm1_rtx)
883 && rtx_equal_p (XEXP (if_info->a, 0), if_info->x)
884 && (reversed_comparison_code (if_info->cond, if_info->jump)
885 != UNKNOWN))
886 {
887 if (STORE_FLAG_VALUE == INTVAL (XEXP (if_info->a, 1)))
888 subtract = 0, normalize = 0;
889 else if (-STORE_FLAG_VALUE == INTVAL (XEXP (if_info->a, 1)))
890 subtract = 1, normalize = 0;
891 else
892 subtract = 0, normalize = INTVAL (XEXP (if_info->a, 1));
893
894 start_sequence ();
895
896 target = noce_emit_store_flag (if_info,
897 gen_reg_rtx (GET_MODE (if_info->x)),
898 1, normalize);
899
900 if (target)
901 target = expand_simple_binop (GET_MODE (if_info->x),
902 subtract ? MINUS : PLUS,
903 if_info->x, target, if_info->x,
904 0, OPTAB_WIDEN);
905 if (target)
906 {
907 if (target != if_info->x)
908 noce_emit_move_insn (if_info->x, target);
909
910 seq = get_insns ();
911 end_sequence ();
912
913 if (seq_contains_jump (seq))
914 return FALSE;
915
916 emit_insn_before_scope (seq, if_info->jump,
917 INSN_SCOPE (if_info->insn_a));
918
919 return TRUE;
920 }
921
922 end_sequence ();
923 }
924
925 return FALSE;
926}
927
928/* Convert "if (test) x = 0;" to "x &= -(test == 0);" */
929
930static int
931noce_try_store_flag_mask (if_info)
932 struct noce_if_info *if_info;
933{
934 rtx target, seq;
935 int reversep;
936
937 reversep = 0;
938 if (! no_new_pseudos
939 && (BRANCH_COST >= 2
940 || STORE_FLAG_VALUE == -1)
941 && ((if_info->a == const0_rtx
942 && rtx_equal_p (if_info->b, if_info->x))
943 || ((reversep = (reversed_comparison_code (if_info->cond,
944 if_info->jump)
945 != UNKNOWN))
946 && if_info->b == const0_rtx
947 && rtx_equal_p (if_info->a, if_info->x))))
948 {
949 start_sequence ();
950 target = noce_emit_store_flag (if_info,
951 gen_reg_rtx (GET_MODE (if_info->x)),
952 reversep, -1);
953 if (target)
954 target = expand_simple_binop (GET_MODE (if_info->x), AND,
955 if_info->x, target, if_info->x, 0,
956 OPTAB_WIDEN);
957
958 if (target)
959 {
960 if (target != if_info->x)
961 noce_emit_move_insn (if_info->x, target);
962
963 seq = get_insns ();
964 end_sequence ();
965
966 if (seq_contains_jump (seq))
967 return FALSE;
968
969 emit_insn_before_scope (seq, if_info->jump,
970 INSN_SCOPE (if_info->insn_a));
971
972 return TRUE;
973 }
974
975 end_sequence ();
976 }
977
978 return FALSE;
979}
980
981/* Helper function for noce_try_cmove and noce_try_cmove_arith. */
982
983static rtx
984noce_emit_cmove (if_info, x, code, cmp_a, cmp_b, vfalse, vtrue)
985 struct noce_if_info *if_info;
986 rtx x, cmp_a, cmp_b, vfalse, vtrue;
987 enum rtx_code code;
988{
989 /* If earliest == jump, try to build the cmove insn directly.
990 This is helpful when combine has created some complex condition
991 (like for alpha's cmovlbs) that we can't hope to regenerate
992 through the normal interface. */
993
994 if (if_info->cond_earliest == if_info->jump)
995 {
996 rtx tmp;
997
998 tmp = gen_rtx_fmt_ee (code, GET_MODE (if_info->cond), cmp_a, cmp_b);
999 tmp = gen_rtx_IF_THEN_ELSE (GET_MODE (x), tmp, vtrue, vfalse);
1000 tmp = gen_rtx_SET (VOIDmode, x, tmp);
1001
1002 start_sequence ();
1003 tmp = emit_insn (tmp);
1004
1005 if (recog_memoized (tmp) >= 0)
1006 {
1007 tmp = get_insns ();
1008 end_sequence ();
1009 emit_insn (tmp);
1010
1011 return x;
1012 }
1013
1014 end_sequence ();
1015 }
1016
1017 /* Don't even try if the comparison operands are weird. */
1018 if (! general_operand (cmp_a, GET_MODE (cmp_a))
1019 || ! general_operand (cmp_b, GET_MODE (cmp_b)))
1020 return NULL_RTX;
1021
1022#if HAVE_conditional_move
1023 return emit_conditional_move (x, code, cmp_a, cmp_b, VOIDmode,
1024 vtrue, vfalse, GET_MODE (x),
1025 (code == LTU || code == GEU
1026 || code == LEU || code == GTU));
1027#else
1028 /* We'll never get here, as noce_process_if_block doesn't call the
1029 functions involved. Ifdef code, however, should be discouraged
1030 because it leads to typos in the code not selected. However,
1031 emit_conditional_move won't exist either. */
1032 return NULL_RTX;
1033#endif
1034}
1035
1036/* Try only simple constants and registers here. More complex cases
1037 are handled in noce_try_cmove_arith after noce_try_store_flag_arith
1038 has had a go at it. */
1039
1040static int
1041noce_try_cmove (if_info)
1042 struct noce_if_info *if_info;
1043{
1044 enum rtx_code code;
1045 rtx target, seq;
1046
1047 if ((CONSTANT_P (if_info->a) || register_operand (if_info->a, VOIDmode))
1048 && (CONSTANT_P (if_info->b) || register_operand (if_info->b, VOIDmode)))
1049 {
1050 start_sequence ();
1051
1052 code = GET_CODE (if_info->cond);
1053 target = noce_emit_cmove (if_info, if_info->x, code,
1054 XEXP (if_info->cond, 0),
1055 XEXP (if_info->cond, 1),
1056 if_info->a, if_info->b);
1057
1058 if (target)
1059 {
1060 if (target != if_info->x)
1061 noce_emit_move_insn (if_info->x, target);
1062
1063 seq = get_insns ();
1064 end_sequence ();
1065 emit_insn_before_scope (seq, if_info->jump,
1066 INSN_SCOPE (if_info->insn_a));
1067 return TRUE;
1068 }
1069 else
1070 {
1071 end_sequence ();
1072 return FALSE;
1073 }
1074 }
1075
1076 return FALSE;
1077}
1078
1079/* Try more complex cases involving conditional_move. */
1080
1081static int
1082noce_try_cmove_arith (if_info)
1083 struct noce_if_info *if_info;
1084{
1085 rtx a = if_info->a;
1086 rtx b = if_info->b;
1087 rtx x = if_info->x;
1088 rtx insn_a, insn_b;
1089 rtx tmp, target;
1090 int is_mem = 0;
1091 enum rtx_code code;
1092
1093 /* A conditional move from two memory sources is equivalent to a
1094 conditional on their addresses followed by a load. Don't do this
1095 early because it'll screw alias analysis. Note that we've
1096 already checked for no side effects. */
1097 if (! no_new_pseudos && cse_not_expected
1098 && GET_CODE (a) == MEM && GET_CODE (b) == MEM
1099 && BRANCH_COST >= 5)
1100 {
1101 a = XEXP (a, 0);
1102 b = XEXP (b, 0);
1103 x = gen_reg_rtx (Pmode);
1104 is_mem = 1;
1105 }
1106
1107 /* ??? We could handle this if we knew that a load from A or B could
1108 not fault. This is also true if we've already loaded
1109 from the address along the path from ENTRY. */
1110 else if (may_trap_p (a) || may_trap_p (b))
1111 return FALSE;
1112
1113 /* if (test) x = a + b; else x = c - d;
1114 => y = a + b;
1115 x = c - d;
1116 if (test)
1117 x = y;
1118 */
1119
1120 code = GET_CODE (if_info->cond);
1121 insn_a = if_info->insn_a;
1122 insn_b = if_info->insn_b;
1123
1124 /* Possibly rearrange operands to make things come out more natural. */
1125 if (reversed_comparison_code (if_info->cond, if_info->jump) != UNKNOWN)
1126 {
1127 int reversep = 0;
1128 if (rtx_equal_p (b, x))
1129 reversep = 1;
1130 else if (general_operand (b, GET_MODE (b)))
1131 reversep = 1;
1132
1133 if (reversep)
1134 {
1135 code = reversed_comparison_code (if_info->cond, if_info->jump);
1136 tmp = a, a = b, b = tmp;
1137 tmp = insn_a, insn_a = insn_b, insn_b = tmp;
1138 }
1139 }
1140
1141 start_sequence ();
1142
1143 /* If either operand is complex, load it into a register first.
1144 The best way to do this is to copy the original insn. In this
1145 way we preserve any clobbers etc that the insn may have had.
1146 This is of course not possible in the IS_MEM case. */
1147 if (! general_operand (a, GET_MODE (a)))
1148 {
1149 rtx set;
1150
1151 if (no_new_pseudos)
1152 goto end_seq_and_fail;
1153
1154 if (is_mem)
1155 {
1156 tmp = gen_reg_rtx (GET_MODE (a));
1157 tmp = emit_insn (gen_rtx_SET (VOIDmode, tmp, a));
1158 }
1159 else if (! insn_a)
1160 goto end_seq_and_fail;
1161 else
1162 {
1163 a = gen_reg_rtx (GET_MODE (a));
1164 tmp = copy_rtx (insn_a);
1165 set = single_set (tmp);
1166 SET_DEST (set) = a;
1167 tmp = emit_insn (PATTERN (tmp));
1168 }
1169 if (recog_memoized (tmp) < 0)
1170 goto end_seq_and_fail;
1171 }
1172 if (! general_operand (b, GET_MODE (b)))
1173 {
1174 rtx set;
1175
1176 if (no_new_pseudos)
1177 goto end_seq_and_fail;
1178
1179 if (is_mem)
1180 {
1181 tmp = gen_reg_rtx (GET_MODE (b));
1182 tmp = emit_insn (gen_rtx_SET (VOIDmode, tmp, b));
1183 }
1184 else if (! insn_b
1185#if 0
1186 /* In the case we are going to duplicate insn originally
1187 present in the front of comparsion, verify that the
1188 comparsion didn't clobbered the operands. */
1189 || modified_between_p (SET_SRC (single_set (insn_b)),
1190 if_info->cond_earliest,
1191 NEXT_INSN (if_info->jump)))
1192#endif
1193 )
1194 goto end_seq_and_fail;
1195 else
1196 {
1197 b = gen_reg_rtx (GET_MODE (b));
1198 tmp = copy_rtx (insn_b);
1199 set = single_set (tmp);
1200 SET_DEST (set) = b;
1201 tmp = emit_insn (PATTERN (tmp));
1202 }
1203 if (recog_memoized (tmp) < 0)
1204 goto end_seq_and_fail;
1205 }
1206
1207 target = noce_emit_cmove (if_info, x, code, XEXP (if_info->cond, 0),
1208 XEXP (if_info->cond, 1), a, b);
1209
1210 if (! target)
1211 goto end_seq_and_fail;
1212
1213 /* If we're handling a memory for above, emit the load now. */
1214 if (is_mem)
1215 {
1216 tmp = gen_rtx_MEM (GET_MODE (if_info->x), target);
1217
1218 /* Copy over flags as appropriate. */
1219 if (MEM_VOLATILE_P (if_info->a) || MEM_VOLATILE_P (if_info->b))
1220 MEM_VOLATILE_P (tmp) = 1;
1221 if (MEM_IN_STRUCT_P (if_info->a) && MEM_IN_STRUCT_P (if_info->b))
1222 MEM_IN_STRUCT_P (tmp) = 1;
1223 if (MEM_SCALAR_P (if_info->a) && MEM_SCALAR_P (if_info->b))
1224 MEM_SCALAR_P (tmp) = 1;
1225 if (MEM_ALIAS_SET (if_info->a) == MEM_ALIAS_SET (if_info->b))
1226 set_mem_alias_set (tmp, MEM_ALIAS_SET (if_info->a));
1227 set_mem_align (tmp,
1228 MIN (MEM_ALIGN (if_info->a), MEM_ALIGN (if_info->b)));
1229
1230 noce_emit_move_insn (if_info->x, tmp);
1231 }
1232 else if (target != x)
1233 noce_emit_move_insn (x, target);
1234
1235 tmp = get_insns ();
1236 end_sequence ();
1237 emit_insn_before_scope (tmp, if_info->jump, INSN_SCOPE (if_info->insn_a));
1238 return TRUE;
1239
1240 end_seq_and_fail:
1241 end_sequence ();
1242 return FALSE;
1243}
1244
1245/* For most cases, the simplified condition we found is the best
1246 choice, but this is not the case for the min/max/abs transforms.
1247 For these we wish to know that it is A or B in the condition. */
1248
1249static rtx
1250noce_get_alt_condition (if_info, target, earliest)
1251 struct noce_if_info *if_info;
1252 rtx target;
1253 rtx *earliest;
1254{
1255 rtx cond, set, insn;
1256 int reverse;
1257
1258 /* If target is already mentioned in the known condition, return it. */
1259 if (reg_mentioned_p (target, if_info->cond))
1260 {
1261 *earliest = if_info->cond_earliest;
1262 return if_info->cond;
1263 }
1264
1265 set = pc_set (if_info->jump);
1266 cond = XEXP (SET_SRC (set), 0);
1267 reverse
1268 = GET_CODE (XEXP (SET_SRC (set), 2)) == LABEL_REF
1269 && XEXP (XEXP (SET_SRC (set), 2), 0) == JUMP_LABEL (if_info->jump);
1270
1271 /* If we're looking for a constant, try to make the conditional
1272 have that constant in it. There are two reasons why it may
1273 not have the constant we want:
1274
1275 1. GCC may have needed to put the constant in a register, because
1276 the target can't compare directly against that constant. For
1277 this case, we look for a SET immediately before the comparison
1278 that puts a constant in that register.
1279
1280 2. GCC may have canonicalized the conditional, for example
1281 replacing "if x < 4" with "if x <= 3". We can undo that (or
1282 make equivalent types of changes) to get the constants we need
1283 if they're off by one in the right direction. */
1284
1285 if (GET_CODE (target) == CONST_INT)
1286 {
1287 enum rtx_code code = GET_CODE (if_info->cond);
1288 rtx op_a = XEXP (if_info->cond, 0);
1289 rtx op_b = XEXP (if_info->cond, 1);
1290 rtx prev_insn;
1291
1292 /* First, look to see if we put a constant in a register. */
1293 prev_insn = PREV_INSN (if_info->cond_earliest);
1294 if (prev_insn
1295 && INSN_P (prev_insn)
1296 && GET_CODE (PATTERN (prev_insn)) == SET)
1297 {
1298 rtx src = find_reg_equal_equiv_note (prev_insn);
1299 if (!src)
1300 src = SET_SRC (PATTERN (prev_insn));
1301 if (GET_CODE (src) == CONST_INT)
1302 {
1303 if (rtx_equal_p (op_a, SET_DEST (PATTERN (prev_insn))))
1304 op_a = src;
1305 else if (rtx_equal_p (op_b, SET_DEST (PATTERN (prev_insn))))
1306 op_b = src;
1307
1308 if (GET_CODE (op_a) == CONST_INT)
1309 {
1310 rtx tmp = op_a;
1311 op_a = op_b;
1312 op_b = tmp;
1313 code = swap_condition (code);
1314 }
1315 }
1316 }
1317
1318 /* Now, look to see if we can get the right constant by
1319 adjusting the conditional. */
1320 if (GET_CODE (op_b) == CONST_INT)
1321 {
1322 HOST_WIDE_INT desired_val = INTVAL (target);
1323 HOST_WIDE_INT actual_val = INTVAL (op_b);
1324
1325 switch (code)
1326 {
1327 case LT:
1328 if (actual_val == desired_val + 1)
1329 {
1330 code = LE;
1331 op_b = GEN_INT (desired_val);
1332 }
1333 break;
1334 case LE:
1335 if (actual_val == desired_val - 1)
1336 {
1337 code = LT;
1338 op_b = GEN_INT (desired_val);
1339 }
1340 break;
1341 case GT:
1342 if (actual_val == desired_val - 1)
1343 {
1344 code = GE;
1345 op_b = GEN_INT (desired_val);
1346 }
1347 break;
1348 case GE:
1349 if (actual_val == desired_val + 1)
1350 {
1351 code = GT;
1352 op_b = GEN_INT (desired_val);
1353 }
1354 break;
1355 default:
1356 break;
1357 }
1358 }
1359
1360 /* If we made any changes, generate a new conditional that is
1361 equivalent to what we started with, but has the right
1362 constants in it. */
1363 if (code != GET_CODE (if_info->cond)
1364 || op_a != XEXP (if_info->cond, 0)
1365 || op_b != XEXP (if_info->cond, 1))
1366 {
1367 cond = gen_rtx_fmt_ee (code, GET_MODE (cond), op_a, op_b);
1368 *earliest = if_info->cond_earliest;
1369 return cond;
1370 }
1371 }
1372
1373 cond = canonicalize_condition (if_info->jump, cond, reverse,
1374 earliest, target);
1375 if (! cond || ! reg_mentioned_p (target, cond))
1376 return NULL;
1377
1378 /* We almost certainly searched back to a different place.
1379 Need to re-verify correct lifetimes. */
1380
1381 /* X may not be mentioned in the range (cond_earliest, jump]. */
1382 for (insn = if_info->jump; insn != *earliest; insn = PREV_INSN (insn))
1383 if (INSN_P (insn) && reg_overlap_mentioned_p (if_info->x, PATTERN (insn)))
1384 return NULL;
1385
1386 /* A and B may not be modified in the range [cond_earliest, jump). */
1387 for (insn = *earliest; insn != if_info->jump; insn = NEXT_INSN (insn))
1388 if (INSN_P (insn)
1389 && (modified_in_p (if_info->a, insn)
1390 || modified_in_p (if_info->b, insn)))
1391 return NULL;
1392
1393 return cond;
1394}
1395
1396/* Convert "if (a < b) x = a; else x = b;" to "x = min(a, b);", etc. */
1397
1398static int
1399noce_try_minmax (if_info)
1400 struct noce_if_info *if_info;
1401{
1402 rtx cond, earliest, target, seq;
1403 enum rtx_code code, op;
1404 int unsignedp;
1405
1406 /* ??? Can't guarantee that expand_binop won't create pseudos. */
1407 if (no_new_pseudos)
1408 return FALSE;
1409
1410 /* ??? Reject modes with NaNs or signed zeros since we don't know how
1411 they will be resolved with an SMIN/SMAX. It wouldn't be too hard
1412 to get the target to tell us... */
1413 if (HONOR_SIGNED_ZEROS (GET_MODE (if_info->x))
1414 || HONOR_NANS (GET_MODE (if_info->x)))
1415 return FALSE;
1416
1417 cond = noce_get_alt_condition (if_info, if_info->a, &earliest);
1418 if (!cond)
1419 return FALSE;
1420
1421 /* Verify the condition is of the form we expect, and canonicalize
1422 the comparison code. */
1423 code = GET_CODE (cond);
1424 if (rtx_equal_p (XEXP (cond, 0), if_info->a))
1425 {
1426 if (! rtx_equal_p (XEXP (cond, 1), if_info->b))
1427 return FALSE;
1428 }
1429 else if (rtx_equal_p (XEXP (cond, 1), if_info->a))
1430 {
1431 if (! rtx_equal_p (XEXP (cond, 0), if_info->b))
1432 return FALSE;
1433 code = swap_condition (code);
1434 }
1435 else
1436 return FALSE;
1437
1438 /* Determine what sort of operation this is. Note that the code is for
1439 a taken branch, so the code->operation mapping appears backwards. */
1440 switch (code)
1441 {
1442 case LT:
1443 case LE:
1444 case UNLT:
1445 case UNLE:
1446 op = SMAX;
1447 unsignedp = 0;
1448 break;
1449 case GT:
1450 case GE:
1451 case UNGT:
1452 case UNGE:
1453 op = SMIN;
1454 unsignedp = 0;
1455 break;
1456 case LTU:
1457 case LEU:
1458 op = UMAX;
1459 unsignedp = 1;
1460 break;
1461 case GTU:
1462 case GEU:
1463 op = UMIN;
1464 unsignedp = 1;
1465 break;
1466 default:
1467 return FALSE;
1468 }
1469
1470 start_sequence ();
1471
1472 target = expand_simple_binop (GET_MODE (if_info->x), op,
1473 if_info->a, if_info->b,
1474 if_info->x, unsignedp, OPTAB_WIDEN);
1475 if (! target)
1476 {
1477 end_sequence ();
1478 return FALSE;
1479 }
1480 if (target != if_info->x)
1481 noce_emit_move_insn (if_info->x, target);
1482
1483 seq = get_insns ();
1484 end_sequence ();
1485
1486 if (seq_contains_jump (seq))
1487 return FALSE;
1488
1489 emit_insn_before_scope (seq, if_info->jump, INSN_SCOPE (if_info->insn_a));
1490 if_info->cond = cond;
1491 if_info->cond_earliest = earliest;
1492
1493 return TRUE;
1494}
1495
1496/* Convert "if (a < 0) x = -a; else x = a;" to "x = abs(a);", etc. */
1497
1498static int
1499noce_try_abs (if_info)
1500 struct noce_if_info *if_info;
1501{
1502 rtx cond, earliest, target, seq, a, b, c;
1503 int negate;
1504
1505 /* ??? Can't guarantee that expand_binop won't create pseudos. */
1506 if (no_new_pseudos)
1507 return FALSE;
1508
1509 /* Recognize A and B as constituting an ABS or NABS. */
1510 a = if_info->a;
1511 b = if_info->b;
1512 if (GET_CODE (a) == NEG && rtx_equal_p (XEXP (a, 0), b))
1513 negate = 0;
1514 else if (GET_CODE (b) == NEG && rtx_equal_p (XEXP (b, 0), a))
1515 {
1516 c = a; a = b; b = c;
1517 negate = 1;
1518 }
1519 else
1520 return FALSE;
1521
1522 cond = noce_get_alt_condition (if_info, b, &earliest);
1523 if (!cond)
1524 return FALSE;
1525
1526 /* Verify the condition is of the form we expect. */
1527 if (rtx_equal_p (XEXP (cond, 0), b))
1528 c = XEXP (cond, 1);
1529 else if (rtx_equal_p (XEXP (cond, 1), b))
1530 c = XEXP (cond, 0);
1531 else
1532 return FALSE;
1533
1534 /* Verify that C is zero. Search backward through the block for
1535 a REG_EQUAL note if necessary. */
1536 if (REG_P (c))
1537 {
1538 rtx insn, note = NULL;
1539 for (insn = earliest;
1540 insn != if_info->test_bb->head;
1541 insn = PREV_INSN (insn))
1542 if (INSN_P (insn)
1543 && ((note = find_reg_note (insn, REG_EQUAL, c))
1544 || (note = find_reg_note (insn, REG_EQUIV, c))))
1545 break;
1546 if (! note)
1547 return FALSE;
1548 c = XEXP (note, 0);
1549 }
1550 if (GET_CODE (c) == MEM
1551 && GET_CODE (XEXP (c, 0)) == SYMBOL_REF
1552 && CONSTANT_POOL_ADDRESS_P (XEXP (c, 0)))
1553 c = get_pool_constant (XEXP (c, 0));
1554
1555 /* Work around funny ideas get_condition has wrt canonicalization.
1556 Note that these rtx constants are known to be CONST_INT, and
1557 therefore imply integer comparisons. */
1558 if (c == constm1_rtx && GET_CODE (cond) == GT)
1559 ;
1560 else if (c == const1_rtx && GET_CODE (cond) == LT)
1561 ;
1562 else if (c != CONST0_RTX (GET_MODE (b)))
1563 return FALSE;
1564
1565 /* Determine what sort of operation this is. */
1566 switch (GET_CODE (cond))
1567 {
1568 case LT:
1569 case LE:
1570 case UNLT:
1571 case UNLE:
1572 negate = !negate;
1573 break;
1574 case GT:
1575 case GE:
1576 case UNGT:
1577 case UNGE:
1578 break;
1579 default:
1580 return FALSE;
1581 }
1582
1583 start_sequence ();
1584
1585 target = expand_simple_unop (GET_MODE (if_info->x), ABS, b, if_info->x, 0);
1586
1587 /* ??? It's a quandry whether cmove would be better here, especially
1588 for integers. Perhaps combine will clean things up. */
1589 if (target && negate)
1590 target = expand_simple_unop (GET_MODE (target), NEG, target, if_info->x, 0);
1591
1592 if (! target)
1593 {
1594 end_sequence ();
1595 return FALSE;
1596 }
1597
1598 if (target != if_info->x)
1599 noce_emit_move_insn (if_info->x, target);
1600
1601 seq = get_insns ();
1602 end_sequence ();
1603
1604 if (seq_contains_jump (seq))
1605 return FALSE;
1606
1607 emit_insn_before_scope (seq, if_info->jump, INSN_SCOPE (if_info->insn_a));
1608 if_info->cond = cond;
1609 if_info->cond_earliest = earliest;
1610
1611 return TRUE;
1612}
1613
1614/* Similar to get_condition, only the resulting condition must be
1615 valid at JUMP, instead of at EARLIEST. */
1616
1617static rtx
1618noce_get_condition (jump, earliest)
1619 rtx jump;
1620 rtx *earliest;
1621{
1622 rtx cond, set, tmp, insn;
1623 bool reverse;
1624
1625 if (! any_condjump_p (jump))
1626 return NULL_RTX;
1627
1628 set = pc_set (jump);
1629
1630 /* If this branches to JUMP_LABEL when the condition is false,
1631 reverse the condition. */
1632 reverse = (GET_CODE (XEXP (SET_SRC (set), 2)) == LABEL_REF
1633 && XEXP (XEXP (SET_SRC (set), 2), 0) == JUMP_LABEL (jump));
1634
1635 /* If the condition variable is a register and is MODE_INT, accept it. */
1636
1637 cond = XEXP (SET_SRC (set), 0);
1638 tmp = XEXP (cond, 0);
1639 if (REG_P (tmp) && GET_MODE_CLASS (GET_MODE (tmp)) == MODE_INT)
1640 {
1641 *earliest = jump;
1642
1643 if (reverse)
1644 cond = gen_rtx_fmt_ee (reverse_condition (GET_CODE (cond)),
1645 GET_MODE (cond), tmp, XEXP (cond, 1));
1646 return cond;
1647 }
1648
1649 /* Otherwise, fall back on canonicalize_condition to do the dirty
1650 work of manipulating MODE_CC values and COMPARE rtx codes. */
1651
1652 tmp = canonicalize_condition (jump, cond, reverse, earliest, NULL_RTX);
1653 if (!tmp)
1654 return NULL_RTX;
1655
1656 /* We are going to insert code before JUMP, not before EARLIEST.
1657 We must therefore be certain that the given condition is valid
1658 at JUMP by virtue of not having been modified since. */
1659 for (insn = *earliest; insn != jump; insn = NEXT_INSN (insn))
1660 if (INSN_P (insn) && modified_in_p (tmp, insn))
1661 break;
1662 if (insn == jump)
1663 return tmp;
1664
1665 /* The condition was modified. See if we can get a partial result
1666 that doesn't follow all the reversals. Perhaps combine can fold
1667 them together later. */
1668 tmp = XEXP (tmp, 0);
1669 if (!REG_P (tmp) || GET_MODE_CLASS (GET_MODE (tmp)) != MODE_INT)
1670 return NULL_RTX;
1671 tmp = canonicalize_condition (jump, cond, reverse, earliest, tmp);
1672 if (!tmp)
1673 return NULL_RTX;
1674
1675 /* For sanity's sake, re-validate the new result. */
1676 for (insn = *earliest; insn != jump; insn = NEXT_INSN (insn))
1677 if (INSN_P (insn) && modified_in_p (tmp, insn))
1678 return NULL_RTX;
1679
1680 return tmp;
1681}
1682
1683/* Return true if OP is ok for if-then-else processing. */
1684
1685static int
1686noce_operand_ok (op)
1687 rtx op;
1688{
1689 /* We special-case memories, so handle any of them with
1690 no address side effects. */
1691 if (GET_CODE (op) == MEM)
1692 return ! side_effects_p (XEXP (op, 0));
1693
1694 if (side_effects_p (op))
1695 return FALSE;
1696
1697 return ! may_trap_p (op);
1698}
1699
1700/* Given a simple IF-THEN or IF-THEN-ELSE block, attempt to convert it
1701 without using conditional execution. Return TRUE if we were
1702 successful at converting the block. */
1703
1704static int
1705noce_process_if_block (ce_info)
1706 struct ce_if_block * ce_info;
1707{
1708 basic_block test_bb = ce_info->test_bb; /* test block */
1709 basic_block then_bb = ce_info->then_bb; /* THEN */
1710 basic_block else_bb = ce_info->else_bb; /* ELSE or NULL */
1711 struct noce_if_info if_info;
1712 rtx insn_a, insn_b;
1713 rtx set_a, set_b;
1714 rtx orig_x, x, a, b;
1715 rtx jump, cond;
1716
1717 /* We're looking for patterns of the form
1718
1719 (1) if (...) x = a; else x = b;
1720 (2) x = b; if (...) x = a;
1721 (3) if (...) x = a; // as if with an initial x = x.
1722
1723 The later patterns require jumps to be more expensive.
1724
1725 ??? For future expansion, look for multiple X in such patterns. */
1726
1727 /* If test is comprised of && or || elements, don't handle it unless it is
1728 the special case of && elements without an ELSE block. */
1729 if (ce_info->num_multiple_test_blocks)
1730 {
1731 if (else_bb || ! ce_info->and_and_p)
1732 return FALSE;
1733
1734 ce_info->test_bb = test_bb = ce_info->last_test_bb;
1735 ce_info->num_multiple_test_blocks = 0;
1736 ce_info->num_and_and_blocks = 0;
1737 ce_info->num_or_or_blocks = 0;
1738 }
1739
1740 /* If this is not a standard conditional jump, we can't parse it. */
1741 jump = test_bb->end;
1742 cond = noce_get_condition (jump, &if_info.cond_earliest);
1743 if (! cond)
1744 return FALSE;
1745
1746 /* If the conditional jump is more than just a conditional
1747 jump, then we can not do if-conversion on this block. */
1748 if (! onlyjump_p (jump))
1749 return FALSE;
1750
1751 /* We must be comparing objects whose modes imply the size. */
1752 if (GET_MODE (XEXP (cond, 0)) == BLKmode)
1753 return FALSE;
1754
1755 /* Look for one of the potential sets. */
1756 insn_a = first_active_insn (then_bb);
1757 if (! insn_a
1758 || insn_a != last_active_insn (then_bb, FALSE)
1759 || (set_a = single_set (insn_a)) == NULL_RTX)
1760 return FALSE;
1761
1762 x = SET_DEST (set_a);
1763 a = SET_SRC (set_a);
1764
1765 /* Look for the other potential set. Make sure we've got equivalent
1766 destinations. */
1767 /* ??? This is overconservative. Storing to two different mems is
1768 as easy as conditionally computing the address. Storing to a
1769 single mem merely requires a scratch memory to use as one of the
1770 destination addresses; often the memory immediately below the
1771 stack pointer is available for this. */
1772 set_b = NULL_RTX;
1773 if (else_bb)
1774 {
1775 insn_b = first_active_insn (else_bb);
1776 if (! insn_b
1777 || insn_b != last_active_insn (else_bb, FALSE)
1778 || (set_b = single_set (insn_b)) == NULL_RTX
1779 || ! rtx_equal_p (x, SET_DEST (set_b)))
1780 return FALSE;
1781 }
1782 else
1783 {
1784 insn_b = prev_nonnote_insn (if_info.cond_earliest);
1785 /* We're going to be moving the evaluation of B down from above
1786 COND_EARLIEST to JUMP. Make sure the relevant data is still
1787 intact. */
1788 if (! insn_b
1789 || GET_CODE (insn_b) != INSN
1790 || (set_b = single_set (insn_b)) == NULL_RTX
1791 || ! rtx_equal_p (x, SET_DEST (set_b))
1792 || reg_overlap_mentioned_p (x, SET_SRC (set_b))
1793 || modified_between_p (SET_SRC (set_b),
1794 PREV_INSN (if_info.cond_earliest), jump)
1795 /* Likewise with X. In particular this can happen when
1796 noce_get_condition looks farther back in the instruction
1797 stream than one might expect. */
1798 || reg_overlap_mentioned_p (x, cond)
1799 || reg_overlap_mentioned_p (x, a)
1800 || modified_between_p (x, PREV_INSN (if_info.cond_earliest), jump))
1801 insn_b = set_b = NULL_RTX;
1802 }
1803
1804 /* If x has side effects then only the if-then-else form is safe to
1805 convert. But even in that case we would need to restore any notes
1806 (such as REG_INC) at then end. That can be tricky if
1807 noce_emit_move_insn expands to more than one insn, so disable the
1808 optimization entirely for now if there are side effects. */
1809 if (side_effects_p (x))
1810 return FALSE;
1811
1812 b = (set_b ? SET_SRC (set_b) : x);
1813
1814 /* Only operate on register destinations, and even then avoid extending
1815 the lifetime of hard registers on small register class machines. */
1816 orig_x = x;
1817 if (GET_CODE (x) != REG
1818 || (SMALL_REGISTER_CLASSES
1819 && REGNO (x) < FIRST_PSEUDO_REGISTER))
1820 {
1821 if (no_new_pseudos)
1822 return FALSE;
1823 x = gen_reg_rtx (GET_MODE (GET_CODE (x) == STRICT_LOW_PART
1824 ? XEXP (x, 0) : x));
1825 }
1826
1827 /* Don't operate on sources that may trap or are volatile. */
1828 if (! noce_operand_ok (a) || ! noce_operand_ok (b))
1829 return FALSE;
1830
1831 /* Set up the info block for our subroutines. */
1832 if_info.test_bb = test_bb;
1833 if_info.cond = cond;
1834 if_info.jump = jump;
1835 if_info.insn_a = insn_a;
1836 if_info.insn_b = insn_b;
1837 if_info.x = x;
1838 if_info.a = a;
1839 if_info.b = b;
1840
1841 /* Try optimizations in some approximation of a useful order. */
1842 /* ??? Should first look to see if X is live incoming at all. If it
1843 isn't, we don't need anything but an unconditional set. */
1844
1845 /* Look and see if A and B are really the same. Avoid creating silly
1846 cmove constructs that no one will fix up later. */
1847 if (rtx_equal_p (a, b))
1848 {
1849 /* If we have an INSN_B, we don't have to create any new rtl. Just
1850 move the instruction that we already have. If we don't have an
1851 INSN_B, that means that A == X, and we've got a noop move. In
1852 that case don't do anything and let the code below delete INSN_A. */
1853 if (insn_b && else_bb)
1854 {
1855 rtx note;
1856
1857 if (else_bb && insn_b == else_bb->end)
1858 else_bb->end = PREV_INSN (insn_b);
1859 reorder_insns (insn_b, insn_b, PREV_INSN (jump));
1860
1861 /* If there was a REG_EQUAL note, delete it since it may have been
1862 true due to this insn being after a jump. */
1863 if ((note = find_reg_note (insn_b, REG_EQUAL, NULL_RTX)) != 0)
1864 remove_note (insn_b, note);
1865
1866 insn_b = NULL_RTX;
1867 }
1868 /* If we have "x = b; if (...) x = a;", and x has side-effects, then
1869 x must be executed twice. */
1870 else if (insn_b && side_effects_p (orig_x))
1871 return FALSE;
1872
1873 x = orig_x;
1874 goto success;
1875 }
1876
1877 /* Disallow the "if (...) x = a;" form (with an implicit "else x = x;")
1878 for most optimizations if writing to x may trap, i.e. its a memory
1879 other than a static var or a stack slot. */
1880 if (! set_b
1881 && GET_CODE (orig_x) == MEM
1882 && ! MEM_NOTRAP_P (orig_x)
1883 && rtx_addr_can_trap_p (XEXP (orig_x, 0)))
1884 {
1885 if (HAVE_conditional_move)
1886 {
1887 if (noce_try_cmove (&if_info))
1888 goto success;
1889 if (! HAVE_conditional_execution
1890 && noce_try_cmove_arith (&if_info))
1891 goto success;
1892 }
1893 return FALSE;
1894 }
1895
1896 if (noce_try_store_flag (&if_info))
1897 goto success;
1898 if (noce_try_minmax (&if_info))
1899 goto success;
1900 if (noce_try_abs (&if_info))
1901 goto success;
1902 if (HAVE_conditional_move
1903 && noce_try_cmove (&if_info))
1904 goto success;
1905 if (! HAVE_conditional_execution)
1906 {
1907 if (noce_try_store_flag_constants (&if_info))
1908 goto success;
1909 if (noce_try_store_flag_inc (&if_info))
1910 goto success;
1911 if (noce_try_store_flag_mask (&if_info))
1912 goto success;
1913 if (HAVE_conditional_move
1914 && noce_try_cmove_arith (&if_info))
1915 goto success;
1916 }
1917
1918 return FALSE;
1919
1920 success:
1921 /* The original sets may now be killed. */
1922 delete_insn (insn_a);
1923
1924 /* Several special cases here: First, we may have reused insn_b above,
1925 in which case insn_b is now NULL. Second, we want to delete insn_b
1926 if it came from the ELSE block, because follows the now correct
1927 write that appears in the TEST block. However, if we got insn_b from
1928 the TEST block, it may in fact be loading data needed for the comparison.
1929 We'll let life_analysis remove the insn if it's really dead. */
1930 if (insn_b && else_bb)
1931 delete_insn (insn_b);
1932
1933 /* The new insns will have been inserted immediately before the jump. We
1934 should be able to remove the jump with impunity, but the condition itself
1935 may have been modified by gcse to be shared across basic blocks. */
1936 delete_insn (jump);
1937
1938 /* If we used a temporary, fix it up now. */
1939 if (orig_x != x)
1940 {
1941 start_sequence ();
1942 noce_emit_move_insn (copy_rtx (orig_x), x);
1943 insn_b = get_insns ();
1944 end_sequence ();
1945
1946 emit_insn_after_scope (insn_b, test_bb->end, INSN_SCOPE (insn_a));
1947 }
1948
1949 /* Merge the blocks! */
1950 merge_if_block (ce_info);
1951
1952 return TRUE;
1953}
1954
1955
1956/* Attempt to convert an IF-THEN or IF-THEN-ELSE block into
1957 straight line code. Return true if successful. */
1958
1959static int
1960process_if_block (ce_info)
1961 struct ce_if_block * ce_info;
1962{
1963 if (! reload_completed
1964 && noce_process_if_block (ce_info))
1965 return TRUE;
1966
1967 if (HAVE_conditional_execution && reload_completed)
1968 {
1969 /* If we have && and || tests, try to first handle combining the && and
1970 || tests into the conditional code, and if that fails, go back and
1971 handle it without the && and ||, which at present handles the && case
1972 if there was no ELSE block. */
1973 if (cond_exec_process_if_block (ce_info, TRUE))
1974 return TRUE;
1975
1976 if (ce_info->num_multiple_test_blocks)
1977 {
1978 cancel_changes (0);
1979
1980 if (cond_exec_process_if_block (ce_info, FALSE))
1981 return TRUE;
1982 }
1983 }
1984
1985 return FALSE;
1986}
1987
1988/* Merge the blocks and mark for local life update. */
1989
1990static void
1991merge_if_block (ce_info)
1992 struct ce_if_block * ce_info;
1993{
1994 basic_block test_bb = ce_info->test_bb; /* last test block */
1995 basic_block then_bb = ce_info->then_bb; /* THEN */
1996 basic_block else_bb = ce_info->else_bb; /* ELSE or NULL */
1997 basic_block join_bb = ce_info->join_bb; /* join block */
1998 basic_block combo_bb;
1999
2000 /* All block merging is done into the lower block numbers. */
2001
2002 combo_bb = test_bb;
2003
2004 /* Merge any basic blocks to handle && and || subtests. Each of
2005 the blocks are on the fallthru path from the predecessor block. */
2006 if (ce_info->num_multiple_test_blocks > 0)
2007 {
2008 basic_block bb = test_bb;
2009 basic_block last_test_bb = ce_info->last_test_bb;
2010 basic_block fallthru = block_fallthru (bb);
2011
2012 do
2013 {
2014 bb = fallthru;
2015 fallthru = block_fallthru (bb);
2016 if (post_dominators)
2017 delete_from_dominance_info (post_dominators, bb);
2018 merge_blocks_nomove (combo_bb, bb);
2019 num_removed_blocks++;
2020 }
2021 while (bb != last_test_bb);
2022 }
2023
2024 /* Merge TEST block into THEN block. Normally the THEN block won't have a
2025 label, but it might if there were || tests. That label's count should be
2026 zero, and it normally should be removed. */
2027
2028 if (then_bb)
2029 {
2030 if (combo_bb->global_live_at_end)
2031 COPY_REG_SET (combo_bb->global_live_at_end,
2032 then_bb->global_live_at_end);
2033 if (post_dominators)
2034 delete_from_dominance_info (post_dominators, then_bb);
2035 merge_blocks_nomove (combo_bb, then_bb);
2036 num_removed_blocks++;
2037 }
2038
2039 /* The ELSE block, if it existed, had a label. That label count
2040 will almost always be zero, but odd things can happen when labels
2041 get their addresses taken. */
2042 if (else_bb)
2043 {
2044 if (post_dominators)
2045 delete_from_dominance_info (post_dominators, else_bb);
2046 merge_blocks_nomove (combo_bb, else_bb);
2047 num_removed_blocks++;
2048 }
2049
2050 /* If there was no join block reported, that means it was not adjacent
2051 to the others, and so we cannot merge them. */
2052
2053 if (! join_bb)
2054 {
2055 rtx last = combo_bb->end;
2056
2057 /* The outgoing edge for the current COMBO block should already
2058 be correct. Verify this. */
2059 if (combo_bb->succ == NULL_EDGE)
2060 {
2061 if (find_reg_note (last, REG_NORETURN, NULL))
2062 ;
2063 else if (GET_CODE (last) == INSN
2064 && GET_CODE (PATTERN (last)) == TRAP_IF
2065 && TRAP_CONDITION (PATTERN (last)) == const_true_rtx)
2066 ;
2067 else
2068 abort ();
2069 }
2070
2071 /* There should still be something at the end of the THEN or ELSE
2072 blocks taking us to our final destination. */
2073 else if (GET_CODE (last) == JUMP_INSN)
2074 ;
2075 else if (combo_bb->succ->dest == EXIT_BLOCK_PTR
2076 && GET_CODE (last) == CALL_INSN
2077 && SIBLING_CALL_P (last))
2078 ;
2079 else if ((combo_bb->succ->flags & EDGE_EH)
2080 && can_throw_internal (last))
2081 ;
2082 else
2083 abort ();
2084 }
2085
2086 /* The JOIN block may have had quite a number of other predecessors too.
2087 Since we've already merged the TEST, THEN and ELSE blocks, we should
2088 have only one remaining edge from our if-then-else diamond. If there
2089 is more than one remaining edge, it must come from elsewhere. There
2090 may be zero incoming edges if the THEN block didn't actually join
2091 back up (as with a call to abort). */
2092 else if ((join_bb->pred == NULL
2093 || join_bb->pred->pred_next == NULL)
2094 && join_bb != EXIT_BLOCK_PTR)
2095 {
2096 /* We can merge the JOIN. */
2097 if (combo_bb->global_live_at_end)
2098 COPY_REG_SET (combo_bb->global_live_at_end,
2099 join_bb->global_live_at_end);
2100
2101 if (post_dominators)
2102 delete_from_dominance_info (post_dominators, join_bb);
2103 merge_blocks_nomove (combo_bb, join_bb);
2104 num_removed_blocks++;
2105 }
2106 else
2107 {
2108 /* We cannot merge the JOIN. */
2109
2110 /* The outgoing edge for the current COMBO block should already
2111 be correct. Verify this. */
2112 if (combo_bb->succ->succ_next != NULL_EDGE
2113 || combo_bb->succ->dest != join_bb)
2114 abort ();
2115
2116 /* Remove the jump and cruft from the end of the COMBO block. */
2117 if (join_bb != EXIT_BLOCK_PTR)
2118 tidy_fallthru_edge (combo_bb->succ, combo_bb, join_bb);
2119 }
2120
2121 num_updated_if_blocks++;
2122}
2123
2124
2125/* Find a block ending in a simple IF condition and try to transform it
2126 in some way. When converting a multi-block condition, put the new code
2127 in the first such block and delete the rest. Return a pointer to this
2128 first block if some transformation was done. Return NULL otherwise. */
2129
2130static basic_block
2131find_if_header (test_bb, pass)
2132 basic_block test_bb;
2133 int pass;
2134{
2135 ce_if_block_t ce_info;
2136 edge then_edge;
2137 edge else_edge;
2138
2139 /* The kind of block we're looking for has exactly two successors. */
2140 if ((then_edge = test_bb->succ) == NULL_EDGE
2141 || (else_edge = then_edge->succ_next) == NULL_EDGE
2142 || else_edge->succ_next != NULL_EDGE)
2143 return NULL;
2144
2145 /* Neither edge should be abnormal. */
2146 if ((then_edge->flags & EDGE_COMPLEX)
2147 || (else_edge->flags & EDGE_COMPLEX))
2148 return NULL;
2149
2150 /* The THEN edge is canonically the one that falls through. */
2151 if (then_edge->flags & EDGE_FALLTHRU)
2152 ;
2153 else if (else_edge->flags & EDGE_FALLTHRU)
2154 {
2155 edge e = else_edge;
2156 else_edge = then_edge;
2157 then_edge = e;
2158 }
2159 else
2160 /* Otherwise this must be a multiway branch of some sort. */
2161 return NULL;
2162
2163 memset ((PTR) &ce_info, '\0', sizeof (ce_info));
2164 ce_info.test_bb = test_bb;
2165 ce_info.then_bb = then_edge->dest;
2166 ce_info.else_bb = else_edge->dest;
2167 ce_info.pass = pass;
2168
2169#ifdef IFCVT_INIT_EXTRA_FIELDS
2170 IFCVT_INIT_EXTRA_FIELDS (&ce_info);
2171#endif
2172
2173 if (find_if_block (&ce_info))
2174 goto success;
2175
2176 if (HAVE_trap && HAVE_conditional_trap
2177 && find_cond_trap (test_bb, then_edge, else_edge))
2178 goto success;
2179
2180 if (post_dominators
2181 && (! HAVE_conditional_execution || reload_completed))
2182 {
2183 if (find_if_case_1 (test_bb, then_edge, else_edge))
2184 goto success;
2185 if (find_if_case_2 (test_bb, then_edge, else_edge))
2186 goto success;
2187 }
2188
2189 return NULL;
2190
2191 success:
2192 if (rtl_dump_file)
2193 fprintf (rtl_dump_file, "Conversion succeeded on pass %d.\n", pass);
2194 return ce_info.test_bb;
2195}
2196
2197/* Return true if a block has two edges, one of which falls through to the next
2198 block, and the other jumps to a specific block, so that we can tell if the
2199 block is part of an && test or an || test. Returns either -1 or the number
2200 of non-note, non-jump, non-USE/CLOBBER insns in the block. */
2201
2202static int
2203block_jumps_and_fallthru_p (cur_bb, target_bb)
2204 basic_block cur_bb;
2205 basic_block target_bb;
2206{
2207 edge cur_edge;
2208 int fallthru_p = FALSE;
2209 int jump_p = FALSE;
2210 rtx insn;
2211 rtx end;
2212 int n_insns = 0;
2213
2214 if (!cur_bb || !target_bb)
2215 return -1;
2216
2217 /* If no edges, obviously it doesn't jump or fallthru. */
2218 if (cur_bb->succ == NULL_EDGE)
2219 return FALSE;
2220
2221 for (cur_edge = cur_bb->succ;
2222 cur_edge != NULL_EDGE;
2223 cur_edge = cur_edge->succ_next)
2224 {
2225 if (cur_edge->flags & EDGE_COMPLEX)
2226 /* Anything complex isn't what we want. */
2227 return -1;
2228
2229 else if (cur_edge->flags & EDGE_FALLTHRU)
2230 fallthru_p = TRUE;
2231
2232 else if (cur_edge->dest == target_bb)
2233 jump_p = TRUE;
2234
2235 else
2236 return -1;
2237 }
2238
2239 if ((jump_p & fallthru_p) == 0)
2240 return -1;
2241
2242 /* Don't allow calls in the block, since this is used to group && and ||
2243 together for conditional execution support. ??? we should support
2244 conditional execution support across calls for IA-64 some day, but
2245 for now it makes the code simpler. */
2246 end = cur_bb->end;
2247 insn = cur_bb->head;
2248
2249 while (insn != NULL_RTX)
2250 {
2251 if (GET_CODE (insn) == CALL_INSN)
2252 return -1;
2253
2254 if (INSN_P (insn)
2255 && GET_CODE (insn) != JUMP_INSN
2256 && GET_CODE (PATTERN (insn)) != USE
2257 && GET_CODE (PATTERN (insn)) != CLOBBER)
2258 n_insns++;
2259
2260 if (insn == end)
2261 break;
2262
2263 insn = NEXT_INSN (insn);
2264 }
2265
2266 return n_insns;
2267}
2268
2269/* Determine if a given basic block heads a simple IF-THEN or IF-THEN-ELSE
2270 block. If so, we'll try to convert the insns to not require the branch.
2271 Return TRUE if we were successful at converting the block. */
2272
2273static int
2274find_if_block (ce_info)
2275 struct ce_if_block * ce_info;
2276{
2277 basic_block test_bb = ce_info->test_bb;
2278 basic_block then_bb = ce_info->then_bb;
2279 basic_block else_bb = ce_info->else_bb;
2280 basic_block join_bb = NULL_BLOCK;
2281 edge then_succ = then_bb->succ;
2282 edge else_succ = else_bb->succ;
2283 int then_predecessors;
2284 int else_predecessors;
2285 edge cur_edge;
2286 basic_block next;
2287
2288 ce_info->last_test_bb = test_bb;
2289
2290 /* Discover if any fall through predecessors of the current test basic block
2291 were && tests (which jump to the else block) or || tests (which jump to
2292 the then block). */
2293 if (HAVE_conditional_execution && reload_completed
2294 && test_bb->pred != NULL_EDGE
2295 && test_bb->pred->pred_next == NULL_EDGE
2296 && test_bb->pred->flags == EDGE_FALLTHRU)
2297 {
2298 basic_block bb = test_bb->pred->src;
2299 basic_block target_bb;
2300 int max_insns = MAX_CONDITIONAL_EXECUTE;
2301 int n_insns;
2302
2303 /* Determine if the preceeding block is an && or || block. */
2304 if ((n_insns = block_jumps_and_fallthru_p (bb, else_bb)) >= 0)
2305 {
2306 ce_info->and_and_p = TRUE;
2307 target_bb = else_bb;
2308 }
2309 else if ((n_insns = block_jumps_and_fallthru_p (bb, then_bb)) >= 0)
2310 {
2311 ce_info->and_and_p = FALSE;
2312 target_bb = then_bb;
2313 }
2314 else
2315 target_bb = NULL_BLOCK;
2316
2317 if (target_bb && n_insns <= max_insns)
2318 {
2319 int total_insns = 0;
2320 int blocks = 0;
2321
2322 ce_info->last_test_bb = test_bb;
2323
2324 /* Found at least one && or || block, look for more. */
2325 do
2326 {
2327 ce_info->test_bb = test_bb = bb;
2328 total_insns += n_insns;
2329 blocks++;
2330
2331 if (bb->pred == NULL_EDGE || bb->pred->pred_next != NULL_EDGE)
2332 break;
2333
2334 bb = bb->pred->src;
2335 n_insns = block_jumps_and_fallthru_p (bb, target_bb);
2336 }
2337 while (n_insns >= 0 && (total_insns + n_insns) <= max_insns);
2338
2339 ce_info->num_multiple_test_blocks = blocks;
2340 ce_info->num_multiple_test_insns = total_insns;
2341
2342 if (ce_info->and_and_p)
2343 ce_info->num_and_and_blocks = blocks;
2344 else
2345 ce_info->num_or_or_blocks = blocks;
2346 }
2347 }
2348
2349 /* Count the number of edges the THEN and ELSE blocks have. */
2350 then_predecessors = 0;
2351 for (cur_edge = then_bb->pred;
2352 cur_edge != NULL_EDGE;
2353 cur_edge = cur_edge->pred_next)
2354 {
2355 then_predecessors++;
2356 if (cur_edge->flags & EDGE_COMPLEX)
2357 return FALSE;
2358 }
2359
2360 else_predecessors = 0;
2361 for (cur_edge = else_bb->pred;
2362 cur_edge != NULL_EDGE;
2363 cur_edge = cur_edge->pred_next)
2364 {
2365 else_predecessors++;
2366 if (cur_edge->flags & EDGE_COMPLEX)
2367 return FALSE;
2368 }
2369
2370 /* The THEN block of an IF-THEN combo must have exactly one predecessor,
2371 other than any || blocks which jump to the THEN block. */
2372 if ((then_predecessors - ce_info->num_or_or_blocks) != 1)
2373 return FALSE;
2374
2375 /* The THEN block of an IF-THEN combo must have zero or one successors. */
2376 if (then_succ != NULL_EDGE
2377 && (then_succ->succ_next != NULL_EDGE
2378 || (then_succ->flags & EDGE_COMPLEX)
2379 || (flow2_completed && tablejump_p (then_bb->end))))
2380 return FALSE;
2381
2382 /* If the THEN block has no successors, conditional execution can still
2383 make a conditional call. Don't do this unless the ELSE block has
2384 only one incoming edge -- the CFG manipulation is too ugly otherwise.
2385 Check for the last insn of the THEN block being an indirect jump, which
2386 is listed as not having any successors, but confuses the rest of the CE
2387 code processing. ??? we should fix this in the future. */
2388 if (then_succ == NULL)
2389 {
2390 if (else_bb->pred->pred_next == NULL_EDGE)
2391 {
2392 rtx last_insn = then_bb->end;
2393
2394 while (last_insn
2395 && GET_CODE (last_insn) == NOTE
2396 && last_insn != then_bb->head)
2397 last_insn = PREV_INSN (last_insn);
2398
2399 if (last_insn
2400 && GET_CODE (last_insn) == JUMP_INSN
2401 && ! simplejump_p (last_insn))
2402 return FALSE;
2403
2404 join_bb = else_bb;
2405 else_bb = NULL_BLOCK;
2406 }
2407 else
2408 return FALSE;
2409 }
2410
2411 /* If the THEN block's successor is the other edge out of the TEST block,
2412 then we have an IF-THEN combo without an ELSE. */
2413 else if (then_succ->dest == else_bb)
2414 {
2415 join_bb = else_bb;
2416 else_bb = NULL_BLOCK;
2417 }
2418
2419 /* If the THEN and ELSE block meet in a subsequent block, and the ELSE
2420 has exactly one predecessor and one successor, and the outgoing edge
2421 is not complex, then we have an IF-THEN-ELSE combo. */
2422 else if (else_succ != NULL_EDGE
2423 && then_succ->dest == else_succ->dest
2424 && else_bb->pred->pred_next == NULL_EDGE
2425 && else_succ->succ_next == NULL_EDGE
2426 && ! (else_succ->flags & EDGE_COMPLEX)
2427 && ! (flow2_completed && tablejump_p (else_bb->end)))
2428 join_bb = else_succ->dest;
2429
2430 /* Otherwise it is not an IF-THEN or IF-THEN-ELSE combination. */
2431 else
2432 return FALSE;
2433
2434 num_possible_if_blocks++;
2435
2436 if (rtl_dump_file)
2437 {
2438 fprintf (rtl_dump_file, "\nIF-THEN%s block found, pass %d, start block %d [insn %d], then %d [%d]",
2439 (else_bb) ? "-ELSE" : "",
2440 ce_info->pass,
2441 test_bb->index, (test_bb->head) ? (int)INSN_UID (test_bb->head) : -1,
2442 then_bb->index, (then_bb->head) ? (int)INSN_UID (then_bb->head) : -1);
2443
2444 if (else_bb)
2445 fprintf (rtl_dump_file, ", else %d [%d]",
2446 else_bb->index, (else_bb->head) ? (int)INSN_UID (else_bb->head) : -1);
2447
2448 fprintf (rtl_dump_file, ", join %d [%d]",
2449 join_bb->index, (join_bb->head) ? (int)INSN_UID (join_bb->head) : -1);
2450
2451 if (ce_info->num_multiple_test_blocks > 0)
2452 fprintf (rtl_dump_file, ", %d %s block%s last test %d [%d]",
2453 ce_info->num_multiple_test_blocks,
2454 (ce_info->and_and_p) ? "&&" : "||",
2455 (ce_info->num_multiple_test_blocks == 1) ? "" : "s",
2456 ce_info->last_test_bb->index,
2457 ((ce_info->last_test_bb->head)
2458 ? (int)INSN_UID (ce_info->last_test_bb->head)
2459 : -1));
2460
2461 fputc ('\n', rtl_dump_file);
2462 }
2463
2464 /* Make sure IF, THEN, and ELSE, blocks are adjacent. Actually, we get the
2465 first condition for free, since we've already asserted that there's a
2466 fallthru edge from IF to THEN. Likewise for the && and || blocks, since
2467 we checked the FALLTHRU flag, those are already adjacent to the last IF
2468 block. */
2469 /* ??? As an enhancement, move the ELSE block. Have to deal with
2470 BLOCK notes, if by no other means than aborting the merge if they
2471 exist. Sticky enough I don't want to think about it now. */
2472 next = then_bb;
2473 if (else_bb && (next = next->next_bb) != else_bb)
2474 return FALSE;
2475 if ((next = next->next_bb) != join_bb && join_bb != EXIT_BLOCK_PTR)
2476 {
2477 if (else_bb)
2478 join_bb = NULL;
2479 else
2480 return FALSE;
2481 }
2482
2483 /* Do the real work. */
2484 ce_info->else_bb = else_bb;
2485 ce_info->join_bb = join_bb;
2486
2487 return process_if_block (ce_info);
2488}
2489
2490/* Convert a branch over a trap, or a branch
2491 to a trap, into a conditional trap. */
2492
2493static int
2494find_cond_trap (test_bb, then_edge, else_edge)
2495 basic_block test_bb;
2496 edge then_edge, else_edge;
2497{
2498 basic_block then_bb = then_edge->dest;
2499 basic_block else_bb = else_edge->dest;
2500 basic_block other_bb, trap_bb;
2501 rtx trap, jump, cond, cond_earliest, seq;
2502 enum rtx_code code;
2503
2504 /* Locate the block with the trap instruction. */
2505 /* ??? While we look for no successors, we really ought to allow
2506 EH successors. Need to fix merge_if_block for that to work. */
2507 if ((trap = block_has_only_trap (then_bb)) != NULL)
2508 trap_bb = then_bb, other_bb = else_bb;
2509 else if ((trap = block_has_only_trap (else_bb)) != NULL)
2510 trap_bb = else_bb, other_bb = then_bb;
2511 else
2512 return FALSE;
2513
2514 if (rtl_dump_file)
2515 {
2516 fprintf (rtl_dump_file, "\nTRAP-IF block found, start %d, trap %d\n",
2517 test_bb->index, trap_bb->index);
2518 }
2519
2520 /* If this is not a standard conditional jump, we can't parse it. */
2521 jump = test_bb->end;
2522 cond = noce_get_condition (jump, &cond_earliest);
2523 if (! cond)
2524 return FALSE;
2525
2526 /* If the conditional jump is more than just a conditional jump, then
2527 we can not do if-conversion on this block. */
2528 if (! onlyjump_p (jump))
2529 return FALSE;
2530
2531 /* We must be comparing objects whose modes imply the size. */
2532 if (GET_MODE (XEXP (cond, 0)) == BLKmode)
2533 return FALSE;
2534
2535 /* Reverse the comparison code, if necessary. */
2536 code = GET_CODE (cond);
2537 if (then_bb == trap_bb)
2538 {
2539 code = reversed_comparison_code (cond, jump);
2540 if (code == UNKNOWN)
2541 return FALSE;
2542 }
2543
2544 /* Attempt to generate the conditional trap. */
2545 seq = gen_cond_trap (code, XEXP (cond, 0), XEXP (cond, 1),
2546 TRAP_CODE (PATTERN (trap)));
2547 if (seq == NULL)
2548 return FALSE;
2549
2550 /* Emit the new insns before cond_earliest. */
2551 emit_insn_before_scope (seq, cond_earliest, INSN_SCOPE (trap));
2552
2553 /* Delete the trap block if possible. */
2554 remove_edge (trap_bb == then_bb ? then_edge : else_edge);
2555 if (trap_bb->pred == NULL)
2556 {
2557 if (post_dominators)
2558 delete_from_dominance_info (post_dominators, trap_bb);
2559 flow_delete_block (trap_bb);
2560 num_removed_blocks++;
2561 }
2562
2563 /* If the non-trap block and the test are now adjacent, merge them.
2564 Otherwise we must insert a direct branch. */
2565 if (test_bb->next_bb == other_bb)
2566 {
2567 struct ce_if_block new_ce_info;
2568 delete_insn (jump);
2569 memset ((PTR) &new_ce_info, '\0', sizeof (new_ce_info));
2570 new_ce_info.test_bb = test_bb;
2571 new_ce_info.then_bb = NULL;
2572 new_ce_info.else_bb = NULL;
2573 new_ce_info.join_bb = other_bb;
2574 merge_if_block (&new_ce_info);
2575 }
2576 else
2577 {
2578 rtx lab, newjump;
2579
2580 lab = JUMP_LABEL (jump);
2581 newjump = emit_jump_insn_after (gen_jump (lab), jump);
2582 LABEL_NUSES (lab) += 1;
2583 JUMP_LABEL (newjump) = lab;
2584 emit_barrier_after (newjump);
2585
2586 delete_insn (jump);
2587 }
2588
2589 return TRUE;
2590}
2591
2592/* Subroutine of find_cond_trap: if BB contains only a trap insn,
2593 return it. */
2594
2595static rtx
2596block_has_only_trap (bb)
2597 basic_block bb;
2598{
2599 rtx trap;
2600
2601 /* We're not the exit block. */
2602 if (bb == EXIT_BLOCK_PTR)
2603 return NULL_RTX;
2604
2605 /* The block must have no successors. */
2606 if (bb->succ)
2607 return NULL_RTX;
2608
2609 /* The only instruction in the THEN block must be the trap. */
2610 trap = first_active_insn (bb);
2611 if (! (trap == bb->end
2612 && GET_CODE (PATTERN (trap)) == TRAP_IF
2613 && TRAP_CONDITION (PATTERN (trap)) == const_true_rtx))
2614 return NULL_RTX;
2615
2616 return trap;
2617}
2618
2619/* Look for IF-THEN-ELSE cases in which one of THEN or ELSE is
2620 transformable, but not necessarily the other. There need be no
2621 JOIN block.
2622
2623 Return TRUE if we were successful at converting the block.
2624
2625 Cases we'd like to look at:
2626
2627 (1)
2628 if (test) goto over; // x not live
2629 x = a;
2630 goto label;
2631 over:
2632
2633 becomes
2634
2635 x = a;
2636 if (! test) goto label;
2637
2638 (2)
2639 if (test) goto E; // x not live
2640 x = big();
2641 goto L;
2642 E:
2643 x = b;
2644 goto M;
2645
2646 becomes
2647
2648 x = b;
2649 if (test) goto M;
2650 x = big();
2651 goto L;
2652
2653 (3) // This one's really only interesting for targets that can do
2654 // multiway branching, e.g. IA-64 BBB bundles. For other targets
2655 // it results in multiple branches on a cache line, which often
2656 // does not sit well with predictors.
2657
2658 if (test1) goto E; // predicted not taken
2659 x = a;
2660 if (test2) goto F;
2661 ...
2662 E:
2663 x = b;
2664 J:
2665
2666 becomes
2667
2668 x = a;
2669 if (test1) goto E;
2670 if (test2) goto F;
2671
2672 Notes:
2673
2674 (A) Don't do (2) if the branch is predicted against the block we're
2675 eliminating. Do it anyway if we can eliminate a branch; this requires
2676 that the sole successor of the eliminated block postdominate the other
2677 side of the if.
2678
2679 (B) With CE, on (3) we can steal from both sides of the if, creating
2680
2681 if (test1) x = a;
2682 if (!test1) x = b;
2683 if (test1) goto J;
2684 if (test2) goto F;
2685 ...
2686 J:
2687
2688 Again, this is most useful if J postdominates.
2689
2690 (C) CE substitutes for helpful life information.
2691
2692 (D) These heuristics need a lot of work. */
2693
2694/* Tests for case 1 above. */
2695
2696static int
2697find_if_case_1 (test_bb, then_edge, else_edge)
2698 basic_block test_bb;
2699 edge then_edge, else_edge;
2700{
2701 basic_block then_bb = then_edge->dest;
2702 basic_block else_bb = else_edge->dest, new_bb;
2703 edge then_succ = then_bb->succ;
2704 int then_bb_index;
2705
2706 /* THEN has one successor. */
2707 if (!then_succ || then_succ->succ_next != NULL)
2708 return FALSE;
2709
2710 /* THEN does not fall through, but is not strange either. */
2711 if (then_succ->flags & (EDGE_COMPLEX | EDGE_FALLTHRU))
2712 return FALSE;
2713
2714 /* THEN has one predecessor. */
2715 if (then_bb->pred->pred_next != NULL)
2716 return FALSE;
2717
2718 /* THEN must do something. */
2719 if (forwarder_block_p (then_bb))
2720 return FALSE;
2721
2722 num_possible_if_blocks++;
2723 if (rtl_dump_file)
2724 fprintf (rtl_dump_file,
2725 "\nIF-CASE-1 found, start %d, then %d\n",
2726 test_bb->index, then_bb->index);
2727
2728 /* THEN is small. */
2729 if (count_bb_insns (then_bb) > BRANCH_COST)
2730 return FALSE;
2731
2732 /* Registers set are dead, or are predicable. */
2733 if (! dead_or_predicable (test_bb, then_bb, else_bb,
2734 then_bb->succ->dest, 1))
2735 return FALSE;
2736
2737 /* Conversion went ok, including moving the insns and fixing up the
2738 jump. Adjust the CFG to match. */
2739
2740 bitmap_operation (test_bb->global_live_at_end,
2741 else_bb->global_live_at_start,
2742 then_bb->global_live_at_end, BITMAP_IOR);
2743
2744 new_bb = redirect_edge_and_branch_force (FALLTHRU_EDGE (test_bb), else_bb);
2745 then_bb_index = then_bb->index;
2746 if (post_dominators)
2747 delete_from_dominance_info (post_dominators, then_bb);
2748 flow_delete_block (then_bb);
2749
2750 /* Make rest of code believe that the newly created block is the THEN_BB
2751 block we removed. */
2752 if (new_bb)
2753 {
2754 new_bb->index = then_bb_index;
2755 BASIC_BLOCK (then_bb_index) = new_bb;
2756 if (post_dominators)
2757 add_to_dominance_info (post_dominators, new_bb);
2758 }
2759 /* We've possibly created jump to next insn, cleanup_cfg will solve that
2760 later. */
2761
2762 num_removed_blocks++;
2763 num_updated_if_blocks++;
2764
2765 return TRUE;
2766}
2767
2768/* Test for case 2 above. */
2769
2770static int
2771find_if_case_2 (test_bb, then_edge, else_edge)
2772 basic_block test_bb;
2773 edge then_edge, else_edge;
2774{
2775 basic_block then_bb = then_edge->dest;
2776 basic_block else_bb = else_edge->dest;
2777 edge else_succ = else_bb->succ;
2778 rtx note;
2779
2780 /* ELSE has one successor. */
2781 if (!else_succ || else_succ->succ_next != NULL)
2782 return FALSE;
2783
2784 /* ELSE outgoing edge is not complex. */
2785 if (else_succ->flags & EDGE_COMPLEX)
2786 return FALSE;
2787
2788 /* ELSE has one predecessor. */
2789 if (else_bb->pred->pred_next != NULL)
2790 return FALSE;
2791
2792 /* THEN is not EXIT. */
2793 if (then_bb->index < 0)
2794 return FALSE;
2795
2796 /* ELSE is predicted or SUCC(ELSE) postdominates THEN. */
2797 note = find_reg_note (test_bb->end, REG_BR_PROB, NULL_RTX);
2798 if (note && INTVAL (XEXP (note, 0)) >= REG_BR_PROB_BASE / 2)
2799 ;
2800 else if (else_succ->dest->index < 0
2801 || dominated_by_p (post_dominators, then_bb,
2802 else_succ->dest))
2803 ;
2804 else
2805 return FALSE;
2806
2807 num_possible_if_blocks++;
2808 if (rtl_dump_file)
2809 fprintf (rtl_dump_file,
2810 "\nIF-CASE-2 found, start %d, else %d\n",
2811 test_bb->index, else_bb->index);
2812
2813 /* ELSE is small. */
2814 if (count_bb_insns (else_bb) > BRANCH_COST)
2815 return FALSE;
2816
2817 /* Registers set are dead, or are predicable. */
2818 if (! dead_or_predicable (test_bb, else_bb, then_bb, else_succ->dest, 0))
2819 return FALSE;
2820
2821 /* Conversion went ok, including moving the insns and fixing up the
2822 jump. Adjust the CFG to match. */
2823
2824 bitmap_operation (test_bb->global_live_at_end,
2825 then_bb->global_live_at_start,
2826 else_bb->global_live_at_end, BITMAP_IOR);
2827
2828 if (post_dominators)
2829 delete_from_dominance_info (post_dominators, else_bb);
2830 flow_delete_block (else_bb);
2831
2832 num_removed_blocks++;
2833 num_updated_if_blocks++;
2834
2835 /* ??? We may now fallthru from one of THEN's successors into a join
2836 block. Rerun cleanup_cfg? Examine things manually? Wait? */
2837
2838 return TRUE;
2839}
2840
2841/* A subroutine of dead_or_predicable called through for_each_rtx.
2842 Return 1 if a memory is found. */
2843
2844static int
2845find_memory (px, data)
2846 rtx *px;
2847 void *data ATTRIBUTE_UNUSED;
2848{
2849 return GET_CODE (*px) == MEM;
2850}
2851
2852/* Used by the code above to perform the actual rtl transformations.
2853 Return TRUE if successful.
2854
2855 TEST_BB is the block containing the conditional branch. MERGE_BB
2856 is the block containing the code to manipulate. NEW_DEST is the
2857 label TEST_BB should be branching to after the conversion.
2858 REVERSEP is true if the sense of the branch should be reversed. */
2859
2860static int
2861dead_or_predicable (test_bb, merge_bb, other_bb, new_dest, reversep)
2862 basic_block test_bb, merge_bb, other_bb;
2863 basic_block new_dest;
2864 int reversep;
2865{
2866 rtx head, end, jump, earliest, old_dest, new_label = NULL_RTX;
2867
2868 jump = test_bb->end;
2869
2870 /* Find the extent of the real code in the merge block. */
2871 head = merge_bb->head;
2872 end = merge_bb->end;
2873
2874 if (GET_CODE (head) == CODE_LABEL)
2875 head = NEXT_INSN (head);
2876 if (GET_CODE (head) == NOTE)
2877 {
2878 if (head == end)
2879 {
2880 head = end = NULL_RTX;
2881 goto no_body;
2882 }
2883 head = NEXT_INSN (head);
2884 }
2885
2886 if (GET_CODE (end) == JUMP_INSN)
2887 {
2888 rtx tmp, insn, label;
2889
2890 if (head == end)
2891 {
2892 head = end = NULL_RTX;
2893 goto no_body;
2894 }
2895
2896 /* If there is a jump table following merge_bb, fail
2897 if there are any insn between head and PREV_INSN (end)
2898 references it. */
2899 if ((label = JUMP_LABEL (end)) != NULL_RTX
2900 && (tmp = NEXT_INSN (label)) != NULL_RTX
2901 && GET_CODE (tmp) == JUMP_INSN
2902 && (GET_CODE (PATTERN (tmp)) == ADDR_VEC
2903 || GET_CODE (PATTERN (tmp)) == ADDR_DIFF_VEC))
2904 {
2905 for (insn = head; insn != PREV_INSN (end); insn = NEXT_INSN (insn))
2906 if (find_reg_note (insn, REG_LABEL, label))
2907 return FALSE;
2908 }
2909
2910 end = PREV_INSN (end);
2911 }
2912
2913 /* Disable handling dead code by conditional execution if the machine needs
2914 to do anything funny with the tests, etc. */
2915#ifndef IFCVT_MODIFY_TESTS
2916 if (HAVE_conditional_execution)
2917 {
2918 /* In the conditional execution case, we have things easy. We know
2919 the condition is reversable. We don't have to check life info,
2920 becase we're going to conditionally execute the code anyway.
2921 All that's left is making sure the insns involved can actually
2922 be predicated. */
2923
2924 rtx cond, prob_val;
2925
2926 cond = cond_exec_get_condition (jump);
2927 if (! cond)
2928 return FALSE;
2929
2930 prob_val = find_reg_note (jump, REG_BR_PROB, NULL_RTX);
2931 if (prob_val)
2932 prob_val = XEXP (prob_val, 0);
2933
2934 if (reversep)
2935 {
2936 enum rtx_code rev = reversed_comparison_code (cond, jump);
2937 if (rev == UNKNOWN)
2938 return FALSE;
2939 cond = gen_rtx_fmt_ee (rev, GET_MODE (cond), XEXP (cond, 0),
2940 XEXP (cond, 1));
2941 if (prob_val)
2942 prob_val = GEN_INT (REG_BR_PROB_BASE - INTVAL (prob_val));
2943 }
2944
2945 if (! cond_exec_process_insns ((ce_if_block_t *)0, head, end, cond,
2946 prob_val, 0))
2947 goto cancel;
2948
2949 earliest = jump;
2950 }
2951 else
2952#endif
2953 {
2954 /* In the non-conditional execution case, we have to verify that there
2955 are no trapping operations, no calls, no references to memory, and
2956 that any registers modified are dead at the branch site. */
2957
2958 rtx insn, cond, prev;
2959 regset_head merge_set_head, tmp_head, test_live_head, test_set_head;
2960 regset merge_set, tmp, test_live, test_set;
2961 struct propagate_block_info *pbi;
2962 int i, fail = 0;
2963
2964 /* Check for no calls or trapping operations. */
2965 for (insn = head; ; insn = NEXT_INSN (insn))
2966 {
2967 if (GET_CODE (insn) == CALL_INSN)
2968 return FALSE;
2969 if (INSN_P (insn))
2970 {
2971 if (may_trap_p (PATTERN (insn)))
2972 return FALSE;
2973
2974 /* ??? Even non-trapping memories such as stack frame
2975 references must be avoided. For stores, we collect
2976 no lifetime info; for reads, we'd have to assert
2977 true_dependence false against every store in the
2978 TEST range. */
2979 if (for_each_rtx (&PATTERN (insn), find_memory, NULL))
2980 return FALSE;
2981 }
2982 if (insn == end)
2983 break;
2984 }
2985
2986 if (! any_condjump_p (jump))
2987 return FALSE;
2988
2989 /* Find the extent of the conditional. */
2990 cond = noce_get_condition (jump, &earliest);
2991 if (! cond)
2992 return FALSE;
2993
2994 /* Collect:
2995 MERGE_SET = set of registers set in MERGE_BB
2996 TEST_LIVE = set of registers live at EARLIEST
2997 TEST_SET = set of registers set between EARLIEST and the
2998 end of the block. */
2999
3000 tmp = INITIALIZE_REG_SET (tmp_head);
3001 merge_set = INITIALIZE_REG_SET (merge_set_head);
3002 test_live = INITIALIZE_REG_SET (test_live_head);
3003 test_set = INITIALIZE_REG_SET (test_set_head);
3004
3005 /* ??? bb->local_set is only valid during calculate_global_regs_live,
3006 so we must recompute usage for MERGE_BB. Not so bad, I suppose,
3007 since we've already asserted that MERGE_BB is small. */
3008 propagate_block (merge_bb, tmp, merge_set, merge_set, 0);
3009
3010 /* For small register class machines, don't lengthen lifetimes of
3011 hard registers before reload. */
3012 if (SMALL_REGISTER_CLASSES && ! reload_completed)
3013 {
3014 EXECUTE_IF_SET_IN_BITMAP
3015 (merge_set, 0, i,
3016 {
3017 if (i < FIRST_PSEUDO_REGISTER
3018 && ! fixed_regs[i]
3019 && ! global_regs[i])
3020 fail = 1;
3021 });
3022 }
3023
3024 /* For TEST, we're interested in a range of insns, not a whole block.
3025 Moreover, we're interested in the insns live from OTHER_BB. */
3026
3027 COPY_REG_SET (test_live, other_bb->global_live_at_start);
3028 pbi = init_propagate_block_info (test_bb, test_live, test_set, test_set,
3029 0);
3030
3031 for (insn = jump; ; insn = prev)
3032 {
3033 prev = propagate_one_insn (pbi, insn);
3034 if (insn == earliest)
3035 break;
3036 }
3037
3038 free_propagate_block_info (pbi);
3039
3040 /* We can perform the transformation if
3041 MERGE_SET & (TEST_SET | TEST_LIVE)
3042 and
3043 TEST_SET & merge_bb->global_live_at_start
3044 are empty. */
3045
3046 bitmap_operation (tmp, test_set, test_live, BITMAP_IOR);
3047 bitmap_operation (tmp, tmp, merge_set, BITMAP_AND);
3048 EXECUTE_IF_SET_IN_BITMAP(tmp, 0, i, fail = 1);
3049
3050 bitmap_operation (tmp, test_set, merge_bb->global_live_at_start,
3051 BITMAP_AND);
3052 EXECUTE_IF_SET_IN_BITMAP(tmp, 0, i, fail = 1);
3053
3054 FREE_REG_SET (tmp);
3055 FREE_REG_SET (merge_set);
3056 FREE_REG_SET (test_live);
3057 FREE_REG_SET (test_set);
3058
3059 if (fail)
3060 return FALSE;
3061 }
3062
3063 no_body:
3064 /* We don't want to use normal invert_jump or redirect_jump because
3065 we don't want to delete_insn called. Also, we want to do our own
3066 change group management. */
3067
3068 old_dest = JUMP_LABEL (jump);
3069 if (other_bb != new_dest)
3070 {
3071 new_label = block_label (new_dest);
3072 if (reversep
3073 ? ! invert_jump_1 (jump, new_label)
3074 : ! redirect_jump_1 (jump, new_label))
3075 goto cancel;
3076 }
3077
3078 if (! apply_change_group ())
3079 return FALSE;
3080
3081 if (other_bb != new_dest)
3082 {
3083 if (old_dest)
3084 LABEL_NUSES (old_dest) -= 1;
3085 if (new_label)
3086 LABEL_NUSES (new_label) += 1;
3087 JUMP_LABEL (jump) = new_label;
3088 if (reversep)
3089 invert_br_probabilities (jump);
3090
3091 redirect_edge_succ (BRANCH_EDGE (test_bb), new_dest);
3092 if (reversep)
3093 {
3094 gcov_type count, probability;
3095 count = BRANCH_EDGE (test_bb)->count;
3096 BRANCH_EDGE (test_bb)->count = FALLTHRU_EDGE (test_bb)->count;
3097 FALLTHRU_EDGE (test_bb)->count = count;
3098 probability = BRANCH_EDGE (test_bb)->probability;
3099 BRANCH_EDGE (test_bb)->probability
3100 = FALLTHRU_EDGE (test_bb)->probability;
3101 FALLTHRU_EDGE (test_bb)->probability = probability;
3102 update_br_prob_note (test_bb);
3103 }
3104 }
3105
3106 /* Move the insns out of MERGE_BB to before the branch. */
3107 if (head != NULL)
3108 {
3109 if (end == merge_bb->end)
3110 merge_bb->end = PREV_INSN (head);
3111
3112 if (squeeze_notes (&head, &end))
3113 return TRUE;
3114
3115 reorder_insns (head, end, PREV_INSN (earliest));
3116 }
3117
3118 /* Remove the jump and edge if we can. */
3119 if (other_bb == new_dest)
3120 {
3121 delete_insn (jump);
3122 remove_edge (BRANCH_EDGE (test_bb));
3123 /* ??? Can't merge blocks here, as then_bb is still in use.
3124 At minimum, the merge will get done just before bb-reorder. */
3125 }
3126
3127 return TRUE;
3128
3129 cancel:
3130 cancel_changes (0);
3131 return FALSE;
3132}
3133
3134
3135/* Main entry point for all if-conversion. */
3136
3137void
3138if_convert (x_life_data_ok)
3139 int x_life_data_ok;
3140{
3141 basic_block bb;
3142 int pass;
3143
3144 num_possible_if_blocks = 0;
3145 num_updated_if_blocks = 0;
3146 num_removed_blocks = 0;
3147 life_data_ok = (x_life_data_ok != 0);
3148
3149 /* Free up basic_block_for_insn so that we don't have to keep it
3150 up to date, either here or in merge_blocks_nomove. */
3151 free_basic_block_vars (1);
3152
3153 /* Compute postdominators if we think we'll use them. */
3154 post_dominators = NULL;
3155 if (HAVE_conditional_execution || life_data_ok)
3156 {
3157 post_dominators = calculate_dominance_info (CDI_POST_DOMINATORS);
3158 }
3159 if (life_data_ok)
3160 clear_bb_flags ();
3161
3162 /* Go through each of the basic blocks looking for things to convert. If we
3163 have conditional execution, we make multiple passes to allow us to handle
3164 IF-THEN{-ELSE} blocks within other IF-THEN{-ELSE} blocks. */
3165 pass = 0;
3166 do
3167 {
3168 cond_exec_changed_p = FALSE;
3169 pass++;
3170
3171#ifdef IFCVT_MULTIPLE_DUMPS
3172 if (rtl_dump_file && pass > 1)
3173 fprintf (rtl_dump_file, "\n\n========== Pass %d ==========\n", pass);
3174#endif
3175
3176 FOR_EACH_BB (bb)
3177 {
3178 basic_block new_bb;
3179 while ((new_bb = find_if_header (bb, pass)))
3180 bb = new_bb;
3181 }
3182
3183#ifdef IFCVT_MULTIPLE_DUMPS
3184 if (rtl_dump_file && cond_exec_changed_p)
3185 print_rtl_with_bb (rtl_dump_file, get_insns ());
3186#endif
3187 }
3188 while (cond_exec_changed_p);
3189
3190#ifdef IFCVT_MULTIPLE_DUMPS
3191 if (rtl_dump_file)
3192 fprintf (rtl_dump_file, "\n\n========== no more changes\n");
3193#endif
3194
3195 if (post_dominators)
3196 free_dominance_info (post_dominators);
3197
3198 if (rtl_dump_file)
3199 fflush (rtl_dump_file);
3200
3201 clear_aux_for_blocks ();
3202
3203 /* Rebuild life info for basic blocks that require it. */
3204 if (num_removed_blocks && life_data_ok)
3205 {
3206 /* If we allocated new pseudos, we must resize the array for sched1. */
3207 if (max_regno < max_reg_num ())
3208 {
3209 max_regno = max_reg_num ();
3210 allocate_reg_info (max_regno, FALSE, FALSE);
3211 }
3212 update_life_info_in_dirty_blocks (UPDATE_LIFE_GLOBAL_RM_NOTES,
3213 PROP_DEATH_NOTES | PROP_SCAN_DEAD_CODE
3214 | PROP_KILL_DEAD_CODE);
3215 }
3216
3217 /* Write the final stats. */
3218 if (rtl_dump_file && num_possible_if_blocks > 0)
3219 {
3220 fprintf (rtl_dump_file,
3221 "\n%d possible IF blocks searched.\n",
3222 num_possible_if_blocks);
3223 fprintf (rtl_dump_file,
3224 "%d IF blocks converted.\n",
3225 num_updated_if_blocks);
3226 fprintf (rtl_dump_file,
3227 "%d basic blocks deleted.\n\n\n",
3228 num_removed_blocks);
3229 }
3230
3231#ifdef ENABLE_CHECKING
3232 verify_flow_info ();
3233#endif
3234}
Note: See TracBrowser for help on using the repository browser.