From: Mike Pall <mike>
Reported by caohongqing.
(cherry picked from commit 5bf0da3d7c02f9959fa3a9fb721e0565137b70c8)
If there is high register pressure, and there are almost all registers
in use during the aforementioned assembling, the same register is chosen
as the one holding the given stack slot and the one holding the constant
value for the type comparison. As the result we get the following
assertion guard check in assembly:
| cmp x0, x0, lsr #32
| bne ->0
Which is always false.
This happens because the `tmp` register (used for loading constant type
to compare in assertion guard) is scratched from `gpr` register set, but
not from `allow` set, which is used during picking the register for slot
loading (at the begging `allow` and `gpr` sets are the same).
This patch changes `allow` set to `gpr` to fix the issue.
Sergey Kaplun:
* added the description and the test for the problem
Part of tarantool/tarantool#8069
---
Branch:
https://github.com/tarantool/luajit/tree/skaplun/or-94-fix-bool-ahuvloadPR:
https://github.com/tarantool/tarantool/pull/8214Issues:
*
https://github.com/tarantool/tarantool/issues/8069*
https://github.com/openresty/luajit2/pull/94 src/lj_asm_arm64.h | 2 +-
.../or-94-arm64-ir-ahuvload-bool.test.lua | 145 ++++++++++++++++++
2 files changed, 146 insertions(+), 1 deletion(-)
create mode 100644 test/tarantool-tests/or-94-arm64-ir-ahuvload-bool.test.lua
diff --git a/src/lj_asm_arm64.h b/src/lj_asm_arm64.h
index 4aeb51f3..30d34ca1 100644
--- a/src/lj_asm_arm64.h
+++ b/src/lj_asm_arm64.h
@@ -1055,7 +1055,7 @@ static void asm_ahuvload(ASMState *as, IRIns *ir)
emit_n(as, (A64I_CMNx^A64I_K12) | A64F_U12(1), tmp);
} else {
emit_nm(as, A64I_CMPx | A64F_SH(A64SH_LSR, 32),
- ra_allock(as, (irt_toitype(ir->t) << 15) | 0x7fff, allow), tmp);
+ ra_allock(as, (irt_toitype(ir->t) << 15) | 0x7fff, gpr), tmp);
}
if (ofs & FUSE_REG)
emit_dnm(as, (A64I_LDRx^A64I_LS_R)|A64I_LS_UXTWx|A64I_LS_SH, tmp, idx, (ofs & 31));
diff --git a/test/tarantool-tests/or-94-arm64-ir-ahuvload-bool.test.lua b/test/tarantool-tests/or-94-arm64-ir-ahuvload-bool.test.lua
new file mode 100644
index 00000000..a9b0071c
--- /dev/null
+++ b/test/tarantool-tests/or-94-arm64-ir-ahuvload-bool.test.lua
@@ -0,0 +1,145 @@
+local tap = require('tap')
+-- Test file to demonstrate the incorrect JIT assembling
+-- for IR_{AHUV}LOAD specialized to boolean.
+-- See also:
https://github.com/openresty/luajit2/pull/94.
+
+-- If there is high register pressure, and there are almost
+-- all registers in use during the aforementioned assembling,
+-- the same register is chosen as the one holding the given
+-- stack slot and the one holding the constant value for the type
+-- comparison. As the result we get the following assertion
+-- guard check in assembly:
+-- | cmp x0, x0, lsr #32
+-- | bne ->0
+-- Which is always false.
+local ffi = require('ffi')
+-- Need for code generation.
+_G.ffi = ffi
+
+local traceinfo = require('jit.util').traceinfo
+
+-- Each payload will be recording with the corresponding IR.
+local TESTS = {
+ {irname = 'ALOAD', payload = 'aload()'},
+ {irname = 'HLOAD', payload = 'hload()'},
+ {irname = 'ULOAD', payload = 'uload()'},
+ {irname = 'VLOAD', payload = '...'},
+}
+local N_TESTS = #TESTS
+
+local test = tap.test('or-94-arm64-ir-ahuvload-bool')
+test:plan(N_TESTS)
+
+-- Functions to be inlined on trace to generate different
+-- types of IRs (ALOAD, HLOAD, ULOAD).
+-- Declare as global for code generation.
+local arr = {true}
+local function aload()
+ return arr[1]
+end
+_G.aload = aload
+
+local h = {data = true}
+local function hload()
+ local boolvalue = h.data
+ return boolvalue
+end
+_G.hload = hload
+
+do
+ local upvalue = true
+ local function uload()
+ return upvalue
+ end
+ -- Make upvalue muttable. Not really need to return this