https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97953
--- Comment #17 from Richard Biener <rguenth at gcc dot gnu.org> --- The issue is a bogus jump threading done in VRP2 caused by bogus range info on the hoisted gimple_code (use->stmt). tree-ssa-loop-ivopts.c.137t.pre- # PT = nonlocal escaped null tree-ssa-loop-ivopts.c.137t.pre- pretmp_252 = use_79(D)->stmt; tree-ssa-loop-ivopts.c.137t.pre: pretmp_31 = MEM[(const struct gimple *)pretmp_252].code; tree-ssa-loop-ivopts.c.137t.pre- if (_1 == 4) the if is the cand->pos == IP_ORIGINAL check. Now after dom3 suddenly we have tree-ssa-loop-ivopts.c.188t.dom3- # PT = nonlocal escaped null tree-ssa-loop-ivopts.c.188t.dom3- pretmp_252 = use_79(D)->stmt; tree-ssa-loop-ivopts.c.188t.dom3- # RANGE [6, 6] NONZERO 6 tree-ssa-loop-ivopts.c.188t.dom3: pretmp_31 = MEM[(const struct gimple *)pretmp_252].code; tree-ssa-loop-ivopts.c.188t.dom3- if (_1 == 4) before DOM the check is below <bb 26> [local count: 972093932]: # PT = nonlocal escaped null # prephitmp_179 = PHI <pretmp_252(5), pretmp_252(6), pretmp_250(23), pretmp_216(25), pretmp_210(21)> _164 = MEM[(const struct gimple *)prephitmp_179].code; # DEBUG g => NULL if (_164 == 6) goto <bb 34>; [26.31%] where DOM seems to CSE the load with the earlier (correct) but then even though it pops the recorded range on pretmp_31 it never backs out the SSA_NAME_RANGE_INFO? It's set here: #0 set_range_info_raw (name=<ssa_name 0x7fffefc9cd38 31>, range_type=VR_RANGE, min=..., max=...) at /home/rguenther/src/trunk/gcc/tree-ssanames.c:359 #1 0x0000000001b1d0f8 in set_range_info (name=<ssa_name 0x7fffefc9cd38 31>, range_type=VR_RANGE, min=..., max=...) at /home/rguenther/src/trunk/gcc/tree-ssanames.c:405 #2 0x00000000027a4d91 in evrp_range_analyzer::set_ssa_range_info (this=0x7fffffffd100, lhs=<ssa_name 0x7fffefc9cd38 31>, vr=0x444dcd0) at /home/rguenther/src/trunk/gcc/gimple-ssa-evrp-analyze.c:113 #3 0x00000000027a5597 in evrp_range_analyzer::record_ranges_from_incoming_edge (this=0x7fffffffd100, bb=<basic_block 0x7fffefca7208 (8)>) at /home/rguenther/src/trunk/gcc/gimple-ssa-evrp-analyze.c:223 #4 0x00000000027a4ad5 in evrp_range_analyzer::enter (this=0x7fffffffd100, bb=<basic_block 0x7fffefca7208 (8)>) at /home/rguenther/src/trunk/gcc/gimple-ssa-evrp-analyze.c:75 #5 0x00000000019643fb in dom_opt_dom_walker::before_dom_children (this=0x7fffffffd0d0, bb=<basic_block 0x7fffefca7208 (8)>) at /home/rguenther/src/trunk/gcc/tree-ssa-dom.c:1420 #6 0x0000000002736350 in dom_walker::walk (this=0x7fffffffd0d0, bb=<basic_block 0x7fffefca7208 (8)>) at /home/rguenther/src/trunk/gcc/domwalk.c:309 #7 0x0000000001962a54 in (anonymous namespace)::pass_dominator::execute (this=0x3f2d540, fun=0x7ffff112fb80) at /home/rguenther/src/trunk/gcc/tree-ssa-dom.c:724 so we have m_update_global_ranges set here. 218 push_value_range (vrs[i].first, vrs[i].second); 219 if (is_fallthru 220 && m_update_global_ranges 221 && all_uses_feed_or_dominated_by_stmt (vrs[i].first, stmt)) 222 { 223 set_ssa_range_info (vrs[i].first, vrs[i].second); 224 maybe_set_nonzero_bits (pred_e, vrs[i].first); but obviously this all_uses_feed_or_dominated_by_stmt doesn't tell us the whole story: (gdb) p debug_immediate_uses_for($12) pretmp_31 : --> single use. if (pretmp_31 != 6) in the IL we have not yet updated _164 = MEM[(const struct gimple *)prephitmp_179].code; # DEBUG g => NULL if (_164 == 6) goto <bb 34>; [26.31%] else goto <bb 27>; [73.69%] to reflect the CSE of this load to pretmp_31! So we have basically _1 = *p; if (...) { if (_1 != 6) gcc_unreachable (); // from the assert } _2 = *p; if (_2 != 6) ... and DOM happily records [6, 6] on _1 based on its single-use and after that DOM itself CSEs the load and optimizes the second test. I think all_uses_feed_or_dominated_by_stmt cannot work on its own. IIRC we have another duplicate of this somewhere. We have to make sure that the definition is post-dominated by the condition as well.