From a96d8d67d0073a7031c0712bc3fb7759417b2125 Mon Sep 17 00:00:00 2001 From: Andrew MacLeod Date: Tue, 29 Jun 2021 10:52:58 -0400 Subject: [PATCH] Fix MINUS_EXPR relations. Flesh out and correct relations for both wrapping and non-wrapping values. gcc/ PR tree-optimization/101254 * range-op.cc (operator_minus::op1_op2_relation_effect): Check for wrapping/non-wrapping when setting the result range. gcc/testsuite * gcc.dg/pr101254.c: New. --- gcc/range-op.cc | 64 ++++++++++++++++++++++++--------- gcc/testsuite/gcc.dg/pr101254.c | 27 ++++++++++++++ 2 files changed, 74 insertions(+), 17 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/pr101254.c diff --git a/gcc/range-op.cc b/gcc/range-op.cc index 29ee9e0f645..97b9843e095 100644 --- a/gcc/range-op.cc +++ b/gcc/range-op.cc @@ -1314,24 +1314,54 @@ operator_minus::op1_op2_relation_effect (irange &lhs_range, tree type, unsigned prec = TYPE_PRECISION (type); signop sgn = TYPE_SIGN (type); - switch (rel) + // == and != produce [0,0] and ~[0,0] regardless of wrapping. + if (rel == EQ_EXPR) + rel_range = int_range<2> (type, wi::zero (prec), wi::zero (prec)); + else if (rel == NE_EXPR) + rel_range = int_range<2> (type, wi::zero (prec), wi::zero (prec), + VR_ANTI_RANGE); + else if (TYPE_OVERFLOW_WRAPS (type)) { - // op1 > op2, op1 - op2 can be restricted to [1, max] - case GT_EXPR: - rel_range = int_range<2> (type, wi::one (prec), - wi::max_value (prec, sgn)); - break; - // op1 >= op2, op1 - op2 can be restricted to [0, max] - case GE_EXPR: - rel_range = int_range<2> (type, wi::zero (prec), - wi::max_value (prec, sgn)); - break; - // op1 == op2, op1 - op2 can be restricted to [0, 0] - case EQ_EXPR: - rel_range = int_range<2> (type, wi::zero (prec), wi::zero (prec)); - break; - default: - return false; + switch (rel) + { + // For wrapping signed values and unsigned, if op1 > op2 or + // op1 < op2, then op1 - op2 can be restricted to ~[0, 0]. + case GT_EXPR: + case LT_EXPR: + rel_range = int_range<2> (type, wi::zero (prec), wi::zero (prec), + VR_ANTI_RANGE); + break; + default: + return false; + } + } + else + { + switch (rel) + { + // op1 > op2, op1 - op2 can be restricted to [1, +INF] + case GT_EXPR: + rel_range = int_range<2> (type, wi::one (prec), + wi::max_value (prec, sgn)); + break; + // op1 >= op2, op1 - op2 can be restricted to [0, +INF] + case GE_EXPR: + rel_range = int_range<2> (type, wi::zero (prec), + wi::max_value (prec, sgn)); + break; + // op1 < op2, op1 - op2 can be restricted to [-INF, -1] + case LT_EXPR: + rel_range = int_range<2> (type, wi::min_value (prec, sgn), + wi::minus_one (prec)); + break; + // op1 <= op2, op1 - op2 can be restricted to [-INF, 0] + case LE_EXPR: + rel_range = int_range<2> (type, wi::min_value (prec, sgn), + wi::zero (prec)); + break; + default: + return false; + } } lhs_range.intersect (rel_range); return true; diff --git a/gcc/testsuite/gcc.dg/pr101254.c b/gcc/testsuite/gcc.dg/pr101254.c new file mode 100644 index 00000000000..b2460ed86f3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr101254.c @@ -0,0 +1,27 @@ +/* PR tree-optimization/101254 */ +/* { dg-do run } */ +/* { dg-options "-O2 -fwrapv" } */ + +int +foo (long long imin, long long imax) +{ + if (imin > imax) + return 0; + else if (imax - imin < 0 || (imax - imin) + 1 < 0) + return 0; + return 1; +} + +int +main () +{ + long long imax = __LONG_LONG_MAX__; + long long imin = -imax - 1; + if (!foo (-10, 10)) + __builtin_abort (); + if (foo (-10, imax)) + __builtin_abort (); + if (foo (imin, imax)) + __builtin_abort (); + return 0; +} -- 2.34.1