[Tarantool-patches] [PATCH luajit] ARM64: Fix IR_SLOAD assembly.
Sergey Bronnikov
sergeyb at tarantool.org
Fri May 16 20:07:45 MSK 2025
Hello, Sergey,
thanks for the patch! Please see my comments.
Sergey
On 5/14/25 14:56, Sergey Kaplun wrote:
> From: Mike Pall <mike>
>
> Reported by Gate88.
>
> (cherry picked from commit 6c4826f12c4d33b8b978004bc681eb1eef2be977)
>
> The issue is in the case when IR SLOAD is unused on a trace, persists
typo: s/, /, it/
> only for typecheck, and has the `num` type. In this case, the `dest`
> register is `RID_NONE`. Hence, the `fmov` instruction is emitted
there are two instructions `fmov` in the generated assembler output,
which one do you mean?
55690afedc fmov d0, x30
55690afee0 ldr w28, [x19, #8]
55690afee4 ldur x3, [x19, #-16]
55690afee8 and x3, x3, #0x7fffffffffff
55690afeec ldr x27, [x3, #48]
55690afef0 ldr x8, [x27, #32]
55690afef4 sub x9, x8, x19
55690afef8 cmp x9, #56
55690afefc bls 0x690affe8 ->0
55690aff00 ldr x6, [x8]
55690aff04 asr x27, x6, #47
55690aff08 cmn x27, #12
55690aff0c bne 0x690affe8 ->0
55690aff10 and x6, x6, #0x7fffffffffff
55690aff14 ldr w7, [x6, #52]
55690aff18 cmp w7, #1
55690aff1c bne 0x690affe8 ->0
55690aff20 ldr x5, [x6, #40]
55690aff24 ldr x27, [x5, #32]
55690aff28 cmp x27, x1
55690aff2c bne 0x690affe8 ->0
55690aff30 ldr x27, [x5, #24]
55690aff34 cmp x0, x27, lsr #32
55690aff38 bls 0x690affe8 ->0
55690aff3c fmov d2, x27
or (probably) you just refer to a C code of `asm_sload`, that emits `fmov`:
1180 if (ra_hasreg(dest) && irt_isnum(t) && !(ir->op2 &
IRSLOAD_CONVERT))
1181 emit_dn(as, A64I_FMOV_D_R, (dest & 31), tmp);
Sorry, it is not easy for me to match IR and ASM, so I believe more
details is required in the description.
I just want to understand a difference for emitted assembler before and
after the patch.
> unconditionally, where the destination register is `d0` (`RID_NONE &
> 31`). So, the value of this register is spoiled. If it holds any value
> evaluated before and used after this SLOAD, it leads to incorrect
> behaviour.
>
> This patch adds the check that the register is in use before emitting
> the instruction.
>
> Sergey Kaplun:
> * added the description and the test for the problem
>
> Part of tarantool/tarantool#11278
> ---
>
> Branch:https://github.com/tarantool/luajit/tree/skaplun/lj-903-arm64-unused-number-sload-typecheck
> Related issues:
> *https://github.com/LuaJIT/LuaJIT/issues/903
> *https://github.com/tarantool/tarantool/issues/11278
>
> src/lj_asm_arm64.h | 2 +-
> ...m64-unused-number-sload-typecheck.test.lua | 45 +++++++++++++++++++
> 2 files changed, 46 insertions(+), 1 deletion(-)
> create mode 100644 test/tarantool-tests/lj-903-arm64-unused-number-sload-typecheck.test.lua
>
> diff --git a/src/lj_asm_arm64.h b/src/lj_asm_arm64.h
> index 554bb60a..9b27473c 100644
> --- a/src/lj_asm_arm64.h
> +++ b/src/lj_asm_arm64.h
> @@ -1177,7 +1177,7 @@ dotypecheck:
> tmp = ra_scratch(as, allow);
> rset_clear(allow, tmp);
> }
> - if (irt_isnum(t) && !(ir->op2 & IRSLOAD_CONVERT))
> + if (ra_hasreg(dest) && irt_isnum(t) && !(ir->op2 & IRSLOAD_CONVERT))
> emit_dn(as, A64I_FMOV_D_R, (dest & 31), tmp);
> /* Need type check, even if the load result is unused. */
> asm_guardcc(as, irt_isnum(t) ? CC_LS : CC_NE);
> diff --git a/test/tarantool-tests/lj-903-arm64-unused-number-sload-typecheck.test.lua b/test/tarantool-tests/lj-903-arm64-unused-number-sload-typecheck.test.lua
> new file mode 100644
> index 00000000..748b88e2
> --- /dev/null
> +++ b/test/tarantool-tests/lj-903-arm64-unused-number-sload-typecheck.test.lua
> @@ -0,0 +1,45 @@
> +local tap = require('tap')
> +-- Test file to demonstrate the incorrect JIT assembling of unused
> +-- `IR_SLOAD` with number type on arm64.
> +-- See alsohttps://github.com/LuaJIT/LuaJIT/issue/903.
typo: s/issue/issues/
> +local test = tap.test('lj-903-arm64-unused-number-sload-typecheck'):skipcond({
> + ['Test requires JIT enabled'] = not jit.status(),
> +})
> +
> +test:plan(1)
> +
> +-- Just use any different numbers (but not integers to avoid
> +-- integer IR type).
> +local SLOT = 0.1
> +local MARKER_VALUE = 4.2
> +-- XXX: Special mapping to avoid folding and removing always true
> +-- comparison.
> +local anchor = {marker = MARKER_VALUE}
> +
> +-- Special function to inline on trace to generate SLOAD
> +-- typecheck.
> +local function sload_unused(x)
> + return x
> +end
> +
> +-- The additional wrapper to use stackslots in the function.
> +local function test_sload()
> + local sload = SLOT
> + for _ = 1, 4 do
> + -- This line should use the `d0` register.
> + local marker = anchor.marker - MARKER_VALUE
> + -- This generates unused IR_SLOAD with typecheck (number).
> + -- Before the patch, it occasionally overwrites the `d0`
> + -- register and causes the execution of the branch.
> + sload_unused(sload)
> + if marker ~= 0 then
> + return false
> + end
> + end
> + return true
> +end
> +
> +jit.opt.start('hotloop=1')
> +test:ok(test_sload(), 'correct SLOAD assembling')
> +
> +test:done(true)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.tarantool.org/pipermail/tarantool-patches/attachments/20250516/05c4e21f/attachment.htm>
More information about the Tarantool-patches
mailing list