When adjusting the value range of an induction variable using SCEV, VRP calls scev_probably_wraps_p() with use_overflow_semantics=true. This parameter set to true makes scev_probably_wraps_p() assume that signed induction variables never wrap, so for these variables it always returns false (when strict overflow rules are in effect). This is wrong because if a signed induction variable really does overflow then we want to give it an INF(OVF) value range and not the (finite) estimation returned by SCEV.
While this change shouldn't make a difference in code generation, it should help improve the coverage of -Wstrict-overflow warnings on induction variables like in the test case. OK after bootstrap + regtest on x86_64-unknown-linux-gnu? gcc/ * tree-vrp.c (adjust_range_with_scev): Call scev_probably_wraps_p with use_overflow_semantics=false. gcc/testsuite/ * gcc.dg/Wstrict-overflow-27.c: New test. --- gcc/testsuite/gcc.dg/Wstrict-overflow-27.c | 22 ++++++++++++++++++++++ gcc/tree-vrp.c | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.dg/Wstrict-overflow-27.c diff --git a/gcc/testsuite/gcc.dg/Wstrict-overflow-27.c b/gcc/testsuite/gcc.dg/Wstrict-overflow-27.c new file mode 100644 index 0000000..c1f27ab --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wstrict-overflow-27.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-options "-fstrict-overflow -O2 -Wstrict-overflow" } */ + +/* Warn about an overflow when folding i < 0. */ + +void bar (unsigned *p); + +int +foo (unsigned *p) +{ + int i; + int sum = 0; + + for (i = 0; i < *p; i++) + { + if (i < 0) /* { dg-warning "signed overflow" } */ + sum += 2; + bar (p); + } + + return sum; +} diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index a75138f..bf9ff61 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -4270,7 +4270,7 @@ adjust_range_with_scev (value_range_t *vr, struct loop *loop, dir == EV_DIR_UNKNOWN /* ... or if it may wrap. */ || scev_probably_wraps_p (init, step, stmt, get_chrec_loop (chrec), - true)) + /*use_overflow_semantics=*/false)) return; /* We use TYPE_MIN_VALUE and TYPE_MAX_VALUE here instead of -- 2.2.0.rc1.23.gf570943