aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorYvan Roux <yvan.roux@linaro.org>2015-10-13 13:19:18 +0200
committerYvan Roux <yvan.roux@linaro.org>2015-10-13 13:19:23 +0200
commitc10891bc12459ef6402dc894d2995082bfdce25b (patch)
tree6aa11a90ef17f4fcfac0f348c2d3558ab5fc5391 /gcc
parente94a9ba47d4902ecbb2dfac8d342deb6d32e67e9 (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.c90
-rw-r--r--gcc/simplify-rtx.c26
-rw-r--r--gcc/testsuite/gcc.target/aarch64/neg_abs_1.c17
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\]*.*" } } */