diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -4812,21 +4812,22 @@ Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); const CmpInst::Predicate Pred = I.getPredicate(); Value *A = nullptr; - // (A & (A-1)) == 0 --> ctpop(A) < 2 (two commuted variants) - // ((A-1) & A) != 0 --> ctpop(A) > 1 (two commuted variants) - if (!match(Op0, m_OneUse(m_c_And(m_Add(m_Value(A), m_AllOnes()), - m_Deferred(A)))) || - !match(Op1, m_ZeroInt())) - A = nullptr; - - // (A & -A) == A --> ctpop(A) < 2 (four commuted variants) - // (-A & A) != A --> ctpop(A) > 1 (four commuted variants) - if (match(Op0, m_OneUse(m_c_And(m_Neg(m_Specific(Op1)), m_Specific(Op1))))) - A = Op1; - else if (match(Op1, - m_OneUse(m_c_And(m_Neg(m_Specific(Op0)), m_Specific(Op0))))) - A = Op0; - + if (I.isEquality()) { + // (A & (A-1)) == 0 --> ctpop(A) < 2 (two commuted variants) + // ((A-1) & A) != 0 --> ctpop(A) > 1 (two commuted variants) + if (!match(Op0, m_OneUse(m_c_And(m_Add(m_Value(A), m_AllOnes()), + m_Deferred(A)))) || + !match(Op1, m_ZeroInt())) + A = nullptr; + + // (A & -A) == A --> ctpop(A) < 2 (four commuted variants) + // (-A & A) != A --> ctpop(A) > 1 (four commuted variants) + if (match(Op0, m_OneUse(m_c_And(m_Neg(m_Specific(Op1)), m_Specific(Op1))))) + A = Op1; + else if (match(Op1, + m_OneUse(m_c_And(m_Neg(m_Specific(Op0)), m_Specific(Op0))))) + A = Op0; + } if (A) { Type *Ty = A->getType(); CallInst *CtPop = Builder.CreateUnaryIntrinsic(Intrinsic::ctpop, A); diff --git a/llvm/test/Transforms/InstCombine/ispow2.ll b/llvm/test/Transforms/InstCombine/ispow2.ll --- a/llvm/test/Transforms/InstCombine/ispow2.ll +++ b/llvm/test/Transforms/InstCombine/ispow2.ll @@ -1140,3 +1140,16 @@ %r = or <2 x i1> %cmp, %notzero ret <2 x i1> %r } + +define i1 @is_pow2_fail_pr63327(i32 %x) { +; CHECK-LABEL: @is_pow2_fail_pr63327( +; CHECK-NEXT: [[NX:%.*]] = sub i32 0, [[X:%.*]] +; CHECK-NEXT: [[X_AND_NX:%.*]] = and i32 [[NX]], [[X]] +; CHECK-NEXT: [[R:%.*]] = icmp sge i32 [[X_AND_NX]], [[X]] +; CHECK-NEXT: ret i1 [[R]] +; + %nx = sub i32 0, %x + %x_and_nx = and i32 %x, %nx + %r = icmp sge i32 %x_and_nx, %x + ret i1 %r +}