LLVM asm with constraints, and 2 operands

kinke noone at nowhere.com
Mon Jul 19 10:21:58 UTC 2021


On Sunday, 18 July 2021 at 16:32:46 UTC, Basile B. wrote:
> - **=x** says "returns in whatever is has to"
> - **x** (1) is the constraint for input `a`, which is passed as 
> operand **$0**
> - **x** (2) is the constraint for input `b`, which is passed as 
> operand **$1**

$0 is actually the output operand, $1 is `a`, and $2 is `b`.

The official docs are here, but IMO not very user-friendly: 
https://llvm.org/docs/LangRef.html#inline-assembler-expressions

I recommend using GDC/GCC inline asm instead, where you'll find 
more examples. For the given paddd example, I'd have gone with

```
int4 _mm_add_int4(int4 a, int4 b)
{
     asm { "paddd %1, %0" : "=*x" (a) : "x" (b); }
     // the above is equivalent to:
     // __asm!void("paddd $1, $0","=*x,x", &a, b);
     return a;
}
```

but the produced asm is rubbish (apparently an LLVM issue):

```
movaps	%xmm1, -24(%rsp)
paddd	%xmm0, %xmm0 // WTF?
movaps	%xmm0, -24(%rsp)
retq
```

What works reliably is a manual mov:

```
int4 _mm_add_int4(int4 a, int4 b)
{
     int4 r;
     asm { "paddd %1, %2; movdqa %2, %0" : "=x" (r) : "x" (a), "x" 
(b); }
     return r;
}
```

=>

```
paddd	%xmm1, %xmm0
movdqa	%xmm0, %xmm0 // useless but cannot be optimized away
retq
```

Note: inline asm syntax and resulting asm in AT&T syntax, *not* 
Intel syntax.


More information about the Digitalmars-d-learn mailing list