75 #define DEBUG_TYPE "poison-checking" 80 cl::desc(
"Check that returns are non-poison (for testing)"));
85 if (
auto *CI = dyn_cast<ConstantInt>(V))
97 Value *Accum = Ops[i++];
98 for (; i < Ops.
size(); i++)
100 Accum =
B.CreateOr(Accum, Ops[i]);
106 assert(isa<BinaryOperator>(
I));
109 Value *LHS =
I.getOperand(0);
110 Value *RHS =
I.getOperand(1);
111 switch (
I.getOpcode()) {
115 if (
I.hasNoSignedWrap()) {
117 B.CreateBinaryIntrinsic(Intrinsic::sadd_with_overflow, LHS, RHS);
118 Checks.
push_back(
B.CreateExtractValue(OverflowOp, 1));
120 if (
I.hasNoUnsignedWrap()) {
122 B.CreateBinaryIntrinsic(Intrinsic::uadd_with_overflow, LHS, RHS);
123 Checks.
push_back(
B.CreateExtractValue(OverflowOp, 1));
127 case Instruction::Sub: {
128 if (
I.hasNoSignedWrap()) {
130 B.CreateBinaryIntrinsic(Intrinsic::ssub_with_overflow, LHS, RHS);
131 Checks.
push_back(
B.CreateExtractValue(OverflowOp, 1));
133 if (
I.hasNoUnsignedWrap()) {
135 B.CreateBinaryIntrinsic(Intrinsic::usub_with_overflow, LHS, RHS);
136 Checks.
push_back(
B.CreateExtractValue(OverflowOp, 1));
141 if (
I.hasNoSignedWrap()) {
143 B.CreateBinaryIntrinsic(Intrinsic::smul_with_overflow, LHS, RHS);
144 Checks.
push_back(
B.CreateExtractValue(OverflowOp, 1));
146 if (
I.hasNoUnsignedWrap()) {
148 B.CreateBinaryIntrinsic(Intrinsic::umul_with_overflow, LHS, RHS);
149 Checks.
push_back(
B.CreateExtractValue(OverflowOp, 1));
153 case Instruction::UDiv: {
162 case Instruction::SDiv: {
171 case Instruction::AShr:
172 case Instruction::LShr:
173 case Instruction::Shl: {
190 if (isa<BinaryOperator>(
I) && !
I.getType()->isVectorTy())
194 switch (
I.getOpcode()) {
199 case Instruction::ExtractElement: {
200 Value *Vec =
I.getOperand(0);
201 auto *VecVTy = dyn_cast<FixedVectorType>(Vec->
getType());
204 Value *Idx =
I.getOperand(1);
205 unsigned NumElts = VecVTy->getNumElements();
212 case Instruction::InsertElement: {
213 Value *Vec =
I.getOperand(0);
214 auto *VecVTy = dyn_cast<FixedVectorType>(Vec->
getType());
217 Value *Idx =
I.getOperand(2);
218 unsigned NumElts = VecVTy->getNumElements();
229 auto Itr = ValToPoison.
find(V);
230 if (Itr != ValToPoison.
end())
232 if (isa<Constant>(V)) {
244 if (
auto *CI = dyn_cast<ConstantInt>(
Cond))
245 if (CI->isAllOnesValue())
248 Module *M =
B.GetInsertBlock()->getModule();
249 M->getOrInsertFunction(
"__poison_checker_assert",
252 Function *TrapFunc = M->getFunction(
"__poison_checker_assert");
253 B.CreateCall(TrapFunc,
Cond);
267 for (
auto I = BB.begin(); isa<PHINode>(&*
I);
I++) {
268 auto *OldPHI = cast<PHINode>(&*
I);
269 auto *NewPHI =
PHINode::Create(Int1Ty, OldPHI->getNumIncomingValues());
270 for (
unsigned i = 0; i < OldPHI->getNumIncomingValues(); i++)
272 OldPHI->getIncomingBlock(i));
273 NewPHI->insertBefore(OldPHI);
274 ValToPoison[OldPHI] = NewPHI;
279 if (isa<PHINode>(
I))
continue;
287 for (
const Value *
Op : NonPoisonOps)
291 if (
auto *RI = dyn_cast<ReturnInst>(&
I))
292 if (RI->getNumOperands() != 0) {
299 for (
Value *V :
I.operands())
308 for (
auto I = BB.begin(); isa<PHINode>(&*
I);
I++) {
309 auto *OldPHI = cast<PHINode>(&*
I);
310 if (!ValToPoison.count(OldPHI))
312 auto *NewPHI = cast<PHINode>(ValToPoison[OldPHI]);
313 for (
unsigned i = 0; i < OldPHI->getNumIncomingValues(); i++) {
314 auto *OldVal = OldPHI->getIncomingValue(i);
315 NewPHI->setIncomingValue(i,
getPoisonFor(ValToPoison, OldVal));
324 bool Changed =
false;
static bool Check(DecodeStatus &Out, DecodeStatus In)
static void generateCreationChecksForBinOp(Instruction &I, SmallVectorImpl< Value * > &Checks)
static ConstantInt * getFalse(LLVMContext &Context)
static IntegerType * getInt1Ty(LLVMContext &C)
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
This class represents lattice values for constants.
A Module instance is used to store all the information related to an LLVM module.
void push_back(const T &Elt)
static void generateCreationChecks(Instruction &I, SmallVectorImpl< Value * > &Checks)
Given an instruction which can produce poison on non-poison inputs (i.e.
bool propagatesPoison(const Operator *I)
Return true if I yields poison or raises UB if any of its operands is poison.
LLVMContext & getContext() const
All values hold a context through their type.
static Value * getPoisonFor(DenseMap< Value *, Value * > &ValToPoison, Value *V)
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 o...
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
bool isIntegerTy() const
True if this is an instance of IntegerType.
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
Type * getType() const
All values are typed, get the type of this value.
unsigned greater or equal
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
static Value * buildOrChain(IRBuilder<> &B, ArrayRef< Value * > Ops)
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
iterator find(const_arg_type_t< KeyT > Val)
initializer< Ty > init(const Ty &Val)
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
A set of analyses that are preserved following a run of a transformation pass.
* if(!EatIfPresent(lltok::kw_thread_local)) return false
parseOptionalThreadLocal := /*empty
LLVM Basic Block Representation.
size_t size() const
size - Get the array size.
static Type * getVoidTy(LLVMContext &C)
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
static bool isConstantFalse(Value *V)
static cl::opt< bool > LocalCheck("poison-checking-function-local", cl::init(false), cl::desc("Check that returns are non-poison (for testing)"))
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
static Constant * get(Type *Ty, uint64_t V, bool isSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...
static void CreateAssert(IRBuilder<> &B, Value *Cond)
static void CreateAssertNot(IRBuilder<> &B, Value *Cond)
static bool rewrite(Function &F)
SmallVector< MachineOperand, 4 > Cond
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
LLVM Value Representation.
A container for analyses that lazily runs them and caches their results.
bool canCreatePoison(const Operator *Op)