https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107107
--- Comment #9 from Richard Biener <rguenth at gcc dot gnu.org> --- The issue is how we value-number for tail-merging. We do Processing block 1: BB4 Value numbering stmt = MEM[(long int *)_3] = 2; RHS 2 simplified to 2 No store match Value numbering store MEM[(long int *)_3] to 2 Setting value number of .MEM_12 to .MEM_12 (changed) marking outgoing edge 4 -> 5 executable Processing block 2: BB3 Value numbering stmt = *_3 = 2; RHS 2 simplified to 2 Setting value number of .MEM_11 to .MEM_12 (changed) marking outgoing edge 3 -> 5 executable Processing block 3: BB5 Value numbering stmt = .MEM_10 = PHI <.MEM_11(3), .MEM_12(4)> Setting value number of .MEM_10 to .MEM_12 (changed) Value numbering stmt = _9 = *p_5(D); Setting value number of _9 to 1 (changed) oops. So we figure that the two stores from '2' are "redundant" which causes us to only consider one (the wrong one) when later looking up *p_5(D). That's if (!resultsame) { /* Only perform the following when being called from PRE which embeds tail merging. */ if (default_vn_walk_kind == VN_WALK) { assign = build2 (MODIFY_EXPR, TREE_TYPE (lhs), lhs, op); vn_reference_lookup (assign, vuse, VN_NOWALK, &vnresult, false); if (vnresult) { VN_INFO (vdef)->visited = true; return set_ssa_val_to (vdef, vnresult->result_vdef); } that's a case I never understood fully (and that seems wrong). That visited flag set is also odd. I'm testing a patch.