Index: lib/Analysis/ValueTracking.cpp =================================================================== --- lib/Analysis/ValueTracking.cpp +++ lib/Analysis/ValueTracking.cpp @@ -1417,12 +1417,25 @@ KnownZero |= KnownZero2.byteSwap(); KnownOne |= KnownOne2.byteSwap(); break; - case Intrinsic::ctlz: + case Intrinsic::ctlz: { + computeKnownBits(I->getOperand(0), KnownZero2, KnownOne2, Depth + 1, Q); + // If we have a known 1, its position is our upper bound. + unsigned PossibleLZ = KnownOne2.countLeadingZeros(); + // If this call is undefined for 0, the result will be less than 2^n. + if (II->getArgOperand(1) == ConstantInt::getTrue(II->getContext())) + PossibleLZ = std::min(PossibleLZ, BitWidth - 1); + unsigned LowBits = Log2_32(PossibleLZ)+1; + KnownZero.setBitsFrom(LowBits); + break; + } case Intrinsic::cttz: { - unsigned LowBits = Log2_32(BitWidth)+1; + computeKnownBits(I->getOperand(0), KnownZero2, KnownOne2, Depth + 1, Q); + // If we have a known 1, its position is our upper bound. + unsigned PossibleTZ = KnownOne2.countTrailingZeros(); // If this call is undefined for 0, the result will be less than 2^n. if (II->getArgOperand(1) == ConstantInt::getTrue(II->getContext())) - LowBits -= 1; + PossibleTZ = std::min(PossibleTZ, BitWidth - 1); + unsigned LowBits = Log2_32(PossibleTZ)+1; KnownZero.setBitsFrom(LowBits); break; } Index: test/Transforms/InstCombine/intrinsics.ll =================================================================== --- test/Transforms/InstCombine/intrinsics.ll +++ test/Transforms/InstCombine/intrinsics.ll @@ -284,10 +284,7 @@ define i1 @cttz_knownbits(i32 %arg) { ; CHECK-LABEL: @cttz_knownbits( -; CHECK-NEXT: [[OR:%.*]] = or i32 [[ARG:%.*]], 4 -; CHECK-NEXT: [[CNT:%.*]] = call i32 @llvm.cttz.i32(i32 [[OR]], i1 true) #0 -; CHECK-NEXT: [[RES:%.*]] = icmp eq i32 [[CNT]], 4 -; CHECK-NEXT: ret i1 [[RES]] +; CHECK-NEXT: ret i1 false ; %or = or i32 %arg, 4 %cnt = call i32 @llvm.cttz.i32(i32 %or, i1 true) nounwind readnone @@ -307,10 +304,7 @@ define i1 @ctlz_knownbits(i8 %arg) { ; CHECK-LABEL: @ctlz_knownbits( -; CHECK-NEXT: [[OR:%.*]] = or i8 [[ARG:%.*]], 32 -; CHECK-NEXT: [[CNT:%.*]] = call i8 @llvm.ctlz.i8(i8 [[OR]], i1 true) #0 -; CHECK-NEXT: [[RES:%.*]] = icmp eq i8 [[CNT]], 4 -; CHECK-NEXT: ret i1 [[RES]] +; CHECK-NEXT: ret i1 false ; %or = or i8 %arg, 32 %cnt = call i8 @llvm.ctlz.i8(i8 %or, i1 true) nounwind readnone