http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57088
Bug #: 57088 Summary: Post-reload instruction splitting clobbers live register Classification: Unclassified Product: gcc Version: 4.9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: target AssignedTo: unassig...@gcc.gnu.org ReportedBy: era...@google.com Created attachment 29952 --> http://gcc.gnu.org/bugzilla/attachment.cgi?id=29952 Test case $ ./trunk_gcc --version trunk_gcc (GCC) 4.9.0 20130423 (experimental) $ ./trunk_gcc -fno-exceptions -m32 -O2 -fpermissive -fPIC -S reduced.ii In the source, the LargeObjectCacheInterface::Update method has the following statement: IOBuffer *save_buf = new VIOBuffer(buffer->Length()); This gets translated to the following assembly fragment: (...) call _Znwj@PLT movl -44(%ebp), %ecx movl -48(%ebp), %edx movl $0, 12(%esp) movl $16, 8(%esp) movl %ecx, (%esp) movl %edx, 4(%esp) movl %ecx, -52(%ebp) call _ZN8IOBufferC2Eiii@PLT (...) Note that the output of operator new is not passed to IOBuffer constructor. Here is the RTL from reduced.ii.210r.postreload: (call_insn 21 20 22 2 (set (reg:SI 0 ax) (call (mem:QI (symbol_ref:SI ("_Znwj") [flags 0x41] <function_decl 0x7f42c2d77100 operator new>) [0 operator new S1 A8]) (const_int 4 [0x4]))) reduced.ii:50 652 {*call_value} (nil) (expr_list:REG_DEP_TRUE (use (reg:SI 3 bx)) (expr_list:REG_BR_PRED (use (mem:SI (reg/f:SI 7 sp) [0 S4 A32])) (nil)))) (insn 22 21 23 2 (set (reg/v/f:SI 2 cx [orig:59 save_buf ] [59]) (reg:SI 0 ax)) reduced.ii:50 85 {*movsi_internal} (expr_list:REG_DEAD (reg:SI 0 ax) (nil))) (insn 23 22 24 2 (set (mem:SI (plus:SI (reg/f:SI 7 sp) (const_int 12 [0xc])) [0 S4 A32]) (const_int 0 [0])) reduced.ii:41 85 {*movsi_internal} (nil)) (insn 24 23 59 2 (set (mem:SI (plus:SI (reg/f:SI 7 sp) (const_int 8 [0x8])) [0 S4 A32]) (const_int 16 [0x10])) reduced.ii:41 85 {*movsi_internal} (nil)) (insn 59 24 25 2 (set (reg:DI 1 dx [orig:78 n ] [78]) (mem/c:DI (plus:SI (reg/f:SI 6 bp) (const_int -48 [0xffffffffffffffd0])) [9 %sfp+-48 S8 A64])) reduced.ii:41 84 {*movdi_internal} (expr_list:REG_DEAD (reg:DI 92) (nil))) (insn 25 59 26 2 (set (mem:SI (plus:SI (reg/f:SI 7 sp) (const_int 4 [0x4])) [0 S4 A32]) (reg:SI 1 dx [orig:78 n ] [78])) reduced.ii:41 85 {*movsi_internal} (expr_list:REG_DEAD (reg:DI 1 dx [orig:78 n ] [78]) (nil))) (insn 26 25 56 2 (set (mem:SI (reg/f:SI 7 sp) [0 S4 A32]) (reg/v/f:SI 2 cx [orig:59 save_buf ] [59])) reduced.ii:41 85 {*movsi_internal} (nil)) (insn 56 26 27 2 (set (mem/c:SI (plus:SI (reg/f:SI 6 bp) (const_int -52 [0xffffffffffffffcc])) [9 %sfp+-52 S4 A32]) (reg/v/f:SI 2 cx [orig:59 save_buf ] [59])) reduced.ii:41 85 {*movsi_internal} (expr_list:REG_DEAD (reg/v/f:SI 2 cx [orig:59 save_buf ] [59]) (nil))) (call_insn 27 56 28 2 (call (mem:QI (symbol_ref:SI ("_ZN8IOBufferC2Eiii") [flags 0x41] <function_decl 0x7f42c2d82d00 __base_ctor >) [0 __base_ctor S1 A8]) The dump from the next pass (split2) shows that insn 59 above is split into: (insn 69 24 70 2 (set (reg:SI 1 dx [orig:78 n ] [78]) (mem/c:SI (plus:SI (reg/f:SI 6 bp) (const_int -48 [0xffffffffffffffd0])) [9 %sfp+-48 S4 A64])) reduced.ii:41 85 {*movsi_internal} (nil)) (insn 70 69 25 2 (set (reg:SI 2 cx [ n+4 ]) (mem/c:SI (plus:SI (reg/f:SI 6 bp) (const_int -44 [0xffffffffffffffd4])) [9 %sfp+-44 S4 A32])) reduced.ii:41 85 {*movsi_internal} (nil)) But here, cx is actually live and the split_after_reload pass clobbers it.