diff --git a/llvm/lib/Analysis/AssumptionCache.cpp b/llvm/lib/Analysis/AssumptionCache.cpp --- a/llvm/lib/Analysis/AssumptionCache.cpp +++ b/llvm/lib/Analysis/AssumptionCache.cpp @@ -105,7 +105,7 @@ if (match(V, m_BitwiseLogic(m_Value(A), m_Value(B)))) { AddAffected(A); AddAffected(B); - // (A << C) or (A >>_s C) or (A >>_u C) where C is some constant. + // (A << C) or (A >>_s C) or (A >>_u C) where C is some constant. } else if (match(V, m_Shift(m_Value(A), m_ConstantInt()))) { AddAffected(A); } @@ -113,15 +113,22 @@ AddAffectedFromEq(A); AddAffectedFromEq(B); + } else if (Pred == ICmpInst::ICMP_NE) { + Value *X, *Y; + // Handle (a & b != 0). If a/b is a power of 2 we can use this + // information. + if (match(A, m_And(m_Value(X), m_Value(Y))) && match(B, m_Zero())) { + AddAffected(X); + AddAffected(Y); + } + } else if (Pred == ICmpInst::ICMP_ULT) { + Value *X; + // Handle (A + C1) u< C2, which is the canonical form of A > C3 && A < C4, + // and recognized by LVI at least. + if (match(A, m_Add(m_Value(X), m_ConstantInt())) && + match(B, m_ConstantInt())) + AddAffected(X); } - - Value *X; - // Handle (A + C1) u< C2, which is the canonical form of A > C3 && A < C4, - // and recognized by LVI at least. - if (Pred == ICmpInst::ICMP_ULT && - match(A, m_Add(m_Value(X), m_ConstantInt())) && - match(B, m_ConstantInt())) - AddAffected(X); } if (TTI) { 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 @@ -940,6 +940,14 @@ Known.Zero.setHighBits(RHSKnown.countMinLeadingZeros()); } break; + case ICmpInst::ICMP_NE: { + // assume (v & b != 0) where b is a power of 2 + const APInt *BPow2; + if (match(Cmp, m_ICmp(Pred, m_c_And(m_V, m_Power2(BPow2)), m_Zero())) && + isValidAssumeForContext(I, Q.CxtI, Q.DT)) { + Known.One |= BPow2->zextOrTrunc(BitWidth); + } + } break; } } diff --git a/llvm/test/Transforms/InstCombine/icmp-ne-pow2.ll b/llvm/test/Transforms/InstCombine/icmp-ne-pow2.ll --- a/llvm/test/Transforms/InstCombine/icmp-ne-pow2.ll +++ b/llvm/test/Transforms/InstCombine/icmp-ne-pow2.ll @@ -9,8 +9,7 @@ ; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 4 ; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[AND]], 0 ; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]]) -; CHECK-NEXT: [[AND2:%.*]] = and i32 [[X]], 4 -; CHECK-NEXT: ret i32 [[AND2]] +; CHECK-NEXT: ret i32 4 ; %and = and i32 %x, 4 %cmp = icmp ne i32 %and, 0 @@ -39,8 +38,7 @@ ; CHECK-NEXT: [[AND:%.*]] = and i64 [[X:%.*]], 1 ; CHECK-NEXT: [[CMP:%.*]] = icmp ne i64 [[AND]], 0 ; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]]) -; CHECK-NEXT: [[OR:%.*]] = or i64 [[X]], 1 -; CHECK-NEXT: ret i64 [[OR]] +; CHECK-NEXT: ret i64 [[X]] ; %and = and i64 %x, 1 %cmp = icmp ne i64 %and, 0 @@ -69,8 +67,7 @@ ; CHECK-NEXT: [[AND:%.*]] = and i16 [[X:%.*]], 16384 ; CHECK-NEXT: [[CMP:%.*]] = icmp ne i16 [[AND]], 0 ; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]]) -; CHECK-NEXT: [[AND2:%.*]] = and i16 [[X]], 16384 -; CHECK-NEXT: ret i16 [[AND2]] +; CHECK-NEXT: ret i16 16384 ; %and = and i16 %x, 16384 %cmp = icmp eq i16 %and, 16384