diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -2046,32 +2046,27 @@ case Instruction::Trunc: return OrZero && isKnownToBeAPowerOfTwo(I->getOperand(0), OrZero, Depth, Q); case Instruction::Shl: - if (OrZero || Q.IIQ.hasNoUnsignedWrap(I) || Q.IIQ.hasNoSignedWrap(I)) - return isKnownToBeAPowerOfTwo(I->getOperand(0), OrZero, Depth, Q); - return false; case Instruction::LShr: - if (OrZero || Q.IIQ.isExact(cast(I))) - return isKnownToBeAPowerOfTwo(I->getOperand(0), OrZero, Depth, Q); - return false; + return isKnownToBeAPowerOfTwo(I->getOperand(0), OrZero, Depth, Q) && + (OrZero || isKnownNonZero(I, Depth, Q)); case Instruction::UDiv: if (Q.IIQ.isExact(cast(I))) return isKnownToBeAPowerOfTwo(I->getOperand(0), OrZero, Depth, Q); return false; case Instruction::Mul: - return OrZero && - isKnownToBeAPowerOfTwo(I->getOperand(1), OrZero, Depth, Q) && - isKnownToBeAPowerOfTwo(I->getOperand(0), OrZero, Depth, Q); + return isKnownToBeAPowerOfTwo(I->getOperand(1), OrZero, Depth, Q) && + isKnownToBeAPowerOfTwo(I->getOperand(0), OrZero, Depth, Q) && + (OrZero || isKnownNonZero(I, Depth, Q)); case Instruction::And: - if (OrZero) { - // A power of two and'd with anything is a power of two or zero. - if (isKnownToBeAPowerOfTwo(I->getOperand(0), /*OrZero*/ true, Depth, Q) || - isKnownToBeAPowerOfTwo(I->getOperand(1), /*OrZero*/ true, Depth, Q)) - return true; - // X & (-X) is always a power of two or zero. - if (match(I->getOperand(0), m_Neg(m_Specific(I->getOperand(1)))) || - match(I->getOperand(1), m_Neg(m_Specific(I->getOperand(0))))) - return true; - } + // A power of two and'd with anything is a power of two or zero. + if (OrZero && + (isKnownToBeAPowerOfTwo(I->getOperand(0), /*OrZero*/ true, Depth, Q) || + isKnownToBeAPowerOfTwo(I->getOperand(1), /*OrZero*/ true, Depth, Q))) + return true; + // X & (-X) is always a power of two or zero. + if (match(I->getOperand(0), m_Neg(m_Specific(I->getOperand(1)))) || + match(I->getOperand(1), m_Neg(m_Specific(I->getOperand(0))))) + return OrZero || isKnownNonZero(I->getOperand(0), Depth, Q); return false; case Instruction::Add: { // Adding a power-of-two or zero to the same power-of-two or zero yields diff --git a/llvm/test/Analysis/ValueTracking/known-power-of-two.ll b/llvm/test/Analysis/ValueTracking/known-power-of-two.ll --- a/llvm/test/Analysis/ValueTracking/known-power-of-two.ll +++ b/llvm/test/Analysis/ValueTracking/known-power-of-two.ll @@ -383,7 +383,7 @@ ; CHECK-NEXT: [[ZP2:%.*]] = shl i16 2, [[ZSMALL]] ; CHECK-NEXT: [[XX:%.*]] = mul nuw nsw i16 [[XP2]], [[ZP2]] ; CHECK-NEXT: [[AND:%.*]] = and i16 [[XX]], [[Y]] -; CHECK-NEXT: [[R:%.*]] = icmp eq i16 [[AND]], [[XX]] +; CHECK-NEXT: [[R:%.*]] = icmp ne i16 [[AND]], 0 ; CHECK-NEXT: ret i1 [[R]] ; %xsmall = and i16 %x, 3 @@ -449,7 +449,7 @@ ; CHECK-NEXT: [[XSMALL:%.*]] = and i16 [[X]], 7 ; CHECK-NEXT: [[XX:%.*]] = shl i16 4, [[XSMALL]] ; CHECK-NEXT: [[AND:%.*]] = and i16 [[XX]], [[Y]] -; CHECK-NEXT: [[R:%.*]] = icmp eq i16 [[AND]], [[XX]] +; CHECK-NEXT: [[R:%.*]] = icmp ne i16 [[AND]], 0 ; CHECK-NEXT: ret i1 [[R]] ; %xsmall = and i16 %x, 7 @@ -500,7 +500,7 @@ ; CHECK-NEXT: [[XSMALL:%.*]] = and i16 [[X]], 7 ; CHECK-NEXT: [[XX:%.*]] = lshr i16 512, [[XSMALL]] ; CHECK-NEXT: [[AND:%.*]] = and i16 [[XX]], [[Y]] -; CHECK-NEXT: [[R:%.*]] = icmp eq i16 [[AND]], [[XX]] +; CHECK-NEXT: [[R:%.*]] = icmp ne i16 [[AND]], 0 ; CHECK-NEXT: ret i1 [[R]] ; %xsmall = and i16 %x, 7 @@ -550,9 +550,9 @@ ; CHECK-SAME: (i16 [[X:%.*]], i16 [[Y:%.*]]) { ; CHECK-NEXT: [[XNZ:%.*]] = or i16 [[X]], 4 ; CHECK-NEXT: [[X_NEG:%.*]] = sub nsw i16 0, [[XNZ]] -; CHECK-NEXT: [[XX:%.*]] = and i16 [[XNZ]], [[X_NEG]] -; CHECK-NEXT: [[AND:%.*]] = and i16 [[XX]], [[Y]] -; CHECK-NEXT: [[R:%.*]] = icmp eq i16 [[AND]], [[XX]] +; CHECK-NEXT: [[TMP1:%.*]] = and i16 [[X_NEG]], [[Y]] +; CHECK-NEXT: [[AND:%.*]] = and i16 [[TMP1]], [[XNZ]] +; CHECK-NEXT: [[R:%.*]] = icmp ne i16 [[AND]], 0 ; CHECK-NEXT: ret i1 [[R]] ; %xnz = or i16 %x, 4 diff --git a/llvm/test/Transforms/InstSimplify/ctpop-pow2.ll b/llvm/test/Transforms/InstSimplify/ctpop-pow2.ll --- a/llvm/test/Transforms/InstSimplify/ctpop-pow2.ll +++ b/llvm/test/Transforms/InstSimplify/ctpop-pow2.ll @@ -41,10 +41,7 @@ define i8 @ctpop_x_nz_and_negx(i8 %x) { ; CHECK-LABEL: @ctpop_x_nz_and_negx( -; CHECK-NEXT: [[X1:%.*]] = or i8 [[X:%.*]], 1 -; CHECK-NEXT: [[V0:%.*]] = sub i8 0, [[X1]] -; CHECK-NEXT: [[V1:%.*]] = and i8 [[X1]], [[V0]] -; CHECK-NEXT: ret i8 [[V1]] +; CHECK-NEXT: ret i8 1 ; %x1 = or i8 %x, 1 %v0 = sub i8 0, %x1 @@ -78,10 +75,7 @@ define i32 @ctpop_2_shl_nz(i32 %x) { ; CHECK-LABEL: @ctpop_2_shl_nz( -; CHECK-NEXT: [[XA30:%.*]] = and i32 30, [[X:%.*]] -; CHECK-NEXT: [[V:%.*]] = shl i32 2, [[XA30]] -; CHECK-NEXT: [[CNT:%.*]] = call i32 @llvm.ctpop.i32(i32 [[V]]) -; CHECK-NEXT: ret i32 [[CNT]] +; CHECK-NEXT: ret i32 1 ; %xa30 = and i32 30, %x %v = shl i32 2, %xa30 @@ -179,10 +173,7 @@ define <2 x i32> @ctpop_shl2_1_vec_nz(<2 x i32> %x) { ; CHECK-LABEL: @ctpop_shl2_1_vec_nz( -; CHECK-NEXT: [[AND:%.*]] = and <2 x i32> [[X:%.*]], -; CHECK-NEXT: [[SHL:%.*]] = shl <2 x i32> , [[AND]] -; CHECK-NEXT: [[CNT:%.*]] = call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> [[SHL]]) -; CHECK-NEXT: ret <2 x i32> [[CNT]] +; CHECK-NEXT: ret <2 x i32> ; %and = and <2 x i32> %x, %shl = shl <2 x i32> , %and