https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89794
Richard Earnshaw <rearnsha at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |segher at gcc dot gnu.org Summary|wrong code with -Og |combine incorrectly |-fno-forward-propagate |forwards register value | |through auto-inc operation --- Comment #5 from Richard Earnshaw <rearnsha at gcc dot gnu.org> --- This appears to be combine missing a PRE_MODIFY operation. After expand we have: (insn 10 7 11 2 (set (reg:DI 127) (zero_extend:DI (mem/c:HI (plus:SI (reg/f:SI 103 afp) (const_int 8 [0x8])) [1 i+0 S2 A32]))) "/tmp/test3.c":10:7 160 {zero_extendhidi2} (nil)) ... (insn 24 23 25 2 (set (reg:SI 133) (plus:SI (reg/f:SI 103 afp) (const_int 8 [0x8]))) "/tmp/test3.c":12:3 4 {*arm_addsi3} (nil)) ... (insn 33 32 34 2 (set (mem/c:HI (reg:SI 133) [0 MEM[(void *)&i]+0 S2 A16]) (reg:HI 141)) "/tmp/test3.c":12:3 189 {*movhi_insn_arch4} (nil)) The auto-inc-dec pass transforms this into: (insn 50 7 10 2 (set (reg/f:SI 133) (reg/f:SI 103 afp)) "/tmp/test3.c":10:7 -1 (nil)) (insn 10 50 12 2 (set (reg:DI 127 [ i ]) (zero_extend:DI (mem/c:HI (pre_modify:SI (reg/f:SI 133) (plus:SI (reg/f:SI 133) (const_int 8 [0x8]))) [1 i+0 S2 A32]))) "/tmp/test3.c":10:7 160 {zero_extendhidi2} (expr_list:REG_INC (reg/f:SI 133) (nil))) ... (insn 33 49 34 2 (set (mem/c:HI (reg/f:SI 133) [0 MEM[(void *)&i]+0 S2 A16]) (subreg:HI (reg:SI 140) 0)) "/tmp/test3.c":12:3 189 {*movhi_insn_arch4} (expr_list:REG_DEAD (reg:SI 140) (expr_list:REG_DEAD (reg/f:SI 133) (nil)))) And combine, missing the pre_modify, then substitutes insn 50 directly into insn 33 Trying 50 -> 33: 50: r133:SI=afp:SI 33: [r133:SI]=r140:SI#0 REG_DEAD r140:SI REG_DEAD r133:SI Successfully matched this instruction: (set (mem/c:HI (reg/f:SI 103 afp) [0 MEM[(void *)&i]+0 S2 A16]) (subreg:HI (reg:SI 140) 0)) Which is clearly wrong as it has now lost the pre-modify operation.