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
7 changed files with 131 additions and 4 deletions
|
@ -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
|
||||
|
|
32
gcc/ifcvt.c
32
gcc/ifcvt.c
|
@ -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)
|
||||
{
|
||||
|
|
54
gcc/optabs.c
54
gcc/optabs.c
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
19
gcc/testsuite/gcc.c-torture/execute/ifcvt-onecmpl-abs-1.c
Normal file
19
gcc/testsuite/gcc.c-torture/execute/ifcvt-onecmpl-abs-1.c
Normal 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;
|
||||
}
|
15
gcc/testsuite/gcc.target/i386/ifcvt-onecmpl-abs-1.c
Normal file
15
gcc/testsuite/gcc.target/i386/ifcvt-onecmpl-abs-1.c
Normal 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;
|
||||
}
|
Loading…
Add table
Reference in a new issue