From 1e27e7a582a9b86bcf86f5c103cd947672746e97 Mon Sep 17 00:00:00 2001 From: Andrew MacLeod Date: Tue, 17 Nov 2020 14:47:58 -0500 Subject: [PATCH] recognize implied ranges for modulo. implement op1_range for modulo with implied positive and negative ranges. gcc/ PR tree-optimization/91029 * range-op.cc (operator_trunc_mod::op1_range): New. gcc/testsuite/ * gcc.dg/pr91029.c: New. --- gcc/range-op.cc | 28 ++++++++++++++++++++ gcc/testsuite/gcc.dg/pr91029.c | 47 ++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 gcc/testsuite/gcc.dg/pr91029.c diff --git a/gcc/range-op.cc b/gcc/range-op.cc index d0adc95527a..f37796cac70 100644 --- a/gcc/range-op.cc +++ b/gcc/range-op.cc @@ -2634,6 +2634,9 @@ public: const wide_int &lh_ub, const wide_int &rh_lb, const wide_int &rh_ub) const; + virtual bool op1_range (irange &r, tree type, + const irange &lhs, + const irange &op2) const; } op_trunc_mod; void @@ -2680,6 +2683,31 @@ operator_trunc_mod::wi_fold (irange &r, tree type, value_range_with_overflow (r, type, new_lb, new_ub); } +bool +operator_trunc_mod::op1_range (irange &r, tree type, + const irange &lhs, + const irange &op2) const +{ + // PR 91029. Check for signed truncation with op2 >= 0. + if (TYPE_SIGN (type) == SIGNED && wi::ge_p (op2.lower_bound (), 0, SIGNED)) + { + unsigned prec = TYPE_PRECISION (type); + // if a & b >=0 , then a >= 0. + if (wi::ge_p (lhs.lower_bound (), 0, SIGNED)) + { + r = value_range (type, wi::zero (prec), wi::max_value (prec, SIGNED)); + return true; + } + // if a & b < 0 , then a <= 0. + if (wi::lt_p (lhs.upper_bound (), 0, SIGNED)) + { + r = value_range (type, wi::min_value (prec, SIGNED), wi::zero (prec)); + return true; + } + } + return false; +} + class operator_logical_not : public range_operator { diff --git a/gcc/testsuite/gcc.dg/pr91029.c b/gcc/testsuite/gcc.dg/pr91029.c new file mode 100644 index 00000000000..8a4134c5d96 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr91029.c @@ -0,0 +1,47 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-evrp" } */ + +void kill (void); +int xx; + +void f1 (int i) +{ + if ((i % 7) == 3) + { + xx = (i < 0); + if (xx) + kill (); + } +} + +void f2 (int i) +{ + if ((i % 7) >= 0) + { + xx = (i < 0); + if (xx) + kill (); + } +} + +void f3 (int i) +{ + if ((i % 7) == -3) + { + xx = (i > 0); + if (xx) + kill (); + } +} + +void f4 (int i) +{ + if ((i % 7) < 0) + { + xx = (i > 0); + if (xx) + kill (); + } +} + +/* { dg-final { scan-tree-dump-not "kill" "evrp" } } */ -- 2.30.2