summaryrefslogtreecommitdiff
path: root/gcc/optabs.c
diff options
context:
space:
mode:
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2009-09-28 21:26:31 +0000
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2009-09-28 21:26:31 +0000
commit94e08e50cec67a1026ae11c82b3a441871da3817 (patch)
tree2b4602f59f93e1c9ebfa00346b0b70ecdd95b378 /gcc/optabs.c
parenta2a58dc4ab39e0b69ec3834a3b8bdc9e018981f7 (diff)
downloadgcc-94e08e50cec67a1026ae11c82b3a441871da3817.tar.gz
./:
* 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@152253 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/optabs.c')
-rw-r--r--gcc/optabs.c54
1 files changed, 54 insertions, 0 deletions
diff --git a/gcc/optabs.c b/gcc/optabs.c
index a1adc581dc1..1c136236060 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,