Duncan Sands
2009-Jan-27 19:42 UTC
[LLVMdev] inline asm semantics: output constraint width smaller than input
Hi,> If yes then this doesnt look all that bad or invasive at first sight (if > the put_user() workaround can be expressed in a cleaner way), but in any > case it would be nice to hear an LLVM person's opinion about roughly when > this is going to be solved in LLVM itself.one thing that seems to be clear to everyone except me is... what are the semantics supposed to be? [My understanding is that what is being discussed is when you have an asm with a register as input and output, but with integer types of different width for the input and output, but I saw some mention of struct types in this thread...]. Presumably this is something obvious, but it would be good to have someone spell it out in small words that even someone like me can understand :) Thanks, Duncan.
Mike Stump
2009-Jan-27 19:56 UTC
[LLVMdev] inline asm semantics: output constraint width smaller than input
On Jan 27, 2009, at 8:42 PM, Duncan Sands wrote:> one thing that seems to be clear to everyone except me is... what > are the > semantics supposed to be?I don't know of any other semantic other than, if they are supposed to be in the same register, then they have to be in the same register.
Duncan Sands
2009-Jan-27 20:24 UTC
[LLVMdev] inline asm semantics: output constraint width smaller than input
On Tuesday 27 January 2009 20:56:30 Mike Stump wrote:> On Jan 27, 2009, at 8:42 PM, Duncan Sands wrote: > > one thing that seems to be clear to everyone except me is... what > > are the > > semantics supposed to be? > > I don't know of any other semantic other than, if they are supposed to > be in the same register, then they have to be in the same register.Sounds logical! But what is the discussion about then? Ciao, Duncan.
H. Peter Anvin
2009-Jan-27 21:25 UTC
[LLVMdev] inline asm semantics: output constraint width smaller than input
Duncan Sands wrote:> Hi, > >> If yes then this doesnt look all that bad or invasive at first sight (if >> the put_user() workaround can be expressed in a cleaner way), but in any >> case it would be nice to hear an LLVM person's opinion about roughly when >> this is going to be solved in LLVM itself. > > one thing that seems to be clear to everyone except me is... what are the > semantics supposed to be? [My understanding is that what is being discussed > is when you have an asm with a register as input and output, but with integer > types of different width for the input and output, but I saw some mention of > struct types in this thread...]. Presumably this is something obvious, but > it would be good to have someone spell it out in small words that even someone > like me can understand :) >I don't know about struct types, but the situation I'm talking about is assembly statements of the form: asm("foo" : "=r" (bar) : "0" (baz)); Here, "bar" and "baz" are constrained to be in the same hardware register (from the "0" constraint in "baz"). The types of "bar" and "baz" are otherwise unrelated. I assume the difficulty here comes from how this needs to be handled from the point of view of the register allocator. If both types fit inside a single allocatable hardware register, the issue is trivial; "bar" and "baz" form a single logical register for the purpose of register allocation. However, things get a bit ugly in the case of different widths that affect individually scheduled registers, like 32- and 64-bit types on a 32-bit machine. Consider the case above where "bar" is a 64-bit type and "baz" is a 32-bit type, then you functionally have, at least on x86: uint64_t tmp = bar; asm("foo" : "+r" (tmp)); baz = (uint32_t)tmp; One could possibly argue that the latter case should be "baz = (uint32_t)(tmp >> 32);" on a bigendian machine... since this is a gcc syntax it probably should be "whatever gcc does" in that case, as opposed to what might make sense. (I'm afraid I don't have a bigendian box readily available at the moment, so I can't test it out to see what gcc does. I have a powerpc machine, but it's at home and turned off.) -hpa
Kyle Moffett
2009-Jan-28 01:45 UTC
[LLVMdev] inline asm semantics: output constraint width smaller than input
On Tue, Jan 27, 2009 at 4:25 PM, H. Peter Anvin <hpa at zytor.com> wrote:> However, things get a bit ugly in the case of different widths that affect > individually scheduled registers, like 32- and 64-bit types on a 32-bit > machine. Consider the case above where "bar" is a 64-bit type and "baz" is > a 32-bit type, then you functionally have, at least on x86: > > uint64_t tmp = bar; > asm("foo" : "+r" (tmp)); > baz = (uint32_t)tmp; > > One could possibly argue that the latter case should be > "baz = (uint32_t)(tmp >> 32);" on a bigendian machine... since this is a gcc > syntax it probably should be "whatever gcc does" in that case, as opposed to > what might make sense. > > (I'm afraid I don't have a bigendian box readily available at the moment, so > I can't test it out to see what gcc does. I have a powerpc machine, but > it's at home and turned off.)Actually, PPC64 boxes basically don't care... the usable GPRs are all either 32-bit (for PPC32) or 64-bit (for PPC64), the <=32-bit instructions are identical across both, they just truncate/sign-extend/etc based on the lower 32-bits of the register. Also, you would only do a right-shift if you were going all the way out to memory as 64-bit and all the way back in as 32-bit... within a single register it's kept coherent. Structs are basically irrelevant for inline ASM as you can't pass a struct to one... you can only pass the *address* of a struct, which is always pointer-sized. I think that really the only sane solution (which is hopefully what GCC does) for integer types is to use a register the same size as the larger of the two integers. Then you copy the value to/from the smaller register (or just mask it on PPC64-alike architectures) before or after the inline ASM. Cheers, Kyle Moffett
Reasonably Related Threads
- [LLVMdev] inline asm semantics: output constraint width smaller than input
- [LLVMdev] inline asm semantics: output constraint width smaller than input
- [LLVMdev] inline asm semantics: output constraint width smaller than input
- [LLVMdev] inline asm semantics: output constraint width smaller than input
- [LLVMdev] inline asm semantics: output constraint width smaller than input