aboutsummaryrefslogtreecommitdiff
path: root/gcc/ifcvt.c
diff options
context:
space:
mode:
authorEaswaran Raman <eraman@google.com>2009-09-28 21:26:31 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2009-09-28 21:26:31 +0000
commit650260479ac18d6e26af41f77c74b451ce426a46 (patch)
tree2b4602f59f93e1c9ebfa00346b0b70ecdd95b378 /gcc/ifcvt.c
parent13ebf17b66c3ff8f4291f046158347191fe396c1 (diff)
downloadgcc-650260479ac18d6e26af41f77c74b451ce426a46.zip
gcc-650260479ac18d6e26af41f77c74b451ce426a46.tar.gz
gcc-650260479ac18d6e26af41f77c74b451ce426a46.tar.bz2
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
Diffstat (limited to 'gcc/ifcvt.c')
-rw-r--r--gcc/ifcvt.c32
1 files changed, 28 insertions, 4 deletions
diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c
index 1cf2608..1ef2d21 100644
--- a/gcc/ifcvt.c
+++ b/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)
{