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: [email protected]
ReportedBy: [email protected]
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.