aboutsummaryrefslogtreecommitdiff
path: root/gcc/simplify-rtx.c
diff options
context:
space:
mode:
authorKyrylo Tkachov <kyrylo.tkachov@arm.com>2016-06-06 16:06:05 +0000
committerKyrylo Tkachov <ktkachov@gcc.gnu.org>2016-06-06 16:06:05 +0000
commit36f9ad69336aeee0aa7cf2d8640fccbec8d659e1 (patch)
treebcfb07a9b834a240baa5c8658d3bcc74e6499f2b /gcc/simplify-rtx.c
parente8536e2b9f96f42d7f12f13254300476debd283a (diff)
downloadgcc-36f9ad69336aeee0aa7cf2d8640fccbec8d659e1.zip
gcc-36f9ad69336aeee0aa7cf2d8640fccbec8d659e1.tar.gz
gcc-36f9ad69336aeee0aa7cf2d8640fccbec8d659e1.tar.bz2
[3/3][RTL ifcvt] PR middle-end/37780: Conditional expression with __builtin_clz() should be optimized out
PR middle-end/37780 * ifcvt.c (noce_try_ifelse_collapse): New function. Declare prototype. (noce_process_if_block): Call noce_try_ifelse_collapse. * simplify-rtx.c (simplify_cond_clz_ctz): New function. (simplify_ternary_operation): Use the above to simplify conditional CLZ/CTZ expressions. * gcc.c-torture/execute/pr37780.c: New test. * gcc.target/aarch64/pr37780_1.c: Likewise. * gcc.target/arm/pr37780_1.c: Likewise. From-SVN: r237141
Diffstat (limited to 'gcc/simplify-rtx.c')
-rw-r--r--gcc/simplify-rtx.c56
1 files changed, 56 insertions, 0 deletions
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
index fdc4b36..2b649fa 100644
--- a/gcc/simplify-rtx.c
+++ b/gcc/simplify-rtx.c
@@ -5267,6 +5267,49 @@ simplify_const_relational_operation (enum rtx_code code,
return 0;
}
+
+/* Recognize expressions of the form (X CMP 0) ? VAL : OP (X)
+ where OP is CLZ or CTZ and VAL is the value from CLZ_DEFINED_VALUE_AT_ZERO
+ or CTZ_DEFINED_VALUE_AT_ZERO respectively and return OP (X) if the expression
+ can be simplified to that or NULL_RTX if not.
+ Assume X is compared against zero with CMP_CODE and the true
+ arm is TRUE_VAL and the false arm is FALSE_VAL. */
+
+static rtx
+simplify_cond_clz_ctz (rtx x, rtx_code cmp_code, rtx true_val, rtx false_val)
+{
+ if (cmp_code != EQ && cmp_code != NE)
+ return NULL_RTX;
+
+ /* Result on X == 0 and X !=0 respectively. */
+ rtx on_zero, on_nonzero;
+ if (cmp_code == EQ)
+ {
+ on_zero = true_val;
+ on_nonzero = false_val;
+ }
+ else
+ {
+ on_zero = false_val;
+ on_nonzero = true_val;
+ }
+
+ rtx_code op_code = GET_CODE (on_nonzero);
+ if ((op_code != CLZ && op_code != CTZ)
+ || !rtx_equal_p (XEXP (on_nonzero, 0), x)
+ || !CONST_INT_P (on_zero))
+ return NULL_RTX;
+
+ HOST_WIDE_INT op_val;
+ machine_mode mode = GET_MODE (on_nonzero);
+ if (((op_code == CLZ && CLZ_DEFINED_VALUE_AT_ZERO (mode, op_val))
+ || (op_code == CTZ && CTZ_DEFINED_VALUE_AT_ZERO (mode, op_val)))
+ && op_val == INTVAL (on_zero))
+ return on_nonzero;
+
+ return NULL_RTX;
+}
+
/* Simplify CODE, an operation with result mode MODE and three operands,
OP0, OP1, and OP2. OP0_MODE was the mode of OP0 before it became
@@ -5400,6 +5443,19 @@ simplify_ternary_operation (enum rtx_code code, machine_mode mode,
}
}
+ /* Convert x == 0 ? N : clz (x) into clz (x) when
+ CLZ_DEFINED_VALUE_AT_ZERO is defined to N for the mode of x.
+ Similarly for ctz (x). */
+ if (COMPARISON_P (op0) && !side_effects_p (op0)
+ && XEXP (op0, 1) == const0_rtx)
+ {
+ rtx simplified
+ = simplify_cond_clz_ctz (XEXP (op0, 0), GET_CODE (op0),
+ op1, op2);
+ if (simplified)
+ return simplified;
+ }
+
if (COMPARISON_P (op0) && ! side_effects_p (op0))
{
machine_mode cmp_mode = (GET_MODE (XEXP (op0, 0)) == VOIDmode