Skip to content

Simplify "X ? X & ~(1U << std::countr_zero(X)) : 0" to "X & (X - 1)" #60801

@kazutakahirata

Description

@kazutakahirata

Compile:

// clang -std=c++20 -march=skylake -O2
#include <bit>

unsigned blsr_human_readable(unsigned X) {
  return X ? X & ~(1U << std::countr_zero(X)) : 0;
}

I get:

  %2 = icmp eq i32 %0, 0
  %3 = tail call i32 @llvm.cttz.i32(i32 %0, i1 false) #3, !range !5
  %4 = shl nuw i32 1, %3
  %5 = xor i32 %4, -1
  %6 = and i32 %5, %0
  %7 = select i1 %2, i32 0, i32 %6
  f3 0f bc cf                tzcnt  %edi,%ecx
  89 f8                      mov    %edi,%eax
  0f b3 c8                   btr    %ecx,%eax
  85 ff                      test   %edi,%edi
  0f 44 c7                   cmove  %edi,%eax

We could transform this into:

unsigned blsr_optimal(unsigned X) {
  return X & (X - 1);
  // %2 = add i32 %0, -1
  // %3 = and i32 %2, %0
  //
  // c4 e2 78 f3 cf             blsr   %edi,%eax
}

Proof: https://alive2.llvm.org/ce/z/zpNB-G

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions