forked from LuaJIT/LuaJIT
-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Limit CSE for IR_CARG to fix loop optimizations.
Thanks to Peter Cawley. (cherry picked from commit 3bdc649) `IR_CALLXS` for the vararg function contains `IR_CARG(fptr, ctid)` as the second operand. The `loop_emit_phi()` scans only the first operand of the IR, so the second is not marked as PHI. In this case, when the IR appears in both the invariant and variant parts of the loop, CSE may remove it and thus lead to incorrect emitting results. This patch tweaks the CSE rules to avoid CSE across the `IR_LOOP`. Sergey Kaplun: * added the description and the test for the problem Part of tarantool/tarantool#10199 Reviewed-by: Sergey Bronnikov <[email protected]> Reviewed-by: Maxim Kokryashkin <[email protected]> Signed-off-by: Sergey Kaplun <[email protected]>
- Loading branch information
Showing
2 changed files
with
67 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
local ffi = require('ffi') | ||
local table_new = require('table.new') | ||
|
||
-- Test file to demonstrate LuaJIT incorrect behaviour for | ||
-- recording the FFI call to the vararg function. See also: | ||
-- https://github.com/LuaJIT/LuaJIT/issues/1244. | ||
local tap = require('tap') | ||
local test = tap.test('lj-1244-missing-phi-carg'):skipcond({ | ||
['Test requires JIT enabled'] = not jit.status(), | ||
}) | ||
|
||
-- Loop unrolls into 2 iterations. Thus means that the loop is | ||
-- executed on trace on the 5th iteration (instead of the usual | ||
-- 4th). Run it even number of iterations to test both, so last is | ||
-- 6th. | ||
local NTESTS = 6 | ||
|
||
test:plan(NTESTS) | ||
|
||
-- XXX: Hack with function's prototypes to avoid creation of | ||
-- custom functions to be loaded via FFI (vararg part will be just | ||
-- ignored). | ||
ffi.cdef[[ | ||
double sin(double, ...); | ||
double cos(double, ...); | ||
]] | ||
|
||
local EXPECTED = {[0] = ffi.C.sin(0), ffi.C.cos(0)} | ||
|
||
-- Array of 2 functions. | ||
local fns = ffi.new('double (*[2])(double, ...)') | ||
fns[0] = ffi.C.cos | ||
fns[1] = ffi.C.sin | ||
|
||
-- Avoid reallocating the table on the trace. | ||
local result = table_new(8, 0) | ||
|
||
jit.opt.start('hotloop=1') | ||
|
||
local fn = fns[0] | ||
-- The first result is `cos()`. | ||
for i = 1, NTESTS do | ||
result[i] = fn(0) | ||
fn = fns[i % 2] | ||
-- The call persists in the invariant part of the loop as well. | ||
-- Hence, XLOAD (part of the IR_CARG -- function to be called) | ||
-- should be marked as PHI, but it isn't due to CSE. | ||
fn(0) | ||
end | ||
|
||
for i = 1, NTESTS do | ||
test:is(result[i], EXPECTED[i % 2], | ||
('correct result on iteration %d'):format(i)) | ||
end | ||
|
||
test:done(true) |