diff --git a/llvm/include/llvm/Analysis/ValueTracking.h b/llvm/include/llvm/Analysis/ValueTracking.h index 67f9f24c3b7a4..cdd8471673c94 100644 --- a/llvm/include/llvm/Analysis/ValueTracking.h +++ b/llvm/include/llvm/Analysis/ValueTracking.h @@ -1268,7 +1268,8 @@ std::optional isImpliedByDomCondition(CmpPredicate Pred, const Value *LHS, /// affected by the condition \p Cond. Used by AssumptionCache and /// DomConditionCache. void findValuesAffectedByCondition(Value *Cond, bool IsAssume, - function_ref InsertAffected); + function_ref InsertAffected, + bool EphemeralOnly = false); } // end namespace llvm diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index e3e026f7979da..a4ad31ad70ea9 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -473,7 +473,17 @@ static bool isEphemeralValueOf(const Instruction *I, const Value *E) { } } - return false; + auto *Assume = dyn_cast(I); + if (!Assume) + return false; + + SmallVector Affected; + auto InsertAffected = [&Affected](Value *V) { Affected.push_back(V); }; + + findValuesAffectedByCondition(Assume->getArgOperand(0), /*IsAssume=*/true, + InsertAffected, /*EphemeralOnly=*/true); + + return is_contained(Affected, E); } // Is this an intrinsic that cannot be speculated but also cannot trap? @@ -10200,35 +10210,39 @@ ConstantRange llvm::computeConstantRange(const Value *V, bool ForSigned, } static void -addValueAffectedByCondition(Value *V, +addValueAffectedByCondition(Value *V, bool EphemeralOnly, bool Ephemeral, function_ref InsertAffected) { assert(V != nullptr); - if (isa(V) || isa(V)) { + if (!EphemeralOnly && (isa(V) || isa(V))) { InsertAffected(V); } else if (auto *I = dyn_cast(V)) { - InsertAffected(V); - // Peek through unary operators to find the source of the condition. Value *Op; if (match(I, m_CombineOr(m_PtrToInt(m_Value(Op)), m_Trunc(m_Value(Op))))) { - if (isa(Op) || isa(Op)) + Ephemeral = true; + if (!EphemeralOnly && (isa(Op) || isa(Op))) InsertAffected(Op); } + if (Ephemeral || !EphemeralOnly) + InsertAffected(V); } } void llvm::findValuesAffectedByCondition( - Value *Cond, bool IsAssume, function_ref InsertAffected) { - auto AddAffected = [&InsertAffected](Value *V) { - addValueAffectedByCondition(V, InsertAffected); + Value *Cond, bool IsAssume, function_ref InsertAffected, + bool EphemeralOnly) { + auto AddAffected = [&InsertAffected, EphemeralOnly](Value *V, + bool Ephemeral) { + addValueAffectedByCondition(V, EphemeralOnly, Ephemeral, InsertAffected); }; - auto AddCmpOperands = [&AddAffected, IsAssume](Value *LHS, Value *RHS) { + auto AddCmpOperands = [&AddAffected, IsAssume](Value *LHS, Value *RHS, + bool EphemeralLhs) { if (IsAssume) { - AddAffected(LHS); - AddAffected(RHS); + AddAffected(LHS, EphemeralLhs); + AddAffected(RHS, /*Ephemeral=*/false); } else if (match(RHS, m_Constant())) - AddAffected(LHS); + AddAffected(LHS, EphemeralLhs); }; SmallVector Worklist; @@ -10241,11 +10255,12 @@ void llvm::findValuesAffectedByCondition( CmpPredicate Pred; Value *A, *B, *X; + bool EphemeralA = false; if (IsAssume) { - AddAffected(V); + AddAffected(V, /*Ephemeral=*/true); if (match(V, m_Not(m_Value(X)))) - AddAffected(X); + AddAffected(X, /*Ephemeral=*/true); } if (match(V, m_LogicalOp(m_Value(A), m_Value(B)))) { @@ -10260,28 +10275,36 @@ void llvm::findValuesAffectedByCondition( } } else if (match(V, m_ICmp(Pred, m_Value(A), m_Value(B)))) { bool HasRHSC = match(B, m_ConstantInt()); + if (HasRHSC && match(A, m_Intrinsic(m_Value(X)))) { + AddAffected(X, /*Ephemeral=*/false); + EphemeralA = true; + } + if (ICmpInst::isEquality(Pred)) { - AddAffected(A); - AddAffected(B); if (HasRHSC) { Value *Y; // (X & C) or (X | C). // (X << C) or (X >>_s C) or (X >>_u C). - if (match(A, m_Shift(m_Value(X), m_ConstantInt()))) - AddAffected(X); - else if (match(A, m_And(m_Value(X), m_Value(Y))) || - match(A, m_Or(m_Value(X), m_Value(Y)))) { - AddAffected(X); - AddAffected(Y); + if (match(A, m_Shift(m_Value(X), m_ConstantInt()))) { + AddAffected(X, /*Ephemeral=*/false); + EphemeralA = true; + } else if (match(A, m_And(m_Value(X), m_Value(Y))) || + match(A, m_Or(m_Value(X), m_Value(Y)))) { + AddAffected(X, /*Ephemeral=*/false); + AddAffected(Y, /*Ephemeral=*/false); + EphemeralA = true; } } + AddAffected(A, EphemeralA); + AddAffected(B, /*Ephemeral=*/false); } else { - AddCmpOperands(A, B); if (HasRHSC) { // Handle (A + C1) u< C2, which is the canonical form of // A > C3 && A < C4. - if (match(A, m_AddLike(m_Value(X), m_ConstantInt()))) - AddAffected(X); + if (match(A, m_AddLike(m_Value(X), m_ConstantInt()))) { + AddAffected(X, /*Ephemeral=*/false); + EphemeralA = true; + } if (ICmpInst::isUnsigned(Pred)) { Value *Y; @@ -10291,46 +10314,51 @@ void llvm::findValuesAffectedByCondition( if (match(A, m_And(m_Value(X), m_Value(Y))) || match(A, m_Or(m_Value(X), m_Value(Y))) || match(A, m_NUWAdd(m_Value(X), m_Value(Y)))) { - AddAffected(X); - AddAffected(Y); + AddAffected(X, /*Ephemeral=*/false); + AddAffected(Y, /*Ephemeral=*/false); } // X nuw- Y u> C -> X u> C if (match(A, m_NUWSub(m_Value(X), m_Value()))) - AddAffected(X); + AddAffected(X, /*Ephemeral=*/false); } } // Handle icmp slt/sgt (bitcast X to int), 0/-1, which is supported // by computeKnownFPClass(). if (match(A, m_ElementWiseBitCast(m_Value(X)))) { - if (Pred == ICmpInst::ICMP_SLT && match(B, m_Zero())) + if (Pred == ICmpInst::ICMP_SLT && match(B, m_Zero())) { InsertAffected(X); - else if (Pred == ICmpInst::ICMP_SGT && match(B, m_AllOnes())) + EphemeralA = true; + } else if (Pred == ICmpInst::ICMP_SGT && match(B, m_AllOnes())) { InsertAffected(X); + EphemeralA = true; + } } - } - if (HasRHSC && match(A, m_Intrinsic(m_Value(X)))) - AddAffected(X); + AddCmpOperands(A, B, EphemeralA); + } } else if (match(V, m_FCmp(Pred, m_Value(A), m_Value(B)))) { - AddCmpOperands(A, B); - // fcmp fneg(x), y // fcmp fabs(x), y // fcmp fneg(fabs(x)), y - if (match(A, m_FNeg(m_Value(A)))) - AddAffected(A); - if (match(A, m_FAbs(m_Value(A)))) - AddAffected(A); + if (match(A, m_FNeg(m_Value(X)))) { + AddAffected(X, /*Ephemeral=*/false); + EphemeralA = true; + } + if (match(A, m_FAbs(m_Value(X)))) { + AddAffected(X, /*Ephemeral=*/false); + EphemeralA = true; + } + AddCmpOperands(A, B, EphemeralA); } else if (match(V, m_Intrinsic(m_Value(A), m_Value()))) { // Handle patterns that computeKnownFPClass() support. - AddAffected(A); + AddAffected(A, /*Ephemeral=*/false); } else if (!IsAssume && match(V, m_Trunc(m_Value(X)))) { // Assume is checked here as X is already added above for assumes in // addValueAffectedByCondition - AddAffected(X); + AddAffected(X, /*Ephemeral=*/false); } else if (!IsAssume && match(V, m_Not(m_Value(X)))) { // Assume is checked here to avoid issues with ephemeral values Worklist.push_back(X); diff --git a/llvm/test/Analysis/ValueTracking/numsignbits-from-assume.ll b/llvm/test/Analysis/ValueTracking/numsignbits-from-assume.ll index 5beb0c7cadfba..835d768e6ad6c 100644 --- a/llvm/test/Analysis/ValueTracking/numsignbits-from-assume.ll +++ b/llvm/test/Analysis/ValueTracking/numsignbits-from-assume.ll @@ -48,7 +48,7 @@ define i32 @computeNumSignBits_sub1(i32 %in) { define i32 @computeNumSignBits_sub2(i32 %in) { ; CHECK-LABEL: @computeNumSignBits_sub2( -; CHECK-NEXT: [[SUB:%.*]] = add nsw i32 [[IN:%.*]], -1 +; CHECK-NEXT: [[SUB:%.*]] = add i32 [[IN:%.*]], -1 ; CHECK-NEXT: [[COND:%.*]] = icmp ult i32 [[SUB]], 43 ; CHECK-NEXT: call void @llvm.assume(i1 [[COND]]) ; CHECK-NEXT: [[SH:%.*]] = shl nuw nsw i32 [[SUB]], 3 diff --git a/llvm/test/Transforms/CorrelatedValuePropagation/add.ll b/llvm/test/Transforms/CorrelatedValuePropagation/add.ll index b1151cdf26ffd..16f9136001d16 100644 --- a/llvm/test/Transforms/CorrelatedValuePropagation/add.ll +++ b/llvm/test/Transforms/CorrelatedValuePropagation/add.ll @@ -562,6 +562,20 @@ join: ret i32 %add } +define i32 @issue90206(i32 noundef %x) { +; CHECK-LABEL: define range(i32 0, -2147483648) i32 @issue90206( +; CHECK-SAME: i32 noundef [[X:%.*]]) { +; CHECK-NEXT: [[R:%.*]] = add i32 [[X]], -1 +; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[R]], -1 +; CHECK-NEXT: tail call void @llvm.assume(i1 [[TMP1]]) +; CHECK-NEXT: ret i32 [[R]] +; + %r = add i32 %x, -1 + %17 = icmp sgt i32 %r, -1 + tail call void @llvm.assume(i1 %17) + ret i32 %r +} + ;. ; CHECK: [[RNG0]] = !{i32 0, i32 2147483647} ;. diff --git a/llvm/test/Transforms/InstCombine/zext-or-icmp.ll b/llvm/test/Transforms/InstCombine/zext-or-icmp.ll index feb4be9e37050..3f16528f1b211 100644 --- a/llvm/test/Transforms/InstCombine/zext-or-icmp.ll +++ b/llvm/test/Transforms/InstCombine/zext-or-icmp.ll @@ -180,11 +180,11 @@ define i8 @PR49475_infloop(i32 %t0, i16 %insert, i64 %e, i8 %i162) "instcombine- ; CHECK-NEXT: [[SEXT:%.*]] = shl i64 [[SUB17]], 32 ; CHECK-NEXT: [[CONV18:%.*]] = ashr exact i64 [[SEXT]], 32 ; CHECK-NEXT: [[CMP:%.*]] = icmp sge i64 [[XOR]], [[CONV18]] -; CHECK-NEXT: [[TRUNC44:%.*]] = zext i1 [[CMP]] to i8 -; CHECK-NEXT: [[INC:%.*]] = add i8 [[I162]], [[TRUNC44]] -; CHECK-NEXT: [[TOBOOL23_NOT:%.*]] = xor i1 [[CMP]], true +; CHECK-NEXT: [[CONV19:%.*]] = zext i1 [[CMP]] to i16 +; CHECK-NEXT: [[OR21:%.*]] = or i16 [[INSERT]], [[CONV19]] +; CHECK-NEXT: [[TOBOOL23_NOT:%.*]] = icmp eq i16 [[OR21]], 0 ; CHECK-NEXT: call void @llvm.assume(i1 [[TOBOOL23_NOT]]) -; CHECK-NEXT: ret i8 [[INC]] +; CHECK-NEXT: ret i8 [[I162]] ; %b = icmp eq i32 %t0, 0 %b2 = icmp eq i16 %insert, 0 diff --git a/llvm/test/Transforms/InstSimplify/ctpop-pow2.ll b/llvm/test/Transforms/InstSimplify/ctpop-pow2.ll index 92e43654806a4..111ac26876083 100644 --- a/llvm/test/Transforms/InstSimplify/ctpop-pow2.ll +++ b/llvm/test/Transforms/InstSimplify/ctpop-pow2.ll @@ -148,6 +148,21 @@ define <2 x i32> @ctpop_lshr_intmin_vec(<2 x i32> %x) { ret <2 x i32> %cnt } +define i1 @issue128152(i32 %x) { +; CHECK-LABEL: @issue128152( +; CHECK-NEXT: [[CTPOP:%.*]] = call i32 @llvm.ctpop.i32(i32 [[X:%.*]]) +; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[CTPOP]], 1 +; CHECK-NEXT: call void @llvm.assume(i1 [[COND]]) +; CHECK-NEXT: [[RES:%.*]] = icmp eq i32 [[X]], 0 +; CHECK-NEXT: ret i1 [[RES]] +; + %ctpop = call i32 @llvm.ctpop.i32(i32 %x) + %cond = icmp eq i32 %ctpop, 1 + %ext = zext i1 %cond to i8 + call void @llvm.assume(i1 %cond) + %res = icmp eq i32 %x, 0 + ret i1 %res +} define <2 x i32> @ctpop_lshr_intmin_intmin_plus1_vec(<2 x i32> %x) { ; CHECK-LABEL: @ctpop_lshr_intmin_intmin_plus1_vec(