[LLVMdev] inline asm constraints in LLVM

Dale Johannesen dalej at apple.com
Fri Aug 13 17:06:56 PDT 2010


On Aug 13, 2010, at 3:59 PMPDT, John Thompson wrote:

> Dale,
>
> I've looked a bit at ChooseConstraintTuple in llvm-gcc, as well as  
> the code generator in Clang and the inline asm handling in LLVM (ala  
> visitInlineAsm).
>
> While I see how Clang could do it to some extent by looking at the  
> expression types of the operands, it seems that LLVM would be in a  
> better position for choosing multiple alternative constraints as it  
> would know what all the operands are, and where they currently are,  
> particularly if part of an earlier transformation resulted in  
> operands Clang thought were in memory were already in registers.   
> And LLVm might need to step in anyway if registers can be allocated.
>
> Or is the constraint handling always performed before such changes  
> as these would be made, such that Clang could know this?

No.  You're right that you would get better code by postponing the  
evaluation of constraints until after some optimizations, like  
constant propagation.  But not very often.

> Or for a more off-the wall question, could asm constraints just be  
> ignored, and let the target code in LLVM choose the appropriate  
> instruction opcodes, and provide any additional piping needed to get  
> the operands in and out of the given assembly instructions?

You can't ignore constraints; a global address can represent either an  
address or an immediate value depending on the constraint, for example.

> What I learned from ChooseConstraintTuple in llvm-gcc is that the  
> constraints need to be considered in parallel.  That is, you collect  
> the first alternative of each constraint string, give it a weight  
> value, including a value meaning the combination won't work, collect  
> the second alternative of each constraint string, give it a weigh,  
> and if better than the first, save it, and so on for each constraint  
> string, finally using the one with the best weight, or erroring if  
> none match at all.

Yes.
If you didn't understand how this works, you should probably look at  
gcc's register allocator too, to see the full horror of what you're  
getting into.  gcc also finds a best match, but is much more  
complicated.  The definition of how inline assembly should work is  
"what gcc does", so ideally this is what you need to imitate.  So far  
we've gone for a lesser target, "functionally equivalent to what gcc  
does", which works pretty well in practice.

>  This would require a few things:
>
> 1. Clang needs to properly output the constraints.  I recently  
> changed Clang to only output the first alternative, as it was  
> outputting the comma, which confused the code generator.

Crashing in the code generator was not good, but this approach doesn't  
really fix it; it's possible the actual operands won't match the first  
alternative, so you'll get a different crash.

> Since apparently multiple constraint letters can be used (not the  
> true multiple-alternative constraints), we probably would need to  
> put in some separator character, such as a vertical bar character  
> ("|") to delimit the constraints.  I think I even saw a mention of  
> "|" at one point in looking at the LLVM code, as if maybe it was  
> considered at one time, but I couldn't tell what it applied to.
>
> 2. Clang might need some change to the constraint representation  
> with respeced to the logic it uses to determine if an operand is to  
> be indirect (using "*"), because seeing "r" and "m" in alternatives  
> results in both the "allowsRegister" and "allowsMemory" flags being  
> set, and the allowsMemory flag is used to add the indirect flag.   
> However, I saw code in LLVM that will insert code for the  
> indirection even if the indirect flag is not present, such that I  
> think we might be able to eliminate that flag and let LLVM deal with  
> it.
>
> 3. LLVM needs code to select the alterinative constraint to use.  To  
> do this, the inline asm handler probably needs to be changed to  
> store the alternatives separately to make it easier to walk them for  
> the selection, perhaps using a SubConstraintInfo class in an array  
> owned by ConstraintInfo.  After the selection, which determines the  
> one subconstraint index needed, the data for the selected  
> alternatives could then be copied to the ConstraintInfo class to  
> reduce impact on the code using it.
>
> I'm willing to have a go at doing this myself, but I think it might  
> be beyond me, particularly since I have no experience modifying LLVM  
> yet, and this is a pretty hairy section.  So it would be great if  
> you or Chris or whoever really knows this code could take it on.

At this point, inline asm is only touched here when something breaks.   
I don't see putting a major effort into it.

>  Of course, this is just my initial brainstorming proposal, to see  
> if you guys would agree that the back-end is more appropriate for  
> the alternative constraint selection.


I think it would be better but not much.  You might want to implement  
the equivalent of ChooseConstraintTuple in clang, which should not be  
very difficult since you've got a working example to copy, and see if  
that meets your needs.  I've been surprised at how well it worked  
here, actually.

If you want to do it the hard way, I think this approach would be best:

Get the back end to handle the separator (vertical bar should work),  
testing with hand-edited .ll files.  Basically this means putting the  
ChooseConstraintTuple logic into visitInlineAsm, I don't think anybody  
earlier than that cares about constraints.

Enhance the IR bitcode readers and writers with the separator (if  
needed, I'm not sure anything in here even looks at constraint strings).

Change the front ends (OK, maybe we only care about clang) to generate  
the separator.

This way llvm-gcc should continue to work while your work is in  
progress.




More information about the llvm-dev mailing list