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/optabs.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/optabs.c')
-rw-r--r-- | gcc/optabs.c | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/gcc/optabs.c b/gcc/optabs.c index a1adc58..1c13623 100644 --- a/gcc/optabs.c +++ b/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, |