https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69320
--- Comment #2 from Jeffrey A. Law <law at redhat dot com> --- Ha! Got it. On the path noted in the earlier comment we have the following: <bb 444>: pred_x ={v} {CLOBBER}; pred_y ={v} {CLOBBER}; _423 = s_46(D)->rd_total; _424 = score[best_374]; _425 = (long int) _424; _426 = _423 + _425; s_46(D)->rd_total = _426; if (best_374 != 2) goto <bb 445>; else goto <bb 449>; I'd looked at that block a few times and even traced where that test came from, the propagation of best_374 into that test and determined that while suboptimal, it was correct (the test originally used a different variable, one which had the range [0..2]. The path by which the "2" appears in that range eventually gets proved unexecutable and removed. Once that happens the original object becomes equivalent to best_374 and the copy propagation occurs in copyprop (which AFAICT doesn't try to use range information to simplify things). Anyway, all that is irrelevant to the problem. ssa_name_has_boolean_range does something like this edge_info->rhs = (integer_zerop (op1) ? true_val : false_val); When it only had to deal with booleans, that was fine because op1 in this context would always be the constant 0 or 1 (it's the RHS of the conditional). But once we start handling integers with a narrow range, that test is wrong. Fixing is trivial. It'll probably take longer to boil down a suitable testcase -- it's late. I'll poke at this further over the weekend.