• Subject: LuaJIT - loop conditional code generation
• From: Jani Piitulainen <jani.piitulainen+ll@...>
• Date: Wed, 29 Feb 2012 19:45:30 +0200

Is there a way to stop simple conditionals in a loop from jumping out of a compiled trace?

"bit.band" with one argument is used here to tell LuaJIT result is a 32-bit integer, it's compiled to nothing. It can sometimes be useful reducing unnecessary double <-> int conversions (like cvtsi2sd & cvtsd2si).

for i=1, 1000000, 1 do
if band(i, 7)==0 then
c = band(c + 1)
end
if band(i, 7)==3 then
c = band(c - 1)
end
a = band(a + c)
end

Using LuaJIT git head x64. The generated code is very similar for x86.

ebx = i, ebp = a, eax = c

->LOOP:
394cffd0  mov r15d, ebx
394cffd3  and r15d, +0x07
394cffd7  jz 0x394c0028 ->6 -- this jumps out of the JITted trace, right? why not jnz to "cmp r15d, +0x03" here + add eax, 1?
394cffdd  cmp r15d, +0x03
394cffe1  jz 0x394c002c ->7
394cffec  cmp ebx, 0x000f4240
394cfff2  jle 0x394cffd0        ->LOOP

Full code:

local bit = require("bit");
local band=bit.band;

function test()
local a=band(0)
local c=band(1)

for i=1, 1000000, 1 do
if band(i, 7)==0 then
c = band(c + 1)
end
if band(i, 7)==3 then
c = band(c - 1)
end
-- changing conditions into following form produces effectively identical x64 code
-- c = band(c + (band(i, 7)==0 and 1 or 0))
-- c = band(c - (band(i, 7)==3 and 1 or 0))
a = band(a + c)
end
return a,c
end

for j=1, 10, 1 do
print(test())
end

Thanks,
Jani Piitulainen

• Follow-Ups: