Hi all,

In this second patch I add the transformation mentioned in the subject to 
simplify-rtx.c.
In combination with the first patch to combine, combine_simplify_rtx now picks 
it up in the
testcase and does the right thing by not emitting an extra negate after the 
conditional negate
operation.

Bootstrapped and tested on aarch64, arm, x86_64.

Ok for trunk?

Thanks,
Kyrill


2015-07-16  Kyrylo Tkachov  <kyrylo.tkac...@arm.com>

    * simplify-rtx.c (simplify_unary_operation_1, NEG case):
    (neg (x ? (neg y) : y)) -> !x ? (neg y) : y.

2015-07-16  Kyrylo Tkachov  <kyrylo.tkac...@arm.com>

    * gcc.target/aarch64/neg_abs_1.c: New test.
commit 5e8d7d5f431b30edfbc5f92004d5252a1ecfc19d
Author: Kyrylo Tkachov <kyrylo.tkac...@arm.com>
Date:   Wed Jul 15 09:19:17 2015 +0100

    [simplify-rtx] Simplify - (y ? -x : x) -> (!y ? -x : x)

diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
index 91e4b9c..b20dd2d 100644
--- a/gcc/simplify-rtx.c
+++ b/gcc/simplify-rtx.c
@@ -957,6 +957,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 0000000..cb2a387
--- /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\]*.*" } } */

Reply via email to