diff mbox

NOP conversions in X+CST+CST

Message ID alpine.DEB.2.02.1706202248370.12192@stedding.saclay.inria.fr
State New
Headers show

Commit Message

Marc Glisse June 20, 2017, 9 p.m. UTC
Hello,

now that FRE was fixed to avoid infinite recursion, this patch passes 
bootstrap+testsuite on x86_64-pc-linux-gnu multilib with all languages 
(including ada).

This isn't exactly the patch that was reverted, because the previous patch 
did not actually handle vectors properly.

It still shouldn't interfere with the patch by Robin Dapp which IIUC only 
handles the case where the conversion is an extension.

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.

Comments

Richard Biener June 21, 2017, 7:16 a.m. UTC | #1
On Tue, Jun 20, 2017 at 11:00 PM, Marc Glisse <marc.glisse@inria.fr> wrote:
> Hello,
>
> now that FRE was fixed to avoid infinite recursion, this patch passes
> bootstrap+testsuite on x86_64-pc-linux-gnu multilib with all languages
> (including ada).
>
> This isn't exactly the patch that was reverted, because the previous patch
> did not actually handle vectors properly.
>
> It still shouldn't interfere with the patch by Robin Dapp which IIUC only
> handles the case where the conversion is an extension.

Ok.

Richard.

> 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.
>
> --
> Marc Glisse
diff mbox

Patch

Index: gcc/match.pd
===================================================================
--- gcc/match.pd	(revision 249413)
+++ gcc/match.pd	(working copy)
@@ -67,20 +67,34 @@  along with GCC; see the file COPYING3.
 			      BUILT_IN_L##FN \
 			      BUILT_IN_LL##FN) \
   (define_operator_list X##FN##L BUILT_IN_I##FN##L \
 				 BUILT_IN_L##FN##L \
 				 BUILT_IN_LL##FN##L)
 
 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.  */
 
 (for op (plus pointer_plus minus bit_ior bit_xor)
   (simplify
     (op @0 integer_zerop)
     (non_lvalue @0)))
 
 /* 0 +p index -> (type)index */
@@ -1289,32 +1303,58 @@  DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
   (simplify
     (plus:c (minus @0 @1) @1)
     @0)
   (simplify
    (minus @0 (plus:c @0 @1))
    (negate @1))
   (simplify
    (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)
    (simplify
     (outer_op (minus CONSTANT_CLASS_P@1 @0) CONSTANT_CLASS_P@2)
     (with { tree cst = const_binop (outer_op, type, @1, @2); }
      (if (cst && !TREE_OVERFLOW (cst))
       (minus { cst; } @0)))))
 
   /* CST1 - (CST2 - A) -> CST3 + A  */
Index: gcc/testsuite/gcc.dg/tree-ssa/addadd-2.c
===================================================================
--- gcc/testsuite/gcc.dg/tree-ssa/addadd-2.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/tree-ssa/addadd-2.c	(working copy)
@@ -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: gcc/testsuite/gcc.dg/tree-ssa/addadd.c
===================================================================
--- gcc/testsuite/gcc.dg/tree-ssa/addadd.c	(revision 249413)
+++ gcc/testsuite/gcc.dg/tree-ssa/addadd.c	(working copy)
@@ -22,13 +22,13 @@  int i(int x){
   x += __INT_MAX__;
   x += __INT_MAX__;
   return x;
 }
 typedef int S __attribute__((vector_size(16)));
 void j(S*x){
   *x += __INT_MAX__;
   *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" } } */