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.

Reply via email to