diff options
author | Kyrylo Tkachov <kyrylo.tkachov@arm.com> | 2016-06-06 16:06:05 +0000 |
---|---|---|
committer | Kyrylo Tkachov <ktkachov@gcc.gnu.org> | 2016-06-06 16:06:05 +0000 |
commit | 36f9ad69336aeee0aa7cf2d8640fccbec8d659e1 (patch) | |
tree | bcfb07a9b834a240baa5c8658d3bcc74e6499f2b /gcc/simplify-rtx.c | |
parent | e8536e2b9f96f42d7f12f13254300476debd283a (diff) | |
download | gcc-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.c | 56 |
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 |