Skip to content

Allow AND-NOT to be emitted from NOT + <some bit/byte reordering> + AND #112425

Closed
@Validark

Description

@Validark

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
}

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions