Skip to content

Commit

Permalink
[ValueTracking] Consider single poison operands in propgatesPoison.
Browse files Browse the repository at this point in the history
This patch updates propgatesPoison to take a Use as argument and
propagatesPoison now returns true if the passed in operand causes the
user to yield poison if the operand is poison

This allows propagating poison if the condition of a select is poison.
This helps improve results for programUndefinedIfUndefOrPoison.

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D111643
  • Loading branch information
fhahn committed Dec 19, 2022
1 parent 6022873 commit 8a3efcd
Show file tree
Hide file tree
Showing 10 changed files with 141 additions and 113 deletions.
16 changes: 9 additions & 7 deletions llvm/include/llvm/Analysis/ValueTracking.h
Original file line number Diff line number Diff line change
Expand Up @@ -603,20 +603,22 @@ bool isGuaranteedToTransferExecutionToSuccessor(
bool isGuaranteedToExecuteForEveryIteration(const Instruction *I,
const Loop *L);

/// Return true if I yields poison or raises UB if any of its operands is
/// poison.
/// Formally, given I = `r = op v1 v2 .. vN`, propagatesPoison returns true
/// if, for all i, r is evaluated to poison or op raises UB if vi = poison.
/// If vi is a vector or an aggregate and r is a single value, any poison
/// element in vi should make r poison or raise UB.
/// Return true if \p PoisonOp's user yields poison or raises UB if its
/// operand \p PoisonOp is poison.
///
/// If \p PoisonOp is a vector or an aggregate and the operation's result is a
/// single value, any poison element in /p PoisonOp should make the result
/// poison or raise UB.
///
/// To filter out operands that raise UB on poison, you can use
/// getGuaranteedNonPoisonOp.
bool propagatesPoison(const Operator *I);
bool propagatesPoison(const Use &PoisonOp);

/// Insert operands of I into Ops such that I will trigger undefined behavior
/// if I is executed and that operand has a poison value.
void getGuaranteedNonPoisonOps(const Instruction *I,
SmallPtrSetImpl<const Value *> &Ops);

/// Insert operands of I into Ops such that I will trigger undefined behavior
/// if I is executed and that operand is not a well-defined value
/// (i.e. has undef bits or poison).
Expand Down
5 changes: 3 additions & 2 deletions llvm/lib/Analysis/ScalarEvolution.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7294,8 +7294,9 @@ bool ScalarEvolution::isAddRecNeverPoison(const Instruction *I, const Loop *L) {
while (!PoisonStack.empty() && !LatchControlDependentOnPoison) {
const Instruction *Poison = PoisonStack.pop_back_val();

for (const auto *PoisonUser : Poison->users()) {
if (propagatesPoison(cast<Operator>(PoisonUser))) {
for (const Use &U : Poison->uses()) {
const User *PoisonUser = U.getUser();
if (propagatesPoison(U)) {
if (Pushed.insert(cast<Instruction>(PoisonUser)).second)
PoisonStack.push_back(cast<Instruction>(PoisonUser));
} else if (auto *BI = dyn_cast<BranchInst>(PoisonUser)) {
Expand Down
35 changes: 16 additions & 19 deletions llvm/lib/Analysis/ValueTracking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5330,15 +5330,12 @@ static bool directlyImpliesPoison(const Value *ValAssumedPoison,
return false;

if (const auto *I = dyn_cast<Instruction>(V)) {
if (propagatesPoison(cast<Operator>(I)))
return any_of(I->operands(), [=](const Value *Op) {
return directlyImpliesPoison(ValAssumedPoison, Op, Depth + 1);
});
if (any_of(I->operands(), [=](const Use &Op) {
return propagatesPoison(Op) &&
directlyImpliesPoison(ValAssumedPoison, Op, Depth + 1);
}))
return true;

// 'select ValAssumedPoison, _, _' is poison.
if (const auto *SI = dyn_cast<SelectInst>(I))
return directlyImpliesPoison(ValAssumedPoison, SI->getCondition(),
Depth + 1);
// V = extractvalue V0, idx
// V2 = extractvalue V0, idx2
// V0's elements are all poison or not. (e.g., add_with_overflow)
Expand Down Expand Up @@ -5496,7 +5493,8 @@ static bool isGuaranteedNotToBeUndefOrPoison(const Value *V,
else if (PoisonOnly && isa<Operator>(Cond)) {
// For poison, we can analyze further
auto *Opr = cast<Operator>(Cond);
if (propagatesPoison(Opr) && is_contained(Opr->operand_values(), V))
if (any_of(Opr->operands(),
[V](const Use &U) { return V == U && propagatesPoison(U); }))
return true;
}
}
Expand Down Expand Up @@ -5618,13 +5616,15 @@ bool llvm::isGuaranteedToExecuteForEveryIteration(const Instruction *I,
llvm_unreachable("Instruction not contained in its own parent basic block.");
}

bool llvm::propagatesPoison(const Operator *I) {
bool llvm::propagatesPoison(const Use &PoisonOp) {
const Operator *I = cast<Operator>(PoisonOp.getUser());
switch (I->getOpcode()) {
case Instruction::Freeze:
case Instruction::Select:
case Instruction::PHI:
case Instruction::Invoke:
return false;
case Instruction::Select:
return PoisonOp.getOperandNo() == 0;
case Instruction::Call:
if (auto *II = dyn_cast<IntrinsicInst>(I)) {
switch (II->getIntrinsicID()) {
Expand Down Expand Up @@ -5805,14 +5805,11 @@ static bool programUndefinedIfUndefOrPoison(const Value *V,
if (!isGuaranteedToTransferExecutionToSuccessor(&I))
return false;

// If this instruction propagates poison, mark it as poison if any of
// its operands are poison
if (propagatesPoison(cast<Operator>(&I))) {
for (const Value *Op : I.operands()) {
if (YieldsPoison.count(Op)) {
YieldsPoison.insert(&I);
break;
}
// If an operand is poison and propagates it, mark I as yielding poison.
for (const Use &Op : I.operands()) {
if (YieldsPoison.count(Op) && propagatesPoison(Op)) {
YieldsPoison.insert(&I);
break;
}
}
}
Expand Down
7 changes: 4 additions & 3 deletions llvm/lib/Transforms/Instrumentation/PoisonChecking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -289,9 +289,10 @@ static bool rewrite(Function &F) {
}

SmallVector<Value*, 4> Checks;
if (propagatesPoison(cast<Operator>(&I)))
for (Value *V : I.operands())
Checks.push_back(getPoisonFor(ValToPoison, V));
for (const Use &U : I.operands()) {
if (ValToPoison.count(U) && propagatesPoison(U))
Checks.push_back(getPoisonFor(ValToPoison, U));
}

if (canCreatePoison(cast<Operator>(&I)))
generateCreationChecks(I, Checks);
Expand Down
4 changes: 3 additions & 1 deletion llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -788,7 +788,9 @@ static bool mustExecuteUBIfPoisonOnPathTo(Instruction *Root,

// If we can't analyze propagation through this instruction, just skip it
// and transitive users. Safe as false is a conservative result.
if (!propagatesPoison(cast<Operator>(I)) && I != Root)
if (I != Root && !any_of(I->operands(), [&KnownPoison](const Use &U) {
return KnownPoison.contains(U) && propagatesPoison(U);
}))
continue;

if (KnownPoison.insert(I).second)
Expand Down
36 changes: 18 additions & 18 deletions llvm/test/Analysis/ScalarEvolution/exit-count-select-safe.ll
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,9 @@ define i32 @logical_or_3ops_duplicate(i32 %n, i32 %m, i32 %k) {
; CHECK-NEXT: %cond_p4 = select i1 %cond_p0, i1 true, i1 %cond_p1
; CHECK-NEXT: --> (true + ((true + %cond_p0) umin_seq (true + %cond_p1))) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
; CHECK-NEXT: %cond_p5 = select i1 %cond_p4, i1 true, i1 %cond_p2
; CHECK-NEXT: --> (true + ((true + %cond_p0) umin_seq (true + %cond_p1) umin_seq (true + %cond_p2))) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
; CHECK-NEXT: --> (true + ((true + %cond_p0) umin_seq ((true + %cond_p1) umin (true + %cond_p2)))) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
; CHECK-NEXT: %cond = select i1 %cond_p5, i1 true, i1 %cond_p3
; CHECK-NEXT: --> (true + ((true + %cond_p0) umin_seq (true + %cond_p1) umin_seq (true + %cond_p2) umin_seq (true + %cond_p3))) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
; CHECK-NEXT: --> (true + ((true + %cond_p0) umin_seq ((true + %cond_p1) umin (true + %cond_p2)) umin_seq (true + %cond_p3))) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
; CHECK-NEXT: Determining loop execution counts for: @logical_or_3ops_duplicate
; CHECK-NEXT: Loop %loop: backedge-taken count is (%n umin_seq %m umin_seq %k)
; CHECK-NEXT: Loop %loop: constant max backedge-taken count is -1
Expand Down Expand Up @@ -432,7 +432,7 @@ define i32 @logical_and_2ops_and_constant(i32 %n, i32 %m, i32 %k) {
; CHECK-NEXT: %umin = call i32 @llvm.umin.i32(i32 %n, i32 42)
; CHECK-NEXT: --> (42 umin %n) U: [0,43) S: [0,43) Exits: (42 umin %n) LoopDispositions: { %loop: Invariant }
; CHECK-NEXT: %cond = select i1 %cond_p1, i1 true, i1 %cond_p0
; CHECK-NEXT: --> (true + ((true + %cond_p1) umin_seq (true + %cond_p0))) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
; CHECK-NEXT: --> (true + ((true + %cond_p1) umin (true + %cond_p0))) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
; CHECK-NEXT: Determining loop execution counts for: @logical_and_2ops_and_constant
; CHECK-NEXT: Loop %loop: backedge-taken count is (42 umin %n)
; CHECK-NEXT: Loop %loop: constant max backedge-taken count is 42
Expand Down Expand Up @@ -574,7 +574,7 @@ define i32 @logical_and_implies_poison1(i32 %n) {
; CHECK-NEXT: %i.next = add i32 %i, 1
; CHECK-NEXT: --> {1,+,1}<%loop> U: full-set S: full-set Exits: (1 + ((1 + %n) umin %n)) LoopDispositions: { %loop: Computable }
; CHECK-NEXT: %cond = select i1 %cond_p0, i1 %cond_p1, i1 false
; CHECK-NEXT: --> (%cond_p0 umin_seq %cond_p1) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
; CHECK-NEXT: --> (%cond_p0 umin %cond_p1) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
; CHECK-NEXT: Determining loop execution counts for: @logical_and_implies_poison1
; CHECK-NEXT: Loop %loop: backedge-taken count is ((1 + %n) umin %n)
; CHECK-NEXT: Loop %loop: constant max backedge-taken count is -1
Expand Down Expand Up @@ -607,7 +607,7 @@ define i32 @logical_and_implies_poison2(i32 %n) {
; CHECK-NEXT: %i.next = add i32 %i, 1
; CHECK-NEXT: --> {1,+,1}<%loop> U: full-set S: full-set Exits: (1 + ((1 + %n) umin %n)) LoopDispositions: { %loop: Computable }
; CHECK-NEXT: %cond = select i1 %cond_p0, i1 %cond_p1, i1 false
; CHECK-NEXT: --> (%cond_p0 umin_seq %cond_p1) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
; CHECK-NEXT: --> (%cond_p1 umin %cond_p0) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
; CHECK-NEXT: Determining loop execution counts for: @logical_and_implies_poison2
; CHECK-NEXT: Loop %loop: backedge-taken count is ((1 + %n) umin %n)
; CHECK-NEXT: Loop %loop: constant max backedge-taken count is -1
Expand Down Expand Up @@ -640,7 +640,7 @@ define i32 @logical_and_implies_poison3(i32 %n, i32 %m) {
; CHECK-NEXT: %i.next = add i32 %i, 1
; CHECK-NEXT: --> {1,+,1}<%loop> U: full-set S: full-set Exits: (1 + ((%n + %m) umin %n)) LoopDispositions: { %loop: Computable }
; CHECK-NEXT: %cond = select i1 %cond_p0, i1 %cond_p1, i1 false
; CHECK-NEXT: --> (%cond_p0 umin_seq %cond_p1) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
; CHECK-NEXT: --> (%cond_p1 umin %cond_p0) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
; CHECK-NEXT: Determining loop execution counts for: @logical_and_implies_poison3
; CHECK-NEXT: Loop %loop: backedge-taken count is ((%n + %m) umin %n)
; CHECK-NEXT: Loop %loop: constant max backedge-taken count is -1
Expand Down Expand Up @@ -704,7 +704,7 @@ define i32 @logical_and_implies_poison_noundef(i32 %n, i32 noundef %m) {
; CHECK-NEXT: %i.next = add i32 %i, 1
; CHECK-NEXT: --> {1,+,1}<%loop> U: full-set S: full-set Exits: (1 + (%n umin %m)) LoopDispositions: { %loop: Computable }
; CHECK-NEXT: %cond = select i1 %cond_p0, i1 %cond_p1, i1 false
; CHECK-NEXT: --> (%cond_p0 umin_seq %cond_p1) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
; CHECK-NEXT: --> (%cond_p0 umin %cond_p1) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
; CHECK-NEXT: Determining loop execution counts for: @logical_and_implies_poison_noundef
; CHECK-NEXT: Loop %loop: backedge-taken count is (%n umin %m)
; CHECK-NEXT: Loop %loop: constant max backedge-taken count is -1
Expand Down Expand Up @@ -768,7 +768,7 @@ define i32 @logical_and_implies_poison_complex1(i32 %n, i32 %m) {
; CHECK-NEXT: %i.next = add i32 %i, 1
; CHECK-NEXT: --> {1,+,1}<%loop> U: full-set S: full-set Exits: (1 + ((%n + %m) umin (1 + %n + %m))) LoopDispositions: { %loop: Computable }
; CHECK-NEXT: %cond = select i1 %cond_p0, i1 %cond_p1, i1 false
; CHECK-NEXT: --> (%cond_p0 umin_seq %cond_p1) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
; CHECK-NEXT: --> (%cond_p0 umin %cond_p1) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
; CHECK-NEXT: Determining loop execution counts for: @logical_and_implies_poison_complex1
; CHECK-NEXT: Loop %loop: backedge-taken count is ((%n + %m) umin (1 + %n + %m))
; CHECK-NEXT: Loop %loop: constant max backedge-taken count is -1
Expand Down Expand Up @@ -804,7 +804,7 @@ define i32 @logical_and_implies_poison_complex2(i32 %n, i32 %m, i32 %l) {
; CHECK-NEXT: %i.next = add i32 %i, 1
; CHECK-NEXT: --> {1,+,1}<%loop> U: full-set S: full-set Exits: (1 + ((%n + %m) umin (%n + %m + %l))) LoopDispositions: { %loop: Computable }
; CHECK-NEXT: %cond = select i1 %cond_p0, i1 %cond_p1, i1 false
; CHECK-NEXT: --> (%cond_p0 umin_seq %cond_p1) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
; CHECK-NEXT: --> (%cond_p0 umin %cond_p1) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
; CHECK-NEXT: Determining loop execution counts for: @logical_and_implies_poison_complex2
; CHECK-NEXT: Loop %loop: backedge-taken count is ((%n + %m) umin (%n + %m + %l))
; CHECK-NEXT: Loop %loop: constant max backedge-taken count is -1
Expand Down Expand Up @@ -874,9 +874,9 @@ define i32 @logical_and_implies_multiple_ops(i32 %n, i32 %m) {
; CHECK-NEXT: %i.next = add i32 %i, 1
; CHECK-NEXT: --> {1,+,1}<%loop> U: full-set S: full-set Exits: (1 + (((1 + %n) umin %n) umin_seq %m)) LoopDispositions: { %loop: Computable }
; CHECK-NEXT: %cond = select i1 %cond_p0, i1 %cond_p1, i1 false
; CHECK-NEXT: --> (%cond_p0 umin_seq %cond_p1) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
; CHECK-NEXT: --> (%cond_p0 umin %cond_p1) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
; CHECK-NEXT: %cond2 = select i1 %cond, i1 %cond_p2, i1 false
; CHECK-NEXT: --> (%cond_p0 umin_seq %cond_p1 umin_seq %cond_p2) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
; CHECK-NEXT: --> ((%cond_p0 umin %cond_p1) umin_seq %cond_p2) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
; CHECK-NEXT: Determining loop execution counts for: @logical_and_implies_multiple_ops
; CHECK-NEXT: Loop %loop: backedge-taken count is (((1 + %n) umin %n) umin_seq %m)
; CHECK-NEXT: Loop %loop: constant max backedge-taken count is -1
Expand Down Expand Up @@ -907,18 +907,18 @@ define i32 @logical_and_implies_multiple_ops2(i32 %n, i32 %m) {
; CHECK-NEXT: %add = add i32 %n, 1
; CHECK-NEXT: --> (1 + %n) U: full-set S: full-set
; CHECK-NEXT: %i = phi i32 [ 0, %entry ], [ %i.next, %loop ]
; CHECK-NEXT: --> {0,+,1}<%loop> U: full-set S: full-set Exits: (%n umin_seq %m umin_seq (1 + %n)) LoopDispositions: { %loop: Computable }
; CHECK-NEXT: --> {0,+,1}<%loop> U: full-set S: full-set Exits: (%n umin_seq ((1 + %n) umin %m)) LoopDispositions: { %loop: Computable }
; CHECK-NEXT: %i.next = add i32 %i, 1
; CHECK-NEXT: --> {1,+,1}<%loop> U: full-set S: full-set Exits: (1 + (%n umin_seq %m umin_seq (1 + %n))) LoopDispositions: { %loop: Computable }
; CHECK-NEXT: --> {1,+,1}<%loop> U: full-set S: full-set Exits: (1 + (%n umin_seq ((1 + %n) umin %m))) LoopDispositions: { %loop: Computable }
; CHECK-NEXT: %cond = select i1 %cond_p0, i1 %cond_p1, i1 false
; CHECK-NEXT: --> (%cond_p0 umin_seq %cond_p1) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
; CHECK-NEXT: %cond2 = select i1 %cond, i1 %cond_p2, i1 false
; CHECK-NEXT: --> (%cond_p0 umin_seq %cond_p1 umin_seq %cond_p2) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
; CHECK-NEXT: --> (%cond_p0 umin_seq (%cond_p1 umin %cond_p2)) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
; CHECK-NEXT: Determining loop execution counts for: @logical_and_implies_multiple_ops2
; CHECK-NEXT: Loop %loop: backedge-taken count is (%n umin_seq %m umin_seq (1 + %n))
; CHECK-NEXT: Loop %loop: backedge-taken count is (%n umin_seq ((1 + %n) umin %m))
; CHECK-NEXT: Loop %loop: constant max backedge-taken count is -1
; CHECK-NEXT: Loop %loop: symbolic max backedge-taken count is (%n umin_seq %m umin_seq (1 + %n))
; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (%n umin_seq %m umin_seq (1 + %n))
; CHECK-NEXT: Loop %loop: symbolic max backedge-taken count is (%n umin_seq ((1 + %n) umin %m))
; CHECK-NEXT: Loop %loop: Predicated backedge-taken count is (%n umin_seq ((1 + %n) umin %m))
; CHECK-NEXT: Predicates:
; CHECK: Loop %loop: Trip multiple is 1
;
Expand Down Expand Up @@ -1352,7 +1352,7 @@ define i32 @logical_and_zero_arg2(i32 %n) {
; CHECK-NEXT: %i.next = add i32 %i, 1
; CHECK-NEXT: --> {1,+,1}<%loop> U: [1,2) S: [1,2) Exits: 1 LoopDispositions: { %loop: Computable }
; CHECK-NEXT: %cond = select i1 %cond_p0, i1 %cond_p1, i1 false
; CHECK-NEXT: --> (%cond_p0 umin_seq %cond_p1) U: full-set S: full-set Exits: false LoopDispositions: { %loop: Variant }
; CHECK-NEXT: --> (%cond_p1 umin %cond_p0) U: full-set S: full-set Exits: false LoopDispositions: { %loop: Variant }
; CHECK-NEXT: Determining loop execution counts for: @logical_and_zero_arg2
; CHECK-NEXT: Loop %loop: backedge-taken count is 0
; CHECK-NEXT: Loop %loop: constant max backedge-taken count is 0
Expand Down
4 changes: 2 additions & 2 deletions llvm/test/Analysis/ScalarEvolution/exit-count-select.ll
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ define void @logical_and_m_const(i32 %n) {
; CHECK-NEXT: %i.next = add i32 %i, 1
; CHECK-NEXT: --> {1,+,1}<%loop> U: [1,4) S: [1,4) Exits: (1 + (2 umin %n))<nuw><nsw> LoopDispositions: { %loop: Computable }
; CHECK-NEXT: %cond = select i1 %cond_i, i1 %cond_i2, i1 false
; CHECK-NEXT: --> (%cond_i umin_seq %cond_i2) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
; CHECK-NEXT: --> (%cond_i2 umin %cond_i) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
; CHECK-NEXT: Determining loop execution counts for: @logical_and_m_const
; CHECK-NEXT: Loop %loop: backedge-taken count is (2 umin %n)
; CHECK-NEXT: Loop %loop: constant max backedge-taken count is 2
Expand Down Expand Up @@ -140,7 +140,7 @@ define void @logical_or_m_const(i32 %n) {
; CHECK-NEXT: %i.next = add i32 %i, 1
; CHECK-NEXT: --> {1,+,1}<%loop> U: [1,4) S: [1,4) Exits: (1 + (2 umin %n))<nuw><nsw> LoopDispositions: { %loop: Computable }
; CHECK-NEXT: %cond = select i1 %cond_i, i1 true, i1 %cond_i2
; CHECK-NEXT: --> (true + ((true + %cond_i) umin_seq (true + %cond_i2))) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
; CHECK-NEXT: --> (true + ((true + %cond_i) umin (true + %cond_i2))) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
; CHECK-NEXT: Determining loop execution counts for: @logical_or_m_const
; CHECK-NEXT: Loop %loop: backedge-taken count is (2 umin %n)
; CHECK-NEXT: Loop %loop: constant max backedge-taken count is 2
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/Analysis/ScalarEvolution/nsw.ll
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,7 @@ define void @select_cond_poison_propagation(ptr %p, i32 %x) nounwind {
; CHECK-NEXT: %iv = phi i32 [ %iv.next, %loop ], [ 0, %entry ]
; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%loop> U: [0,-2147483648) S: [0,-2147483648) Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
; CHECK-NEXT: %iv.next = add nsw i32 %iv, 1
; CHECK-NEXT: --> {1,+,1}<nuw><%loop> U: [1,0) S: [1,0) Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
; CHECK-NEXT: --> {1,+,1}<nuw><nsw><%loop> U: [1,-2147483648) S: [1,-2147483648) Exits: <<Unknown>> LoopDispositions: { %loop: Computable }
; CHECK-NEXT: %sel = select i1 %cmp, i32 10, i32 20
; CHECK-NEXT: --> %sel U: [0,31) S: [0,31) Exits: <<Unknown>> LoopDispositions: { %loop: Variant }
; CHECK-NEXT: %cond = call i1 @cond()
Expand Down
2 changes: 2 additions & 0 deletions llvm/test/Instrumentation/PoisonChecking/ub-checks.ll
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ define noundef i32 @select_cond_may_be_poison(i32 %a, i32 %b) {
; CHECK-NEXT: [[ADD:%.*]] = add nuw i32 [[A]], 1
; CHECK-NEXT: [[T:%.*]] = trunc i32 [[ADD]] to i1
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[T]], i32 [[ADD]], i32 [[B:%.*]]
; CHECK-NEXT: [[TMP3:%.*]] = xor i1 [[TMP2]], true
; CHECK-NEXT: call void @__poison_checker_assert(i1 [[TMP3]])
; CHECK-NEXT: ret i32 [[SEL]]
;
%add = add nuw i32 %a, 1
Expand Down
Loading

0 comments on commit 8a3efcd

Please sign in to comment.