Avoid redundant MOVes in generated code
I stumbled upon this generated code:
Everything is fine, a heap check like many others.
c2ro:
Hp = Hp + 16;
if (Hp > I64[BaseReg + 856]) goto c2rt; else goto c2rs;
c2rt:
I64[BaseReg + 904] = 16;
I64[Sp - 48] = block_c2rp_info;
I64[Sp - 40] = _s2pI::I64;
I64[Sp - 32] = _s2pJ::I64;
I64[Sp - 24] = _s2pK::I64;
I64[Sp - 16] = _s2pN::I64;
I64[Sp - 8] = _s2pO::I64;
Sp = Sp - 48;
call stg_gc_noregs() returns to c2rp, args: 8, res: 8, upd: 8;
c2rp:
_s2pI::I64 = I64[Sp + 8];
_s2pJ::I64 = I64[Sp + 16];
_s2pK::I64 = I64[Sp + 24];
_s2pN::I64 = I64[Sp + 32];
_s2pO::I64 = I64[Sp + 40];
Sp = Sp + 48;
goto c2ro;
c2rs:
Compiled to assembler:
_c2ro:
addq $16,%r12 ; Heap check as usual
cmpq 856(%r13),%r12
ja _c2rt
_c2rs:
...
_c2rt:
movq $16,904(%r13)
movq $block_c2rp_info,-48(%rbp)
movq %r14,-40(%rbp) ; copy out sequence: move live variables
movq %rsi,-32(%rbp) ; to stack
movq %rax,-24(%rbp)
movq %rbx,-16(%rbp)
movq %rdi,-8(%rbp)
addq $-48,%rbp
jmp stg_gc_noregs
...
.align 8
.quad 1989
.quad 32
block_c2rp_info:
_c2rp:
movq 8(%rbp),%rax ; we returned from gc land, now copy live variables back in
movq 16(%rbp),%rbx
movq 24(%rbp),%rcx
movq 32(%rbp),%rdx
movq 40(%rbp),%rsi
addq $48,%rbp
_n2st: ; Oh dear! We are moving our freshly moved register again for no obvious reason!
movq %rsi,%rdi
movq %rbx,%rsi
movq %rdx,%rbx
movq %rax,%r14
movq %rcx,%rax
jmp _c2ro
What is happening here that GHC isn't able to directly assign the correct registers? Also the label _n2st
suggest it is inserted at a later stage than the generated cmm code (Every other label is named contigously).
Trac metadata
Trac field | Value |
---|---|
Version | 8.0.2 |
Type | Bug |
TypeOfFailure | OtherFailure |
Priority | normal |
Resolution | Unresolved |
Component | Compiler |
Test case | |
Differential revisions | |
BlockedBy | |
Related | |
Blocking | |
CC | |
Operating system | |
Architecture |