https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69615
--- Comment #6 from Jakub Jelinek <jakub at gcc dot gnu.org> --- For r0_to_imax_1 the following works for me: --- gcc/fold-const.c.jj 2018-05-31 20:53:33.000000000 +0200 +++ gcc/fold-const.c 2018-06-02 18:36:23.795635887 +0200 @@ -5084,6 +5084,35 @@ 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)))))) + && tree_int_cst_equal (low1, TYPE_MAX_VALUE (TREE_TYPE (low1))) + && operand_equal_p (low1, high1, 0) + && merge_ranges (pin_p, plow, phigh, in0_p, low0, high0, + !in1_p, NULL_TREE, range_predecessor (low1))) + return true; + + /* Similarly for first range != low0 where low0 is the type minimum of + the type, try first merging with > low0 range. */ + if (low0 + && high0 + && (TREE_CODE (TREE_TYPE (low0)) == INTEGER_TYPE + || (TREE_CODE (TREE_TYPE (low0)) == ENUMERAL_TYPE + && known_eq (TYPE_PRECISION (TREE_TYPE (low0)), + GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (low0)))))) + && tree_int_cst_equal (low0, TYPE_MIN_VALUE (TREE_TYPE (low0))) + && operand_equal_p (low0, high0, 0) + && merge_ranges (pin_p, plow, phigh, !in0_p, range_successor (low0), + NULL_TREE, in1_p, low1, high1)) + 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. */ The thing is that we canonicalize < INT_MAX (and <= INT_MAX-1) to != INT_MAX-1 and in the range code we'd better try the first form instead.