Index: lib/Transforms/InstCombine/InstCombineCalls.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineCalls.cpp +++ lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -1264,12 +1264,20 @@ assert((II.getIntrinsicID() == Intrinsic::cttz || II.getIntrinsicID() == Intrinsic::ctlz) && "Expected cttz or ctlz intrinsic"); + bool IsTZ = II.getIntrinsicID() == Intrinsic::cttz; Value *Op0 = II.getArgOperand(0); + Value *X; + // ctlz(bitreverse(x)) -> cttz(x) + // cttz(bitreverse(x)) -> ctlz(x) + if (match(Op0, m_BitReverse(m_Value(X)))) { + return IC.replaceInstUsesWith(II, IC.Builder.CreateBinaryIntrinsic( + IsTZ ? Intrinsic::ctlz : Intrinsic::cttz, + X, II.getArgOperand(1))); + } KnownBits Known = IC.computeKnownBits(Op0, 0, &II); // Create a mask for bits above (ctlz) or below (cttz) the first known one. - bool IsTZ = II.getIntrinsicID() == Intrinsic::cttz; unsigned PossibleZeros = IsTZ ? Known.countMaxTrailingZeros() : Known.countMaxLeadingZeros(); unsigned DefiniteZeros = IsTZ ? Known.countMinTrailingZeros() Index: test/Transforms/InstCombine/ctlz-cttz-bitreverse.ll =================================================================== --- test/Transforms/InstCombine/ctlz-cttz-bitreverse.ll +++ test/Transforms/InstCombine/ctlz-cttz-bitreverse.ll @@ -0,0 +1,26 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -instcombine -S < %s | FileCheck %s + +define i32 @ctlz_bitreverse(i32) { +; CHECK-LABEL: @ctlz_bitreverse( +; CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.cttz.i32(i32 [[TMP0:%.*]], i1 true), !range !0 +; CHECK-NEXT: ret i32 [[TMP2]] +; + %2 = tail call i32 @llvm.bitreverse.i32(i32 %0) + %3 = tail call i32 @llvm.ctlz.i32(i32 %2, i1 true) + ret i32 %3 +} + +define i32 @cttz_bitreverse(i32) { +; CHECK-LABEL: @cttz_bitreverse( +; CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.ctlz.i32(i32 [[TMP0:%.*]], i1 true), !range !0 +; CHECK-NEXT: ret i32 [[TMP2]] +; + %2 = tail call i32 @llvm.bitreverse.i32(i32 %0) + %3 = tail call i32 @llvm.cttz.i32(i32 %2, i1 true) + ret i32 %3 +} + +declare i32 @llvm.bitreverse.i32(i32) +declare i32 @llvm.ctlz.i32(i32, i1) +declare i32 @llvm.cttz.i32(i32, i1)