https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93946
--- Comment #4 from Richard Biener <rguenth at gcc dot gnu.org> --- OK, so the fix works but on x86_64 with -m32 RTL opts (sched2) end up wrecking things... foo: .LFB0: .cfi_startproc movl 4(%esp), %eax movl 8(%esp), %edx movl $1, (%eax) movl (%eax), %eax movl $0, (%edx) movl $0, 4(%edx) ret (insn:TI 7 18 10 2 (set (mem/j:SI (reg/v/f:SI 0 ax [orig:83 bv ] [83]) [1 bv_3(D)->b.u.f+0 S4 A32]) (const_int 1 [0x1])) "/space/rguenther/src/gcc/gcc/testsuite/gcc.dg/torture/pr93946-1.c":14:13 67 {*movsi_internal} (nil)) (insn 18 7 20 2 (set (reg/v/f:SI 1 dx [orig:84 ptr ] [84]) (mem/f/c:SI (plus:SI (reg/f:SI 7 sp) (const_int 8 [0x8])) [9 ptr+0 S4 A32])) "/space/rguenther/src/gcc/gcc/testsuite/gcc.dg/torture/pr93946-1.c":15:12 67 {*movsi_internal} (expr_list:REG_EQUIV (mem/f/c:SI (plus:SI (reg/f:SI 16 argp) (const_int 4 [0x4])) [9 ptr+0 S4 A32]) (nil))) (insn:TI 20 10 21 2 (set (mem/j:SI (reg/v/f:SI 1 dx [orig:84 ptr ] [84]) [1 MEM[(struct aa *)ptr_1(D)].a.u.i+0 S4 A32]) (const_int 0 [0])) "/space/rguenther/src/gcc/gcc/testsuite/gcc.dg/torture/pr93946-1.c":15:12 67 {*movsi_internal} (nil)) (insn:TI 21 20 16 2 (set (mem/j:SI (plus:SI (reg/v/f:SI 1 dx [orig:84 ptr ] [84]) (const_int 4 [0x4])) [1 MEM[(struct aa *)ptr_1(D)].a.u.i+4 S4 A32]) (const_int 0 [0])) "/space/rguenther/src/gcc/gcc/testsuite/gcc.dg/torture/pr93946-1.c":15:12 67 {*movsi_internal} (expr_list:REG_DEAD (reg/v/f:SI 1 dx [orig:84 ptr ] [84]) (nil))) (insn 10 7 20 2 (set (reg:SI 0 ax [orig:86 bv_3(D)->b.u.f ] [86]) (mem/j:SI (reg/v/f:SI 0 ax [orig:83 bv ] [83]) [1 bv_3(D)->b.u.f+0 S4 A32])) "/space/rguenther/src/gcc/gcc/testsuite/gcc.dg/torture/pr93946-1.c":17:17 67 {*movsi_internal} (nil)) Ah, something dropped the store to b.u.f and split the store to i. DSE. Obviously. pr93946-1.c.263r.dse1: processing cselib load against insn 9 pr93946-1.c.263r.dse1:Locally deleting insn 9 because insn 8 stores the same value and couldn't be eliminated pr93946-1.c.263r.dse1:Locally deleting insn 9 indeed I remember touching DSE back in time. It still only does /* We can only remove the later store if the earlier aliases at least all accesses the later one. */ && (MEM_ALIAS_SET (mem) == MEM_ALIAS_SET (s_info->mem) || alias_set_subset_of (MEM_ALIAS_SET (mem), MEM_ALIAS_SET (s_info->mem)))) not considering the base set of the other store. Now, we could allow the DSE by clearing MEM_EXPR here or adjusting MEM_ALIAS_SET. But not sure if we want that?