diff options
author | Yvan Roux <yvan.roux@linaro.org> | 2015-10-13 13:19:18 +0200 |
---|---|---|
committer | Yvan Roux <yvan.roux@linaro.org> | 2015-10-13 13:19:23 +0200 |
commit | c10891bc12459ef6402dc894d2995082bfdce25b (patch) | |
tree | 6aa11a90ef17f4fcfac0f348c2d3558ab5fc5391 /gcc | |
parent | e94a9ba47d4902ecbb2dfac8d342deb6d32e67e9 (diff) |
gcc/
Backport from trunk r225996.
2015-07-20 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
* combine.c (combine_simplify_rtx): Move simplification step
before various transformations/substitutions.
gcc/
Backport from trunk r225997.
2015-07-20 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
* simplify-rtx.c (simplify_unary_operation_1, NEG case):
(neg (x ? (neg y) : y)) -> !x ? (neg y) : y.
gcc/testsuite/
Backport from trunk r225997.
2015-07-20 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
* gcc.target/aarch64/neg_abs_1.c: New test.
Change-Id: Ib48417a225b1654ea0c37d256e99639d22005a10
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/combine.c | 90 | ||||
-rw-r--r-- | gcc/simplify-rtx.c | 26 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/aarch64/neg_abs_1.c | 17 |
3 files changed, 88 insertions, 45 deletions
diff --git a/gcc/combine.c b/gcc/combine.c index e35e45968ac..21e5ee594f1 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -5511,6 +5511,51 @@ combine_simplify_rtx (rtx x, machine_mode op0_mode, int in_dest, SUBST (XEXP (x, 1), temp); } + /* Try to fold this expression in case we have constants that weren't + present before. */ + temp = 0; + switch (GET_RTX_CLASS (code)) + { + case RTX_UNARY: + if (op0_mode == VOIDmode) + op0_mode = GET_MODE (XEXP (x, 0)); + temp = simplify_unary_operation (code, mode, XEXP (x, 0), op0_mode); + break; + case RTX_COMPARE: + case RTX_COMM_COMPARE: + { + machine_mode cmp_mode = GET_MODE (XEXP (x, 0)); + if (cmp_mode == VOIDmode) + { + cmp_mode = GET_MODE (XEXP (x, 1)); + if (cmp_mode == VOIDmode) + cmp_mode = op0_mode; + } + temp = simplify_relational_operation (code, mode, cmp_mode, + XEXP (x, 0), XEXP (x, 1)); + } + break; + case RTX_COMM_ARITH: + case RTX_BIN_ARITH: + temp = simplify_binary_operation (code, mode, XEXP (x, 0), XEXP (x, 1)); + break; + case RTX_BITFIELD_OPS: + case RTX_TERNARY: + temp = simplify_ternary_operation (code, mode, op0_mode, XEXP (x, 0), + XEXP (x, 1), XEXP (x, 2)); + break; + default: + break; + } + + if (temp) + { + x = temp; + code = GET_CODE (temp); + op0_mode = VOIDmode; + mode = GET_MODE (temp); + } + /* If this is a simple operation applied to an IF_THEN_ELSE, try applying it to the arms of the IF_THEN_ELSE. This often simplifies things. Check for cases where both arms are testing the same @@ -5610,51 +5655,6 @@ combine_simplify_rtx (rtx x, machine_mode op0_mode, int in_dest, } } - /* Try to fold this expression in case we have constants that weren't - present before. */ - temp = 0; - switch (GET_RTX_CLASS (code)) - { - case RTX_UNARY: - if (op0_mode == VOIDmode) - op0_mode = GET_MODE (XEXP (x, 0)); - temp = simplify_unary_operation (code, mode, XEXP (x, 0), op0_mode); - break; - case RTX_COMPARE: - case RTX_COMM_COMPARE: - { - machine_mode cmp_mode = GET_MODE (XEXP (x, 0)); - if (cmp_mode == VOIDmode) - { - cmp_mode = GET_MODE (XEXP (x, 1)); - if (cmp_mode == VOIDmode) - cmp_mode = op0_mode; - } - temp = simplify_relational_operation (code, mode, cmp_mode, - XEXP (x, 0), XEXP (x, 1)); - } - break; - case RTX_COMM_ARITH: - case RTX_BIN_ARITH: - temp = simplify_binary_operation (code, mode, XEXP (x, 0), XEXP (x, 1)); - break; - case RTX_BITFIELD_OPS: - case RTX_TERNARY: - temp = simplify_ternary_operation (code, mode, op0_mode, XEXP (x, 0), - XEXP (x, 1), XEXP (x, 2)); - break; - default: - break; - } - - if (temp) - { - x = temp; - code = GET_CODE (temp); - op0_mode = VOIDmode; - mode = GET_MODE (temp); - } - /* First see if we can apply the inverse distributive law. */ if (code == PLUS || code == MINUS || code == AND || code == IOR || code == XOR) diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index 7dd45ec61db..f29cc1b1de2 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -978,6 +978,32 @@ simplify_unary_operation_1 (enum rtx_code code, machine_mode mode, rtx op) if (GET_CODE (op) == NEG) return XEXP (op, 0); + /* (neg (x ? (neg y) : y)) == !x ? (neg y) : y. + If comparison is not reversible use + x ? y : (neg y). */ + if (GET_CODE (op) == IF_THEN_ELSE) + { + rtx cond = XEXP (op, 0); + rtx true_rtx = XEXP (op, 1); + rtx false_rtx = XEXP (op, 2); + + if ((GET_CODE (true_rtx) == NEG + && rtx_equal_p (XEXP (true_rtx, 0), false_rtx)) + || (GET_CODE (false_rtx) == NEG + && rtx_equal_p (XEXP (false_rtx, 0), true_rtx))) + { + if (reversed_comparison_code (cond, NULL_RTX) != UNKNOWN) + temp = reversed_comparison (cond, mode); + else + { + temp = cond; + std::swap (true_rtx, false_rtx); + } + return simplify_gen_ternary (IF_THEN_ELSE, mode, + mode, temp, true_rtx, false_rtx); + } + } + /* (neg (plus X 1)) can become (not X). */ if (GET_CODE (op) == PLUS && XEXP (op, 1) == const1_rtx) diff --git a/gcc/testsuite/gcc.target/aarch64/neg_abs_1.c b/gcc/testsuite/gcc.target/aarch64/neg_abs_1.c new file mode 100644 index 00000000000..cb2a387088c --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/neg_abs_1.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-save-temps -O2" } */ + +int +f1 (int x) +{ + return x < 0 ? x : -x; +} + +long long +f2 (long long x) +{ + return x < 0 ? x : -x; +} + +/* { dg-final { scan-assembler-not "\tneg\tw\[0-9\]*.*" } } */ +/* { dg-final { scan-assembler-not "\tneg\tx\[0-9\]*.*" } } */ |