Commit d27555bf by Kyrylo Tkachov Committed by Kyrylo Tkachov

[RTL-ifcvt] Improve conditional select ops on immediates (fix failing x86_64 cmov tests)

	PR rtl-optimization/67103
	* ifcvt.c (noce_try_store_flag_constants): Move
	x = (-(test != 0) & (b - a)) + a transformation to...
	(noce_try_cmove): ... Here.  Try it if normal conditional
	move fails.

From-SVN: r226853
parent 89711ff6
2015-08-13 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
PR rtl-optimization/67103
* ifcvt.c (noce_try_store_flag_constants): Move
x = (-(test != 0) & (b - a)) + a transformation to...
(noce_try_cmove): ... Here. Try it if normal conditional
move fails.
2015-08-13 Robert Suchanek <robert.suchanek@imgtec.com> 2015-08-13 Robert Suchanek <robert.suchanek@imgtec.com>
* config/mips/mips.c (mips_rtx_cost_data): Remove costs for W32 and W64 * config/mips/mips.c (mips_rtx_cost_data): Remove costs for W32 and W64
......
...@@ -1239,9 +1239,6 @@ noce_try_store_flag_constants (struct noce_if_info *if_info) ...@@ -1239,9 +1239,6 @@ noce_try_store_flag_constants (struct noce_if_info *if_info)
normalize = -1; normalize = -1;
reversep = true; reversep = true;
} }
else if ((if_info->branch_cost >= 2 && STORE_FLAG_VALUE == -1)
|| if_info->branch_cost >= 3)
normalize = -1;
else else
return FALSE; return FALSE;
...@@ -1287,18 +1284,10 @@ noce_try_store_flag_constants (struct noce_if_info *if_info) ...@@ -1287,18 +1284,10 @@ noce_try_store_flag_constants (struct noce_if_info *if_info)
target, gen_int_mode (ifalse, mode), target, gen_int_mode (ifalse, mode),
if_info->x, 0, OPTAB_WIDEN); if_info->x, 0, OPTAB_WIDEN);
} }
/* if (test) x = a; else x = b;
=> x = (-(test != 0) & (b - a)) + a; */
else else
{ {
target = expand_simple_binop (mode, AND, end_sequence ();
target, gen_int_mode (diff, mode), return FALSE;
if_info->x, 0, OPTAB_WIDEN);
if (target)
target = expand_simple_binop (mode, PLUS,
target, gen_int_mode (ifalse, mode),
if_info->x, 0, OPTAB_WIDEN);
} }
if (! target) if (! target)
...@@ -1615,11 +1604,67 @@ noce_try_cmove (struct noce_if_info *if_info) ...@@ -1615,11 +1604,67 @@ noce_try_cmove (struct noce_if_info *if_info)
INSN_LOCATION (if_info->insn_a)); INSN_LOCATION (if_info->insn_a));
return TRUE; return TRUE;
} }
else /* If both a and b are constants try a last-ditch transformation:
if (test) x = a; else x = b;
=> x = (-(test != 0) & (b - a)) + a;
Try this only if the target-specific expansion above has failed.
The target-specific expander may want to generate sequences that
we don't know about, so give them a chance before trying this
approach. */
else if (!targetm.have_conditional_execution ()
&& CONST_INT_P (if_info->a) && CONST_INT_P (if_info->b)
&& ((if_info->branch_cost >= 2 && STORE_FLAG_VALUE == -1)
|| if_info->branch_cost >= 3))
{ {
end_sequence (); machine_mode mode = GET_MODE (if_info->x);
return FALSE; HOST_WIDE_INT ifalse = INTVAL (if_info->a);
HOST_WIDE_INT itrue = INTVAL (if_info->b);
rtx target = noce_emit_store_flag (if_info, if_info->x, false, -1);
if (!target)
{
end_sequence ();
return FALSE;
}
HOST_WIDE_INT diff = (unsigned HOST_WIDE_INT) itrue - ifalse;
/* Make sure we can represent the difference
between the two values. */
if ((diff > 0)
!= ((ifalse < 0) != (itrue < 0) ? ifalse < 0 : ifalse < itrue))
{
end_sequence ();
return FALSE;
}
diff = trunc_int_for_mode (diff, mode);
target = expand_simple_binop (mode, AND,
target, gen_int_mode (diff, mode),
if_info->x, 0, OPTAB_WIDEN);
if (target)
target = expand_simple_binop (mode, PLUS,
target, gen_int_mode (ifalse, mode),
if_info->x, 0, OPTAB_WIDEN);
if (target)
{
if (target != if_info->x)
noce_emit_move_insn (if_info->x, target);
seq = end_ifcvt_sequence (if_info);
if (!seq)
return FALSE;
emit_insn_before_setloc (seq, if_info->jump,
INSN_LOCATION (if_info->insn_a));
return TRUE;
}
else
{
end_sequence ();
return FALSE;
}
} }
else
end_sequence ();
} }
return FALSE; return FALSE;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment