Hi! When hacking on range reassoc opt, I've noticed we can emit code with undefined behavior even when there wasn't one originally, in particular for: (X - 43U) <= 3U || (X - 75U) <= 3U and this loop can transform that into ((X - 43U) & ~(75U - 43U)) <= 3U. */ we actually don't transform it to what the comment says, but ((X - 43) & ~(75U - 43U)) <= 3U i.e. the initial subtraction can be performed in signed type, if in here X is e.g. INT_MIN or INT_MIN + 42, the subtraction at gimple level would be UB (not caught by -fsanitize=undefined, because that is handled much earlier).
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2014-10-14 Jakub Jelinek <ja...@redhat.com> * tree-ssa-reassoc.c (optimize_range_tests_diff): Perform MINUS_EXPR in unsigned type to avoid undefined behavior. --- gcc/tree-ssa-reassoc.c.jj 2014-10-13 17:54:33.000000000 +0200 +++ gcc/tree-ssa-reassoc.c 2014-10-13 17:58:07.312705218 +0200 @@ -2250,8 +2250,13 @@ optimize_range_tests_diff (enum tree_cod if (tree_log2 (tem1) < 0) return false; + type = unsigned_type_for (type); + tem1 = fold_convert (type, tem1); + tem2 = fold_convert (type, tem2); + lowi = fold_convert (type, lowi); mask = fold_build1 (BIT_NOT_EXPR, type, tem1); - tem1 = fold_binary (MINUS_EXPR, type, rangei->exp, lowi); + tem1 = fold_binary (MINUS_EXPR, type, + fold_convert (type, rangei->exp), lowi); tem1 = fold_build2 (BIT_AND_EXPR, type, tem1, mask); lowj = build_int_cst (type, 0); if (update_range_test (rangei, rangej, 1, opcode, ops, tem1, Jakub