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> 2009-09-28 Ian Lance Taylor <iant@google.com>
PR middle-end/40500 PR middle-end/40500

View File

@ -1744,13 +1744,16 @@ noce_try_minmax (struct noce_if_info *if_info)
return TRUE; 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 static int
noce_try_abs (struct noce_if_info *if_info) noce_try_abs (struct noce_if_info *if_info)
{ {
rtx cond, earliest, target, seq, a, b, c; rtx cond, earliest, target, seq, a, b, c;
int negate; int negate;
bool one_cmpl = false;
/* Reject modes with signed zeros. */ /* Reject modes with signed zeros. */
if (HONOR_SIGNED_ZEROS (GET_MODE (if_info->x))) 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; c = a; a = b; b = c;
negate = 1; 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 else
return FALSE; return FALSE;
@ -1839,13 +1853,23 @@ noce_try_abs (struct noce_if_info *if_info)
} }
start_sequence (); start_sequence ();
if (one_cmpl)
target = expand_abs_nojump (GET_MODE (if_info->x), b, if_info->x, 1); 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 /* ??? It's a quandary whether cmove would be better here, especially
for integers. Perhaps combine will clean things up. */ for integers. Perhaps combine will clean things up. */
if (target && negate) 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) if (! target)
{ {

View File

@ -3488,6 +3488,60 @@ expand_abs (enum machine_mode mode, rtx op0, rtx target,
return 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 /* A subroutine of expand_copysign, perform the copysign operation using the
abs and neg primitives advertised to exist on the target. The assumption 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, 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_nojump (enum machine_mode, rtx, rtx, int);
extern rtx expand_abs (enum machine_mode, rtx, rtx, int, 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. */ /* Expand the copysign operation. */
extern rtx expand_copysign (rtx, rtx, rtx); 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> 2009-09-28 Janis Johnson <janis187@us.ibm.com>
* g++.dg/dfp/dfp.exp: Run tests from c-c++-common/dfp. * 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;
}