diff options
author | Easwaran Raman <eraman@google.com> | 2009-09-28 21:26:31 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2009-09-28 21:26:31 +0000 |
commit | 650260479ac18d6e26af41f77c74b451ce426a46 (patch) | |
tree | 2b4602f59f93e1c9ebfa00346b0b70ecdd95b378 /gcc/ifcvt.c | |
parent | 13ebf17b66c3ff8f4291f046158347191fe396c1 (diff) | |
download | gcc-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.c | 32 |
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) { |