aboutsummaryrefslogtreecommitdiff
path: root/gcc/match.pd
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@gcc.gnu.org>2019-12-02 09:51:49 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2019-12-02 09:51:49 +0100
commita213ab38560f0b95ec318b2a4795e66cc0518848 (patch)
tree39451dd44a61601d97dcf6462ceede232af61ca9 /gcc/match.pd
parent9b14fc3326e087975653b1af8ac54114041cde51 (diff)
downloadgcc-a213ab38560f0b95ec318b2a4795e66cc0518848.zip
gcc-a213ab38560f0b95ec318b2a4795e66cc0518848.tar.gz
gcc-a213ab38560f0b95ec318b2a4795e66cc0518848.tar.bz2
re PR tree-optimization/92712 (Performance regression with assumed values)
PR tree-optimization/92712 * match.pd ((A * B) +- A -> (B +- 1) * A, A +- (A * B) -> (1 +- B) * A): Allow optimizing signed integers even when we don't know anything about range of A, but do know something about range of B and the simplification won't introduce new UB. * gcc.dg/tree-ssa/pr92712-1.c: New test. * gcc.dg/tree-ssa/pr92712-2.c: New test. * gcc.dg/tree-ssa/pr92712-3.c: New test. * gfortran.dg/loop_versioning_1.f90: Adjust expected number of likely to be innermost dimension messages. * gfortran.dg/loop_versioning_10.f90: Likewise. * gfortran.dg/loop_versioning_6.f90: Likewise. From-SVN: r278894
Diffstat (limited to 'gcc/match.pd')
-rw-r--r--gcc/match.pd32
1 files changed, 28 insertions, 4 deletions
diff --git a/gcc/match.pd b/gcc/match.pd
index eabd01f..14f6a9d 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -2480,18 +2480,42 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(plusminus @0 (mult:c@3 @0 @2))
(if ((!ANY_INTEGRAL_TYPE_P (type)
|| TYPE_OVERFLOW_WRAPS (type)
+ /* For @0 + @0*@2 this transformation would introduce UB
+ (where there was none before) for @0 in [-1,0] and @2 max.
+ For @0 - @0*@2 this transformation would introduce UB
+ for @0 0 and @2 in [min,min+1] or @0 -1 and @2 min+1. */
|| (INTEGRAL_TYPE_P (type)
- && tree_expr_nonzero_p (@0)
- && expr_not_equal_to (@0, wi::minus_one (TYPE_PRECISION (type)))))
+ && ((tree_expr_nonzero_p (@0)
+ && expr_not_equal_to (@0,
+ wi::minus_one (TYPE_PRECISION (type))))
+ || (plusminus == PLUS_EXPR
+ ? expr_not_equal_to (@2,
+ wi::max_value (TYPE_PRECISION (type), SIGNED))
+ /* Let's ignore the @0 -1 and @2 min case. */
+ : (expr_not_equal_to (@2,
+ wi::min_value (TYPE_PRECISION (type), SIGNED))
+ && expr_not_equal_to (@2,
+ wi::min_value (TYPE_PRECISION (type), SIGNED)
+ + 1))))))
&& single_use (@3))
(mult (plusminus { build_one_cst (type); } @2) @0)))
(simplify
(plusminus (mult:c@3 @0 @2) @0)
(if ((!ANY_INTEGRAL_TYPE_P (type)
|| TYPE_OVERFLOW_WRAPS (type)
+ /* For @0*@2 + @0 this transformation would introduce UB
+ (where there was none before) for @0 in [-1,0] and @2 max.
+ For @0*@2 - @0 this transformation would introduce UB
+ for @0 0 and @2 min. */
|| (INTEGRAL_TYPE_P (type)
- && tree_expr_nonzero_p (@0)
- && expr_not_equal_to (@0, wi::minus_one (TYPE_PRECISION (type)))))
+ && ((tree_expr_nonzero_p (@0)
+ && (plusminus == MINUS_EXPR
+ || expr_not_equal_to (@0,
+ wi::minus_one (TYPE_PRECISION (type)))))
+ || expr_not_equal_to (@2,
+ (plusminus == PLUS_EXPR
+ ? wi::max_value (TYPE_PRECISION (type), SIGNED)
+ : wi::min_value (TYPE_PRECISION (type), SIGNED))))))
&& single_use (@3))
(mult (plusminus @2 { build_one_cst (type); }) @0))))))