ifcvt.c (noce_try_abs): Recognize pattern and call expand_one_cmpl_abs_nojump.

./:	* ifcvt.c (noce_try_abs): Recognize pattern and call
	expand_one_cmpl_abs_nojump.
	* optabs.c (expand_one_cmpl_abs_nojump): New function.
	* optabs.h (expand_one_cmpl_abs_nojump): Declare.
testsuite/:
	* gcc.target/i386/ifcvt-onecmpl-abs-1.c: New file.
	* gcc.c-torture/execute/ifcvt-onecmpl-abs-1.c: New file.

From-SVN: r152253
This commit is contained in:
Easwaran Raman 2009-09-28 21:26:31 +00:00 committed by Ian Lance Taylor
parent 13ebf17b66
commit 650260479a
7 changed files with 131 additions and 4 deletions

View File

@ -1,3 +1,10 @@
2009-09-28 Easwaran Raman <eraman@google.com>
* ifcvt.c (noce_try_abs): Recognize pattern and call
expand_one_cmpl_abs_nojump.
* optabs.c (expand_one_cmpl_abs_nojump): New function.
* optabs.h (expand_one_cmpl_abs_nojump): Declare.
2009-09-28 Ian Lance Taylor <iant@google.com>
PR middle-end/40500

View File

@ -1744,13 +1744,16 @@ noce_try_minmax (struct noce_if_info *if_info)
return TRUE;
}
/* Convert "if (a < 0) x = -a; else x = a;" to "x = abs(a);", etc. */
/* Convert "if (a < 0) x = -a; else x = a;" to "x = abs(a);",
"if (a < 0) x = ~a; else x = a;" to "x = one_cmpl_abs(a);",
etc. */
static int
noce_try_abs (struct noce_if_info *if_info)
{
rtx cond, earliest, target, seq, a, b, c;
int negate;
bool one_cmpl = false;
/* Reject modes with signed zeros. */
if (HONOR_SIGNED_ZEROS (GET_MODE (if_info->x)))
@ -1768,6 +1771,17 @@ noce_try_abs (struct noce_if_info *if_info)
c = a; a = b; b = c;
negate = 1;
}
else if (GET_CODE (a) == NOT && rtx_equal_p (XEXP (a, 0), b))
{
negate = 0;
one_cmpl = true;
}
else if (GET_CODE (b) == NOT && rtx_equal_p (XEXP (b, 0), a))
{
c = a; a = b; b = c;
negate = 1;
one_cmpl = true;
}
else
return FALSE;
@ -1839,13 +1853,23 @@ noce_try_abs (struct noce_if_info *if_info)
}
start_sequence ();
target = expand_abs_nojump (GET_MODE (if_info->x), b, if_info->x, 1);
if (one_cmpl)
target = expand_one_cmpl_abs_nojump (GET_MODE (if_info->x), b,
if_info->x);
else
target = expand_abs_nojump (GET_MODE (if_info->x), b, if_info->x, 1);
/* ??? 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);
{
if (one_cmpl)
target = expand_simple_unop (GET_MODE (target), NOT, target,
if_info->x, 0);
else
target = expand_simple_unop (GET_MODE (target), NEG, target,
if_info->x, 0);
}
if (! target)
{

View File

@ -3488,6 +3488,60 @@ expand_abs (enum machine_mode mode, rtx op0, rtx target,
return target;
}
/* Emit code to compute the one's complement absolute value of OP0
(if (OP0 < 0) OP0 = ~OP0), with result to TARGET if convenient.
(TARGET may be NULL_RTX.) The return value says where the result
actually is to be found.
MODE is the mode of the operand; the mode of the result is
different but can be deduced from MODE. */
rtx
expand_one_cmpl_abs_nojump (enum machine_mode mode, rtx op0, rtx target)
{
rtx temp;
/* Not applicable for floating point modes. */
if (FLOAT_MODE_P (mode))
return NULL_RTX;
/* If we have a MAX insn, we can do this as MAX (x, ~x). */
if (optab_handler (smax_optab, mode)->insn_code != CODE_FOR_nothing)
{
rtx last = get_last_insn ();
temp = expand_unop (mode, one_cmpl_optab, op0, NULL_RTX, 0);
if (temp != 0)
temp = expand_binop (mode, smax_optab, op0, temp, target, 0,
OPTAB_WIDEN);
if (temp != 0)
return temp;
delete_insns_since (last);
}
/* If this machine has expensive jumps, we can do one's complement
absolute value of X as (((signed) x >> (W-1)) ^ x). */
if (GET_MODE_CLASS (mode) == MODE_INT
&& BRANCH_COST (optimize_insn_for_speed_p (),
false) >= 2)
{
rtx extended = expand_shift (RSHIFT_EXPR, mode, op0,
size_int (GET_MODE_BITSIZE (mode) - 1),
NULL_RTX, 0);
temp = expand_binop (mode, xor_optab, extended, op0, target, 0,
OPTAB_LIB_WIDEN);
if (temp != 0)
return temp;
}
return NULL_RTX;
}
/* A subroutine of expand_copysign, perform the copysign operation using the
abs and neg primitives advertised to exist on the target. The assumption
is that we have a split register file, and leaving op0 in fp registers,

View File

@ -706,6 +706,9 @@ extern rtx expand_unop (enum machine_mode, optab, rtx, rtx, int);
extern rtx expand_abs_nojump (enum machine_mode, rtx, rtx, int);
extern rtx expand_abs (enum machine_mode, rtx, rtx, int, int);
/* Expand the one's complement absolute value operation. */
extern rtx expand_one_cmpl_abs_nojump (enum machine_mode, rtx, rtx);
/* Expand the copysign operation. */
extern rtx expand_copysign (rtx, rtx, rtx);

View File

@ -1,3 +1,8 @@
2009-09-28 Easwaran Raman <eraman@google.com>
* gcc.target/i386/ifcvt-onecmpl-abs-1.c: New file.
* gcc.c-torture/execute/ifcvt-onecmpl-abs-1.c: New file.
2009-09-28 Janis Johnson <janis187@us.ibm.com>
* g++.dg/dfp/dfp.exp: Run tests from c-c++-common/dfp.

View File

@ -0,0 +1,19 @@
extern void abort(void);
__attribute__ ((noinline))
int foo(int n)
{
if (n < 0)
n = ~n;
return n;
}
int main(void)
{
if (foo (-1) != 0)
abort ();
return 0;
}

View File

@ -0,0 +1,15 @@
/* { dg-do compile } */
/* This test checks for if-conversion of one's complement
* abs function. */
/* { dg-options "-O" } */
/* { dg-final { scan-assembler "sar" } } */
/* { dg-final { scan-assembler "xor" } } */
/* Check code generation for one's complement version of abs */
int onecmplabs(int x)
{
if (x < 0)
x = ~x;
return x;
}