Re: [patch 5/8] Immediate Values - x86 Optimization (update)

Mathieu Desnoyers
2007-11-13T22:02:47Z

* H. Peter Anvin (hpa@zytor.com) wrote:
> Mathieu Desnoyers wrote:
>> * H. Peter Anvin (hpa@zytor.com) wrote:
>>> Mathieu Desnoyers wrote:
>>>> * H. Peter Anvin (hpa@zytor.com) wrote:
>>>>> Mathieu Desnoyers wrote:
>>>>>>> - Use "=g" constraint for char immediate value inline assembly.
>>>>>>>
>>>>>>> "=g" is the same as "=rmi" which is inherently bogus. In your actual
>>>>>>> code you use "=r", the correct constraint is "=q".
>>>>>> q
>>>>>> Any register accessible as rl. In 32-bit mode, a, b, c, and d; in
>>>>>> 64-bit mode, any integer register. I am worried that "=q" might
>>>>>> exclude the si and di registers in 32-bit mode.
>>>>>> What exactly is wrong with "=r" ?
>>>>> For "char" (8-bit) values, sp/bp/si/di are illegal in 32-bit mode.
>>>>>
>>>>> Hence "=q".
>>>>>
>>>> Ah! yep, I see, so we say:
>>>> 1 byte : "=q"
>>>> 2 bytes : "=r"
>>>> 4 bytes : "=r"
>>>> 8 bytes : "=r"
>>>> ? (si and di appear to be legal for 2 and 4 bytes in 32-bit mode)
>>> That's right.
>>>
>>> -hpa
>
> Something else to watch out for... in 64-bit mode the lengths most of these
> will depend on which register is used, since whether or not a REX prefix is
> needed will vary.
>
> As far as I can tell, you're assuming fixed length instructions, which is
> wrong unless you manually constrain yourself to only legacy registers.
>

This is what I was pointing out in this previous message :
http://lkml.org/lkml/2007/10/20/92

"I am still trying to figure out if we must assume that gas will produce
different length opcodes for mov instructions. The choice is:
- Either I use a "r" constraint and let gcc produce the instructions,
that I need to assume to have correct size so I can align their
immediate values (therefore, taking the offset from the end of the
instruction will not help). Here, if gas changes its behavior
dramatically for a given immediate value size, it will break.

- Second choice is to stick to a particular register, choosing the one
with the less side-effect, and encoding the instruction ourselves. I
start to think that this second solution might be safer, even though
we wouldn't let the compiler select the register which has the less
impact by itself."

Andi seemed to trust gas stability and you answered:

"The comment was referring to x86-64, but I incorrectly remembered that
applying to "movq $imm,%reg" as opposed to loading from an absolute
address. gas actually has a special opcode (movabs) for the 64-bit
version of the latter variant, which is only available with %rax and its
subregisters.

Nevermind, in other words. It's still true, though, that the immediate
will always be the last thing in the instruction -- that's a fixture of
the instruction format."

So, in the end, is there a way to make x86_64 use a fixed-size opcode
for the 1, 2, 4 and 8 bytes load immediates or we will have to force the
use of a specific register ?

(and we can't take a pointer from the end of the instruction, because we
need to align the immediate value correctly)

Mathieu