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:
parent
13ebf17b66
commit
650260479a
|
@ -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
|
||||||
|
|
32
gcc/ifcvt.c
32
gcc/ifcvt.c
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
54
gcc/optabs.c
54
gcc/optabs.c
|
@ -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,
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
Loading…
Reference in New Issue