lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


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
394cffe7  add ebp, eax
394cffe9  add ebx, +0x01
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