// bitreverse(bitreverse(x)) -> x
if (match(Op0, m_BitReverse(m_Value(X)))) return X;
break;
+ case Intrinsic::ctpop: {
+ // If everything but the lowest bit is zero, that bit is the pop-count. Ex:
+ // ctpop(and X, 1) --> and X, 1
+ unsigned BitWidth = Op0->getType()->getScalarSizeInBits();
+ if (MaskedValueIsZero(Op0, APInt::getHighBitsSet(BitWidth, BitWidth - 1),
+ Q.DL, 0, Q.AC, Q.CxtI, Q.DT))
+ return Op0;
+ break;
+ }
case Intrinsic::exp:
// exp(log(x)) -> x
if (Q.CxtI->hasAllowReassoc() &&
ret <2 x i1> %res
}
-; Make sure we don't add range metadata to i1 ctpop.
+; No intrinsic or range needed - ctpop of bool bit is the bit itself.
+
define i1 @test6(i1 %arg) {
; CHECK-LABEL: @test6(
-; CHECK-NEXT: [[CNT:%.*]] = call i1 @llvm.ctpop.i1(i1 [[ARG:%.*]])
-; CHECK-NEXT: ret i1 [[CNT]]
+; CHECK-NEXT: ret i1 [[ARG:%.*]]
;
%cnt = call i1 @llvm.ctpop.i1(i1 %arg)
ret i1 %cnt
define i32 @ctpop_lowbit(i32 %x) {
; CHECK-LABEL: @ctpop_lowbit(
; CHECK-NEXT: [[B:%.*]] = and i32 [[X:%.*]], 1
-; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.ctpop.i32(i32 [[B]])
-; CHECK-NEXT: ret i32 [[R]]
+; CHECK-NEXT: ret i32 [[B]]
;
%b = and i32 %x, 1
%r = call i32 @llvm.ctpop.i32(i32 %b)
ret i32 %r
}
+; Negative test - only low bit allowed
+; This could be reduced by instcombine to and+shift.
+
define i32 @ctpop_pow2(i32 %x) {
; CHECK-LABEL: @ctpop_pow2(
; CHECK-NEXT: [[B:%.*]] = and i32 [[X:%.*]], 4
define <3 x i33> @ctpop_signbit(<3 x i33> %x) {
; CHECK-LABEL: @ctpop_signbit(
; CHECK-NEXT: [[B:%.*]] = lshr <3 x i33> [[X:%.*]], <i33 32, i33 32, i33 32>
-; CHECK-NEXT: [[R:%.*]] = tail call <3 x i33> @llvm.ctpop.v3i33(<3 x i33> [[B]])
-; CHECK-NEXT: ret <3 x i33> [[R]]
+; CHECK-NEXT: ret <3 x i33> [[B]]
;
%b = lshr <3 x i33> %x, <i33 32, i33 32, i33 32>
%r = tail call <3 x i33> @llvm.ctpop.v3i33(<3 x i33> %b)
ret <3 x i33> %r
}
+; Negative test - only 1 bit allowed
+
define <3 x i33> @ctpop_notsignbit(<3 x i33> %x) {
; CHECK-LABEL: @ctpop_notsignbit(
; CHECK-NEXT: [[B:%.*]] = lshr <3 x i33> [[X:%.*]], <i33 31, i33 31, i33 31>
define i1 @ctpop_bool(i1 %x) {
; CHECK-LABEL: @ctpop_bool(
-; CHECK-NEXT: [[R:%.*]] = tail call i1 @llvm.ctpop.i1(i1 [[X:%.*]])
-; CHECK-NEXT: ret i1 [[R]]
+; CHECK-NEXT: ret i1 [[X:%.*]]
;
%r = tail call i1 @llvm.ctpop.i1(i1 %x)
ret i1 %r