#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SmallSet.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Instruction.h"
/// value (all bits poison).
const Value *getGuaranteedNonFullPoisonOp(const Instruction *I);
+ /// Return true if the given instruction must trigger undefined behavior.
+ /// when I is executed with any operands which appear in KnownPoison holding
+ /// a full-poison value at the point of execution.
+ bool mustTriggerUB(const Instruction *I,
+ const SmallSet<const Value *, 16>& KnownPoison);
+
/// Return true if this function can prove that if PoisonI is executed
/// and yields a full-poison value (all bits poison), then that will
/// trigger undefined behavior.
}
}
+bool llvm::mustTriggerUB(const Instruction *I,
+ const SmallSet<const Value *, 16>& KnownPoison) {
+ auto *NotPoison = getGuaranteedNonFullPoisonOp(I);
+ return (NotPoison && KnownPoison.count(NotPoison));
+}
+
+
bool llvm::programUndefinedIfFullPoison(const Instruction *PoisonI) {
// We currently only look for uses of poison values within the same basic
// block, as that makes it easier to guarantee that the uses will be
while (Iter++ < MaxDepth) {
for (auto &I : make_range(Begin, End)) {
if (&I != PoisonI) {
- const Value *NotPoison = getGuaranteedNonFullPoisonOp(&I);
- if (NotPoison != nullptr && YieldsPoison.count(NotPoison))
+ if (mustTriggerUB(&I, YieldsPoison))
return true;
if (!isGuaranteedToTransferExecutionToSuccessor(&I))
return false;