ifcvt.c (noce_try_store_flag_constants): Don't check no_new_pseudos here.
* ifcvt.c (noce_try_store_flag_constants): Don't check no_new_pseudos here. (noce_try_store_flag_constants): Don't check no_new_pseudos. (noce_try_addcc, noce_try_store_flag_mask, noce_try_cmove_arith, noce_try_cmove_arith, noce_try_minmax, noce_try_abs, noce_try_sign_mask): Likewise. (if_convert): Check no_new_pseudos here. (cond_exec_process_if_block, noce_process_if_block, find_if_block): Remove prototypes. (struct noce_if_info): Add then_bb, else_bb, join_bb members. (noce_get_condition): Handle new then_else_reversed argument. (noce_init_if_info): Remove, fold into noce_find_if_block. (noce_process_if_block): Take a struct noce_if_info as the argument. Don't set up one based on ce_if_info. Update pointer references accordingly. (cond_move_process_if_block): Likewise. (process_if_block): Removed. (find_if_block): Removed. Move functionality two new functions, noce_find_if_block and cond_exec_find_if_block. (noce_find_if_block): New function. Be aware of IF-THEN-JOIN blocks and the symmetric IF-ELSE-JOIN case. (cond_exec_find_if_block): Also new function mostly based on old find_if_block and process_if_block. (find_if_header): Replace find_if_block call with separately guarded calls to noce_find_if_block and cond_exec_find_if_block. (find_cond_trap): Update noce_get_condition call. (dead_or_predicable): Likewise. From-SVN: r123223
This commit is contained in:
parent
646714ab75
commit
93242b9c1b
2 changed files with 239 additions and 173 deletions
|
@ -1,3 +1,34 @@
|
|||
2007-03-26 Steven Bosscher <steven@gcc.gnu.org>
|
||||
|
||||
* ifcvt.c (noce_try_store_flag_constants): Don't check
|
||||
no_new_pseudos here.
|
||||
(noce_try_store_flag_constants): Don't check no_new_pseudos.
|
||||
(noce_try_addcc, noce_try_store_flag_mask, noce_try_cmove_arith,
|
||||
noce_try_cmove_arith, noce_try_minmax, noce_try_abs,
|
||||
noce_try_sign_mask): Likewise.
|
||||
(if_convert): Check no_new_pseudos here.
|
||||
|
||||
(cond_exec_process_if_block, noce_process_if_block, find_if_block):
|
||||
Remove prototypes.
|
||||
(struct noce_if_info): Add then_bb, else_bb, join_bb members.
|
||||
(noce_get_condition): Handle new then_else_reversed argument.
|
||||
(noce_init_if_info): Remove, fold into noce_find_if_block.
|
||||
(noce_process_if_block): Take a struct noce_if_info as the
|
||||
argument. Don't set up one based on ce_if_info. Update pointer
|
||||
references accordingly.
|
||||
(cond_move_process_if_block): Likewise.
|
||||
(process_if_block): Removed.
|
||||
(find_if_block): Removed. Move functionality two new functions,
|
||||
noce_find_if_block and cond_exec_find_if_block.
|
||||
(noce_find_if_block): New function. Be aware of IF-THEN-JOIN
|
||||
blocks and the symmetric IF-ELSE-JOIN case.
|
||||
(cond_exec_find_if_block): Also new function mostly based on old
|
||||
find_if_block and process_if_block.
|
||||
(find_if_header): Replace find_if_block call with separately
|
||||
guarded calls to noce_find_if_block and cond_exec_find_if_block.
|
||||
(find_cond_trap): Update noce_get_condition call.
|
||||
(dead_or_predicable): Likewise.
|
||||
|
||||
2007-03-26 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* config/i386/i386.c (IX86_BUILTIN_CMPNEPD, IX86_BUILTIN_CMPNESD):
|
||||
|
|
381
gcc/ifcvt.c
381
gcc/ifcvt.c
|
@ -96,16 +96,14 @@ static rtx last_active_insn (basic_block, int);
|
|||
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 rtx noce_get_condition (rtx, rtx *, bool);
|
||||
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 noce_find_if_block (basic_block, edge, edge, int);
|
||||
static int cond_exec_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 *);
|
||||
|
@ -598,8 +596,8 @@ cond_exec_process_if_block (ce_if_block_t * ce_info,
|
|||
|
||||
struct noce_if_info
|
||||
{
|
||||
/* A basic block that ends in a simple conditional jump. */
|
||||
basic_block test_bb;
|
||||
/* The basic blocks that make up the IF-THEN-{ELSE-,}JOIN block. */
|
||||
basic_block test_bb, then_bb, else_bb, join_bb;
|
||||
|
||||
/* The jump that ends TEST_BB. */
|
||||
rtx jump;
|
||||
|
@ -938,8 +936,7 @@ noce_try_store_flag_constants (struct noce_if_info *if_info)
|
|||
int normalize, can_reverse;
|
||||
enum machine_mode mode;
|
||||
|
||||
if (! no_new_pseudos
|
||||
&& GET_CODE (if_info->a) == CONST_INT
|
||||
if (GET_CODE (if_info->a) == CONST_INT
|
||||
&& GET_CODE (if_info->b) == CONST_INT)
|
||||
{
|
||||
mode = GET_MODE (if_info->x);
|
||||
|
@ -1065,8 +1062,7 @@ noce_try_addcc (struct noce_if_info *if_info)
|
|||
rtx target, seq;
|
||||
int subtract, normalize;
|
||||
|
||||
if (! no_new_pseudos
|
||||
&& GET_CODE (if_info->a) == PLUS
|
||||
if (GET_CODE (if_info->a) == PLUS
|
||||
&& rtx_equal_p (XEXP (if_info->a, 0), if_info->b)
|
||||
&& (reversed_comparison_code (if_info->cond, if_info->jump)
|
||||
!= UNKNOWN))
|
||||
|
@ -1157,9 +1153,8 @@ noce_try_store_flag_mask (struct noce_if_info *if_info)
|
|||
int reversep;
|
||||
|
||||
reversep = 0;
|
||||
if (! no_new_pseudos
|
||||
&& (BRANCH_COST >= 2
|
||||
|| STORE_FLAG_VALUE == -1)
|
||||
if ((BRANCH_COST >= 2
|
||||
|| STORE_FLAG_VALUE == -1)
|
||||
&& ((if_info->a == const0_rtx
|
||||
&& rtx_equal_p (if_info->b, if_info->x))
|
||||
|| ((reversep = (reversed_comparison_code (if_info->cond,
|
||||
|
@ -1314,7 +1309,8 @@ noce_try_cmove_arith (struct noce_if_info *if_info)
|
|||
conditional on their addresses followed by a load. Don't do this
|
||||
early because it'll screw alias analysis. Note that we've
|
||||
already checked for no side effects. */
|
||||
if (! no_new_pseudos && cse_not_expected
|
||||
/* ??? FIXME: Magic number 5. */
|
||||
if (cse_not_expected
|
||||
&& MEM_P (a) && MEM_P (b)
|
||||
&& BRANCH_COST >= 5)
|
||||
{
|
||||
|
@ -1389,9 +1385,6 @@ noce_try_cmove_arith (struct noce_if_info *if_info)
|
|||
{
|
||||
rtx set;
|
||||
|
||||
if (no_new_pseudos)
|
||||
goto end_seq_and_fail;
|
||||
|
||||
if (is_mem)
|
||||
{
|
||||
tmp = gen_reg_rtx (GET_MODE (a));
|
||||
|
@ -1414,9 +1407,6 @@ noce_try_cmove_arith (struct noce_if_info *if_info)
|
|||
{
|
||||
rtx set, last;
|
||||
|
||||
if (no_new_pseudos)
|
||||
goto end_seq_and_fail;
|
||||
|
||||
if (is_mem)
|
||||
{
|
||||
tmp = gen_reg_rtx (GET_MODE (b));
|
||||
|
@ -1648,10 +1638,6 @@ noce_try_minmax (struct noce_if_info *if_info)
|
|||
enum rtx_code code, op;
|
||||
int unsignedp;
|
||||
|
||||
/* ??? Can't guarantee that expand_binop won't create pseudos. */
|
||||
if (no_new_pseudos)
|
||||
return FALSE;
|
||||
|
||||
/* ??? Reject modes with NaNs or signed zeros since we don't know how
|
||||
they will be resolved with an SMIN/SMAX. It wouldn't be too hard
|
||||
to get the target to tell us... */
|
||||
|
@ -1744,10 +1730,6 @@ noce_try_abs (struct noce_if_info *if_info)
|
|||
rtx cond, earliest, target, seq, a, b, c;
|
||||
int negate;
|
||||
|
||||
/* ??? Can't guarantee that expand_binop won't create pseudos. */
|
||||
if (no_new_pseudos)
|
||||
return FALSE;
|
||||
|
||||
/* Recognize A and B as constituting an ABS or NABS. The canonical
|
||||
form is a branch around the negation, taken when the object is the
|
||||
first operand of a comparison against 0 that evaluates to true. */
|
||||
|
@ -1868,9 +1850,6 @@ noce_try_sign_mask (struct noce_if_info *if_info)
|
|||
enum rtx_code code;
|
||||
bool b_unconditional;
|
||||
|
||||
if (no_new_pseudos)
|
||||
return FALSE;
|
||||
|
||||
cond = if_info->cond;
|
||||
code = GET_CODE (cond);
|
||||
m = XEXP (cond, 0);
|
||||
|
@ -2036,10 +2015,13 @@ noce_try_bitop (struct noce_if_info *if_info)
|
|||
|
||||
|
||||
/* Similar to get_condition, only the resulting condition must be
|
||||
valid at JUMP, instead of at EARLIEST. */
|
||||
valid at JUMP, instead of at EARLIEST.
|
||||
|
||||
If THEN_ELSE_REVERSED is true, the fallthrough goes to the THEN
|
||||
block of the caller, and we have to reverse the condition. */
|
||||
|
||||
static rtx
|
||||
noce_get_condition (rtx jump, rtx *earliest)
|
||||
noce_get_condition (rtx jump, rtx *earliest, bool then_else_reversed)
|
||||
{
|
||||
rtx cond, set, tmp;
|
||||
bool reverse;
|
||||
|
@ -2054,6 +2036,11 @@ noce_get_condition (rtx jump, rtx *earliest)
|
|||
reverse = (GET_CODE (XEXP (SET_SRC (set), 2)) == LABEL_REF
|
||||
&& XEXP (XEXP (SET_SRC (set), 2), 0) == JUMP_LABEL (jump));
|
||||
|
||||
/* We may have to reverse because the caller's if block is not canonical
|
||||
(i.e. the ELSE block isn't the fallthrough block for the TEST block). */
|
||||
if (then_else_reversed)
|
||||
reverse = !reverse;
|
||||
|
||||
/* If the condition variable is a register and is MODE_INT, accept it. */
|
||||
|
||||
cond = XEXP (SET_SRC (set), 0);
|
||||
|
@ -2074,52 +2061,6 @@ noce_get_condition (rtx jump, rtx *earliest)
|
|||
NULL_RTX, false, true);
|
||||
}
|
||||
|
||||
/* Initialize for a simple IF-THEN or IF-THEN-ELSE block. We will not
|
||||
be using conditional execution. Set some fields of IF_INFO based
|
||||
on CE_INFO: test_bb, cond, jump, cond_earliest. Return TRUE if
|
||||
things look OK. */
|
||||
|
||||
static int
|
||||
noce_init_if_info (struct ce_if_block *ce_info, struct noce_if_info *if_info)
|
||||
{
|
||||
basic_block test_bb = ce_info->test_bb;
|
||||
rtx cond, jump;
|
||||
|
||||
/* If test is comprised of && or || elements, don't handle it unless
|
||||
it is the special case of && elements without an ELSE block. */
|
||||
if (ce_info->num_multiple_test_blocks)
|
||||
{
|
||||
if (ce_info->else_bb || !ce_info->and_and_p)
|
||||
return FALSE;
|
||||
|
||||
ce_info->test_bb = test_bb = ce_info->last_test_bb;
|
||||
ce_info->num_multiple_test_blocks = 0;
|
||||
ce_info->num_and_and_blocks = 0;
|
||||
ce_info->num_or_or_blocks = 0;
|
||||
}
|
||||
|
||||
/* If this is not a standard conditional jump, we can't parse it. */
|
||||
jump = BB_END (test_bb);
|
||||
cond = noce_get_condition (jump, &if_info->cond_earliest);
|
||||
if (!cond)
|
||||
return FALSE;
|
||||
|
||||
/* If the conditional jump is more than just a conditional
|
||||
jump, then we can not do if-conversion on this block. */
|
||||
if (! onlyjump_p (jump))
|
||||
return FALSE;
|
||||
|
||||
/* We must be comparing objects whose modes imply the size. */
|
||||
if (GET_MODE (XEXP (cond, 0)) == BLKmode)
|
||||
return FALSE;
|
||||
|
||||
if_info->test_bb = test_bb;
|
||||
if_info->cond = cond;
|
||||
if_info->jump = jump;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Return true if OP is ok for if-then-else processing. */
|
||||
|
||||
static int
|
||||
|
@ -2189,22 +2130,22 @@ noce_mem_write_may_trap_or_fault_p (rtx mem)
|
|||
return false;
|
||||
}
|
||||
|
||||
/* Given a simple IF-THEN or IF-THEN-ELSE block, attempt to convert it
|
||||
without using conditional execution. Return TRUE if we were
|
||||
successful at converting the block. */
|
||||
/* Given a simple IF-THEN-JOIN or IF-THEN-ELSE-JOIN block, attempt to convert
|
||||
it without using conditional execution. Return TRUE if we were successful
|
||||
at converting the block. */
|
||||
|
||||
static int
|
||||
noce_process_if_block (struct ce_if_block * ce_info)
|
||||
noce_process_if_block (struct noce_if_info *if_info)
|
||||
{
|
||||
basic_block test_bb = ce_info->test_bb; /* test block */
|
||||
basic_block then_bb = ce_info->then_bb; /* THEN */
|
||||
basic_block else_bb = ce_info->else_bb; /* ELSE or NULL */
|
||||
basic_block join_bb;
|
||||
struct noce_if_info if_info;
|
||||
basic_block test_bb = if_info->test_bb; /* test block */
|
||||
basic_block then_bb = if_info->then_bb; /* THEN */
|
||||
basic_block else_bb = if_info->else_bb; /* ELSE or NULL */
|
||||
basic_block join_bb = if_info->join_bb; /* JOIN */
|
||||
rtx jump = if_info->jump;
|
||||
rtx cond = if_info->cond;
|
||||
rtx insn_a, insn_b;
|
||||
rtx set_a, set_b;
|
||||
rtx orig_x, x, a, b;
|
||||
rtx jump, cond;
|
||||
|
||||
/* We're looking for patterns of the form
|
||||
|
||||
|
@ -2216,12 +2157,6 @@ noce_process_if_block (struct ce_if_block * ce_info)
|
|||
|
||||
??? For future expansion, look for multiple X in such patterns. */
|
||||
|
||||
if (!noce_init_if_info (ce_info, &if_info))
|
||||
return FALSE;
|
||||
|
||||
cond = if_info.cond;
|
||||
jump = if_info.jump;
|
||||
|
||||
/* Look for one of the potential sets. */
|
||||
insn_a = first_active_insn (then_bb);
|
||||
if (! insn_a
|
||||
|
@ -2251,7 +2186,7 @@ noce_process_if_block (struct ce_if_block * ce_info)
|
|||
}
|
||||
else
|
||||
{
|
||||
insn_b = prev_nonnote_insn (if_info.cond_earliest);
|
||||
insn_b = prev_nonnote_insn (if_info->cond_earliest);
|
||||
/* We're going to be moving the evaluation of B down from above
|
||||
COND_EARLIEST to JUMP. Make sure the relevant data is still
|
||||
intact. */
|
||||
|
@ -2261,13 +2196,13 @@ noce_process_if_block (struct ce_if_block * ce_info)
|
|||
|| ! rtx_equal_p (x, SET_DEST (set_b))
|
||||
|| reg_overlap_mentioned_p (x, SET_SRC (set_b))
|
||||
|| modified_between_p (SET_SRC (set_b),
|
||||
PREV_INSN (if_info.cond_earliest), jump)
|
||||
PREV_INSN (if_info->cond_earliest), jump)
|
||||
/* Likewise with X. In particular this can happen when
|
||||
noce_get_condition looks farther back in the instruction
|
||||
stream than one might expect. */
|
||||
|| reg_overlap_mentioned_p (x, cond)
|
||||
|| reg_overlap_mentioned_p (x, a)
|
||||
|| modified_between_p (x, PREV_INSN (if_info.cond_earliest), jump))
|
||||
|| modified_between_p (x, PREV_INSN (if_info->cond_earliest), jump))
|
||||
insn_b = set_b = NULL_RTX;
|
||||
}
|
||||
|
||||
|
@ -2288,7 +2223,7 @@ noce_process_if_block (struct ce_if_block * ce_info)
|
|||
|| (SMALL_REGISTER_CLASSES
|
||||
&& REGNO (x) < FIRST_PSEUDO_REGISTER))
|
||||
{
|
||||
if (no_new_pseudos || GET_MODE (x) == BLKmode)
|
||||
if (GET_MODE (x) == BLKmode)
|
||||
return FALSE;
|
||||
|
||||
if (GET_MODE (x) == ZERO_EXTRACT
|
||||
|
@ -2305,11 +2240,11 @@ noce_process_if_block (struct ce_if_block * ce_info)
|
|||
return FALSE;
|
||||
|
||||
/* Set up the info block for our subroutines. */
|
||||
if_info.insn_a = insn_a;
|
||||
if_info.insn_b = insn_b;
|
||||
if_info.x = x;
|
||||
if_info.a = a;
|
||||
if_info.b = b;
|
||||
if_info->insn_a = insn_a;
|
||||
if_info->insn_b = insn_b;
|
||||
if_info->x = x;
|
||||
if_info->a = a;
|
||||
if_info->b = b;
|
||||
|
||||
/* Try optimizations in some approximation of a useful order. */
|
||||
/* ??? Should first look to see if X is live incoming at all. If it
|
||||
|
@ -2359,31 +2294,31 @@ noce_process_if_block (struct ce_if_block * ce_info)
|
|||
if (!set_b && MEM_P (orig_x) && noce_mem_write_may_trap_or_fault_p (orig_x))
|
||||
return FALSE;
|
||||
|
||||
if (noce_try_move (&if_info))
|
||||
if (noce_try_move (if_info))
|
||||
goto success;
|
||||
if (noce_try_store_flag (&if_info))
|
||||
if (noce_try_store_flag (if_info))
|
||||
goto success;
|
||||
if (noce_try_bitop (&if_info))
|
||||
if (noce_try_bitop (if_info))
|
||||
goto success;
|
||||
if (noce_try_minmax (&if_info))
|
||||
if (noce_try_minmax (if_info))
|
||||
goto success;
|
||||
if (noce_try_abs (&if_info))
|
||||
if (noce_try_abs (if_info))
|
||||
goto success;
|
||||
if (HAVE_conditional_move
|
||||
&& noce_try_cmove (&if_info))
|
||||
&& noce_try_cmove (if_info))
|
||||
goto success;
|
||||
if (! HAVE_conditional_execution)
|
||||
{
|
||||
if (noce_try_store_flag_constants (&if_info))
|
||||
if (noce_try_store_flag_constants (if_info))
|
||||
goto success;
|
||||
if (noce_try_addcc (&if_info))
|
||||
if (noce_try_addcc (if_info))
|
||||
goto success;
|
||||
if (noce_try_store_flag_mask (&if_info))
|
||||
if (noce_try_store_flag_mask (if_info))
|
||||
goto success;
|
||||
if (HAVE_conditional_move
|
||||
&& noce_try_cmove_arith (&if_info))
|
||||
&& noce_try_cmove_arith (if_info))
|
||||
goto success;
|
||||
if (noce_try_sign_mask (&if_info))
|
||||
if (noce_try_sign_mask (if_info))
|
||||
goto success;
|
||||
}
|
||||
|
||||
|
@ -2409,8 +2344,6 @@ noce_process_if_block (struct ce_if_block * ce_info)
|
|||
/* The original THEN and ELSE blocks may now be removed. The test block
|
||||
must now jump to the join block. If the test block and the join block
|
||||
can be merged, do so. */
|
||||
|
||||
join_bb = single_succ (then_bb);
|
||||
if (else_bb)
|
||||
{
|
||||
delete_basic_block (else_bb);
|
||||
|
@ -2572,19 +2505,20 @@ cond_move_convert_if_block (struct noce_if_info *if_infop,
|
|||
return true;
|
||||
}
|
||||
|
||||
/* Given a simple IF-THEN or IF-THEN-ELSE block, attempt to convert it
|
||||
using only conditional moves. Return TRUE if we were successful at
|
||||
/* Given a simple IF-THEN-JOIN or IF-THEN-ELSE-JOIN block, attempt to convert
|
||||
it using only conditional moves. Return TRUE if we were successful at
|
||||
converting the block. */
|
||||
|
||||
static int
|
||||
cond_move_process_if_block (struct ce_if_block *ce_info)
|
||||
cond_move_process_if_block (struct noce_if_info *if_info)
|
||||
{
|
||||
basic_block test_bb = ce_info->test_bb;
|
||||
basic_block then_bb = ce_info->then_bb;
|
||||
basic_block else_bb = ce_info->else_bb;
|
||||
basic_block join_bb;
|
||||
struct noce_if_info if_info;
|
||||
rtx jump, cond, seq, loc_insn;
|
||||
basic_block test_bb = if_info->test_bb;
|
||||
basic_block then_bb = if_info->then_bb;
|
||||
basic_block else_bb = if_info->else_bb;
|
||||
basic_block join_bb = if_info->join_bb;
|
||||
rtx jump = if_info->jump;
|
||||
rtx cond = if_info->cond;
|
||||
rtx seq, loc_insn;
|
||||
int max_reg, size, c, reg;
|
||||
rtx *then_vals;
|
||||
rtx *else_vals;
|
||||
|
@ -2592,17 +2526,6 @@ cond_move_process_if_block (struct ce_if_block *ce_info)
|
|||
VEC (int, heap) *else_regs = NULL;
|
||||
unsigned int i;
|
||||
|
||||
if (!HAVE_conditional_move || no_new_pseudos)
|
||||
return FALSE;
|
||||
|
||||
memset (&if_info, 0, sizeof if_info);
|
||||
|
||||
if (!noce_init_if_info (ce_info, &if_info))
|
||||
return FALSE;
|
||||
|
||||
cond = if_info.cond;
|
||||
jump = if_info.jump;
|
||||
|
||||
/* Build a mapping for each block to the value used for each
|
||||
register. */
|
||||
max_reg = max_reg_num ();
|
||||
|
@ -2655,16 +2578,16 @@ cond_move_process_if_block (struct ce_if_block *ce_info)
|
|||
/* Try to emit the conditional moves. First do the then block,
|
||||
then do anything left in the else blocks. */
|
||||
start_sequence ();
|
||||
if (!cond_move_convert_if_block (&if_info, then_bb, cond,
|
||||
if (!cond_move_convert_if_block (if_info, then_bb, cond,
|
||||
then_vals, else_vals, false)
|
||||
|| (else_bb
|
||||
&& !cond_move_convert_if_block (&if_info, else_bb, cond,
|
||||
&& !cond_move_convert_if_block (if_info, else_bb, cond,
|
||||
then_vals, else_vals, true)))
|
||||
{
|
||||
end_sequence ();
|
||||
return FALSE;
|
||||
}
|
||||
seq = end_ifcvt_sequence (&if_info);
|
||||
seq = end_ifcvt_sequence (if_info);
|
||||
if (!seq)
|
||||
return FALSE;
|
||||
|
||||
|
@ -2676,7 +2599,6 @@ cond_move_process_if_block (struct ce_if_block *ce_info)
|
|||
}
|
||||
emit_insn_before_setloc (seq, jump, INSN_LOCATOR (loc_insn));
|
||||
|
||||
join_bb = single_succ (then_bb);
|
||||
if (else_bb)
|
||||
{
|
||||
delete_basic_block (else_bb);
|
||||
|
@ -2705,40 +2627,127 @@ cond_move_process_if_block (struct ce_if_block *ce_info)
|
|||
}
|
||||
|
||||
|
||||
/* Attempt to convert an IF-THEN or IF-THEN-ELSE block into
|
||||
straight line code. Return true if successful. */
|
||||
/* Determine if a given basic block heads a simple IF-THEN-JOIN or an
|
||||
IF-THEN-ELSE-JOIN block.
|
||||
|
||||
If so, we'll try to convert the insns to not require the branch,
|
||||
using only transformations that do not require conditional execution.
|
||||
|
||||
Return TRUE if we were successful at converting the block. */
|
||||
|
||||
static int
|
||||
process_if_block (struct ce_if_block * ce_info)
|
||||
noce_find_if_block (basic_block test_bb,
|
||||
edge then_edge, edge else_edge,
|
||||
int pass)
|
||||
{
|
||||
if (! reload_completed
|
||||
&& noce_process_if_block (ce_info))
|
||||
basic_block then_bb, else_bb, join_bb;
|
||||
bool then_else_reversed = false;
|
||||
rtx jump, cond;
|
||||
struct noce_if_info if_info;
|
||||
|
||||
/* We only ever should get here before reload. */
|
||||
gcc_assert (!reload_completed);
|
||||
|
||||
/* Recognize an IF-THEN-ELSE-JOIN block. */
|
||||
if (single_pred_p (then_edge->dest)
|
||||
&& single_succ_p (then_edge->dest)
|
||||
&& single_pred_p (else_edge->dest)
|
||||
&& single_succ_p (else_edge->dest)
|
||||
&& single_succ (then_edge->dest) == single_succ (else_edge->dest))
|
||||
{
|
||||
then_bb = then_edge->dest;
|
||||
else_bb = else_edge->dest;
|
||||
join_bb = single_succ (then_bb);
|
||||
}
|
||||
/* Recognize an IF-THEN-JOIN block. */
|
||||
else if (single_pred_p (then_edge->dest)
|
||||
&& single_succ_p (then_edge->dest)
|
||||
&& single_succ (then_edge->dest) == else_edge->dest)
|
||||
{
|
||||
then_bb = then_edge->dest;
|
||||
else_bb = NULL_BLOCK;
|
||||
join_bb = else_edge->dest;
|
||||
}
|
||||
/* Recognize an IF-ELSE-JOIN block. We can have those because the order
|
||||
of basic blocks in cfglayout mode does not matter, so the fallthrough
|
||||
edge can go to any basic block (and not just to bb->next_bb, like in
|
||||
cfgrtl mode). */
|
||||
else if (single_pred_p (else_edge->dest)
|
||||
&& single_succ_p (else_edge->dest)
|
||||
&& single_succ (else_edge->dest) == then_edge->dest)
|
||||
{
|
||||
/* The noce transformations do not apply to IF-ELSE-JOIN blocks.
|
||||
To make this work, we have to invert the THEN and ELSE blocks
|
||||
and reverse the jump condition. */
|
||||
then_bb = else_edge->dest;
|
||||
else_bb = NULL_BLOCK;
|
||||
join_bb = single_succ (then_bb);
|
||||
then_else_reversed = true;
|
||||
}
|
||||
else
|
||||
/* Not a form we can handle. */
|
||||
return FALSE;
|
||||
|
||||
/* The edges of the THEN and ELSE blocks cannot have complex edges. */
|
||||
if (single_succ_edge (then_bb)->flags & EDGE_COMPLEX)
|
||||
return FALSE;
|
||||
if (else_bb
|
||||
&& single_succ_edge (else_bb)->flags & EDGE_COMPLEX)
|
||||
return FALSE;
|
||||
|
||||
num_possible_if_blocks++;
|
||||
|
||||
if (dump_file)
|
||||
{
|
||||
fprintf (dump_file,
|
||||
"\nIF-THEN%s-JOIN block found, pass %d, test %d, then %d",
|
||||
(else_bb) ? "-ELSE" : "",
|
||||
pass, test_bb->index, then_bb->index);
|
||||
|
||||
if (else_bb)
|
||||
fprintf (dump_file, ", else %d", else_bb->index);
|
||||
|
||||
fprintf (dump_file, ", join %d\n", join_bb->index);
|
||||
}
|
||||
|
||||
/* If the conditional jump is more than just a conditional
|
||||
jump, then we can not do if-conversion on this block. */
|
||||
jump = BB_END (test_bb);
|
||||
if (! onlyjump_p (jump))
|
||||
return FALSE;
|
||||
|
||||
/* If this is not a standard conditional jump, we can't parse it. */
|
||||
cond = noce_get_condition (jump,
|
||||
&if_info.cond_earliest,
|
||||
then_else_reversed);
|
||||
if (!cond)
|
||||
return FALSE;
|
||||
|
||||
/* We must be comparing objects whose modes imply the size. */
|
||||
if (GET_MODE (XEXP (cond, 0)) == BLKmode)
|
||||
return FALSE;
|
||||
|
||||
/* Initialize an IF_INFO struct to pass around. */
|
||||
memset (&if_info, 0, sizeof if_info);
|
||||
if_info.test_bb = test_bb;
|
||||
if_info.then_bb = then_bb;
|
||||
if_info.else_bb = else_bb;
|
||||
if_info.join_bb = join_bb;
|
||||
if_info.cond = cond;
|
||||
if_info.jump = jump;
|
||||
|
||||
/* Do the real work. */
|
||||
|
||||
if (noce_process_if_block (&if_info))
|
||||
return TRUE;
|
||||
|
||||
if (HAVE_conditional_move
|
||||
&& cond_move_process_if_block (ce_info))
|
||||
&& cond_move_process_if_block (&if_info))
|
||||
return TRUE;
|
||||
|
||||
if (HAVE_conditional_execution && reload_completed)
|
||||
{
|
||||
/* If we have && and || tests, try to first handle combining the && and
|
||||
|| tests into the conditional code, and if that fails, go back and
|
||||
handle it without the && and ||, which at present handles the && case
|
||||
if there was no ELSE block. */
|
||||
if (cond_exec_process_if_block (ce_info, TRUE))
|
||||
return TRUE;
|
||||
|
||||
if (ce_info->num_multiple_test_blocks)
|
||||
{
|
||||
cancel_changes (0);
|
||||
|
||||
if (cond_exec_process_if_block (ce_info, FALSE))
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/* Merge the blocks and mark for local life update. */
|
||||
|
||||
|
@ -2901,7 +2910,12 @@ find_if_header (basic_block test_bb, int pass)
|
|||
IFCVT_INIT_EXTRA_FIELDS (&ce_info);
|
||||
#endif
|
||||
|
||||
if (find_if_block (&ce_info))
|
||||
if (! reload_completed
|
||||
&& noce_find_if_block (test_bb, then_edge, else_edge, pass))
|
||||
goto success;
|
||||
|
||||
if (HAVE_conditional_execution && reload_completed
|
||||
&& cond_exec_find_if_block (&ce_info))
|
||||
goto success;
|
||||
|
||||
if (HAVE_trap && HAVE_conditional_trap
|
||||
|
@ -2999,7 +3013,7 @@ block_jumps_and_fallthru_p (basic_block cur_bb, basic_block target_bb)
|
|||
Return TRUE if we were successful at converting the block. */
|
||||
|
||||
static int
|
||||
find_if_block (struct ce_if_block * ce_info)
|
||||
cond_exec_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;
|
||||
|
@ -3011,11 +3025,14 @@ find_if_block (struct ce_if_block * ce_info)
|
|||
|
||||
ce_info->last_test_bb = test_bb;
|
||||
|
||||
/* We only ever should get here after reload,
|
||||
and only if we have conditional execution. */
|
||||
gcc_assert (HAVE_conditional_execution && reload_completed);
|
||||
|
||||
/* Discover if any fall through predecessors of the current test basic block
|
||||
were && tests (which jump to the else block) or || tests (which jump to
|
||||
the then block). */
|
||||
if (HAVE_conditional_execution && reload_completed
|
||||
&& single_pred_p (test_bb)
|
||||
if (single_pred_p (test_bb)
|
||||
&& single_pred_edge (test_bb)->flags == EDGE_FALLTHRU)
|
||||
{
|
||||
basic_block bb = single_pred (test_bb);
|
||||
|
@ -3201,10 +3218,24 @@ find_if_block (struct ce_if_block * ce_info)
|
|||
}
|
||||
|
||||
/* Do the real work. */
|
||||
|
||||
ce_info->else_bb = else_bb;
|
||||
ce_info->join_bb = join_bb;
|
||||
|
||||
return process_if_block (ce_info);
|
||||
/* If we have && and || tests, try to first handle combining the && and ||
|
||||
tests into the conditional code, and if that fails, go back and handle
|
||||
it without the && and ||, which at present handles the && case if there
|
||||
was no ELSE block. */
|
||||
if (cond_exec_process_if_block (ce_info, TRUE))
|
||||
return TRUE;
|
||||
|
||||
if (ce_info->num_multiple_test_blocks)
|
||||
{
|
||||
cancel_changes (0);
|
||||
|
||||
if (cond_exec_process_if_block (ce_info, FALSE))
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert a branch over a trap, or a branch
|
||||
|
@ -3237,7 +3268,7 @@ find_cond_trap (basic_block test_bb, edge then_edge, edge else_edge)
|
|||
|
||||
/* If this is not a standard conditional jump, we can't parse it. */
|
||||
jump = BB_END (test_bb);
|
||||
cond = noce_get_condition (jump, &cond_earliest);
|
||||
cond = noce_get_condition (jump, &cond_earliest, false);
|
||||
if (! cond)
|
||||
return FALSE;
|
||||
|
||||
|
@ -3733,7 +3764,7 @@ dead_or_predicable (basic_block test_bb, basic_block merge_bb,
|
|||
return FALSE;
|
||||
|
||||
/* Find the extent of the conditional. */
|
||||
cond = noce_get_condition (jump, &earliest);
|
||||
cond = noce_get_condition (jump, &earliest, false);
|
||||
if (! cond)
|
||||
return FALSE;
|
||||
|
||||
|
@ -3908,6 +3939,10 @@ if_convert (int x_life_data_ok)
|
|||
num_true_changes = 0;
|
||||
life_data_ok = (x_life_data_ok != 0);
|
||||
|
||||
/* Some transformations in this pass can create new pseudos,
|
||||
if the pass runs before reload. Make sure we can do so. */
|
||||
gcc_assert (! no_new_pseudos || reload_completed);
|
||||
|
||||
loop_optimizer_init (AVOID_CFG_MODIFICATIONS);
|
||||
if (current_loops)
|
||||
{
|
||||
|
|
Loading…
Add table
Reference in a new issue