diff options
author | Alan Wu <XrXr@users.noreply.github.com> | 2021-11-05 15:44:29 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-11-05 15:44:29 -0400 |
commit | 91a9062626733c7d11ea4795bd1957a21f2adec6 (patch) | |
tree | e844b4b0c7c8c52e26701539b0fba103a58425f6 /misc | |
parent | 82ae9b092cf51062c49b95e81ad184e1dea0df1e (diff) | |
download | ruby-91a9062626733c7d11ea4795bd1957a21f2adec6.tar.gz |
YJIT: use shorter encoding for mov(r64,imm) when unambiguous (#5081)
* YJIT: use shorter encoding for mov(r64,imm) when unambiguous
Previously, for small constants such as `mov(RAX, imm_opnd(Qundef))`,
we emit an instruction with an 8-byte immediate. This form commonly
gets the `movabs` mnemonic.
In 64-bit mode, 32-bit operands get zero extended to 64-bit to fill the
register, so when the immediate is small enough, we can save 4 bytes by
using the `mov` variant that takes a 32-bit immediate and does a zero
extension.
Not implement with this change, there is an imm32 variant of `mov` that
does sign extension we could use. When the constant is negative, we
fallback to the `movabs` form.
In railsbench, this change yields roughly a 12% code size reduction for
the outlined block.
Co-authored-by: Jemma Issroff <jemmaissroff@gmail.com>
* [ci skip] comment edit. Please squash.
Co-authored-by: Jemma Issroff <jemmaissroff@gmail.com>
Diffstat (limited to 'misc')
-rw-r--r-- | misc/yjit_asm_tests.c | 12 |
1 files changed, 11 insertions, 1 deletions
diff --git a/misc/yjit_asm_tests.c b/misc/yjit_asm_tests.c index 5708d3abad..5548af07f5 100644 --- a/misc/yjit_asm_tests.c +++ b/misc/yjit_asm_tests.c @@ -182,10 +182,20 @@ void run_assembler_tests(void) // mov cb_set_pos(cb, 0); mov(cb, EAX, imm_opnd(7)); check_bytes(cb, "B807000000"); cb_set_pos(cb, 0); mov(cb, EAX, imm_opnd(-3)); check_bytes(cb, "B8FDFFFFFF"); - cb_set_pos(cb, 0); mov(cb, R15, imm_opnd(3)); check_bytes(cb, "49BF0300000000000000"); + cb_set_pos(cb, 0); mov(cb, R15, imm_opnd(3)); check_bytes(cb, "41BF03000000"); cb_set_pos(cb, 0); mov(cb, EAX, EBX); check_bytes(cb, "89D8"); cb_set_pos(cb, 0); mov(cb, EAX, ECX); check_bytes(cb, "89C8"); cb_set_pos(cb, 0); mov(cb, EDX, mem_opnd(32, RBX, 128)); check_bytes(cb, "8B9380000000"); + + // Test `mov rax, 3` => `mov eax, 3` optimization + cb_set_pos(cb, 0); mov(cb, R8, imm_opnd(0x34)); check_bytes(cb, "41B834000000"); + cb_set_pos(cb, 0); mov(cb, R8, imm_opnd(0x80000000)); check_bytes(cb, "49B80000008000000000"); + cb_set_pos(cb, 0); mov(cb, R8, imm_opnd(-1)); check_bytes(cb, "49B8FFFFFFFFFFFFFFFF"); + + cb_set_pos(cb, 0); mov(cb, RAX, imm_opnd(0x34)); check_bytes(cb, "B834000000"); + cb_set_pos(cb, 0); mov(cb, RAX, imm_opnd(0x80000000)); check_bytes(cb, "48B80000008000000000"); + cb_set_pos(cb, 0); mov(cb, RAX, imm_opnd(-52)); check_bytes(cb, "48B8CCFFFFFFFFFFFFFF"); + cb_set_pos(cb, 0); mov(cb, RAX, imm_opnd(-1)); check_bytes(cb, "48B8FFFFFFFFFFFFFFFF"); /* test( delegate void (CodeBlock cb) { cb.mov(X86Opnd(AL), X86Opnd(8, RCX, 0, 1, RDX)); }, |