[Patch] EAX -> EDX:EAX sign extension shortcuts, and MOVSX shortcuts for AX register
Original Reporter info from Mantis: CuriousKit @CuriousKit
-
Reporter name: J. Gareth Moreton
Original Reporter info from Mantis: CuriousKit @CuriousKit
- Reporter name: J. Gareth Moreton
Description:
Find attached a couple of patches that search for instruction combinations that sign-extend EAX to EDX:EAX and attempt to convert them into more optimal forms via the CWDE/cwtl, CDQ/cltd, CDQE/cltq and CQO/cqto opcodes.
mov-cdq.patch, all take place in OptPass2MOV:
- movl %eax,%edx; sarl $31,%edx -> cltd
- movq %rax,%rdx; sarq $63,%rdx -> cqto (x86_64 only)
- movl %edx,%eax; sarl $31,%edx -> movl %edx,%eax; cltd (-Os only due to cltd's dependency on %eax)
- movq %rdx,%rax; sarq $63,%rdx -> movq %rdx,%rax; cqto (x86_64 only; -Os only due to cqto's dependency on %rax)
---
A more complex one - either of the following combinations (these sequences sign-extend a 32-bit integer to a 64-bit integer, so are common around Int64-types under i386):
movl r/m,%edx; movl %edx,%eax; sarl $31,%edx
movl r/m,%eax; movl %eax,%edx; sarl $31,%edx
movl r/m,%edx; movl r/m,%eax; sarl $31,%edx
movl r/m,%eax; movl r/m,%edx; sarl $31,%edx
...become...
movl r/m,%eax <-- always %eax, even if it was %edx before
cltd
----
A very complex one, not performed on x86_64 (the first 4 instructions are the implemention of Abs() for LongInt on x86 platforms that don't have CMOV available... x86_64 always has CMOV available):
movl %eax,%edx
sarl $31,%eax
xorl %eax,%edx
subl %eax,%edx
(instruction that uses %edx)
(%eax and %edx deallocated)
...becomes...
cltd
xorl %edx,%eax <-- note the registers have swapped
subl %edx,%eax
(instruction that uses %eax) <-- %eax rather than %edx
----
movsx-cdq.patch, all take place in a new PostPeepholeOptMOVSX routine:
movswl %ax,%eax -> cwtl
movslq %eax,%rax -> cltq (x86_64 only)
Steps to reproduce:
Apply patches and confirm correct compilation as well as size saving with no penalty to speed (except when -Os is specified).
Additional information:
A 64-bit version of the "movl r/m" one is present in mov-cdq.patch, but commented out, because these combinations arise when sign-extending a LongInt to Int64, among other reasons. Equivalent instructions that sign-extend from %rax to %rdx:%rax are not performed because there is no Int128 type, but the code is left in the patch in a commented-out state should such need for it arise in the future.
Extensive testing has been performed for -Os under i386-win32, i386-linux, x86_64-win64 and x86_64-linux.