From 11d6b45d431b0aa30cf5ce3941b01ba4fd342af5 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Thu, 25 May 2017 10:45:48 +0200 Subject: [PATCH] Allow some NOP conversions in (X+CST1)+CST2 in match.pd 2017-05-25 Marc Glisse gcc/ * match.pd ((A +- CST1) +- CST2): Allow some conversions. * tree.c (drop_tree_overflow): Handle COMPLEX_CST and VECTOR_CST. gcc/testsuite/ * gcc.dg/tree-ssa/addadd.c: New file. From-SVN: r248448 --- gcc/ChangeLog | 5 ++++ gcc/match.pd | 40 ++++++++++++++++++++------ gcc/testsuite/ChangeLog | 4 +++ gcc/testsuite/gcc.dg/tree-ssa/addadd.c | 34 ++++++++++++++++++++++ gcc/tree.c | 19 ++++++++++++ 5 files changed, 94 insertions(+), 8 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/addadd.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5445bd5fd1f..cf75376b851 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2017-05-25 Marc Glisse + + * match.pd ((A +- CST1) +- CST2): Allow some conversions. + * tree.c (drop_tree_overflow): Handle COMPLEX_CST and VECTOR_CST. + 2017-05-25 Marc Glisse * fold-const.c (fold_binary_loc) [(A & C) == D]: Remove transformation. diff --git a/gcc/match.pd b/gcc/match.pd index 618b2ec3da8..77271a01619 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -1299,15 +1299,39 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) /* (A +- CST1) +- CST2 -> A + CST3 */ (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 (convert? (inner_op @0 CONSTANT_CLASS_P@1)) CONSTANT_CLASS_P@2) + (if (tree_nop_conversion_p (type, TREE_TYPE (@0))) + /* 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 (convert @0) (inner_op @2 (convert @1))) + (minus (convert @0) (neg_inner_op @2 (convert @1)))) + (if (!ANY_INTEGRAL_TYPE_P (TREE_TYPE (@0)) + || TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0))) + (if (outer_op == PLUS_EXPR) + (convert (plus @0 (inner_op (convert @2) @1))) + (convert (minus @0 (neg_inner_op (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); } + (convert (inner_op + (convert:utype @0) + (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 84026e31153..efe1dcb14f8 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2017-05-25 Marc Glisse + + * gcc.dg/tree-ssa/addadd.c: New file. + 2017-05-24 Nathan Sidwell * g++.dg/lookup/friend12.C: Adjust diagnostics. diff --git a/gcc/testsuite/gcc.dg/tree-ssa/addadd.c b/gcc/testsuite/gcc.dg/tree-ssa/addadd.c new file mode 100644 index 00000000000..16474db6565 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/addadd.c @@ -0,0 +1,34 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-optimized" } */ + +int f(unsigned x){ + x += 123; + int y = x; + y -= 99; + return y; +} +unsigned g(int x){ + x += 123; + unsigned y = x; + y -= 99; + return y; +} +int h(int x){ + x += __INT_MAX__; + x += 1; + return x; +} +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" } } */ +/* { dg-final { scan-tree-dump-times "\\(unsigned int\\)" 2 "optimized" } } */ +/* { dg-final { scan-tree-dump-not "2147483647" "optimized" } } */ diff --git a/gcc/tree.c b/gcc/tree.c index db316207369..a58f9aaa69e 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -13138,6 +13138,25 @@ drop_tree_overflow (tree t) and drop the flag. */ t = copy_node (t); TREE_OVERFLOW (t) = 0; + + /* For constants that contain nested constants, drop the flag + from those as well. */ + if (TREE_CODE (t) == COMPLEX_CST) + { + if (TREE_OVERFLOW (TREE_REALPART (t))) + TREE_REALPART (t) = drop_tree_overflow (TREE_REALPART (t)); + if (TREE_OVERFLOW (TREE_IMAGPART (t))) + TREE_IMAGPART (t) = drop_tree_overflow (TREE_IMAGPART (t)); + } + if (TREE_CODE (t) == VECTOR_CST) + { + for (unsigned i = 0; i < VECTOR_CST_NELTS (t); ++i) + { + tree& elt = VECTOR_CST_ELT (t, i); + if (TREE_OVERFLOW (elt)) + elt = drop_tree_overflow (elt); + } + } return t; } -- 2.30.2