Open
Description
Zig Version
0.14.0-dev.1417+242d268a0
Steps to Reproduce and Observed Behavior
This code:
fn valignq(a: @Vector(64, u8), b: @Vector(64, u8), comptime imm: u6) @Vector(64, u8) {
return asm (
\\valignq %[imm], %[b], %[a], %[out]
: [out] "=v" (-> @Vector(64, u8)),
: [a] "v" (a),
[b] "v" (b),
[imm] "n" (imm),
);
}
export fn valignq_ext(a: @Vector(64, u8), b: @Vector(64, u8)) @Vector(64, u8) {
return valignq(a, b, 32);
}
Results in this assembly:
valignq_ext:
valignq zmm0, zmm0, zmm1, 224
ret
What I assume is happening here is described in the title. 32
as a u6
is 0b100000
, but this gets turned into an i6
, then sign-extended to an i8
. So we end up with 0b11100000
, which is 224
as a u8
.
This can be worked around by wrapping imm
in @as(u8, imm)
:
fn valignq(a: @Vector(64, u8), b: @Vector(64, u8), comptime imm: u6) @Vector(64, u8) {
return asm (
\\valignq %[imm], %[b], %[a], %[out]
: [out] "=v" (-> @Vector(64, u8)),
: [a] "v" (a),
[b] "v" (b),
[imm] "n" (@as(u8, imm)),
);
}
It would be nice if the language did this automatically or if there was a helpful compiler error.
Expected Behavior
valignq_ext:
valignq zmm0, zmm0, zmm1, 32
ret