ifcvt.c (cond_move_convert_if_block): New function, code factored out from...

* ifcvt.c (cond_move_convert_if_block): New function, code
	factored out from...
	(cond_move_process_if_block): ...here.  Call the new function
	on the THEN and ELSE blocks.
	(merge_if_block): Do not copy global_live_at_end, merge_blocks
	already takes care of this.

From-SVN: r120524
This commit is contained in:
Steven Bosscher 2007-01-06 13:56:53 +00:00
parent 472017b355
commit dc1f5a1118
2 changed files with 83 additions and 78 deletions

View File

@ -1,3 +1,12 @@
2007-01-06 Steven Bosscher <steven@gcc.gnu.org>
* ifcvt.c (cond_move_convert_if_block): New function, code
factored out from...
(cond_move_process_if_block): ...here. Call the new function
on the THEN and ELSE blocks.
(merge_if_block): Do not copy global_live_at_end, merge_blocks
already takes care of this.
2007-01-05 Manuel Lopez-Ibanez <manu@gcc.gnu.org> 2007-01-05 Manuel Lopez-Ibanez <manu@gcc.gnu.org>
PR c/19978 PR c/19978

View File

@ -2466,6 +2466,70 @@ check_cond_move_block (basic_block bb, rtx *vals, rtx cond)
return TRUE; return TRUE;
} }
/* Given a basic block BB suitable for conditional move conversion,
a condition COND, and arrays THEN_VALS and ELSE_VALS containing the
register values depending on COND, emit the insns in the block as
conditional moves. If ELSE_BLOCK is true, THEN_BB was already
processed. The caller has started a sequence for the conversion.
Return true if successful, false if something goes wrong. */
static bool
cond_move_convert_if_block (struct noce_if_info *if_infop,
basic_block bb, rtx cond,
rtx *then_vals, rtx *else_vals,
bool else_block_p)
{
enum rtx_code code;
rtx insn, cond_arg0, cond_arg1;
code = GET_CODE (cond);
cond_arg0 = XEXP (cond, 0);
cond_arg1 = XEXP (cond, 1);
FOR_BB_INSNS (bb, insn)
{
rtx set, target, dest, t, e;
unsigned int regno;
if (!INSN_P (insn) || JUMP_P (insn))
continue;
set = single_set (insn);
gcc_assert (set && REG_P (SET_DEST (set)));
dest = SET_DEST (set);
regno = REGNO (dest);
t = then_vals[regno];
e = else_vals[regno];
if (else_block_p)
{
/* If this register was set in the then block, we already
handled this case there. */
if (t)
continue;
t = dest;
gcc_assert (e);
}
else
{
gcc_assert (t);
if (!e)
e = dest;
}
target = noce_emit_cmove (if_infop, dest, code, cond_arg0, cond_arg1,
t, e);
if (!target)
return false;
if (target != dest)
noce_emit_move_insn (dest, target);
}
return true;
}
/* Given a simple IF-THEN or IF-THEN-ELSE block, attempt to convert it /* 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 using only conditional moves. Return TRUE if we were successful at
converting the block. */ converting the block. */
@ -2476,11 +2540,10 @@ cond_move_process_if_block (struct ce_if_block *ce_info)
basic_block then_bb = ce_info->then_bb; basic_block then_bb = ce_info->then_bb;
basic_block else_bb = ce_info->else_bb; basic_block else_bb = ce_info->else_bb;
struct noce_if_info if_info; struct noce_if_info if_info;
rtx jump, cond, insn, seq, cond_arg0, cond_arg1, loc_insn; rtx jump, cond, insn, seq, loc_insn;
int max_reg, size, c, i; int max_reg, size, c, i;
rtx *then_vals; rtx *then_vals;
rtx *else_vals; rtx *else_vals;
enum rtx_code code;
if (!HAVE_conditional_move || no_new_pseudos) if (!HAVE_conditional_move || no_new_pseudos)
return FALSE; return FALSE;
@ -2537,78 +2600,18 @@ cond_move_process_if_block (struct ce_if_block *ce_info)
if (c > MAX_CONDITIONAL_EXECUTE) if (c > MAX_CONDITIONAL_EXECUTE)
return FALSE; return FALSE;
/* Emit the conditional moves. First do the then block, then do /* Try to emit the conditional moves. First do the then block,
anything left in the else blocks. */ then do anything left in the else blocks. */
code = GET_CODE (cond);
cond_arg0 = XEXP (cond, 0);
cond_arg1 = XEXP (cond, 1);
start_sequence (); start_sequence ();
if (!cond_move_convert_if_block (&if_info, then_bb, cond,
FOR_BB_INSNS (then_bb, insn) then_vals, else_vals, false)
|| (else_bb
&& !cond_move_convert_if_block (&if_info, else_bb, cond,
then_vals, else_vals, true)))
{ {
rtx set, target, dest, t, e; end_sequence ();
unsigned int regno; return FALSE;
if (!INSN_P (insn) || JUMP_P (insn))
continue;
set = single_set (insn);
gcc_assert (set && REG_P (SET_DEST (set)));
dest = SET_DEST (set);
regno = REGNO (dest);
t = then_vals[regno];
e = else_vals[regno];
gcc_assert (t);
if (!e)
e = dest;
target = noce_emit_cmove (&if_info, dest, code, cond_arg0, cond_arg1,
t, e);
if (!target)
{
end_sequence ();
return FALSE;
}
if (target != dest)
noce_emit_move_insn (dest, target);
} }
if (else_bb)
{
FOR_BB_INSNS (else_bb, insn)
{
rtx set, target, dest;
unsigned int regno;
if (!INSN_P (insn) || JUMP_P (insn))
continue;
set = single_set (insn);
gcc_assert (set && REG_P (SET_DEST (set)));
dest = SET_DEST (set);
regno = REGNO (dest);
/* If this register was set in the then block, we already
handled this case above. */
if (then_vals[regno])
continue;
gcc_assert (else_vals[regno]);
target = noce_emit_cmove (&if_info, dest, code, cond_arg0, cond_arg1,
dest, else_vals[regno]);
if (!target)
{
end_sequence ();
return FALSE;
}
if (target != dest)
noce_emit_move_insn (dest, target);
}
}
seq = end_ifcvt_sequence (&if_info); seq = end_ifcvt_sequence (&if_info);
if (!seq) if (!seq)
return FALSE; return FALSE;
@ -2711,9 +2714,6 @@ merge_if_block (struct ce_if_block * ce_info)
if (then_bb) if (then_bb)
{ {
if (combo_bb->il.rtl->global_live_at_end)
COPY_REG_SET (combo_bb->il.rtl->global_live_at_end,
then_bb->il.rtl->global_live_at_end);
merge_blocks (combo_bb, then_bb); merge_blocks (combo_bb, then_bb);
num_true_changes++; num_true_changes++;
} }
@ -2764,10 +2764,6 @@ merge_if_block (struct ce_if_block * ce_info)
&& join_bb != EXIT_BLOCK_PTR) && join_bb != EXIT_BLOCK_PTR)
{ {
/* We can merge the JOIN. */ /* We can merge the JOIN. */
if (combo_bb->il.rtl->global_live_at_end)
COPY_REG_SET (combo_bb->il.rtl->global_live_at_end,
join_bb->il.rtl->global_live_at_end);
merge_blocks (combo_bb, join_bb); merge_blocks (combo_bb, join_bb);
num_true_changes++; num_true_changes++;
} }