The following fixes PR84933 without really tackling the underlying issue of having out-of-bound ranges in the lattice (out-of-bound with respect to TYPE_MIN/MAX_VALUE) which is not sth I'd like to resolve at this point. It simply avoids the bogus transform in set_and_canonicalize_value_range that results in this case (~[0, 5] -> [4, 1] with TYPE_MAX_VALUE == 1). I realize there are similar conditions throughout the code so a more conservative "fix" would be to not use TYPE_MIN/MAX_VALUE at all but IIRC that will regress some optimization cases - still that's sth to consider for GCC9.
Bootstrapped on x86_64-unknown-linux-gnu, testing in progress. Richard. 2018-03-19 Richard Biener <rguent...@suse.de> PR tree-optimization/84933 * tree-vrp.c (set_and_canonicalize_value_range): Treat out-of-bound values as -INF/INF when canonicalizing an ANTI_RANGE to a RANGE. * g++.dg/pr84933.C: New testcase. Index: gcc/tree-vrp.c =================================================================== --- gcc/tree-vrp.c (revision 258641) +++ gcc/tree-vrp.c (working copy) @@ -386,8 +386,13 @@ set_and_canonicalize_value_range (value_ /* Anti-ranges that can be represented as ranges should be so. */ if (t == VR_ANTI_RANGE) { - bool is_min = vrp_val_is_min (min); - bool is_max = vrp_val_is_max (max); + /* For -fstrict-enums we may receive out-of-range ranges so consider + values < -INF and values > INF as -INF/INF as well. */ + tree type = TREE_TYPE (min); + bool is_min = (INTEGRAL_TYPE_P (type) + && tree_int_cst_compare (min, TYPE_MIN_VALUE (type)) <= 0); + bool is_max = (INTEGRAL_TYPE_P (type) + && tree_int_cst_compare (max, TYPE_MAX_VALUE (type)) >= 0); if (is_min && is_max) { Index: gcc/testsuite/g++.dg/pr84933.C =================================================================== --- gcc/testsuite/g++.dg/pr84933.C (nonexistent) +++ gcc/testsuite/g++.dg/pr84933.C (working copy) @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -fstrict-enums -fno-inline" } */ + +enum a {}; +int *d; +int b, e, f; +a c, g; +class h { + virtual unsigned i(); +}; +class j : h { + unsigned i() { + for (;;) { + b = c <= 0; + if (b) + e = *d; + b = g && c; + if (b) + f = *d; + } + } +}; +void k() { new j; }