This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Generalize -(-X) a little


On Thu, 2 Nov 2017, Richard Biener wrote:

You can handle floats as followup but some testcases that shouldn't be
optimized for the INT_MIN / unsigned case would be nice.

New version, that does a bit more.

Bootstrap+regtest on powerpc64le-unknown-linux-gnu.

2017-11-03  Marc Glisse  <marc.glisse@inria.fr>

gcc/
	* fold-const.c (fold_negate_expr_1): Call generic_simplify. Remove
	NEGATE_EXPR handling.
	* match.pd (-(-A)): Rewrite.

gcc/testsuite/
	* gcc.dg/tree-ssa/negneg-1.c: New file.
	* gcc.dg/tree-ssa/negneg-2.c: Likewise.
	* gcc.dg/tree-ssa/negneg-3.c: Likewise.
	* gcc.dg/tree-ssa/negneg-4.c: Likewise.


--
Marc Glisse
Index: gcc/fold-const.c
===================================================================
--- gcc/fold-const.c	(revision 254348)
+++ gcc/fold-const.c	(working copy)
@@ -585,25 +585,20 @@ fold_negate_expr_1 (location_t loc, tree
 				fold_negate_expr (loc, TREE_OPERAND (t, 0)),
 				fold_negate_expr (loc, TREE_OPERAND (t, 1)));
       break;
 
     case CONJ_EXPR:
       if (negate_expr_p (t))
 	return fold_build1_loc (loc, CONJ_EXPR, type,
 				fold_negate_expr (loc, TREE_OPERAND (t, 0)));
       break;
 
-    case NEGATE_EXPR:
-      if (!TYPE_OVERFLOW_SANITIZED (type))
-	return TREE_OPERAND (t, 0);
-      break;
-
     case PLUS_EXPR:
       if (!HONOR_SIGN_DEPENDENT_ROUNDING (element_mode (type))
 	  && !HONOR_SIGNED_ZEROS (element_mode (type)))
 	{
 	  /* -(A + B) -> (-B) - A.  */
 	  if (negate_expr_p (TREE_OPERAND (t, 1)))
 	    {
 	      tem = negate_expr (TREE_OPERAND (t, 1));
 	      return fold_build2_loc (loc, MINUS_EXPR, type,
 				      tem, TREE_OPERAND (t, 0));
@@ -706,21 +701,21 @@ fold_negate_expr_1 (location_t loc, tree
 	      temp = fold_build2_loc (loc, RSHIFT_EXPR, ntype, temp, op1);
 	      return fold_convert_loc (loc, type, temp);
 	    }
 	}
       break;
 
     default:
       break;
     }
 
-  return NULL_TREE;
+  return generic_simplify (loc, NEGATE_EXPR, type, t);
 }
 
 /* A wrapper for fold_negate_expr_1.  */
 
 static tree
 fold_negate_expr (location_t loc, tree t)
 {
   tree type = TREE_TYPE (t);
   STRIP_SIGN_NOPS (t);
   tree tem = fold_negate_expr_1 (loc, t);
Index: gcc/match.pd
===================================================================
--- gcc/match.pd	(revision 254348)
+++ gcc/match.pd	(working copy)
@@ -1496,26 +1496,45 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
   (if (tree_nop_conversion_p (type, TREE_TYPE (@1))
        && !TYPE_OVERFLOW_SANITIZED (type))
    (with
     {
      tree t1 = type;
      if (INTEGRAL_TYPE_P (type)
 	 && TYPE_OVERFLOW_WRAPS (type) != TYPE_OVERFLOW_WRAPS (TREE_TYPE (@1)))
        t1 = TYPE_OVERFLOW_WRAPS (type) ? type : TREE_TYPE (@1);
     }
     (convert (plus (convert:t1 @0) (convert:t1 @1))))))
- /* -(-A) -> A */
+ /* -(T)(-A) -> (T)A
+    Sign-extension is ok except for INT_MIN, which thankfully cannot
+    happen without overflow.  */
  (simplify
-  (negate (convert? (negate @1)))
-  (if (tree_nop_conversion_p (type, TREE_TYPE (@1))
-       && !TYPE_OVERFLOW_SANITIZED (type))
+  (negate (convert (negate @1)))
+  (if (INTEGRAL_TYPE_P (type)
+       && (TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (@1))
+	   || (!TYPE_UNSIGNED (TREE_TYPE (@1))
+	       && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@1))))
+       && !TYPE_OVERFLOW_SANITIZED (type)
+       && !TYPE_OVERFLOW_SANITIZED (TREE_TYPE (@1)))
    (convert @1)))
