From ed73f46f30cabeea4de64e7cce0682a7a610ffb6 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Wed, 21 Jun 2017 13:16:27 +0200 Subject: [PATCH] NOP conversions in X+CST+CST 2017-06-21 Marc Glisse 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 | 5 +++ gcc/match.pd | 58 +++++++++++++++++++++++++++----- gcc/testsuite/ChangeLog | 5 +++ gcc/testsuite/gcc.dg/tree-ssa/addadd-2.c | 15 +++++++++ gcc/testsuite/gcc.dg/tree-ssa/addadd.c | 6 ++-- 5 files changed, 77 insertions(+), 12 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/addadd-2.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a40820ba10e..65ff2356f3b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2017-06-21 Marc Glisse + + * match.pd (nop_convert): New predicate. + ((A +- CST1) +- CST2): Allow some NOP conversions. + 2017-06-21 Jakub Jelinek PR c++/81130 diff --git a/gcc/match.pd b/gcc/match.pd index 244e9eb5257..7bd26763826 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -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) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a7524ac3fe7..ccfd2746b87 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2017-06-21 Marc Glisse + + * gcc.dg/tree-ssa/addadd.c: Un-XFAIL. + * gcc.dg/tree-ssa/addadd-2.c: New file. + 2017-06-21 Tom de Vries * 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 index 00000000000..39aa032c9b1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/addadd-2.c @@ -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" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/addadd.c b/gcc/testsuite/gcc.dg/tree-ssa/addadd.c index 669cfbc47ec..16474db6565 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/addadd.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/addadd.c @@ -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" } } */ -- 2.11.4.GIT