[x86] CheckJumpMovTransferOpt (part of OptPass2JMP) now also copies over register deallocations for better optimisation
Summary
This merge request improves upon the CheckJumpMovTransferOpt optimisation by also copying over register deallocations (and reallocating them after the jump for reasons of consistency) that appear after the distant label. This permits more accurate register tracking and the potential removal of more redundant instructions.
This requires a new support function named GetNextInstructionOrRegAlloc
that stops on register allocation on top of anything else that doesn't fall into the SkipInstr
collection.
System
- Processor architecture: i386, x86_64
What is the current bug behavior?
Whenever a jump redirect duplicates assignments (indicated by the debug message "Peephole Optimization: Duplicated 1 assignment(s) and redirected jump" or similar), the end result may include assignments to registers that are no longer in use if you follow the program flow (this is usually caused by other MOV optimisations).
What is the behavior after applying this patch?
More redundant writes are successfully optimised out.
Relevant logs and/or screenshots
In cgbase
(x86-64-win64, -O4), before:
...
.Lj111:
cmpq $16,%rcx
jne .Lj117
movb $5,%dl
# Peephole Optimization: Duplicated 1 assignment(s) and redirected jump
# Peephole Optimization: %dl = $5; changed to minimise pipeline stall (MovMov2Mov 6b)
movb $5,%al
ret
.p2align 4,,10
.p2align 3
.Lj117:
cmpq $8,%rcx
jng .Lj120
xorb %dl,%dl
# Peephole Optimization: Duplicated 1 assignment(s) and redirected jump
# Peephole Optimization: %dl = $0; changed to minimise pipeline stall (MovMov2Mov 6b)
xorb %al,%al
ret
...
After:
...
.Lj111:
cmpq $16,%rcx
jne .Lj117
# Peephole Optimization: MovMov2Mov 5 done
movb $5,%al
# Peephole Optimization: Duplicated 1 assignment(s) and redirected jump
ret
.p2align 4,,10
.p2align 3
.Lj117:
cmpq $8,%rcx
jng .Lj120
# Peephole Optimization: MovMov2Mov 5 done
xorb %al,%al
# Peephole Optimization: Duplicated 1 assignment(s) and redirected jump
ret
...
Additional notes:
Sometimes, a mov %reg,%reg
can appear, such as this example in the System unit - before:
.section .text.n_system_$$_align$qword$qword$$qword,"ax"
...
andn %r9,%rax,%rax
movq %rax,%rcx
# Peephole Optimization: Duplicated 1 assignment(s) and redirected jump
# Peephole Optimization: %rcx = %rax; changed to minimise pipeline stall (MovXXX2MovXXX)
# Peephole Optimization: Mov2Nop 4 done
ret
After:
.section .text.n_system_$$_align$qword$qword$$qword,"ax"
...
andn %r9,%rax,%rax
# Peephole Optimization: Mov2Nop 3 done
# Peephole Optimization: Duplicated 1 assignment(s) and redirected jump
# Peephole Optimization: %rcx = %rax; changed to minimise pipeline stall (MovXXX2MovXXX)
movq %rax,%rax
ret
In this situation, it's because %rcx was originally copied into %rax, which is the function result. !310 (merged) helps to correct this issue by permitting the FuncMov2Func
optimisation to run in Pass 2, which includes an addition to remove mov %reg,%reg
which is otherwise only performed in Pass 1.