+ (simplify
+  (negate (convert negate_expr_p@1))
+  (if (SCALAR_FLOAT_TYPE_P (type)
+       && ((DECIMAL_FLOAT_TYPE_P (type)
+	    == DECIMAL_FLOAT_TYPE_P (TREE_TYPE (@1))
+	    && TYPE_PRECISION (type) >= TYPE_PRECISION (TREE_TYPE (@1)))
+	   || !HONOR_SIGN_DEPENDENT_ROUNDING (type)))
+   (convert (negate @1))))
+ (simplify
+  (negate (nop_convert (negate @1)))
+  (if (!TYPE_OVERFLOW_SANITIZED (type)
+       && !TYPE_OVERFLOW_SANITIZED (TREE_TYPE (@1)))
+   (view_convert @1)))
 
  /* We can't reassociate floating-point unless -fassociative-math
     or fixed-point plus or minus because of saturation to +-Inf.  */
  (if ((!FLOAT_TYPE_P (type) || flag_associative_math)
       && !FIXED_POINT_TYPE_P (type))
 
   /* Match patterns that allow contracting a plus-minus pair
      irrespective of overflow issues.  */
   /* (A +- B) - A       ->  +- B */
   /* (A +- B) -+ B      ->  A */
Index: gcc/testsuite/gcc.dg/tree-ssa/negneg-1.c
===================================================================
--- gcc/testsuite/gcc.dg/tree-ssa/negneg-1.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/tree-ssa/negneg-1.c	(working copy)
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-O -frounding-math -fdump-tree-optimized-raw -Wno-psabi" } */
+
+#define DEF(num, T1, T2) T2 f##num(T1 x) { \
+    T1 y = -x; \
+    T2 z = (T2)y; \
+    return -z; \
+}
+DEF(0, int, long long)
+DEF(1, int, unsigned long long)
+DEF(2, long long, int)
+DEF(3, unsigned long long, int)
+DEF(4, long long, unsigned)
+DEF(5, unsigned long long, unsigned)
+DEF(6, float, double)
+
+typedef int vec __attribute__((vector_size(4*sizeof(int))));
+typedef unsigned uvec __attribute__((vector_size(4*sizeof(int))));
+void h(vec*p,uvec*q){
+    vec a = -*p;
+    *q = -(uvec)a;
+}
+
+/* { dg-final { scan-tree-dump-not "negate_expr" "optimized"} } */
Index: gcc/testsuite/gcc.dg/tree-ssa/negneg-2.c
===================================================================
--- gcc/testsuite/gcc.dg/tree-ssa/negneg-2.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/tree-ssa/negneg-2.c	(working copy)
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fno-rounding-math -fdump-tree-optimized-raw" } */
+
+#define DEF(num, T1, T2) T2 f##num(T1 x) { \
+    T1 y = -x; \
+    T2 z = (T2)y; \
+    return -z; \
+}
+DEF(0, double, float)
+
+/* { dg-final { scan-tree-dump-not "negate_expr" "optimized"} } */
Index: gcc/testsuite/gcc.dg/tree-ssa/negneg-3.c
===================================================================
--- gcc/testsuite/gcc.dg/tree-ssa/negneg-3.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/tree-ssa/negneg-3.c	(working copy)
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O -frounding-math -fdump-tree-optimized-raw" } */
+
+// This assumes that long long is strictly larger than int
+
+#define DEF(num, T1, T2) T2 f##num(T1 x) { \
+    T1 y = -x; \
+    T2 z = (T2)y; \
+    return -z; \
+}
+DEF(0, unsigned, long long)
+DEF(1, unsigned, unsigned long long)
+DEF(2, double, float)
+
+/* { dg-final { scan-tree-dump-times "negate_expr" 6 "optimized"} } */
Index: gcc/testsuite/gcc.dg/tree-ssa/negneg-4.c
===================================================================
--- gcc/testsuite/gcc.dg/tree-ssa/negneg-4.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/tree-ssa/negneg-4.c	(working copy)
@@ -0,0 +1,18 @@
+/* { dg-do run } */
+/* { dg-options "-O -fwrapv" } */
+
+#define DEF(num, T1, T2) T2 f##num(T1 x) { \
+    T1 y = -x; \
+    T2 z = (T2)y; \
+    return -z; \
+}
+DEF(0, int, long long)
+
+int main(){
+    volatile int a = -1 - __INT_MAX__;
+    volatile long long b = f0 (a);
+    volatile long long c = a;
+    volatile long long d = -c;
+    if (b != d)
+      __builtin_abort();
+}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]