Hi! We canonicalize x < type_max_val (type (x)) as x != type_max_val (type (x)) and similarly for x > type_min_val (type (x)). Unfortunately the former form is what is often more beneficial for merge_ranges, if we have as in the testcase e.g. x >= 0 && x != __INT_MAX__, in?_p is different and we don't optimize it, but it can be optimized into [0, __INT_MAX__-1] range.
Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2018-06-03 Jakub Jelinek <ja...@redhat.com> PR tree-optimization/69615 * fold-const.c (merge_ranges): If range1 is - [x, x] and x is the maximum or minimum of the type, try to merge it also as if range1 is + [-, x - 1] or + [x + 1, -]. * gcc.dg/pr69615.c: New test. --- gcc/fold-const.c.jj 2018-05-31 20:53:33.000000000 +0200 +++ gcc/fold-const.c 2018-06-02 19:20:10.210975502 +0200 @@ -5084,6 +5084,29 @@ merge_ranges (int *pin_p, tree *plow, tr tem = high0, high0 = high1, high1 = tem; } + /* If the second range is != high1 where high1 is the type maximum of + the type, try first merging with < high1 range. */ + if (low1 + && high1 + && TREE_CODE (low1) == INTEGER_CST + && (TREE_CODE (TREE_TYPE (low1)) == INTEGER_TYPE + || (TREE_CODE (TREE_TYPE (low1)) == ENUMERAL_TYPE + && known_eq (TYPE_PRECISION (TREE_TYPE (low1)), + GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (low1)))))) + && operand_equal_p (low1, high1, 0)) + { + if (tree_int_cst_equal (low1, TYPE_MAX_VALUE (TREE_TYPE (low1))) + && merge_ranges (pin_p, plow, phigh, in0_p, low0, high0, + !in1_p, NULL_TREE, range_predecessor (low1))) + return true; + /* Similarly for the second range != low1 where low1 is the type minimum + of the type, try first merging with > low1 range. */ + if (tree_int_cst_equal (low1, TYPE_MIN_VALUE (TREE_TYPE (low1))) + && merge_ranges (pin_p, plow, phigh, in0_p, low0, high0, + !in1_p, range_successor (low1), NULL_TREE)) + return true; + } + /* Now flag two cases, whether the ranges are disjoint or whether the second range is totally subsumed in the first. Note that the tests below are simplified by the ones above. */ --- gcc/testsuite/gcc.dg/pr69615.c.jj 2018-06-02 19:40:26.282663273 +0200 +++ gcc/testsuite/gcc.dg/pr69615.c 2018-06-02 19:40:01.427633205 +0200 @@ -0,0 +1,37 @@ +/* PR tree-optimization/69615 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* { dg-final { scan-tree-dump-not " >= 0" "optimized" } } */ +/* { dg-final { scan-tree-dump-not " < 0" "optimized" } } */ +/* { dg-final { scan-tree-dump-not " <= 23" "optimized" } } */ +/* { dg-final { scan-tree-dump-not " > 23" "optimized" } } */ + +extern void foo (void); + +void +f1 (int x) +{ + if (x >= 0 && x <= __INT_MAX__ - 1) + foo (); +} + +void +f2 (int x, int y) +{ + if (x >= 0 && y && x <= __INT_MAX__ - 1) + foo (); +} + +void +f3 (int x) +{ + if (x > -__INT_MAX__ - 1 && x <= 23) + foo (); +} + +void +f4 (int x, int y) +{ + if (x > -__INT_MAX__ - 1 && y && x <= 23) + foo (); +} Jakub