code generation for calls in JITted code after r88984

Hi,

After this commit:
http://llvm.org/viewvc/llvm-project?view=rev&revision=88984

the X86 JIT no longer emits calls using call , but always uses mov REG, , call *REG. This causes problems for the usage of LLVM in JITs since the JIT can no longer patch the callsite after the callee have been compiled. According to the comments for the commit, this was done to fix the large code model on amd64, but this affects JITs which can guarantee that both the caller and callee have 32 bit addresses, since the code model is set uncoditionally to Large, even if another code model was passed to createJIT ():

http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86TargetMachine.cpp?r1=86251&r2=88984&pathrev=88984

Would it be possible to fix this or make it configurable ?

thanks

Zoltan

Jeffrey can speak more to this, but this was done specifically to fix
the JIT on x86_64, because we have no way of ensuring that we can
allocate all the memory for code within one 32-bit swath of the
virtual address space. How are you making this guarantee in your JIT?

How does this break patching the stub? Is <ADDR> the stub address or
the code address? If it's the stub address, you should be able to
patch the stub.

I agree we shouldn't use the far call sequence on vanilla x86, since
all possible addresses can be represented as immediates.

Reid

Hi,

After this commit:
http://llvm.org/viewvc/llvm-project?view=rev&revision=88984

the X86 JIT no longer emits calls using call <ADDR>, but always uses mov
REG, <ADDR>, call *REG.

That should only be the x86-64 JIT. If the x86-32 JIT does that, it's
definitely a bug. For x86-64, it's required unless the
JITMemoryManager can guarantee that it only allocates code within 2GB
of the text segment.

This causes problems for the usage of LLVM in JITs
since the JIT can no longer patch the callsite after the callee have been
compiled.

As far as I know, the JIT only tries to patch the callsite when it's
compiling lazily. In that case, it uses X86JITInfo::emitFunctionStub()
to emit a stub with known layout that it can patch. It doesn't try to
patch the call to the stub.

If you've found a broken case here, could you send a (small!) test
program with its compilation line, or a patch to
http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ExecutionEngine/JIT/JITTest.cpp
that exposes it? English descriptions of these problems tend to be too
vague to reproduce.

According to the comments for the commit, this was done to fix the
large code model on amd64, but this affects JITs which can guarantee that
both the caller and callee have 32 bit addresses, since the code model is
set uncoditionally to Large, even if another code model was passed to
createJIT ():

JIT::createJIT() intends to obey the CodeModel you pass it, but
someone else was complaining of a bug there too. The CodeModel is
definitely intended to be configurable, specifically so that users can
specify the guarantees their JITMemoryManager provides. Still, it's
supposed to be an optimization. The large code model should always
produce correct code.

Hi,

Hi,

After this commit:
http://llvm.org/viewvc/llvm-project?view=rev&revision=88984

the X86 JIT no longer emits calls using call , but always uses mov
REG, , call *REG.

That should only be the x86-64 JIT. If the x86-32 JIT does that, it’s
definitely a bug. For x86-64, it’s required unless the
JITMemoryManager can guarantee that it only allocates code within 2GB
of the text segment.

Our memory manager allocates memory using the MAP_32BIT flag to mmap, so it
can guarantee that it is a 32 bit address.

This causes problems for the usage of LLVM in JITs
since the JIT can no longer patch the callsite after the callee have been
compiled.

As far as I know, the JIT only tries to patch the callsite when it’s
compiling lazily. In that case, it uses X86JITInfo::emitFunctionStub()
to emit a stub with known layout that it can patch. It doesn’t try to
patch the call to the stub.

If you’ve found a broken case here, could you send a (small!) test
program with its compilation line, or a patch to
http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ExecutionEngine/JIT/JITTest.cpp
that exposes it? English descriptions of these problems tend to be too
vague to reproduce.

We are using our pre-existing JIT code (mono), and only parts of the LLVM JIT infrastructure,
we would prefer patching the calling code instead of patching the stub, to avoid the overhead of going through the stub at every call, also our JIT expects to be able to patch the call sites.

someone else was complaining of a bug there too. The CodeModel is
definitely intended to be configurable, specifically so that users can
specify the guarantees their JITMemoryManager provides. Still, it’s
supposed to be an optimization. The large code model should always
produce correct code.

It does produce current code, its just that our code depends on LLVM generating normal direct calls and we would like a way to force it to do that. Passing CodeModel::Default to createJIT () used to do that, but it doesn’t any more, since it is overwritten with Large.

Zoltan

It does produce current code, its just that our code depends on LLVM generating normal direct calls and we would like a way to force it to do that. Passing CodeModel::Default to createJIT () used to do that, but it doesn't any more, since it is overwritten with Large.

Working on it.

-eric