/// \code
/// int a = ctlz(x & -x);
// x ? 31 - a : a;
+// // or
+// x ? 31 - a : 32;
/// \code
///
/// into:
if (ICI->getPredicate() == ICmpInst::ICMP_NE)
std::swap(TrueVal, FalseVal);
+ Value *Ctlz;
if (!match(FalseVal,
- m_Xor(m_Deferred(TrueVal), m_SpecificInt(BitWidth - 1))))
+ m_Xor(m_Value(Ctlz), m_SpecificInt(BitWidth - 1))))
return nullptr;
- if (!match(TrueVal, m_Intrinsic<Intrinsic::ctlz>()))
+ if (!match(Ctlz, m_Intrinsic<Intrinsic::ctlz>()))
+ return nullptr;
+
+ if (TrueVal != Ctlz && !match(TrueVal, m_SpecificInt(BitWidth)))
return nullptr;
Value *X = ICI->getOperand(0);
- auto *II = cast<IntrinsicInst>(TrueVal);
+ auto *II = cast<IntrinsicInst>(Ctlz);
if (!match(II->getOperand(0), m_c_And(m_Specific(X), m_Neg(m_Specific(X)))))
return nullptr;
define i32 @select_clz_to_ctz_constant_for_zero(i32 %a) {
; CHECK-LABEL: @select_clz_to_ctz_constant_for_zero(
-; CHECK-NEXT: [[SUB:%.*]] = sub i32 0, [[A:%.*]]
-; CHECK-NEXT: [[AND:%.*]] = and i32 [[SUB]], [[A]]
-; CHECK-NEXT: [[LZ:%.*]] = tail call i32 @llvm.ctlz.i32(i32 [[AND]], i1 false), !range [[RNG0]]
-; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[A]], 0
-; CHECK-NEXT: [[SUB1:%.*]] = xor i32 [[LZ]], 31
-; CHECK-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i32 32, i32 [[SUB1]]
+; CHECK-NEXT: [[COND:%.*]] = call i32 @llvm.cttz.i32(i32 [[A:%.*]], i1 false), !range [[RNG0]]
; CHECK-NEXT: ret i32 [[COND]]
;
%sub = sub i32 0, %a