This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
NOP conversions in X+CST+CST
- From: Marc Glisse <marc dot glisse at inria dot fr>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 20 Jun 2017 23:00:48 +0200 (CEST)
- Subject: NOP conversions in X+CST+CST
- Authentication-results: sourceware.org; auth=none
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.
--
Marc Glisse
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" } } */