summaryrefslogtreecommitdiffstats
path: root/contrib/gcc/ifcvt.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/gcc/ifcvt.c')
-rw-r--r--contrib/gcc/ifcvt.c779
1 files changed, 437 insertions, 342 deletions
diff --git a/contrib/gcc/ifcvt.c b/contrib/gcc/ifcvt.c
index c336004..640ab2c 100644
--- a/contrib/gcc/ifcvt.c
+++ b/contrib/gcc/ifcvt.c
@@ -1,5 +1,5 @@
/* If-conversion support.
- Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
+ Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
This file is part of GCC.
@@ -20,6 +20,8 @@
#include "config.h"
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
#include "rtl.h"
#include "regs.h"
@@ -33,8 +35,11 @@
#include "expr.h"
#include "real.h"
#include "output.h"
+#include "optabs.h"
#include "toplev.h"
#include "tm_p.h"
+#include "cfgloop.h"
+#include "target.h"
#ifndef HAVE_conditional_execution
@@ -70,8 +75,8 @@ static int num_possible_if_blocks;
execution. */
static int num_updated_if_blocks;
-/* # of basic blocks that were removed. */
-static int num_removed_blocks;
+/* # of changes made which require life information to be updated. */
+static int num_true_changes;
/* Whether conditional execution changes were made. */
static int cond_exec_changed_p;
@@ -79,51 +84,76 @@ static int cond_exec_changed_p;
/* True if life data ok at present. */
static bool life_data_ok;
-/* The post-dominator relation on the original block numbers. */
-static dominance_info post_dominators;
-
/* Forward references. */
-static int count_bb_insns PARAMS ((basic_block));
-static rtx first_active_insn PARAMS ((basic_block));
-static rtx last_active_insn PARAMS ((basic_block, int));
-static int seq_contains_jump PARAMS ((rtx));
-static basic_block block_fallthru PARAMS ((basic_block));
-static int cond_exec_process_insns PARAMS ((ce_if_block_t *,
- rtx, rtx, rtx, rtx, int));
-static rtx cond_exec_get_condition PARAMS ((rtx));
-static int cond_exec_process_if_block PARAMS ((ce_if_block_t *, int));
-static rtx noce_get_condition PARAMS ((rtx, rtx *));
-static int noce_operand_ok PARAMS ((rtx));
-static int noce_process_if_block PARAMS ((ce_if_block_t *));
-static int process_if_block PARAMS ((ce_if_block_t *));
-static void merge_if_block PARAMS ((ce_if_block_t *));
-static int find_cond_trap PARAMS ((basic_block, edge, edge));
-static basic_block find_if_header PARAMS ((basic_block, int));
-static int block_jumps_and_fallthru_p PARAMS ((basic_block, basic_block));
-static int find_if_block PARAMS ((ce_if_block_t *));
-static int find_if_case_1 PARAMS ((basic_block, edge, edge));
-static int find_if_case_2 PARAMS ((basic_block, edge, edge));
-static int find_memory PARAMS ((rtx *, void *));
-static int dead_or_predicable PARAMS ((basic_block, basic_block,
- basic_block, basic_block, int));
-static void noce_emit_move_insn PARAMS ((rtx, rtx));
-static rtx block_has_only_trap PARAMS ((basic_block));
+static int count_bb_insns (basic_block);
+static rtx first_active_insn (basic_block);
+static rtx last_active_insn (basic_block, int);
+static int seq_contains_jump (rtx);
+static basic_block block_fallthru (basic_block);
+static int cond_exec_process_insns (ce_if_block_t *, rtx, rtx, rtx, rtx, int);
+static rtx cond_exec_get_condition (rtx);
+static int cond_exec_process_if_block (ce_if_block_t *, int);
+static rtx noce_get_condition (rtx, rtx *);
+static int noce_operand_ok (rtx);
+static int noce_process_if_block (ce_if_block_t *);
+static int process_if_block (ce_if_block_t *);
+static void merge_if_block (ce_if_block_t *);
+static int find_cond_trap (basic_block, edge, edge);
+static basic_block find_if_header (basic_block, int);
+static int block_jumps_and_fallthru_p (basic_block, basic_block);
+static int find_if_block (ce_if_block_t *);
+static int find_if_case_1 (basic_block, edge, edge);
+static int find_if_case_2 (basic_block, edge, edge);
+static int find_memory (rtx *, void *);
+static int dead_or_predicable (basic_block, basic_block, basic_block,
+ basic_block, int);
+static void noce_emit_move_insn (rtx, rtx);
+static rtx block_has_only_trap (basic_block);
+static void mark_loop_exit_edges (void);
+/* Sets EDGE_LOOP_EXIT flag for all loop exits. */
+static void
+mark_loop_exit_edges (void)
+{
+ struct loops loops;
+ basic_block bb;
+ edge e;
+
+ flow_loops_find (&loops, LOOP_TREE);
+ free_dominance_info (CDI_DOMINATORS);
+
+ if (loops.num > 1)
+ {
+ FOR_EACH_BB (bb)
+ {
+ for (e = bb->succ; e; e = e->succ_next)
+ {
+ if (find_common_loop (bb->loop_father, e->dest->loop_father)
+ != bb->loop_father)
+ e->flags |= EDGE_LOOP_EXIT;
+ else
+ e->flags &= ~EDGE_LOOP_EXIT;
+ }
+ }
+ }
+
+ flow_loops_free (&loops);
+}
+
/* Count the number of non-jump active insns in BB. */
static int
-count_bb_insns (bb)
- basic_block bb;
+count_bb_insns (basic_block bb)
{
int count = 0;
- rtx insn = bb->head;
+ rtx insn = BB_HEAD (bb);
while (1)
{
if (GET_CODE (insn) == CALL_INSN || GET_CODE (insn) == INSN)
count++;
- if (insn == bb->end)
+ if (insn == BB_END (bb))
break;
insn = NEXT_INSN (insn);
}
@@ -134,21 +164,20 @@ count_bb_insns (bb)
/* Return the first non-jump active insn in the basic block. */
static rtx
-first_active_insn (bb)
- basic_block bb;
+first_active_insn (basic_block bb)
{
- rtx insn = bb->head;
+ rtx insn = BB_HEAD (bb);
if (GET_CODE (insn) == CODE_LABEL)
{
- if (insn == bb->end)
+ if (insn == BB_END (bb))
return NULL_RTX;
insn = NEXT_INSN (insn);
}
while (GET_CODE (insn) == NOTE)
{
- if (insn == bb->end)
+ if (insn == BB_END (bb))
return NULL_RTX;
insn = NEXT_INSN (insn);
}
@@ -162,12 +191,10 @@ first_active_insn (bb)
/* Return the last non-jump active (non-jump) insn in the basic block. */
static rtx
-last_active_insn (bb, skip_use_p)
- basic_block bb;
- int skip_use_p;
+last_active_insn (basic_block bb, int skip_use_p)
{
- rtx insn = bb->end;
- rtx head = bb->head;
+ rtx insn = BB_END (bb);
+ rtx head = BB_HEAD (bb);
while (GET_CODE (insn) == NOTE
|| GET_CODE (insn) == JUMP_INSN
@@ -186,14 +213,13 @@ last_active_insn (bb, skip_use_p)
return insn;
}
-/* It is possible, especially when having dealt with multi-word
+/* It is possible, especially when having dealt with multi-word
arithmetic, for the expanders to have emitted jumps. Search
through the sequence and return TRUE if a jump exists so that
we can abort the conversion. */
static int
-seq_contains_jump (insn)
- rtx insn;
+seq_contains_jump (rtx insn)
{
while (insn)
{
@@ -205,8 +231,7 @@ seq_contains_jump (insn)
}
static basic_block
-block_fallthru (bb)
- basic_block bb;
+block_fallthru (basic_block bb)
{
edge e;
@@ -223,13 +248,12 @@ block_fallthru (bb)
insns were processed. */
static int
-cond_exec_process_insns (ce_info, start, end, test, prob_val, mod_ok)
- ce_if_block_t *ce_info ATTRIBUTE_UNUSED; /* if block information */
- rtx start; /* first insn to look at */
- rtx end; /* last insn to look at */
- rtx test; /* conditional execution test */
- rtx prob_val; /* probability of branch taken. */
- int mod_ok; /* true if modifications ok last insn. */
+cond_exec_process_insns (ce_if_block_t *ce_info ATTRIBUTE_UNUSED,
+ /* if block information */rtx start,
+ /* first insn to look at */rtx end,
+ /* last insn to look at */rtx test,
+ /* conditional execution test */rtx prob_val,
+ /* probability of branch taken. */int mod_ok)
{
int must_be_last = FALSE;
rtx insn;
@@ -250,7 +274,7 @@ cond_exec_process_insns (ce_info, start, end, test, prob_val, mod_ok)
/* Remove USE insns that get in the way. */
if (reload_completed && GET_CODE (PATTERN (insn)) == USE)
{
- /* ??? Ug. Actually unlinking the thing is problematic,
+ /* ??? Ug. Actually unlinking the thing is problematic,
given what we'd have to coordinate with our callers. */
PUT_CODE (insn, NOTE);
NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
@@ -314,8 +338,7 @@ cond_exec_process_insns (ce_info, start, end, test, prob_val, mod_ok)
/* Return the condition for a jump. Do not do any special processing. */
static rtx
-cond_exec_get_condition (jump)
- rtx jump;
+cond_exec_get_condition (rtx jump)
{
rtx test_if, cond;
@@ -346,9 +369,8 @@ cond_exec_get_condition (jump)
converting the block. */
static int
-cond_exec_process_if_block (ce_info, do_multiple_p)
- ce_if_block_t * ce_info; /* if block information */
- int do_multiple_p; /* != 0 if we should handle && and || blocks */
+cond_exec_process_if_block (ce_if_block_t * ce_info,
+ /* if block information */int do_multiple_p)
{
basic_block test_bb = ce_info->test_bb; /* last test block */
basic_block then_bb = ce_info->then_bb; /* THEN */
@@ -383,13 +405,13 @@ cond_exec_process_if_block (ce_info, do_multiple_p)
/* Find the conditional jump to the ELSE or JOIN part, and isolate
the test. */
- test_expr = cond_exec_get_condition (test_bb->end);
+ test_expr = cond_exec_get_condition (BB_END (test_bb));
if (! test_expr)
return FALSE;
/* If the conditional jump is more than just a conditional jump,
then we can not do conditional execution conversion on this block. */
- if (! onlyjump_p (test_bb->end))
+ if (! onlyjump_p (BB_END (test_bb)))
return FALSE;
/* Collect the bounds of where we're to search, skipping any labels, jumps
@@ -413,10 +435,10 @@ cond_exec_process_if_block (ce_info, do_multiple_p)
/* Map test_expr/test_jump into the appropriate MD tests to use on
the conditionally executed code. */
-
+
true_expr = test_expr;
- false_code = reversed_comparison_code (true_expr, test_bb->end);
+ false_code = reversed_comparison_code (true_expr, BB_END (test_bb));
if (false_code != UNKNOWN)
false_expr = gen_rtx_fmt_ee (false_code, GET_MODE (true_expr),
XEXP (true_expr, 0), XEXP (true_expr, 1));
@@ -428,12 +450,12 @@ cond_exec_process_if_block (ce_info, do_multiple_p)
conditional execution register from a comparison, it can do so here. */
IFCVT_MODIFY_TESTS (ce_info, true_expr, false_expr);
- /* See if the conversion failed */
+ /* See if the conversion failed. */
if (!true_expr || !false_expr)
goto fail;
#endif
- true_prob_val = find_reg_note (test_bb->end, REG_BR_PROB, NULL_RTX);
+ true_prob_val = find_reg_note (BB_END (test_bb), REG_BR_PROB, NULL_RTX);
if (true_prob_val)
{
true_prob_val = XEXP (true_prob_val, 0);
@@ -467,11 +489,11 @@ cond_exec_process_if_block (ce_info, do_multiple_p)
/* If the conditional jump is more than just a conditional jump, then
we can not do conditional execution conversion on this block. */
- if (! onlyjump_p (bb->end))
+ if (! onlyjump_p (BB_END (bb)))
goto fail;
/* Find the conditional jump and isolate the test. */
- t = cond_exec_get_condition (bb->end);
+ t = cond_exec_get_condition (BB_END (bb));
if (! t)
goto fail;
@@ -497,7 +519,7 @@ cond_exec_process_if_block (ce_info, do_multiple_p)
#ifdef IFCVT_MODIFY_MULTIPLE_TESTS
IFCVT_MODIFY_MULTIPLE_TESTS (ce_info, bb, t, f);
- /* See if the conversion failed */
+ /* See if the conversion failed. */
if (!t || !f)
goto fail;
#endif
@@ -539,7 +561,7 @@ cond_exec_process_if_block (ce_info, do_multiple_p)
}
#ifdef IFCVT_MODIFY_FINAL
- /* Do any machine dependent final modifications */
+ /* Do any machine dependent final modifications. */
IFCVT_MODIFY_FINAL (ce_info);
#endif
@@ -563,10 +585,10 @@ cond_exec_process_if_block (ce_info, do_multiple_p)
return FALSE;
}
-/* Used by noce_process_if_block to communicate with its subroutines.
+/* Used by noce_process_if_block to communicate with its subroutines.
The subroutines know that A and B may be evaluated freely. They
- know that X is a register. They should insert new instructions
+ know that X is a register. They should insert new instructions
before cond_earliest. */
struct noce_if_info
@@ -577,29 +599,25 @@ struct noce_if_info
rtx jump, cond, cond_earliest;
};
-static rtx noce_emit_store_flag PARAMS ((struct noce_if_info *,
- rtx, int, int));
-static int noce_try_store_flag PARAMS ((struct noce_if_info *));
-static int noce_try_store_flag_inc PARAMS ((struct noce_if_info *));
-static int noce_try_store_flag_constants PARAMS ((struct noce_if_info *));
-static int noce_try_store_flag_mask PARAMS ((struct noce_if_info *));
-static rtx noce_emit_cmove PARAMS ((struct noce_if_info *,
- rtx, enum rtx_code, rtx,
- rtx, rtx, rtx));
-static int noce_try_cmove PARAMS ((struct noce_if_info *));
-static int noce_try_cmove_arith PARAMS ((struct noce_if_info *));
-static rtx noce_get_alt_condition PARAMS ((struct noce_if_info *,
- rtx, rtx *));
-static int noce_try_minmax PARAMS ((struct noce_if_info *));
-static int noce_try_abs PARAMS ((struct noce_if_info *));
+static rtx noce_emit_store_flag (struct noce_if_info *, rtx, int, int);
+static int noce_try_move (struct noce_if_info *);
+static int noce_try_store_flag (struct noce_if_info *);
+static int noce_try_addcc (struct noce_if_info *);
+static int noce_try_store_flag_constants (struct noce_if_info *);
+static int noce_try_store_flag_mask (struct noce_if_info *);
+static rtx noce_emit_cmove (struct noce_if_info *, rtx, enum rtx_code, rtx,
+ rtx, rtx, rtx);
+static int noce_try_cmove (struct noce_if_info *);
+static int noce_try_cmove_arith (struct noce_if_info *);
+static rtx noce_get_alt_condition (struct noce_if_info *, rtx, rtx *);
+static int noce_try_minmax (struct noce_if_info *);
+static int noce_try_abs (struct noce_if_info *);
/* Helper function for noce_try_store_flag*. */
static rtx
-noce_emit_store_flag (if_info, x, reversep, normalize)
- struct noce_if_info *if_info;
- rtx x;
- int reversep, normalize;
+noce_emit_store_flag (struct noce_if_info *if_info, rtx x, int reversep,
+ int normalize)
{
rtx cond = if_info->cond;
int cond_complex;
@@ -655,10 +673,11 @@ noce_emit_store_flag (if_info, x, reversep, normalize)
|| code == GEU || code == GTU), normalize);
}
-/* Emit instruction to move an rtx into STRICT_LOW_PART. */
+/* Emit instruction to move an rtx, possibly into STRICT_LOW_PART.
+ X is the destination/target and Y is the value to copy. */
+
static void
-noce_emit_move_insn (x, y)
- rtx x, y;
+noce_emit_move_insn (rtx x, rtx y)
{
enum machine_mode outmode, inmode;
rtx outer, inner;
@@ -679,6 +698,69 @@ noce_emit_move_insn (x, y)
GET_MODE_BITSIZE (inmode));
}
+/* Unshare sequence SEQ produced by if conversion. We care to mark
+ all arguments that may be shared with outer instruction stream. */
+static void
+unshare_ifcvt_sequence (struct noce_if_info *if_info, rtx seq)
+{
+ set_used_flags (if_info->x);
+ set_used_flags (if_info->cond);
+ unshare_all_rtl_in_chain (seq);
+}
+
+/* Convert "if (a != b) x = a; else x = b" into "x = a" and
+ "if (a == b) x = a; else x = b" into "x = b". */
+
+static int
+noce_try_move (struct noce_if_info *if_info)
+{
+ rtx cond = if_info->cond;
+ enum rtx_code code = GET_CODE (cond);
+ rtx y, seq;
+
+ if (code != NE && code != EQ)
+ return FALSE;
+
+ /* This optimization isn't valid if either A or B could be a NaN
+ or a signed zero. */
+ if (HONOR_NANS (GET_MODE (if_info->x))
+ || HONOR_SIGNED_ZEROS (GET_MODE (if_info->x)))
+ return FALSE;
+
+ /* Check whether the operands of the comparison are A and in
+ either order. */
+ if ((rtx_equal_p (if_info->a, XEXP (cond, 0))
+ && rtx_equal_p (if_info->b, XEXP (cond, 1)))
+ || (rtx_equal_p (if_info->a, XEXP (cond, 1))
+ && rtx_equal_p (if_info->b, XEXP (cond, 0))))
+ {
+ y = (code == EQ) ? if_info->a : if_info->b;
+
+ /* Avoid generating the move if the source is the destination. */
+ if (! rtx_equal_p (if_info->x, y))
+ {
+ start_sequence ();
+ noce_emit_move_insn (if_info->x, y);
+ seq = get_insns ();
+ unshare_ifcvt_sequence (if_info, seq);
+ end_sequence ();
+
+ /* Make sure that all of the instructions emitted are
+ recognizable. As an excersise for the reader, build
+ a general mechanism that allows proper placement of
+ required clobbers. */
+ for (y = seq; y ; y = NEXT_INSN (y))
+ if (recog_memoized (y) == -1)
+ return FALSE;
+
+ emit_insn_before_setloc (seq, if_info->jump,
+ INSN_LOCATOR (if_info->insn_a));
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
/* Convert "if (test) x = 1; else x = 0".
Only try 0 and STORE_FLAG_VALUE here. Other combinations will be
@@ -686,8 +768,7 @@ noce_emit_move_insn (x, y)
a go at the conversion. */
static int
-noce_try_store_flag (if_info)
- struct noce_if_info *if_info;
+noce_try_store_flag (struct noce_if_info *if_info)
{
int reversep;
rtx target, seq;
@@ -714,8 +795,9 @@ noce_try_store_flag (if_info)
noce_emit_move_insn (if_info->x, target);
seq = get_insns ();
+ unshare_ifcvt_sequence (if_info, seq);
end_sequence ();
- emit_insn_before_scope (seq, if_info->jump, INSN_SCOPE (if_info->insn_a));
+ emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATOR (if_info->insn_a));
return TRUE;
}
@@ -729,8 +811,7 @@ noce_try_store_flag (if_info)
/* Convert "if (test) x = a; else x = b", for A and B constant. */
static int
-noce_try_store_flag_constants (if_info)
- struct noce_if_info *if_info;
+noce_try_store_flag_constants (struct noce_if_info *if_info)
{
rtx target, seq;
int reversep;
@@ -780,7 +861,7 @@ noce_try_store_flag_constants (if_info)
return FALSE;
if (reversep)
- {
+ {
tmp = itrue; itrue = ifalse; ifalse = tmp;
diff = trunc_int_for_mode (-diff, mode);
}
@@ -845,12 +926,13 @@ noce_try_store_flag_constants (if_info)
noce_emit_move_insn (if_info->x, target);
seq = get_insns ();
+ unshare_ifcvt_sequence (if_info, seq);
end_sequence ();
if (seq_contains_jump (seq))
return FALSE;
- emit_insn_before_scope (seq, if_info->jump, INSN_SCOPE (if_info->insn_a));
+ emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATOR (if_info->insn_a));
return TRUE;
}
@@ -858,65 +940,96 @@ noce_try_store_flag_constants (if_info)
return FALSE;
}
-/* Convert "if (test) foo++" into "foo += (test != 0)", and
+/* Convert "if (test) foo++" into "foo += (test != 0)", and
similarly for "foo--". */
static int
-noce_try_store_flag_inc (if_info)
- struct noce_if_info *if_info;
+noce_try_addcc (struct noce_if_info *if_info)
{
rtx target, seq;
int subtract, normalize;
if (! no_new_pseudos
- && (BRANCH_COST >= 2
- || HAVE_incscc
- || HAVE_decscc)
- /* Should be no `else' case to worry about. */
- && if_info->b == if_info->x
&& GET_CODE (if_info->a) == PLUS
- && (XEXP (if_info->a, 1) == const1_rtx
- || XEXP (if_info->a, 1) == constm1_rtx)
- && rtx_equal_p (XEXP (if_info->a, 0), if_info->x)
+ && rtx_equal_p (XEXP (if_info->a, 0), if_info->b)
&& (reversed_comparison_code (if_info->cond, if_info->jump)
!= UNKNOWN))
{
- if (STORE_FLAG_VALUE == INTVAL (XEXP (if_info->a, 1)))
- subtract = 0, normalize = 0;
- else if (-STORE_FLAG_VALUE == INTVAL (XEXP (if_info->a, 1)))
- subtract = 1, normalize = 0;
- else
- subtract = 0, normalize = INTVAL (XEXP (if_info->a, 1));
-
- start_sequence ();
-
- target = noce_emit_store_flag (if_info,
- gen_reg_rtx (GET_MODE (if_info->x)),
- 1, normalize);
+ rtx cond = if_info->cond;
+ enum rtx_code code = reversed_comparison_code (cond, if_info->jump);
- if (target)
- target = expand_simple_binop (GET_MODE (if_info->x),
- subtract ? MINUS : PLUS,
- if_info->x, target, if_info->x,
- 0, OPTAB_WIDEN);
- if (target)
+ /* First try to use addcc pattern. */
+ if (general_operand (XEXP (cond, 0), VOIDmode)
+ && general_operand (XEXP (cond, 1), VOIDmode))
{
- if (target != if_info->x)
- noce_emit_move_insn (if_info->x, target);
-
- seq = get_insns ();
+ start_sequence ();
+ target = emit_conditional_add (if_info->x, code,
+ XEXP (cond, 0),
+ XEXP (cond, 1),
+ VOIDmode,
+ if_info->b,
+ XEXP (if_info->a, 1),
+ GET_MODE (if_info->x),
+ (code == LTU || code == GEU
+ || code == LEU || code == GTU));
+ if (target)
+ {
+ if (target != if_info->x)
+ noce_emit_move_insn (if_info->x, target);
+
+ seq = get_insns ();
+ unshare_ifcvt_sequence (if_info, seq);
+ end_sequence ();
+ emit_insn_before_setloc (seq, if_info->jump,
+ INSN_LOCATOR (if_info->insn_a));
+ return TRUE;
+ }
end_sequence ();
+ }
- if (seq_contains_jump (seq))
- return FALSE;
+ /* If that fails, construct conditional increment or decrement using
+ setcc. */
+ if (BRANCH_COST >= 2
+ && (XEXP (if_info->a, 1) == const1_rtx
+ || XEXP (if_info->a, 1) == constm1_rtx))
+ {
+ start_sequence ();
+ if (STORE_FLAG_VALUE == INTVAL (XEXP (if_info->a, 1)))
+ subtract = 0, normalize = 0;
+ else if (-STORE_FLAG_VALUE == INTVAL (XEXP (if_info->a, 1)))
+ subtract = 1, normalize = 0;
+ else
+ subtract = 0, normalize = INTVAL (XEXP (if_info->a, 1));
- emit_insn_before_scope (seq, if_info->jump,
- INSN_SCOPE (if_info->insn_a));
- return TRUE;
- }
+ target = noce_emit_store_flag (if_info,
+ gen_reg_rtx (GET_MODE (if_info->x)),
+ 1, normalize);
- end_sequence ();
+ if (target)
+ target = expand_simple_binop (GET_MODE (if_info->x),
+ subtract ? MINUS : PLUS,
+ if_info->b, target, if_info->x,
+ 0, OPTAB_WIDEN);
+ if (target)
+ {
+ if (target != if_info->x)
+ noce_emit_move_insn (if_info->x, target);
+
+ seq = get_insns ();
+ unshare_ifcvt_sequence (if_info, seq);
+ end_sequence ();
+
+ if (seq_contains_jump (seq))
+ return FALSE;
+
+ emit_insn_before_setloc (seq, if_info->jump,
+ INSN_LOCATOR (if_info->insn_a));
+
+ return TRUE;
+ }
+ end_sequence ();
+ }
}
return FALSE;
@@ -925,8 +1038,7 @@ noce_try_store_flag_inc (if_info)
/* Convert "if (test) x = 0;" to "x &= -(test == 0);" */
static int
-noce_try_store_flag_mask (if_info)
- struct noce_if_info *if_info;
+noce_try_store_flag_mask (struct noce_if_info *if_info)
{
rtx target, seq;
int reversep;
@@ -949,7 +1061,8 @@ noce_try_store_flag_mask (if_info)
reversep, -1);
if (target)
target = expand_simple_binop (GET_MODE (if_info->x), AND,
- if_info->x, target, if_info->x, 0,
+ if_info->x,
+ target, if_info->x, 0,
OPTAB_WIDEN);
if (target)
@@ -958,13 +1071,14 @@ noce_try_store_flag_mask (if_info)
noce_emit_move_insn (if_info->x, target);
seq = get_insns ();
+ unshare_ifcvt_sequence (if_info, seq);
end_sequence ();
if (seq_contains_jump (seq))
return FALSE;
- emit_insn_before_scope (seq, if_info->jump,
- INSN_SCOPE (if_info->insn_a));
+ emit_insn_before_setloc (seq, if_info->jump,
+ INSN_LOCATOR (if_info->insn_a));
return TRUE;
}
@@ -978,10 +1092,8 @@ noce_try_store_flag_mask (if_info)
/* Helper function for noce_try_cmove and noce_try_cmove_arith. */
static rtx
-noce_emit_cmove (if_info, x, code, cmp_a, cmp_b, vfalse, vtrue)
- struct noce_if_info *if_info;
- rtx x, cmp_a, cmp_b, vfalse, vtrue;
- enum rtx_code code;
+noce_emit_cmove (struct noce_if_info *if_info, rtx x, enum rtx_code code,
+ rtx cmp_a, rtx cmp_b, rtx vfalse, rtx vtrue)
{
/* If earliest == jump, try to build the cmove insn directly.
This is helpful when combine has created some complex condition
@@ -1024,7 +1136,7 @@ noce_emit_cmove (if_info, x, code, cmp_a, cmp_b, vfalse, vtrue)
#else
/* We'll never get here, as noce_process_if_block doesn't call the
functions involved. Ifdef code, however, should be discouraged
- because it leads to typos in the code not selected. However,
+ because it leads to typos in the code not selected. However,
emit_conditional_move won't exist either. */
return NULL_RTX;
#endif
@@ -1035,8 +1147,7 @@ noce_emit_cmove (if_info, x, code, cmp_a, cmp_b, vfalse, vtrue)
has had a go at it. */
static int
-noce_try_cmove (if_info)
- struct noce_if_info *if_info;
+noce_try_cmove (struct noce_if_info *if_info)
{
enum rtx_code code;
rtx target, seq;
@@ -1058,9 +1169,10 @@ noce_try_cmove (if_info)
noce_emit_move_insn (if_info->x, target);
seq = get_insns ();
+ unshare_ifcvt_sequence (if_info, seq);
end_sequence ();
- emit_insn_before_scope (seq, if_info->jump,
- INSN_SCOPE (if_info->insn_a));
+ emit_insn_before_setloc (seq, if_info->jump,
+ INSN_LOCATOR (if_info->insn_a));
return TRUE;
}
else
@@ -1076,8 +1188,7 @@ noce_try_cmove (if_info)
/* Try more complex cases involving conditional_move. */
static int
-noce_try_cmove_arith (if_info)
- struct noce_if_info *if_info;
+noce_try_cmove_arith (struct noce_if_info *if_info)
{
rtx a = if_info->a;
rtx b = if_info->b;
@@ -1113,7 +1224,7 @@ noce_try_cmove_arith (if_info)
if (test)
x = y;
*/
-
+
code = GET_CODE (if_info->cond);
insn_a = if_info->insn_a;
insn_b = if_info->insn_b;
@@ -1139,7 +1250,7 @@ noce_try_cmove_arith (if_info)
/* If either operand is complex, load it into a register first.
The best way to do this is to copy the original insn. In this
- way we preserve any clobbers etc that the insn may have had.
+ way we preserve any clobbers etc that the insn may have had.
This is of course not possible in the IS_MEM case. */
if (! general_operand (a, GET_MODE (a)))
{
@@ -1176,18 +1287,11 @@ noce_try_cmove_arith (if_info)
if (is_mem)
{
tmp = gen_reg_rtx (GET_MODE (b));
- tmp = emit_insn (gen_rtx_SET (VOIDmode, tmp, b));
+ tmp = emit_insn (gen_rtx_SET (VOIDmode,
+ tmp,
+ b));
}
- else if (! insn_b
-#if 0
- /* In the case we are going to duplicate insn originally
- present in the front of comparsion, verify that the
- comparsion didn't clobbered the operands. */
- || modified_between_p (SET_SRC (single_set (insn_b)),
- if_info->cond_earliest,
- NEXT_INSN (if_info->jump)))
-#endif
- )
+ else if (! insn_b)
goto end_seq_and_fail;
else
{
@@ -1230,8 +1334,9 @@ noce_try_cmove_arith (if_info)
noce_emit_move_insn (x, target);
tmp = get_insns ();
+ unshare_ifcvt_sequence (if_info, tmp);
end_sequence ();
- emit_insn_before_scope (tmp, if_info->jump, INSN_SCOPE (if_info->insn_a));
+ emit_insn_before_setloc (tmp, if_info->jump, INSN_LOCATOR (if_info->insn_a));
return TRUE;
end_seq_and_fail:
@@ -1244,10 +1349,8 @@ noce_try_cmove_arith (if_info)
For these we wish to know that it is A or B in the condition. */
static rtx
-noce_get_alt_condition (if_info, target, earliest)
- struct noce_if_info *if_info;
- rtx target;
- rtx *earliest;
+noce_get_alt_condition (struct noce_if_info *if_info, rtx target,
+ rtx *earliest)
{
rtx cond, set, insn;
int reverse;
@@ -1368,7 +1471,7 @@ noce_get_alt_condition (if_info, target, earliest)
}
cond = canonicalize_condition (if_info->jump, cond, reverse,
- earliest, target);
+ earliest, target, false);
if (! cond || ! reg_mentioned_p (target, cond))
return NULL;
@@ -1393,9 +1496,8 @@ noce_get_alt_condition (if_info, target, earliest)
/* Convert "if (a < b) x = a; else x = b;" to "x = min(a, b);", etc. */
static int
-noce_try_minmax (if_info)
- struct noce_if_info *if_info;
-{
+noce_try_minmax (struct noce_if_info *if_info)
+{
rtx cond, earliest, target, seq;
enum rtx_code code, op;
int unsignedp;
@@ -1478,12 +1580,13 @@ noce_try_minmax (if_info)
noce_emit_move_insn (if_info->x, target);
seq = get_insns ();
- end_sequence ();
+ unshare_ifcvt_sequence (if_info, seq);
+ end_sequence ();
if (seq_contains_jump (seq))
return FALSE;
- emit_insn_before_scope (seq, if_info->jump, INSN_SCOPE (if_info->insn_a));
+ emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATOR (if_info->insn_a));
if_info->cond = cond;
if_info->cond_earliest = earliest;
@@ -1493,9 +1596,8 @@ noce_try_minmax (if_info)
/* Convert "if (a < 0) x = -a; else x = a;" to "x = abs(a);", etc. */
static int
-noce_try_abs (if_info)
- struct noce_if_info *if_info;
-{
+noce_try_abs (struct noce_if_info *if_info)
+{
rtx cond, earliest, target, seq, a, b, c;
int negate;
@@ -1515,7 +1617,7 @@ noce_try_abs (if_info)
}
else
return FALSE;
-
+
cond = noce_get_alt_condition (if_info, b, &earliest);
if (!cond)
return FALSE;
@@ -1534,9 +1636,9 @@ noce_try_abs (if_info)
{
rtx insn, note = NULL;
for (insn = earliest;
- insn != if_info->test_bb->head;
+ insn != BB_HEAD (if_info->test_bb);
insn = PREV_INSN (insn))
- if (INSN_P (insn)
+ if (INSN_P (insn)
&& ((note = find_reg_note (insn, REG_EQUAL, c))
|| (note = find_reg_note (insn, REG_EQUIV, c))))
break;
@@ -1550,7 +1652,7 @@ noce_try_abs (if_info)
c = get_pool_constant (XEXP (c, 0));
/* Work around funny ideas get_condition has wrt canonicalization.
- Note that these rtx constants are known to be CONST_INT, and
+ Note that these rtx constants are known to be CONST_INT, and
therefore imply integer comparisons. */
if (c == constm1_rtx && GET_CODE (cond) == GT)
;
@@ -1579,9 +1681,9 @@ noce_try_abs (if_info)
start_sequence ();
- target = expand_simple_unop (GET_MODE (if_info->x), ABS, b, if_info->x, 0);
+ target = expand_abs_nojump (GET_MODE (if_info->x), b, if_info->x, 1);
- /* ??? It's a quandry whether cmove would be better here, especially
+ /* ??? It's a quandary whether cmove would be better here, especially
for integers. Perhaps combine will clean things up. */
if (target && negate)
target = expand_simple_unop (GET_MODE (target), NEG, target, if_info->x, 0);
@@ -1596,12 +1698,13 @@ noce_try_abs (if_info)
noce_emit_move_insn (if_info->x, target);
seq = get_insns ();
- end_sequence ();
+ unshare_ifcvt_sequence (if_info, seq);
+ end_sequence ();
if (seq_contains_jump (seq))
return FALSE;
- emit_insn_before_scope (seq, if_info->jump, INSN_SCOPE (if_info->insn_a));
+ emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATOR (if_info->insn_a));
if_info->cond = cond;
if_info->cond_earliest = earliest;
@@ -1612,9 +1715,7 @@ noce_try_abs (if_info)
valid at JUMP, instead of at EARLIEST. */
static rtx
-noce_get_condition (jump, earliest)
- rtx jump;
- rtx *earliest;
+noce_get_condition (rtx jump, rtx *earliest)
{
rtx cond, set, tmp, insn;
bool reverse;
@@ -1646,7 +1747,8 @@ noce_get_condition (jump, earliest)
/* Otherwise, fall back on canonicalize_condition to do the dirty
work of manipulating MODE_CC values and COMPARE rtx codes. */
- tmp = canonicalize_condition (jump, cond, reverse, earliest, NULL_RTX);
+ tmp = canonicalize_condition (jump, cond, reverse, earliest, NULL_RTX,
+ false);
if (!tmp)
return NULL_RTX;
@@ -1665,7 +1767,8 @@ noce_get_condition (jump, earliest)
tmp = XEXP (tmp, 0);
if (!REG_P (tmp) || GET_MODE_CLASS (GET_MODE (tmp)) != MODE_INT)
return NULL_RTX;
- tmp = canonicalize_condition (jump, cond, reverse, earliest, tmp);
+ tmp = canonicalize_condition (jump, cond, reverse, earliest, tmp,
+ false);
if (!tmp)
return NULL_RTX;
@@ -1680,8 +1783,7 @@ noce_get_condition (jump, earliest)
/* Return true if OP is ok for if-then-else processing. */
static int
-noce_operand_ok (op)
- rtx op;
+noce_operand_ok (rtx op)
{
/* We special-case memories, so handle any of them with
no address side effects. */
@@ -1699,8 +1801,7 @@ noce_operand_ok (op)
successful at converting the block. */
static int
-noce_process_if_block (ce_info)
- struct ce_if_block * ce_info;
+noce_process_if_block (struct ce_if_block * ce_info)
{
basic_block test_bb = ce_info->test_bb; /* test block */
basic_block then_bb = ce_info->then_bb; /* THEN */
@@ -1735,7 +1836,7 @@ noce_process_if_block (ce_info)
}
/* If this is not a standard conditional jump, we can't parse it. */
- jump = test_bb->end;
+ jump = BB_END (test_bb);
cond = noce_get_condition (jump, &if_info.cond_earliest);
if (! cond)
return FALSE;
@@ -1800,7 +1901,7 @@ noce_process_if_block (ce_info)
/* If x has side effects then only the if-then-else form is safe to
convert. But even in that case we would need to restore any notes
- (such as REG_INC) at then end. That can be tricky if
+ (such as REG_INC) at then end. That can be tricky if
noce_emit_move_insn expands to more than one insn, so disable the
optimization entirely for now if there are side effects. */
if (side_effects_p (x))
@@ -1815,7 +1916,7 @@ noce_process_if_block (ce_info)
|| (SMALL_REGISTER_CLASSES
&& REGNO (x) < FIRST_PSEUDO_REGISTER))
{
- if (no_new_pseudos)
+ if (no_new_pseudos || GET_MODE (x) == BLKmode)
return FALSE;
x = gen_reg_rtx (GET_MODE (GET_CODE (x) == STRICT_LOW_PART
? XEXP (x, 0) : x));
@@ -1851,8 +1952,8 @@ noce_process_if_block (ce_info)
{
rtx note;
- if (else_bb && insn_b == else_bb->end)
- else_bb->end = PREV_INSN (insn_b);
+ if (else_bb && insn_b == BB_END (else_bb))
+ BB_END (else_bb) = PREV_INSN (insn_b);
reorder_insns (insn_b, insn_b, PREV_INSN (jump));
/* If there was a REG_EQUAL note, delete it since it may have been
@@ -1866,11 +1967,32 @@ noce_process_if_block (ce_info)
x must be executed twice. */
else if (insn_b && side_effects_p (orig_x))
return FALSE;
-
+
x = orig_x;
goto success;
}
+ /* Disallow the "if (...) x = a;" form (with an implicit "else x = x;")
+ for most optimizations if writing to x may trap, i.e. its a memory
+ other than a static var or a stack slot. */
+ if (! set_b
+ && GET_CODE (orig_x) == MEM
+ && ! MEM_NOTRAP_P (orig_x)
+ && rtx_addr_can_trap_p (XEXP (orig_x, 0)))
+ {
+ if (HAVE_conditional_move)
+ {
+ if (noce_try_cmove (&if_info))
+ goto success;
+ if (! HAVE_conditional_execution
+ && noce_try_cmove_arith (&if_info))
+ goto success;
+ }
+ return FALSE;
+ }
+
+ if (noce_try_move (&if_info))
+ goto success;
if (noce_try_store_flag (&if_info))
goto success;
if (noce_try_minmax (&if_info))
@@ -1884,7 +2006,7 @@ noce_process_if_block (ce_info)
{
if (noce_try_store_flag_constants (&if_info))
goto success;
- if (noce_try_store_flag_inc (&if_info))
+ if (noce_try_addcc (&if_info))
goto success;
if (noce_try_store_flag_mask (&if_info))
goto success;
@@ -1917,11 +2039,13 @@ noce_process_if_block (ce_info)
if (orig_x != x)
{
start_sequence ();
- noce_emit_move_insn (copy_rtx (orig_x), x);
+ noce_emit_move_insn (orig_x, x);
insn_b = get_insns ();
+ set_used_flags (orig_x);
+ unshare_all_rtl_in_chain (insn_b);
end_sequence ();
- emit_insn_after_scope (insn_b, test_bb->end, INSN_SCOPE (insn_a));
+ emit_insn_after_setloc (insn_b, BB_END (test_bb), INSN_LOCATOR (insn_a));
}
/* Merge the blocks! */
@@ -1934,8 +2058,7 @@ noce_process_if_block (ce_info)
straight line code. Return true if successful. */
static int
-process_if_block (ce_info)
- struct ce_if_block * ce_info;
+process_if_block (struct ce_if_block * ce_info)
{
if (! reload_completed
&& noce_process_if_block (ce_info))
@@ -1965,8 +2088,7 @@ process_if_block (ce_info)
/* Merge the blocks and mark for local life update. */
static void
-merge_if_block (ce_info)
- struct ce_if_block * ce_info;
+merge_if_block (struct ce_if_block * ce_info)
{
basic_block test_bb = ce_info->test_bb; /* last test block */
basic_block then_bb = ce_info->then_bb; /* THEN */
@@ -1985,15 +2107,15 @@ merge_if_block (ce_info)
basic_block bb = test_bb;
basic_block last_test_bb = ce_info->last_test_bb;
basic_block fallthru = block_fallthru (bb);
-
+
do
{
bb = fallthru;
fallthru = block_fallthru (bb);
- if (post_dominators)
- delete_from_dominance_info (post_dominators, bb);
- merge_blocks_nomove (combo_bb, bb);
- num_removed_blocks++;
+ if (dom_computed[CDI_POST_DOMINATORS] >= DOM_NO_FAST_QUERY)
+ delete_from_dominance_info (CDI_POST_DOMINATORS, bb);
+ merge_blocks (combo_bb, bb);
+ num_true_changes++;
}
while (bb != last_test_bb);
}
@@ -2007,10 +2129,10 @@ merge_if_block (ce_info)
if (combo_bb->global_live_at_end)
COPY_REG_SET (combo_bb->global_live_at_end,
then_bb->global_live_at_end);
- if (post_dominators)
- delete_from_dominance_info (post_dominators, then_bb);
- merge_blocks_nomove (combo_bb, then_bb);
- num_removed_blocks++;
+ if (dom_computed[CDI_POST_DOMINATORS] >= DOM_NO_FAST_QUERY)
+ delete_from_dominance_info (CDI_POST_DOMINATORS, then_bb);
+ merge_blocks (combo_bb, then_bb);
+ num_true_changes++;
}
/* The ELSE block, if it existed, had a label. That label count
@@ -2018,10 +2140,10 @@ merge_if_block (ce_info)
get their addresses taken. */
if (else_bb)
{
- if (post_dominators)
- delete_from_dominance_info (post_dominators, else_bb);
- merge_blocks_nomove (combo_bb, else_bb);
- num_removed_blocks++;
+ if (dom_computed[CDI_POST_DOMINATORS] >= DOM_NO_FAST_QUERY)
+ delete_from_dominance_info (CDI_POST_DOMINATORS, else_bb);
+ merge_blocks (combo_bb, else_bb);
+ num_true_changes++;
}
/* If there was no join block reported, that means it was not adjacent
@@ -2029,7 +2151,7 @@ merge_if_block (ce_info)
if (! join_bb)
{
- rtx last = combo_bb->end;
+ rtx last = BB_END (combo_bb);
/* The outgoing edge for the current COMBO block should already
be correct. Verify this. */
@@ -2064,7 +2186,7 @@ merge_if_block (ce_info)
Since we've already merged the TEST, THEN and ELSE blocks, we should
have only one remaining edge from our if-then-else diamond. If there
is more than one remaining edge, it must come from elsewhere. There
- may be zero incoming edges if the THEN block didn't actually join
+ may be zero incoming edges if the THEN block didn't actually join
back up (as with a call to abort). */
else if ((join_bb->pred == NULL
|| join_bb->pred->pred_next == NULL)
@@ -2075,10 +2197,10 @@ merge_if_block (ce_info)
COPY_REG_SET (combo_bb->global_live_at_end,
join_bb->global_live_at_end);
- if (post_dominators)
- delete_from_dominance_info (post_dominators, join_bb);
- merge_blocks_nomove (combo_bb, join_bb);
- num_removed_blocks++;
+ if (dom_computed[CDI_POST_DOMINATORS] >= DOM_NO_FAST_QUERY)
+ delete_from_dominance_info (CDI_POST_DOMINATORS, join_bb);
+ merge_blocks (combo_bb, join_bb);
+ num_true_changes++;
}
else
{
@@ -2104,9 +2226,7 @@ merge_if_block (ce_info)
first block if some transformation was done. Return NULL otherwise. */
static basic_block
-find_if_header (test_bb, pass)
- basic_block test_bb;
- int pass;
+find_if_header (basic_block test_bb, int pass)
{
ce_if_block_t ce_info;
edge then_edge;
@@ -2123,6 +2243,11 @@ find_if_header (test_bb, pass)
|| (else_edge->flags & EDGE_COMPLEX))
return NULL;
+ /* Nor exit the loop. */
+ if ((then_edge->flags & EDGE_LOOP_EXIT)
+ || (else_edge->flags & EDGE_LOOP_EXIT))
+ return NULL;
+
/* The THEN edge is canonically the one that falls through. */
if (then_edge->flags & EDGE_FALLTHRU)
;
@@ -2136,7 +2261,7 @@ find_if_header (test_bb, pass)
/* Otherwise this must be a multiway branch of some sort. */
return NULL;
- memset ((PTR) &ce_info, '\0', sizeof (ce_info));
+ memset (&ce_info, '\0', sizeof (ce_info));
ce_info.test_bb = test_bb;
ce_info.then_bb = then_edge->dest;
ce_info.else_bb = else_edge->dest;
@@ -2153,7 +2278,7 @@ find_if_header (test_bb, pass)
&& find_cond_trap (test_bb, then_edge, else_edge))
goto success;
- if (post_dominators
+ if (dom_computed[CDI_POST_DOMINATORS] >= DOM_NO_FAST_QUERY
&& (! HAVE_conditional_execution || reload_completed))
{
if (find_if_case_1 (test_bb, then_edge, else_edge))
@@ -2176,9 +2301,7 @@ find_if_header (test_bb, pass)
of non-note, non-jump, non-USE/CLOBBER insns in the block. */
static int
-block_jumps_and_fallthru_p (cur_bb, target_bb)
- basic_block cur_bb;
- basic_block target_bb;
+block_jumps_and_fallthru_p (basic_block cur_bb, basic_block target_bb)
{
edge cur_edge;
int fallthru_p = FALSE;
@@ -2219,8 +2342,8 @@ block_jumps_and_fallthru_p (cur_bb, target_bb)
together for conditional execution support. ??? we should support
conditional execution support across calls for IA-64 some day, but
for now it makes the code simpler. */
- end = cur_bb->end;
- insn = cur_bb->head;
+ end = BB_END (cur_bb);
+ insn = BB_HEAD (cur_bb);
while (insn != NULL_RTX)
{
@@ -2247,8 +2370,7 @@ block_jumps_and_fallthru_p (cur_bb, target_bb)
Return TRUE if we were successful at converting the block. */
static int
-find_if_block (ce_info)
- struct ce_if_block * ce_info;
+find_if_block (struct ce_if_block * ce_info)
{
basic_block test_bb = ce_info->test_bb;
basic_block then_bb = ce_info->then_bb;
@@ -2276,7 +2398,7 @@ find_if_block (ce_info)
int max_insns = MAX_CONDITIONAL_EXECUTE;
int n_insns;
- /* Determine if the preceeding block is an && or || block. */
+ /* Determine if the preceding block is an && or || block. */
if ((n_insns = block_jumps_and_fallthru_p (bb, else_bb)) >= 0)
{
ce_info->and_and_p = TRUE;
@@ -2284,7 +2406,7 @@ find_if_block (ce_info)
}
else if ((n_insns = block_jumps_and_fallthru_p (bb, then_bb)) >= 0)
{
- ce_info->and_and_p = FALSE;
+ ce_info->and_and_p = FALSE;
target_bb = then_bb;
}
else
@@ -2352,7 +2474,7 @@ find_if_block (ce_info)
if (then_succ != NULL_EDGE
&& (then_succ->succ_next != NULL_EDGE
|| (then_succ->flags & EDGE_COMPLEX)
- || (flow2_completed && tablejump_p (then_bb->end))))
+ || (flow2_completed && tablejump_p (BB_END (then_bb), NULL, NULL))))
return FALSE;
/* If the THEN block has no successors, conditional execution can still
@@ -2365,11 +2487,11 @@ find_if_block (ce_info)
{
if (else_bb->pred->pred_next == NULL_EDGE)
{
- rtx last_insn = then_bb->end;
+ rtx last_insn = BB_END (then_bb);
while (last_insn
&& GET_CODE (last_insn) == NOTE
- && last_insn != then_bb->head)
+ && last_insn != BB_HEAD (then_bb))
last_insn = PREV_INSN (last_insn);
if (last_insn
@@ -2400,12 +2522,12 @@ find_if_block (ce_info)
&& else_bb->pred->pred_next == NULL_EDGE
&& else_succ->succ_next == NULL_EDGE
&& ! (else_succ->flags & EDGE_COMPLEX)
- && ! (flow2_completed && tablejump_p (else_bb->end)))
+ && ! (flow2_completed && tablejump_p (BB_END (else_bb), NULL, NULL)))
join_bb = else_succ->dest;
/* Otherwise it is not an IF-THEN or IF-THEN-ELSE combination. */
else
- return FALSE;
+ return FALSE;
num_possible_if_blocks++;
@@ -2414,15 +2536,15 @@ find_if_block (ce_info)
fprintf (rtl_dump_file, "\nIF-THEN%s block found, pass %d, start block %d [insn %d], then %d [%d]",
(else_bb) ? "-ELSE" : "",
ce_info->pass,
- test_bb->index, (test_bb->head) ? (int)INSN_UID (test_bb->head) : -1,
- then_bb->index, (then_bb->head) ? (int)INSN_UID (then_bb->head) : -1);
+ test_bb->index, (BB_HEAD (test_bb)) ? (int)INSN_UID (BB_HEAD (test_bb)) : -1,
+ then_bb->index, (BB_HEAD (then_bb)) ? (int)INSN_UID (BB_HEAD (then_bb)) : -1);
if (else_bb)
fprintf (rtl_dump_file, ", else %d [%d]",
- else_bb->index, (else_bb->head) ? (int)INSN_UID (else_bb->head) : -1);
+ else_bb->index, (BB_HEAD (else_bb)) ? (int)INSN_UID (BB_HEAD (else_bb)) : -1);
fprintf (rtl_dump_file, ", join %d [%d]",
- join_bb->index, (join_bb->head) ? (int)INSN_UID (join_bb->head) : -1);
+ join_bb->index, (BB_HEAD (join_bb)) ? (int)INSN_UID (BB_HEAD (join_bb)) : -1);
if (ce_info->num_multiple_test_blocks > 0)
fprintf (rtl_dump_file, ", %d %s block%s last test %d [%d]",
@@ -2430,8 +2552,8 @@ find_if_block (ce_info)
(ce_info->and_and_p) ? "&&" : "||",
(ce_info->num_multiple_test_blocks == 1) ? "" : "s",
ce_info->last_test_bb->index,
- ((ce_info->last_test_bb->head)
- ? (int)INSN_UID (ce_info->last_test_bb->head)
+ ((BB_HEAD (ce_info->last_test_bb))
+ ? (int)INSN_UID (BB_HEAD (ce_info->last_test_bb))
: -1));
fputc ('\n', rtl_dump_file);
@@ -2467,9 +2589,7 @@ find_if_block (ce_info)
to a trap, into a conditional trap. */
static int
-find_cond_trap (test_bb, then_edge, else_edge)
- basic_block test_bb;
- edge then_edge, else_edge;
+find_cond_trap (basic_block test_bb, edge then_edge, edge else_edge)
{
basic_block then_bb = then_edge->dest;
basic_block else_bb = else_edge->dest;
@@ -2494,7 +2614,7 @@ find_cond_trap (test_bb, then_edge, else_edge)
}
/* If this is not a standard conditional jump, we can't parse it. */
- jump = test_bb->end;
+ jump = BB_END (test_bb);
cond = noce_get_condition (jump, &cond_earliest);
if (! cond)
return FALSE;
@@ -2518,22 +2638,24 @@ find_cond_trap (test_bb, then_edge, else_edge)
}
/* Attempt to generate the conditional trap. */
- seq = gen_cond_trap (code, XEXP (cond, 0), XEXP (cond, 1),
+ seq = gen_cond_trap (code, XEXP (cond, 0),
+ XEXP (cond, 1),
TRAP_CODE (PATTERN (trap)));
if (seq == NULL)
return FALSE;
+ num_true_changes++;
+
/* Emit the new insns before cond_earliest. */
- emit_insn_before_scope (seq, cond_earliest, INSN_SCOPE (trap));
+ emit_insn_before_setloc (seq, cond_earliest, INSN_LOCATOR (trap));
/* Delete the trap block if possible. */
remove_edge (trap_bb == then_bb ? then_edge : else_edge);
if (trap_bb->pred == NULL)
{
- if (post_dominators)
- delete_from_dominance_info (post_dominators, trap_bb);
- flow_delete_block (trap_bb);
- num_removed_blocks++;
+ if (dom_computed[CDI_POST_DOMINATORS] >= DOM_NO_FAST_QUERY)
+ delete_from_dominance_info (CDI_POST_DOMINATORS, trap_bb);
+ delete_block (trap_bb);
}
/* If the non-trap block and the test are now adjacent, merge them.
@@ -2542,7 +2664,7 @@ find_cond_trap (test_bb, then_edge, else_edge)
{
struct ce_if_block new_ce_info;
delete_insn (jump);
- memset ((PTR) &new_ce_info, '\0', sizeof (new_ce_info));
+ memset (&new_ce_info, '\0', sizeof (new_ce_info));
new_ce_info.test_bb = test_bb;
new_ce_info.then_bb = NULL;
new_ce_info.else_bb = NULL;
@@ -2565,12 +2687,11 @@ find_cond_trap (test_bb, then_edge, else_edge)
return TRUE;
}
-/* Subroutine of find_cond_trap: if BB contains only a trap insn,
+/* Subroutine of find_cond_trap: if BB contains only a trap insn,
return it. */
static rtx
-block_has_only_trap (bb)
- basic_block bb;
+block_has_only_trap (basic_block bb)
{
rtx trap;
@@ -2584,7 +2705,7 @@ block_has_only_trap (bb)
/* The only instruction in the THEN block must be the trap. */
trap = first_active_insn (bb);
- if (! (trap == bb->end
+ if (! (trap == BB_END (bb)
&& GET_CODE (PATTERN (trap)) == TRAP_IF
&& TRAP_CONDITION (PATTERN (trap)) == const_true_rtx))
return NULL_RTX;
@@ -2670,9 +2791,7 @@ block_has_only_trap (bb)
/* Tests for case 1 above. */
static int
-find_if_case_1 (test_bb, then_edge, else_edge)
- basic_block test_bb;
- edge then_edge, else_edge;
+find_if_case_1 (basic_block test_bb, edge then_edge, edge else_edge)
{
basic_block then_bb = then_edge->dest;
basic_block else_bb = else_edge->dest, new_bb;
@@ -2706,7 +2825,7 @@ find_if_case_1 (test_bb, then_edge, else_edge)
return FALSE;
/* Registers set are dead, or are predicable. */
- if (! dead_or_predicable (test_bb, then_bb, else_bb,
+ if (! dead_or_predicable (test_bb, then_bb, else_bb,
then_bb->succ->dest, 1))
return FALSE;
@@ -2716,12 +2835,12 @@ find_if_case_1 (test_bb, then_edge, else_edge)
bitmap_operation (test_bb->global_live_at_end,
else_bb->global_live_at_start,
then_bb->global_live_at_end, BITMAP_IOR);
-
+
new_bb = redirect_edge_and_branch_force (FALLTHRU_EDGE (test_bb), else_bb);
then_bb_index = then_bb->index;
- if (post_dominators)
- delete_from_dominance_info (post_dominators, then_bb);
- flow_delete_block (then_bb);
+ if (dom_computed[CDI_POST_DOMINATORS] >= DOM_NO_FAST_QUERY)
+ delete_from_dominance_info (CDI_POST_DOMINATORS, then_bb);
+ delete_block (then_bb);
/* Make rest of code believe that the newly created block is the THEN_BB
block we removed. */
@@ -2729,13 +2848,13 @@ find_if_case_1 (test_bb, then_edge, else_edge)
{
new_bb->index = then_bb_index;
BASIC_BLOCK (then_bb_index) = new_bb;
- if (post_dominators)
- add_to_dominance_info (post_dominators, new_bb);
+ if (dom_computed[CDI_POST_DOMINATORS] >= DOM_NO_FAST_QUERY)
+ add_to_dominance_info (CDI_POST_DOMINATORS, new_bb);
}
/* We've possibly created jump to next insn, cleanup_cfg will solve that
later. */
- num_removed_blocks++;
+ num_true_changes++;
num_updated_if_blocks++;
return TRUE;
@@ -2744,9 +2863,7 @@ find_if_case_1 (test_bb, then_edge, else_edge)
/* Test for case 2 above. */
static int
-find_if_case_2 (test_bb, then_edge, else_edge)
- basic_block test_bb;
- edge then_edge, else_edge;
+find_if_case_2 (basic_block test_bb, edge then_edge, edge else_edge)
{
basic_block then_bb = then_edge->dest;
basic_block else_bb = else_edge->dest;
@@ -2770,11 +2887,11 @@ find_if_case_2 (test_bb, then_edge, else_edge)
return FALSE;
/* ELSE is predicted or SUCC(ELSE) postdominates THEN. */
- note = find_reg_note (test_bb->end, REG_BR_PROB, NULL_RTX);
+ note = find_reg_note (BB_END (test_bb), REG_BR_PROB, NULL_RTX);
if (note && INTVAL (XEXP (note, 0)) >= REG_BR_PROB_BASE / 2)
;
else if (else_succ->dest->index < 0
- || dominated_by_p (post_dominators, then_bb,
+ || dominated_by_p (CDI_POST_DOMINATORS, then_bb,
else_succ->dest))
;
else
@@ -2800,12 +2917,12 @@ find_if_case_2 (test_bb, then_edge, else_edge)
bitmap_operation (test_bb->global_live_at_end,
then_bb->global_live_at_start,
else_bb->global_live_at_end, BITMAP_IOR);
-
- if (post_dominators)
- delete_from_dominance_info (post_dominators, else_bb);
- flow_delete_block (else_bb);
- num_removed_blocks++;
+ if (dom_computed[CDI_POST_DOMINATORS] >= DOM_NO_FAST_QUERY)
+ delete_from_dominance_info (CDI_POST_DOMINATORS, else_bb);
+ delete_block (else_bb);
+
+ num_true_changes++;
num_updated_if_blocks++;
/* ??? We may now fallthru from one of THEN's successors into a join
@@ -2818,9 +2935,7 @@ find_if_case_2 (test_bb, then_edge, else_edge)
Return 1 if a memory is found. */
static int
-find_memory (px, data)
- rtx *px;
- void *data ATTRIBUTE_UNUSED;
+find_memory (rtx *px, void *data ATTRIBUTE_UNUSED)
{
return GET_CODE (*px) == MEM;
}
@@ -2834,18 +2949,16 @@ find_memory (px, data)
REVERSEP is true if the sense of the branch should be reversed. */
static int
-dead_or_predicable (test_bb, merge_bb, other_bb, new_dest, reversep)
- basic_block test_bb, merge_bb, other_bb;
- basic_block new_dest;
- int reversep;
+dead_or_predicable (basic_block test_bb, basic_block merge_bb,
+ basic_block other_bb, basic_block new_dest, int reversep)
{
rtx head, end, jump, earliest, old_dest, new_label = NULL_RTX;
- jump = test_bb->end;
+ jump = BB_END (test_bb);
/* Find the extent of the real code in the merge block. */
- head = merge_bb->head;
- end = merge_bb->end;
+ head = BB_HEAD (merge_bb);
+ end = BB_END (merge_bb);
if (GET_CODE (head) == CODE_LABEL)
head = NEXT_INSN (head);
@@ -2861,28 +2974,11 @@ dead_or_predicable (test_bb, merge_bb, other_bb, new_dest, reversep)
if (GET_CODE (end) == JUMP_INSN)
{
- rtx tmp, insn, label;
-
if (head == end)
{
head = end = NULL_RTX;
goto no_body;
}
-
- /* If there is a jump table following merge_bb, fail
- if there are any insn between head and PREV_INSN (end)
- references it. */
- if ((label = JUMP_LABEL (end)) != NULL_RTX
- && (tmp = NEXT_INSN (label)) != NULL_RTX
- && GET_CODE (tmp) == JUMP_INSN
- && (GET_CODE (PATTERN (tmp)) == ADDR_VEC
- || GET_CODE (PATTERN (tmp)) == ADDR_DIFF_VEC))
- {
- for (insn = head; insn != PREV_INSN (end); insn = NEXT_INSN (insn))
- if (find_reg_note (insn, REG_LABEL, label))
- return FALSE;
- }
-
end = PREV_INSN (end);
}
@@ -2892,8 +2988,8 @@ dead_or_predicable (test_bb, merge_bb, other_bb, new_dest, reversep)
if (HAVE_conditional_execution)
{
/* In the conditional execution case, we have things easy. We know
- the condition is reversable. We don't have to check life info,
- becase we're going to conditionally execute the code anyway.
+ the condition is reversible. We don't have to check life info
+ because we're going to conditionally execute the code anyway.
All that's left is making sure the insns involved can actually
be predicated. */
@@ -2979,7 +3075,7 @@ dead_or_predicable (test_bb, merge_bb, other_bb, new_dest, reversep)
test_set = INITIALIZE_REG_SET (test_set_head);
/* ??? bb->local_set is only valid during calculate_global_regs_live,
- so we must recompute usage for MERGE_BB. Not so bad, I suppose,
+ so we must recompute usage for MERGE_BB. Not so bad, I suppose,
since we've already asserted that MERGE_BB is small. */
propagate_block (merge_bb, tmp, merge_set, merge_set, 0);
@@ -3082,8 +3178,8 @@ dead_or_predicable (test_bb, merge_bb, other_bb, new_dest, reversep)
/* Move the insns out of MERGE_BB to before the branch. */
if (head != NULL)
{
- if (end == merge_bb->end)
- merge_bb->end = PREV_INSN (head);
+ if (end == BB_END (merge_bb))
+ BB_END (merge_bb) = PREV_INSN (head);
if (squeeze_notes (&head, &end))
return TRUE;
@@ -3110,27 +3206,27 @@ dead_or_predicable (test_bb, merge_bb, other_bb, new_dest, reversep)
/* Main entry point for all if-conversion. */
void
-if_convert (x_life_data_ok)
- int x_life_data_ok;
+if_convert (int x_life_data_ok)
{
basic_block bb;
int pass;
num_possible_if_blocks = 0;
num_updated_if_blocks = 0;
- num_removed_blocks = 0;
+ num_true_changes = 0;
life_data_ok = (x_life_data_ok != 0);
+ if (! (* targetm.cannot_modify_jumps_p) ())
+ mark_loop_exit_edges ();
+
/* Free up basic_block_for_insn so that we don't have to keep it
- up to date, either here or in merge_blocks_nomove. */
+ up to date, either here or in merge_blocks. */
free_basic_block_vars (1);
/* Compute postdominators if we think we'll use them. */
- post_dominators = NULL;
if (HAVE_conditional_execution || life_data_ok)
- {
- post_dominators = calculate_dominance_info (CDI_POST_DOMINATORS);
- }
+ calculate_dominance_info (CDI_POST_DOMINATORS);
+
if (life_data_ok)
clear_bb_flags ();
@@ -3167,8 +3263,7 @@ if_convert (x_life_data_ok)
fprintf (rtl_dump_file, "\n\n========== no more changes\n");
#endif
- if (post_dominators)
- free_dominance_info (post_dominators);
+ free_dominance_info (CDI_POST_DOMINATORS);
if (rtl_dump_file)
fflush (rtl_dump_file);
@@ -3176,7 +3271,7 @@ if_convert (x_life_data_ok)
clear_aux_for_blocks ();
/* Rebuild life info for basic blocks that require it. */
- if (num_removed_blocks && life_data_ok)
+ if (num_true_changes && life_data_ok)
{
/* If we allocated new pseudos, we must resize the array for sched1. */
if (max_regno < max_reg_num ())
@@ -3199,8 +3294,8 @@ if_convert (x_life_data_ok)
"%d IF blocks converted.\n",
num_updated_if_blocks);
fprintf (rtl_dump_file,
- "%d basic blocks deleted.\n\n\n",
- num_removed_blocks);
+ "%d true changes made.\n\n\n",
+ num_true_changes);
}
#ifdef ENABLE_CHECKING
OpenPOWER on IntegriCloud