Skip to content

1 << cttz(z) should be folded into z & -z even on machines with cttz built-in #91305

Closed
@Validark

Description

@Validark

https://alive2.llvm.org/ce/z/on8IIK suggests 1 << cttz(z) = z & -z is already folded by instcombine

Originally posted by @RKSimon in #90000 (comment)

This code:

export fn bar(y: u64) u64 {
    if (y == 0) return 0;
    return @as(u64, 1) << @intCast(@ctz(y));
}

Gives me this emit for the risc-v sifive u74:

bar:
        neg     a1, a0
        and     a0, a0, a1
        ret

Exactly what we want.

Now, let's "upgrade" to the sifive x280:

bar:
        ctz     a1, a0
        li      a2, 1
        sll     a1, a2, a1
        bnez    a0, .LBB0_2
        li      a1, 0
.LBB0_2:
        mv      a0, a1
        ret

Oops! Same problem occurs on x86 Zen 3:

bar:
        tzcnt   rax, rdi
        mov     ecx, 1
        shlx    rax, rcx, rax
        cmovb   rax, rdi
        ret

And on aarch64 apple_latest:

bar:
        rbit    x8, x0
        clz     x8, x8
        mov     w9, #1
        lsl     x8, x9, x8
        cmp     x0, #0
        csel    x0, xzr, x8, eq
        ret

Godbolt link

Related: #84763 #90000

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions