[LLVMdev] VEX prefixes for JIT in llvm 3.5

Matt Godbolt matt at godbolt.org
Fri Sep 19 06:05:31 PDT 2014


Thanks again Lang, that all makes sense. In my case the debugabbility
is not the primary desire (although it's definitely a nice bonus!).
I'm mainly after logging to disc what got compiled and executed for
auditing purposes.

Much appreciated,

Matt :)

On Thu, Sep 18, 2014 at 4:15 PM, Lang Hames <lhames at gmail.com> wrote:
> Hi Matt,
>
> CCing the Dev list, as I accidentally dropped them off my last reply.
>
> Regarding loadObject, that API is very much hypothetical at the moment
> (there is a RuntimeDyld::loadObject, but it returns something else). Some
> background may make it clearer where I'm thinking of going with this though:
>
> MCJIT builds on RuntimeDyld. RuntimeDyld is responsible for making object
> files in memory (instances of llvm::object::ObjectFile) runnable. It does
> this by allocating memory for the sections, applying relocations, and
> providing symbol lookup. To a very rough approximation, MCJIT is just:
>
> class MCJIT {
> private:
>   RuntimeDyld Dyld;
> public:
>   void* getSymbolAddress(StringRef Name) { return
> Dyld.getSymbolAddress(Name); }
>   void addModule(Module *M) { Dyld.loadObject(CodeGenIRToObject(M)); }
> };
>
> All the interesting parts of MCJIT have to do with module ownership, setting
> up the CodeGen pipeline, etc.
>
> If you're happy to handle codegen and module ownership yourself, you could
> actually talk to RuntimeDyld directly, rather than going through MCJIT.
> That's what I'm doing in that example, just for the sake of simplicity. For
> clients who want to keep using MCJIT we just need to add an API to get at
> the underlying Dyld state so that, if they want to, clients can inspect
> RuntimeDyld::JITObjects (these don't exist yet either, but are easy to add).
> Exactly what that API will look like I'm not sure yet. It may be as simple
> as 'RuntimeDyld::JITObject getJITObject(Module *M)' in the end.
>
> So short version: The loadObject API in the example above doesn't exist yet,
> and even if it did you probably wouldn't want to use it. However, there's a
> plan to get this kind of information to JIT clients in the future.
>
> On a related note, the demand for this kind of API usually comes from a
> desire to debug either the JIT or the JIT'd code. If we had a proper
> debugger registration system (i.e. a way to get relocated Dwarf to JIT
> clients and system debuggers), that could be used to find out most of the
> interesting things about relocated sections (including their, size, address,
> etc). This is also on the drawing board, but waiting for me to find time to
> do it.
>
> Cheers,
> Lang.
>
> On Thu, Sep 18, 2014 at 1:11 PM, Matt Godbolt <matt at godbolt.org> wrote:
>>
>> Thanks Lang, I guessed as much.  I already have the MCDisassembler
>> stuff all sorted (we're using it already with the JIT callback
>> NotifyFunctionEmitted) and we do in fact use it for non-debug too
>> (it's a one-time startup cost for us and it's useful to log to disc
>> all this stuff to spot regressions etc).
>>
>> I really appreciate you taking the time to have a think about this for us
>> :)
>>
>> I realise you're busy but if you have a second or two it seems both
>> Philip and I are unaware of the loadObject() style way of JITting.
>> We're also using the ExecutionEngine to build our code - can you point
>> us both in the direction of how one might use the loadObject style,
>> should you think it worthwhile?
>>
>> Cheers, Matt :)
>>
>> On Thu, Sep 18, 2014 at 1:46 PM, Lang Hames <lhames at gmail.com> wrote:
>> > Hi Matt,
>> >
>> > "Disassemble" is just pseudocode there, but the MCDisassembler in LLVM
>> > does
>> > have a reasonably friendly interface. You can look at the code in
>> > tools/llvm-mc to see how it's used.
>> >
>> > DEBUG is just a macro to wrap code so that it only executes for Debug
>> > builds. My assumption was that you were disassembling for some sort of
>> > debug
>> > dump (I've written things like that in the past for debugging the JIT
>> > infrastructure). If this is functionality that you want to be compiled
>> > into
>> > your project all the time you can just drop the reference to DEBUG.
>> >
>> > - Lang.
>> >
>> > On Thu, Sep 18, 2014 at 11:00 AM, Matt Godbolt <matt at godbolt.org> wrote:
>> >>
>> >> Hi Lang,
>> >>
>> >> Thanks for the reply, I'm glad it sounds like you have a fairly simple
>> >> suggested improvement.
>> >>
>> >> I'm not too familiar with the inner workings of llvm, so apologies if
>> >> this is a dumb question; what's the "Disassemble" and DEBUG() parts
>> >> doing here?  Are these the in the user code? I don't interact with the
>> >> RuntimeDyld directly anywhere in my code, so I'm not sure where this
>> >> code would go. If it's user code and I can somehow get hold of a
>> >> RuntimeDyld then this seems like a good match, as it seems pretty much
>> >> what I'm doing in NotifyObjectEmitted already.
>> >>
>> >> Cheers, Matt :)
>> >>
>> >> On Thu, Sep 18, 2014 at 12:17 PM, Lang Hames <lhames at gmail.com> wrote:
>> >> > Hi Matt, Philip,
>> >> >
>> >> > You could get the data you want by recording the addresses returned
>> >> > by
>> >> > the
>> >> > allocateCodeSection and allocateDataSection methods on your
>> >> > RTDyldMemoryManager, then disassembling those sections after you've
>> >> > called
>> >> > resolveRelocations. That's a little unsatisfying though. For one
>> >> > thing,
>> >> > unless you very carefully maintain the association with the original
>> >> > object
>> >> > via back-channels there will be no way of knowing which section
>> >> > belongs
>> >> > to
>> >> > which object file.
>> >> >
>> >> > With a bit of cleanup though, we could do something more like this:
>> >> >
>> >> > const RuntimeDyld::JITObject& JO = RTDyld.loadObject(Object);
>> >> > // ...
>> >> > RTDyld.resolveRelocations();
>> >> >
>> >> > DEBUG(
>> >> >   for (const RuntimeDyld::JITObject::Section& S : JO.sections())
>> >> >     if (S.isText())
>> >> >       Disassemble(S.getAddr(), S.getSize());
>> >> > );
>> >> >
>> >> > How does that look?
>> >> >
>> >> > Cheers,
>> >> > Lang.
>> >> >
>> >> >
>> >> > On Wed, Sep 17, 2014 at 3:08 PM, Philip Reames
>> >> > <listmail at philipreames.com>
>> >> > wrote:
>> >> >>
>> >> >>
>> >> >> On 09/17/2014 12:45 PM, Matt Godbolt wrote:
>> >> >>>
>> >> >>> Great stuff; thanks both!
>> >> >>>
>> >> >>> I'm also looking to turn my MCJIT conversion spike into our main
>> >> >>> use
>> >> >>> case. The only thing I'm missing is the ability to get a
>> >> >>> post-linked
>> >> >>> copy of the generated assembly.
>> >> >>>
>> >> >>> In JIT I used JITEventListener's NotifyFunctionEmitted and used a
>> >> >>> MCDisassembler to disassemble the stream (with my own custom
>> >> >>> annotators), and redirected the output to the relevant place for
>> >> >>> auditing of our app.
>> >> >>>
>> >> >>> With MCJIT I notice that NotifyFunctionEmitted is gone
>> >> >>> (understandably) and so I hook NotifyObjectEmitted. I then run
>> >> >>> through
>> >> >>> all the function symbols and dump them as before. Yay.  Except that
>> >> >>> in
>> >> >>> MCJIT terms the linking hasn't happened, so all the globals and
>> >> >>> external functions are all zeros at this point. (If I hackily
>> >> >>> observe
>> >> >>> the same code later on I see the linker has appropriately populated
>> >> >>> these addresses).  This makes my nicely annotated code a little
>> >> >>> unreadable, unfortunately.
>> >> >>>
>> >> >>> Does anyone have any suggestions as to how I might get to
>> >> >>> disassemble
>> >> >>> the post-linked code?
>> >> >>
>> >> >> my 2 cents: It seems like we need a different event type.  Having
>> >> >> access
>> >> >> to the object before linking (and relocation?) seems useful, but I
>> >> >> suspect
>> >> >> most users (myself included) want the final object after everything
>> >> >> is
>> >> >> done.
>> >> >>
>> >> >> Philip
>> >> >>
>> >> >>
>> >> >> On Wed, Sep 17, 2014 at 2:35 PM, Yaron Keren <yaron.keren at gmail.com>
>> >> >> wrote:
>> >> >>>>
>> >> >>>> Hi,
>> >> >>>>
>> >> >>>> You need to call llvm::sys::getHostCPUName() and pass the result
>> >> >>>> to
>> >> >>>> createTargetMachine() passed to the JIT. This patch should be
>> >> >>>> applied:
>> >> >>>>
>> >> >>>>   http://llvm.org/bugs/show_bug.cgi?id=17422
>> >> >>>>
>> >> >>>> Anyhow, the JIT was removed from current code and will not be in
>> >> >>>> next
>> >> >>>> LLVM
>> >> >>>> release.
>> >> >>>>
>> >> >>>> Yaron
>> >> >>>>
>> >> >>>>
>> >> >>>> 2014-09-17 22:27 GMT+03:00 Matt Godbolt <matt at godbolt.org>:
>> >> >>>>>
>> >> >>>>> Hi Jim,
>> >> >>>>>
>> >> >>>>> Thanks for a very quick reply! That indeed does the trick!
>> >> >>>>>
>> >> >>>>> Presumably the default has changed in 3.5 to be a "generic" CPU
>> >> >>>>> instead of the native one? If that's the case I wonder why:
>> >> >>>>> especially
>> >> >>>>> when JITting it really only makes sense to target the actual CPU
>> >> >>>>> -
>> >> >>>>> unless I'm missing something? :)
>> >> >>>>>
>> >> >>>>> Thanks again,
>> >> >>>>>
>> >> >>>>> Matt
>> >> >>>>>
>> >> >>>>> On Wed, Sep 17, 2014 at 2:16 PM, Jim Grosbach
>> >> >>>>> <grosbach at apple.com>
>> >> >>>>> wrote:
>> >> >>>>>>
>> >> >>>>>> Hi Matt,
>> >> >>>>>>
>> >> >>>>>> I suspect you need to specify the target CPU when you create the
>> >> >>>>>> JIT.
>> >> >>>>>> It’s just a method on the builder (e.g., builder.setMCPU(MCPU)).
>> >> >>>>>> If
>> >> >>>>>> you want
>> >> >>>>>> auto-detection based on the host CPU, sys::getHostCPUName()
>> >> >>>>>> returns
>> >> >>>>>> a
>> >> >>>>>> value
>> >> >>>>>> suitable to be passed directly into the builder.
>> >> >>>>>>
>> >> >>>>>> -Jim
>> >> >>>>>>
>> >> >>>>>>> On Sep 17, 2014, at 11:44 AM, Matt Godbolt <matt at godbolt.org>
>> >> >>>>>>> wrote:
>> >> >>>>>>>
>> >> >>>>>>> Hi guys,
>> >> >>>>>>>
>> >> >>>>>>> I just upgraded our JIT system to use llvm 3.5 and noticed one
>> >> >>>>>>> big
>> >> >>>>>>> change in our generated code: we don't see any non-destructive
>> >> >>>>>>> VEX
>> >> >>>>>>> prefix instructions being emitted any more (vmulsd xmm0, xmm1,
>> >> >>>>>>> blah)
>> >> >>>>>>> etc.
>> >> >>>>>>>
>> >> >>>>>>> It's long been on my list of things to investigate anyway as I
>> >> >>>>>>> noticed
>> >> >>>>>>> llvm didn't emit VZEROUPPER calls either, so I supposed it
>> >> >>>>>>> might
>> >> >>>>>>> not
>> >> >>>>>>> be a bad thing to disable vex.
>> >> >>>>>>>
>> >> >>>>>>> That being said, try as I might I can't force avx on
>> >> >>>>>>> (builder.setMCPU("core-avx-i") and/or
>> >> >>>>>>> builder.setMAttrs(vector<string>{"+avx"});). We're still using
>> >> >>>>>>> the
>> >> >>>>>>> old
>> >> >>>>>>> JIT but I just spiked out a move to MCJIT and I still don't see
>> >> >>>>>>> the
>> >> >>>>>>> VEX instructions.
>> >> >>>>>>>
>> >> >>>>>>> Was there a deliberate change on the llvm-side to discourage
>> >> >>>>>>> VEX
>> >> >>>>>>> instructions unless they make a big enough difference (and/or
>> >> >>>>>>> is
>> >> >>>>>>> VZEROUPPER now emitted?).
>> >> >>>>>>>
>> >> >>>>>>> If not, how might I go about digging further into this?
>> >> >>>>>>>
>> >> >>>>>>> Many thanks in advance, Matt
>> >> >>>>>>>
>> >> >>>>>>> --
>> >> >>>>>>> Matt
>> >> >>>>>>> _______________________________________________
>> >> >>>>>>> LLVM Developers mailing list
>> >> >>>>>>> LLVMdev at cs.uiuc.edu         http://llvm.cs.uiuc.edu
>> >> >>>>>>> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
>> >> >>>>>
>> >> >>>>>
>> >> >>>>>
>> >> >>>>> --
>> >> >>>>> Matt
>> >> >>>>>
>> >> >>>>> _______________________________________________
>> >> >>>>> LLVM Developers mailing list
>> >> >>>>> LLVMdev at cs.uiuc.edu         http://llvm.cs.uiuc.edu
>> >> >>>>> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
>> >> >>>>
>> >> >>>>
>> >> >>>
>> >> >>>
>> >> >>
>> >> >> _______________________________________________
>> >> >> LLVM Developers mailing list
>> >> >> LLVMdev at cs.uiuc.edu         http://llvm.cs.uiuc.edu
>> >> >> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
>> >> >
>> >> >
>> >>
>> >>
>> >>
>> >> --
>> >> Matt
>> >
>> >
>>
>>
>>
>> --
>> Matt
>
>



-- 
Matt




More information about the llvm-dev mailing list