NOP conversions in X+CST+CST
authorMarc Glisse <marc.glisse@inria.fr>
Wed, 21 Jun 2017 11:16:27 +0000 (13:16 +0200)
committerMarc Glisse <glisse@gcc.gnu.org>
Wed, 21 Jun 2017 11:16:27 +0000 (11:16 +0000)
2017-06-21  Marc Glisse  <marc.glisse@inria.fr>

gcc/
* match.pd (nop_convert): New predicate.
((A +- CST1) +- CST2): Allow some NOP conversions.

gcc/testsuite/
* gcc.dg/tree-ssa/addadd.c: Un-XFAIL.
* gcc.dg/tree-ssa/addadd-2.c: New file.

From-SVN: r249447

gcc/ChangeLog
gcc/match.pd
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/addadd-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/addadd.c

index a40820ba10e0b799bf35fe5f96c0404d50b06952..65ff2356f3bcb24ccb3cb4b62c634ca92453f273 100644 (file)
@@ -1,3 +1,8 @@
+2017-06-21  Marc Glisse  <marc.glisse@inria.fr>
+
+       * match.pd (nop_convert): New predicate.
+       ((A +- CST1) +- CST2): Allow some NOP conversions.
+
 2017-06-21  Jakub Jelinek  <jakub@redhat.com>
 
        PR c++/81130
index 244e9eb52573dd59c36633aaf518b74b94df1a77..7bd26763826b1d5d59cd0093e7898ff0bc66b502 100644 (file)
@@ -74,6 +74,20 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (FLOOR)
 DEFINE_INT_AND_FLOAT_ROUND_FN (CEIL)
 DEFINE_INT_AND_FLOAT_ROUND_FN (ROUND)
 DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
+    
+/* As opposed to convert?, this still creates a single pattern, so
+   it is not a suitable replacement for convert? in all cases.  */
+(match (nop_convert @0)
+ (convert @0)
+ (if (tree_nop_conversion_p (type, TREE_TYPE (@0)))))
+(match (nop_convert @0)
+ (view_convert @0)
+ (if (VECTOR_TYPE_P (type) && VECTOR_TYPE_P (TREE_TYPE (@0))
+      && TYPE_VECTOR_SUBPARTS (type) == TYPE_VECTOR_SUBPARTS (TREE_TYPE (@0))
+      && tree_nop_conversion_p (TREE_TYPE (type), TREE_TYPE (TREE_TYPE (@0))))))
+/* This one has to be last, or it shadows the others.  */
+(match (nop_convert @0)
+ @0) 
 
 /* Simplifications of operations with one constant operand and
    simplifications to constants or single values.  */
@@ -1296,18 +1310,44 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
    (minus @0 (minus @0 @1))
    @1)
 
-  /* (A +- CST1) +- CST2 -> A + CST3  */
+  /* (A +- CST1) +- CST2 -> A + CST3
+     Use view_convert because it is safe for vectors and equivalent for
+     scalars.  */
   (for outer_op (plus minus)
    (for inner_op (plus minus)
+       neg_inner_op (minus plus)
     (simplify
-     (outer_op (inner_op @0 CONSTANT_CLASS_P@1) CONSTANT_CLASS_P@2)
-     /* If the constant operation overflows we cannot do the transform
-       as we would introduce undefined overflow, for example
-       with (a - 1) + INT_MIN.  */
-     (with { tree cst = const_binop (outer_op == inner_op
-                                    ? PLUS_EXPR : MINUS_EXPR, type, @1, @2); }
-      (if (cst && !TREE_OVERFLOW (cst))
-       (inner_op @0 { cst; } ))))))
+     (outer_op (nop_convert (inner_op @0 CONSTANT_CLASS_P@1))
+              CONSTANT_CLASS_P@2)
+     /* If one of the types wraps, use that one.  */
+     (if (!ANY_INTEGRAL_TYPE_P (type) || TYPE_OVERFLOW_WRAPS (type))
+      (if (outer_op == PLUS_EXPR)
+       (plus (view_convert @0) (inner_op @2 (view_convert @1)))
+       (minus (view_convert @0) (neg_inner_op @2 (view_convert @1))))
+      (if (!ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0))
+          || TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0)))
+       (if (outer_op == PLUS_EXPR)
+       (view_convert (plus @0 (inner_op (view_convert @2) @1)))
+       (view_convert (minus @0 (neg_inner_op (view_convert @2) @1))))
+       /* If the constant operation overflows we cannot do the transform
+         directly as we would introduce undefined overflow, for example
+         with (a - 1) + INT_MIN.  */
+       (if (types_match (type, @0))
+       (with { tree cst = const_binop (outer_op == inner_op
+                                       ? PLUS_EXPR : MINUS_EXPR,
+                                       type, @1, @2); }
+        (if (cst && !TREE_OVERFLOW (cst))
+         (inner_op @0 { cst; } )
+         /* X+INT_MAX+1 is X-INT_MIN.  */
+         (if (INTEGRAL_TYPE_P (type) && cst
+              && wi::eq_p (cst, wi::min_value (type)))
+          (neg_inner_op @0 { wide_int_to_tree (type, cst); })
+          /* Last resort, use some unsigned type.  */
+          (with { tree utype = unsigned_type_for (type); }
+           (view_convert (inner_op
+                          (view_convert:utype @0)
+                          (view_convert:utype
+                           { drop_tree_overflow (cst); })))))))))))))
 
   /* (CST1 - A) +- CST2 -> CST3 - A  */
   (for outer_op (plus minus)
index a7524ac3fe75d35999d80bf0e67a245667177984..ccfd2746b876d5df7a0233e6eb4be8ce4d011af6 100644 (file)
@@ -1,3 +1,8 @@
+2017-06-21  Marc Glisse  <marc.glisse@inria.fr>
+
+       * gcc.dg/tree-ssa/addadd.c: Un-XFAIL.
+       * gcc.dg/tree-ssa/addadd-2.c: New file.
+
 2017-06-21  Tom de Vries  <tom@codesourcery.com>
 
        * lib/target-supports.exp (add_options_for_stack_size): New proc.
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/addadd-2.c b/gcc/testsuite/gcc.dg/tree-ssa/addadd-2.c
new file mode 100644 (file)
index 0000000..39aa032
--- /dev/null
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-optimized" } */
+
+typedef int S __attribute__((vector_size(64)));
+typedef unsigned U __attribute__((vector_size(64)));
+void j(S*x){
+  *x += __INT_MAX__;
+  *x += __INT_MAX__;
+}
+void k(S*x){
+  U y = (U)(*x + __INT_MAX__);
+  *x = (S)(y + __INT_MAX__);
+}
+
+/* { dg-final { scan-tree-dump-not "2147483647" "optimized" } } */
index 669cfbc47ec23d611af981f8c712c2a931badfde..16474db65658a5e3e88b141b24f991c80936a9e9 100644 (file)
@@ -29,6 +29,6 @@ void j(S*x){
   *x += __INT_MAX__;
 }
 
-/* { dg-final { scan-tree-dump-times " \\+ 24;" 2 "optimized" { xfail *-*-* } } } */
-/* { dg-final { scan-tree-dump-times "\\(unsigned int\\)" 2 "optimized" { xfail *-*-* }  } } */
-/* { dg-final { scan-tree-dump-not "2147483647" "optimized" { xfail *-*-* }  } } */
+/* { dg-final { scan-tree-dump-times " \\+ 24;" 2 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "\\(unsigned int\\)" 2 "optimized" } } */
+/* { dg-final { scan-tree-dump-not "2147483647" "optimized" } } */