Extended Inline asm with double data type crashes clang

Hi,

Clang crashes when below snippet of code is compiled (used latest svn version)

double func1()
{
double x ;
asm ( “” : “=r”(x) : “0”(x) );
return x;
}

clang -S test1.c
Assertion failed: (PartVT.isInteger() || PartVT == MVT::x86mmx) && ValueVT.isInteger() && “Unknown mismatch!”, file …......\lib\CodeGen\SelectionDAG\SelectionDAGBuilder.cpp, line 378

Compilation sucessful, If data type passed to inline asm is of float
float x ;

asm ( “” : “=r”(x) : “0”(x) );

(or) If double data type passed to float type of registers
double x;
asm ( “” : “=t”(x) : “0”(x) );

It seems currently LLVM (selectionDAG) doesn’t handle double to general purpose register storing.
Could anyone please comment on this.

Regards,
Rajesh

I reported http://llvm.org/pr14393 to track it.

Thanks Rafael,

Hello All,

Could anyone please comment, which part in selectiondag need to be understood/modified to fix this.

Regards,
Rajesh

Hi all,

I tried same code on gcc for arm(hard float),

double f2 ()
{
double x = 10.0;
asm (“” : “=r” (x) : “0” (x));
return x;
}

arm-linux-gnueabi-gcc -S -mhard-float pr39058.c -O2

Generates proper code,
mov r3, #0
mov r2, #0
movt r3, 16420
fmdrr d0, r2, r3
bx lr

But llvm crashes, If data type is “double”, register type is “int”.
Any comments why does llvm currently handle this case ?

Regards,
Rajesh

"r" is supposed to be a single register, not a register pair; the fact
that gcc accepts this is probably an accident. clang should reject
this code (without crashing, of course).

-Eli

"r" is supposed to be a single register, not a register pair; the fact
that gcc accepts this is probably an accident. clang should reject
this code (without crashing, of course).

I'm not quite convinced by this. On AArch64, GCC supports the %H, %Q
and %R operand modifiers which very explicitly deal with a pair of
64-bit registers. These are intended to be used with the 'r'
constraint (I asked, specifically because there wasn't a corresponding
"register-pair" constraint).

It could just be the new port and no-one's noticed the rules have been
broken yet, of course. So we could take the high road, but it's a
little unclear who we should go whinging to that GCC is breaking the
rules of the GCC-specific inline assembly syntax.

Tim.

Hmm... it isn't completely without precedent to have a constraint
which refers to multiple registers (like the x86 "A" constraint), but
it doesn't seem like something which can be done generically: what
"pairs" would we allow for "r" on e.g. x86?

Of course, while writing this, I just realized this is a variant of a
bug which has been discussed on llvm-commits: PR13622. And gcc
actually does implement pairs on x86; I think the choice of registers
is based on some internal register allocator sequence. And gcc also
knows how to allocate register triplets on x86 (though I have no clue
how you would use them). :slight_smile:

Ugh, I wish gcc's inline asm extension didn't expose so much of the
insanity of gcc internals.

-Eli

Ugh, I wish gcc's inline asm extension didn't expose so much of the
insanity of gcc internals.

Now that I can agree with!

Tim.

> I'm not quite convinced by this. On AArch64, GCC supports the %H, %Q
> and %R operand modifiers which very explicitly deal with a pair of
> 64-bit registers. These are intended to be used with the 'r'
> constraint (I asked, specifically because there wasn't a corresponding
> "register-pair" constraint).
>

Admittedly it's a new port, but yes, this is how gcc's register allocation
works.

> It could just be the new port and no-one's noticed the rules have been
> broken yet, of course. So we could take the high road, but it's a
> little unclear who we should go whinging to that GCC is breaking the
> rules of the GCC-specific inline assembly syntax.

Hmm... it isn't completely without precedent to have a constraint
which refers to multiple registers (like the x86 "A" constraint), but
it doesn't seem like something which can be done generically: what
"pairs" would we allow for "r" on e.g. x86?

Of course, while writing this, I just realized this is a variant of a
bug which has been discussed on llvm-commits: PR13622. And gcc
actually does implement pairs on x86; I think the choice of registers
is based on some internal register allocator sequence. And gcc also
knows how to allocate register triplets on x86 (though I have no clue
how you would use them). :slight_smile:

Ugh, I wish gcc's inline asm extension didn't expose so much of the
insanity of gcc internals.

Yes, inline assembly that exposes register allocation details is pretty
annoying.

Jakob: Thoughts on how you'd want to model this as it goes through the
allocator?

-eric

The allocator wants all constraints expressed as register classes. Even-odd pairs of consecutive registers should be modeled as pseudo-registers. This is what Weiming is currently working on for ARM register pairs using the new GPRPair register class. (Feel free to review his patch from 11/19).

However, a pair of registers that don’t constrain the register allocator should be modeled as two separate virtual registers.

So if GCC is using register pairs just to model an illegal type like i64 on ARM, the constraint should be handled by multiple virtual registers. If there are additional constraints on the register pair (e.g. they must be consecutive), the pair should be modeled as a single virtual register with sub-registers.

The INLINEASM MachineInstr already supports a single constraint mapping to multiple MachineOperands. X86 “m” constraints map to 5 operands, for example. A single “r” constraint should be able to map to multiple register operands as well.

/jakob