/// 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);
+ SmallVectorImpl<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).
void getGuaranteedWellDefinedOps(const Instruction *I,
- SmallPtrSetImpl<const Value *> &Ops);
+ SmallVectorImpl<const Value *> &Ops);
/// Return true if the given instruction must trigger undefined behavior
/// when I is executed with any operands which appear in KnownPoison holding
}
void llvm::getGuaranteedWellDefinedOps(
- const Instruction *I, SmallPtrSetImpl<const Value *> &Operands) {
+ const Instruction *I, SmallVectorImpl<const Value *> &Operands) {
switch (I->getOpcode()) {
case Instruction::Store:
- Operands.insert(cast<StoreInst>(I)->getPointerOperand());
+ Operands.push_back(cast<StoreInst>(I)->getPointerOperand());
break;
case Instruction::Load:
- Operands.insert(cast<LoadInst>(I)->getPointerOperand());
+ Operands.push_back(cast<LoadInst>(I)->getPointerOperand());
break;
// Since dereferenceable attribute imply noundef, atomic operations
// also implicitly have noundef pointers too
case Instruction::AtomicCmpXchg:
- Operands.insert(cast<AtomicCmpXchgInst>(I)->getPointerOperand());
+ Operands.push_back(cast<AtomicCmpXchgInst>(I)->getPointerOperand());
break;
case Instruction::AtomicRMW:
- Operands.insert(cast<AtomicRMWInst>(I)->getPointerOperand());
+ Operands.push_back(cast<AtomicRMWInst>(I)->getPointerOperand());
break;
case Instruction::Call:
case Instruction::Invoke: {
const CallBase *CB = cast<CallBase>(I);
if (CB->isIndirectCall())
- Operands.insert(CB->getCalledOperand());
+ Operands.push_back(CB->getCalledOperand());
for (unsigned i = 0; i < CB->arg_size(); ++i) {
if (CB->paramHasAttr(i, Attribute::NoUndef) ||
CB->paramHasAttr(i, Attribute::Dereferenceable))
- Operands.insert(CB->getArgOperand(i));
+ Operands.push_back(CB->getArgOperand(i));
}
break;
}
case Instruction::Ret:
if (I->getFunction()->hasRetAttribute(Attribute::NoUndef))
- Operands.insert(I->getOperand(0));
+ Operands.push_back(I->getOperand(0));
break;
case Instruction::Switch:
- Operands.insert(cast<SwitchInst>(I)->getCondition());
+ Operands.push_back(cast<SwitchInst>(I)->getCondition());
break;
case Instruction::Br: {
auto *BR = cast<BranchInst>(I);
if (BR->isConditional())
- Operands.insert(BR->getCondition());
+ Operands.push_back(BR->getCondition());
break;
}
default:
}
void llvm::getGuaranteedNonPoisonOps(const Instruction *I,
- SmallPtrSetImpl<const Value *> &Operands) {
+ SmallVectorImpl<const Value *> &Operands) {
getGuaranteedWellDefinedOps(I, Operands);
switch (I->getOpcode()) {
// Divisors of these operations are allowed to be partially undef.
case Instruction::SDiv:
case Instruction::URem:
case Instruction::SRem:
- Operands.insert(I->getOperand(1));
+ Operands.push_back(I->getOperand(1));
break;
default:
break;
bool llvm::mustTriggerUB(const Instruction *I,
const SmallSet<const Value *, 16>& KnownPoison) {
- SmallPtrSet<const Value *, 4> NonPoisonOps;
+ SmallVector<const Value *, 4> NonPoisonOps;
getGuaranteedNonPoisonOps(I, NonPoisonOps);
for (const auto *V : NonPoisonOps)
if (--ScanLimit == 0)
break;
- SmallPtrSet<const Value *, 4> WellDefinedOps;
+ SmallVector<const Value *, 4> WellDefinedOps;
getGuaranteedWellDefinedOps(&I, WellDefinedOps);
- if (WellDefinedOps.contains(V))
+ if (is_contained(WellDefinedOps, V))
return true;
if (!isGuaranteedToTransferExecutionToSuccessor(&I))
// Note: There are many more sources of documented UB, but this pass only
// attempts to find UB triggered by propagation of poison.
- SmallPtrSet<const Value *, 4> NonPoisonOps;
+ SmallVector<const Value *, 4> NonPoisonOps;
+ SmallPtrSet<const Value *, 4> SeenNonPoisonOps;
getGuaranteedNonPoisonOps(&I, NonPoisonOps);
for (const Value *Op : NonPoisonOps)
- CreateAssertNot(B, getPoisonFor(ValToPoison, const_cast<Value *>(Op)));
+ if (SeenNonPoisonOps.insert(Op).second)
+ CreateAssertNot(B,
+ getPoisonFor(ValToPoison, const_cast<Value *>(Op)));
if (LocalCheck)
if (auto *RI = dyn_cast<ReturnInst>(&I))