Closed
Description
Zen 5 Assembly:
foo:
mov rax, rdi
- not rax
bswap rax
- and rax, rdi
+ andn rax, rax, rdi
ret
Zig version: (Godbolt)
export fn foo(a: u64) u64 {
return a & ~@byteSwap(a);
}
export fn bar(a: u64) u64 {
return andn(a, @byteSwap(a));
}
LLVM version (optimized): (Godbolt)
define dso_local i64 @foo(i64 %0) local_unnamed_addr {
Entry:
%1 = xor i64 %0, -1
%2 = tail call i64 @llvm.bswap.i64(i64 %1)
%3 = and i64 %2, %0
ret i64 %3
}
declare i64 @llvm.bswap.i64(i64) #1
define dso_local i64 @bar(i64 %0) local_unnamed_addr {
Entry:
%1 = tail call i64 @llvm.bswap.i64(i64 %0)
%2 = tail call i64 asm "andn ${1}, ${2}, ${0}", "=r,r,r,~{dirflag},~{fpsr},~{flags}"(i64 %0, i64 %1) #3
ret i64 %2
}
Problem occurs in foo
even when you manually change it to:
define dso_local i64 @foo(i64 %0) local_unnamed_addr {
Entry:
%1 = tail call i64 @llvm.bswap.i64(i64 %0)
%2 = xor i64 %1, -1
%3 = and i64 %2, %0
ret i64 %3
}