https://gcc.gnu.org/bugzilla/show_bug.cgi?id=34072
Andrew Pinski <pinskia at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Severity|normal |enhancement Known to work| |11.0 Component|target |rtl-optimization --- Comment #4 from Andrew Pinski <pinskia at gcc dot gnu.org> --- GCC 11 RTL before combine: (insn 2 4 3 2 (set (reg/v:DI 84 [ x ]) (mem/c:DI (reg/f:SI 16 argp) [1 x+0 S8 A32])) "/app/example.cpp":3:45 74 {*movdi_internal} (nil)) (note 3 2 6 2 NOTE_INSN_FUNCTION_BEG) (insn 6 3 7 2 (parallel [ (set (reg:DI 86) (lshiftrt:DI (reg/v:DI 84 [ x ]) (const_int 8 [0x8]))) (clobber (reg:CC 17 flags)) ]) "/app/example.cpp":3:58 688 {*lshrdi3_doubleword} (expr_list:REG_DEAD (reg/v:DI 84 [ x ]) (expr_list:REG_UNUSED (reg:CC 17 flags) (nil)))) (insn 7 6 12 2 (set (reg:QI 85) (subreg:QI (reg:DI 86) 0)) "/app/example.cpp":3:63 77 {*movqi_internal} (expr_list:REG_DEAD (reg:DI 86) (nil))) (insn 12 7 13 2 (set (reg/i:QI 0 ax) (reg:QI 85)) "/app/example.cpp":3:66 77 {*movqi_internal} (expr_list:REG_DEAD (reg:QI 85) (nil))) GCC 10- before combine: ((insn 2 4 3 2 (set (reg/v:DI 84 [ x ]) (mem/c:DI (reg/f:SI 16 argp) [1 x+0 S8 A32])) "/app/example.cpp":3:45 66 {*movdi_internal} (nil)) (note 3 2 6 2 NOTE_INSN_FUNCTION_BEG) (insn 6 3 12 2 (parallel [ (set (reg:DI 86) (lshiftrt:DI (reg/v:DI 84 [ x ]) (const_int 8 [0x8]))) (clobber (reg:CC 17 flags)) ]) "/app/example.cpp":3:58 624 {*lshrdi3_doubleword} (expr_list:REG_DEAD (reg/v:DI 84 [ x ]) (expr_list:REG_UNUSED (reg:CC 17 flags) (nil)))) (insn 12 6 13 2 (set (reg/i:QI 0 ax) (subreg:QI (reg:DI 86) 0)) "/app/example.cpp":3:66 69 {*movqi_internal} (expr_list:REG_DEAD (reg:DI 86) (nil))) fwprop used to prop insn 7 into insn 12; I think this changed with r11-6188. With this change combine can do: Trying 6 -> 7: 6: {r86:DI=r84:DI 0>>0x8;clobber flags:CC;} REG_DEAD r84:DI REG_UNUSED flags:CC 7: r85:QI=r86:DI#0 REG_DEAD r86:DI Successfully matched this instruction: (set (subreg:SI (reg:QI 85) 0) (zero_extract:SI (subreg:SI (reg/v:DI 84 [ x ]) 0) (const_int 8 [0x8]) (const_int 8 [0x8]))) Trying 2 -> 7: 2: r84:DI=[argp:SI] 7: r85:QI#0=zero_extract(r84:DI#0,0x8,0x8) REG_DEAD r84:DI Successfully matched this instruction: (set (subreg:SI (reg:QI 85) 0) (zero_extend:SI (mem/c:QI (plus:SI (reg/f:SI 16 argp) (const_int 1 [0x1])) [1 x+1 S1 A8]))) Where before combine would produce: Trying 2 -> 6: 2: r84:DI=[argp:SI] 6: {r86:DI=r84:DI 0>>0x8;clobber flags:CC;} REG_DEAD r84:DI REG_UNUSED flags:CC Failed to match this instruction: (parallel [ (set (reg:DI 86) (lshiftrt:DI (mem/c:DI (reg/f:SI 16 argp) [1 x+0 S8 A32]) (const_int 8 [0x8]))) (clobber (reg:CC 17 flags)) ]) And we would never combine into 12 insn. As for the C++ example: combine does Trying 14 -> 6: 14: r85:SI=[argp:SI] 6: r84:QI#0=zero_extract(r85:SI,0x8,0x8) REG_DEAD r85:SI Successfully matched this instruction: (set (subreg:SI (reg:QI 84) 0) (zero_extend:SI (mem/c:QI (plus:SI (reg/f:SI 16 argp) (const_int 1 [0x1])) [1 x+1 S1 A8]))) But never tries to move the subreg from the lhs to rhs of the set .... So we still have an issue for the C++ example with memcpy.