1f47a313eSPhilip Reames //===- PoisonChecking.cpp - -----------------------------------------------===//
2f47a313eSPhilip Reames //
3f47a313eSPhilip Reames // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4f47a313eSPhilip Reames // See https://llvm.org/LICENSE.txt for license information.
5f47a313eSPhilip Reames // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f47a313eSPhilip Reames //
7f47a313eSPhilip Reames //===----------------------------------------------------------------------===//
8f47a313eSPhilip Reames //
9f47a313eSPhilip Reames // Implements a transform pass which instruments IR such that poison semantics
10f47a313eSPhilip Reames // are made explicit.  That is, it provides a (possibly partial) executable
11f47a313eSPhilip Reames // semantics for every instruction w.r.t. poison as specified in the LLVM
12f47a313eSPhilip Reames // LangRef.  There are obvious parallels to the sanitizer tools, but this pass
13f47a313eSPhilip Reames // is focused purely on the semantics of LLVM IR, not any particular source
14f47a313eSPhilip Reames // language.   If you're looking for something to see if your C/C++ contains
15f47a313eSPhilip Reames // UB, this is not it.
16f47a313eSPhilip Reames //
17f47a313eSPhilip Reames // The rewritten semantics of each instruction will include the following
18f47a313eSPhilip Reames // components:
19f47a313eSPhilip Reames //
20f47a313eSPhilip Reames // 1) The original instruction, unmodified.
21f47a313eSPhilip Reames // 2) A propagation rule which translates dynamic information about the poison
22f47a313eSPhilip Reames //    state of each input to whether the dynamic output of the instruction
23f47a313eSPhilip Reames //    produces poison.
2480c46c53SPhilip Reames // 3) A creation rule which validates any poison producing flags on the
25f47a313eSPhilip Reames //    instruction itself (e.g. checks for overflow on nsw).
26f47a313eSPhilip Reames // 4) A check rule which traps (to a handler function) if this instruction must
27f47a313eSPhilip Reames //    execute undefined behavior given the poison state of it's inputs.
28f47a313eSPhilip Reames //
2980c46c53SPhilip Reames // This is a must analysis based transform; that is, the resulting code may
3080c46c53SPhilip Reames // produce a false negative result (not report UB when actually exists
3180c46c53SPhilip Reames // according to the LangRef spec), but should never produce a false positive
3280c46c53SPhilip Reames // (report UB where it doesn't exist).
33f47a313eSPhilip Reames //
34f47a313eSPhilip Reames // Use cases for this pass include:
35f47a313eSPhilip Reames // - Understanding (and testing!) the implications of the definition of poison
36f47a313eSPhilip Reames //   from the LangRef.
37f47a313eSPhilip Reames // - Validating the output of a IR fuzzer to ensure that all programs produced
38f47a313eSPhilip Reames //   are well defined on the specific input used.
39f47a313eSPhilip Reames // - Finding/confirming poison specific miscompiles by checking the poison
40f47a313eSPhilip Reames //   status of an input/IR pair is the same before and after an optimization
41f47a313eSPhilip Reames //   transform.
42f47a313eSPhilip Reames // - Checking that a bugpoint reduction does not introduce UB which didn't
43f47a313eSPhilip Reames //   exist in the original program being reduced.
44f47a313eSPhilip Reames //
45f47a313eSPhilip Reames // The major sources of inaccuracy are currently:
46f47a313eSPhilip Reames // - Most validation rules not yet implemented for instructions with poison
47f47a313eSPhilip Reames //   relavant flags.  At the moment, only nsw/nuw on add/sub are supported.
48f47a313eSPhilip Reames // - UB which is control dependent on a branch on poison is not yet
49f47a313eSPhilip Reames //   reported. Currently, only data flow dependence is modeled.
50f47a313eSPhilip Reames // - Poison which is propagated through memory is not modeled.  As such,
51f47a313eSPhilip Reames //   storing poison to memory and then reloading it will cause a false negative
52f47a313eSPhilip Reames //   as we consider the reloaded value to not be poisoned.
53f47a313eSPhilip Reames // - Poison propagation across function boundaries is not modeled.  At the
54f47a313eSPhilip Reames //   moment, all arguments and return values are assumed not to be poison.
55f47a313eSPhilip Reames // - Undef is not modeled.  In particular, the optimizer's freedom to pick
56f47a313eSPhilip Reames //   concrete values for undef bits so as to maximize potential for producing
57f47a313eSPhilip Reames //   poison is not modeled.
58f47a313eSPhilip Reames //
59f47a313eSPhilip Reames //===----------------------------------------------------------------------===//
60f47a313eSPhilip Reames 
61f47a313eSPhilip Reames #include "llvm/Transforms/Instrumentation/PoisonChecking.h"
62f47a313eSPhilip Reames #include "llvm/ADT/DenseMap.h"
63f47a313eSPhilip Reames #include "llvm/Analysis/ValueTracking.h"
644c1a1d3cSReid Kleckner #include "llvm/IR/IRBuilder.h"
654c1a1d3cSReid Kleckner #include "llvm/Support/CommandLine.h"
66f47a313eSPhilip Reames 
67f47a313eSPhilip Reames using namespace llvm;
68f47a313eSPhilip Reames 
69f47a313eSPhilip Reames #define DEBUG_TYPE "poison-checking"
70f47a313eSPhilip Reames 
71f47a313eSPhilip Reames static cl::opt<bool>
72f47a313eSPhilip Reames LocalCheck("poison-checking-function-local",
73f47a313eSPhilip Reames            cl::init(false),
74f47a313eSPhilip Reames            cl::desc("Check that returns are non-poison (for testing)"));
75f47a313eSPhilip Reames 
76f47a313eSPhilip Reames 
isConstantFalse(Value * V)77f47a313eSPhilip Reames static bool isConstantFalse(Value* V) {
78f47a313eSPhilip Reames   assert(V->getType()->isIntegerTy(1));
79f47a313eSPhilip Reames   if (auto *CI = dyn_cast<ConstantInt>(V))
80f47a313eSPhilip Reames     return CI->isZero();
81f47a313eSPhilip Reames   return false;
82f47a313eSPhilip Reames }
83f47a313eSPhilip Reames 
buildOrChain(IRBuilder<> & B,ArrayRef<Value * > Ops)84f47a313eSPhilip Reames static Value *buildOrChain(IRBuilder<> &B, ArrayRef<Value*> Ops) {
85f47a313eSPhilip Reames   if (Ops.size() == 0)
86f47a313eSPhilip Reames     return B.getFalse();
87f47a313eSPhilip Reames   unsigned i = 0;
88f47a313eSPhilip Reames   for (; i < Ops.size() && isConstantFalse(Ops[i]); i++) {}
89f47a313eSPhilip Reames   if (i == Ops.size())
90f47a313eSPhilip Reames     return B.getFalse();
91f47a313eSPhilip Reames   Value *Accum = Ops[i++];
92f47a313eSPhilip Reames   for (; i < Ops.size(); i++)
93f47a313eSPhilip Reames     if (!isConstantFalse(Ops[i]))
94f47a313eSPhilip Reames       Accum = B.CreateOr(Accum, Ops[i]);
95f47a313eSPhilip Reames   return Accum;
96f47a313eSPhilip Reames }
97f47a313eSPhilip Reames 
generateCreationChecksForBinOp(Instruction & I,SmallVectorImpl<Value * > & Checks)98463513e9SPhilip Reames static void generateCreationChecksForBinOp(Instruction &I,
99463513e9SPhilip Reames                                            SmallVectorImpl<Value*> &Checks) {
100f47a313eSPhilip Reames   assert(isa<BinaryOperator>(I));
101f47a313eSPhilip Reames 
102f47a313eSPhilip Reames   IRBuilder<> B(&I);
103f47a313eSPhilip Reames   Value *LHS = I.getOperand(0);
104f47a313eSPhilip Reames   Value *RHS = I.getOperand(1);
105f47a313eSPhilip Reames   switch (I.getOpcode()) {
106f47a313eSPhilip Reames   default:
107f47a313eSPhilip Reames     return;
108f47a313eSPhilip Reames   case Instruction::Add: {
109f47a313eSPhilip Reames     if (I.hasNoSignedWrap()) {
110f47a313eSPhilip Reames       auto *OverflowOp =
111f47a313eSPhilip Reames         B.CreateBinaryIntrinsic(Intrinsic::sadd_with_overflow, LHS, RHS);
112f47a313eSPhilip Reames       Checks.push_back(B.CreateExtractValue(OverflowOp, 1));
113f47a313eSPhilip Reames     }
114f47a313eSPhilip Reames     if (I.hasNoUnsignedWrap()) {
115f47a313eSPhilip Reames       auto *OverflowOp =
116f47a313eSPhilip Reames         B.CreateBinaryIntrinsic(Intrinsic::uadd_with_overflow, LHS, RHS);
117f47a313eSPhilip Reames       Checks.push_back(B.CreateExtractValue(OverflowOp, 1));
118f47a313eSPhilip Reames     }
119f47a313eSPhilip Reames     break;
120f47a313eSPhilip Reames   }
121f47a313eSPhilip Reames   case Instruction::Sub: {
122f47a313eSPhilip Reames     if (I.hasNoSignedWrap()) {
123f47a313eSPhilip Reames       auto *OverflowOp =
124f47a313eSPhilip Reames         B.CreateBinaryIntrinsic(Intrinsic::ssub_with_overflow, LHS, RHS);
125f47a313eSPhilip Reames       Checks.push_back(B.CreateExtractValue(OverflowOp, 1));
126f47a313eSPhilip Reames     }
127f47a313eSPhilip Reames     if (I.hasNoUnsignedWrap()) {
128f47a313eSPhilip Reames       auto *OverflowOp =
129f47a313eSPhilip Reames         B.CreateBinaryIntrinsic(Intrinsic::usub_with_overflow, LHS, RHS);
130f47a313eSPhilip Reames       Checks.push_back(B.CreateExtractValue(OverflowOp, 1));
131f47a313eSPhilip Reames     }
132f47a313eSPhilip Reames     break;
133f47a313eSPhilip Reames   }
134f47a313eSPhilip Reames   case Instruction::Mul: {
135f47a313eSPhilip Reames     if (I.hasNoSignedWrap()) {
136f47a313eSPhilip Reames       auto *OverflowOp =
137f47a313eSPhilip Reames         B.CreateBinaryIntrinsic(Intrinsic::smul_with_overflow, LHS, RHS);
138f47a313eSPhilip Reames       Checks.push_back(B.CreateExtractValue(OverflowOp, 1));
139f47a313eSPhilip Reames     }
140f47a313eSPhilip Reames     if (I.hasNoUnsignedWrap()) {
141f47a313eSPhilip Reames       auto *OverflowOp =
142f47a313eSPhilip Reames         B.CreateBinaryIntrinsic(Intrinsic::umul_with_overflow, LHS, RHS);
143f47a313eSPhilip Reames       Checks.push_back(B.CreateExtractValue(OverflowOp, 1));
144f47a313eSPhilip Reames     }
145f47a313eSPhilip Reames     break;
146f47a313eSPhilip Reames   }
1473b38b925SPhilip Reames   case Instruction::UDiv: {
1483b38b925SPhilip Reames     if (I.isExact()) {
1493b38b925SPhilip Reames       auto *Check =
1503b38b925SPhilip Reames         B.CreateICmp(ICmpInst::ICMP_NE, B.CreateURem(LHS, RHS),
1513b38b925SPhilip Reames                      ConstantInt::get(LHS->getType(), 0));
1523b38b925SPhilip Reames       Checks.push_back(Check);
1533b38b925SPhilip Reames     }
1543b38b925SPhilip Reames     break;
1553b38b925SPhilip Reames   }
1563b38b925SPhilip Reames   case Instruction::SDiv: {
1573b38b925SPhilip Reames     if (I.isExact()) {
1583b38b925SPhilip Reames       auto *Check =
1593b38b925SPhilip Reames         B.CreateICmp(ICmpInst::ICMP_NE, B.CreateSRem(LHS, RHS),
1603b38b925SPhilip Reames                      ConstantInt::get(LHS->getType(), 0));
1613b38b925SPhilip Reames       Checks.push_back(Check);
1623b38b925SPhilip Reames     }
1633b38b925SPhilip Reames     break;
1643b38b925SPhilip Reames   }
1653dbd7e98SPhilip Reames   case Instruction::AShr:
1663dbd7e98SPhilip Reames   case Instruction::LShr:
1673dbd7e98SPhilip Reames   case Instruction::Shl: {
1683dbd7e98SPhilip Reames     Value *ShiftCheck =
1693dbd7e98SPhilip Reames       B.CreateICmp(ICmpInst::ICMP_UGE, RHS,
1703dbd7e98SPhilip Reames                    ConstantInt::get(RHS->getType(),
1713dbd7e98SPhilip Reames                                     LHS->getType()->getScalarSizeInBits()));
1723dbd7e98SPhilip Reames     Checks.push_back(ShiftCheck);
1733dbd7e98SPhilip Reames     break;
1743dbd7e98SPhilip Reames   }
175f47a313eSPhilip Reames   };
176f47a313eSPhilip Reames }
177f47a313eSPhilip Reames 
178463513e9SPhilip Reames /// Given an instruction which can produce poison on non-poison inputs
179463513e9SPhilip Reames /// (i.e. canCreatePoison returns true), generate runtime checks to produce
180463513e9SPhilip Reames /// boolean indicators of when poison would result.
generateCreationChecks(Instruction & I,SmallVectorImpl<Value * > & Checks)181463513e9SPhilip Reames static void generateCreationChecks(Instruction &I,
182463513e9SPhilip Reames                                    SmallVectorImpl<Value*> &Checks) {
183f47a313eSPhilip Reames   IRBuilder<> B(&I);
1843dbd7e98SPhilip Reames   if (isa<BinaryOperator>(I) && !I.getType()->isVectorTy())
185463513e9SPhilip Reames     generateCreationChecksForBinOp(I, Checks);
1863dbd7e98SPhilip Reames 
187bc93c2d7SMarek Kurdej   // Handle non-binops separately
1883dbd7e98SPhilip Reames   switch (I.getOpcode()) {
1893dbd7e98SPhilip Reames   default:
19075ca7127SPhilip Reames     // Note there are a couple of missing cases here, once implemented, this
19175ca7127SPhilip Reames     // should become an llvm_unreachable.
1923dbd7e98SPhilip Reames     break;
1933dbd7e98SPhilip Reames   case Instruction::ExtractElement: {
1943dbd7e98SPhilip Reames     Value *Vec = I.getOperand(0);
1957ca56c90SChristopher Tetreault     auto *VecVTy = dyn_cast<FixedVectorType>(Vec->getType());
1967ca56c90SChristopher Tetreault     if (!VecVTy)
1973dbd7e98SPhilip Reames       break;
1983dbd7e98SPhilip Reames     Value *Idx = I.getOperand(1);
1993bebf028SChristopher Tetreault     unsigned NumElts = VecVTy->getNumElements();
2003dbd7e98SPhilip Reames     Value *Check =
2013dbd7e98SPhilip Reames       B.CreateICmp(ICmpInst::ICMP_UGE, Idx,
2023dbd7e98SPhilip Reames                    ConstantInt::get(Idx->getType(), NumElts));
2033dbd7e98SPhilip Reames     Checks.push_back(Check);
2043dbd7e98SPhilip Reames     break;
2053dbd7e98SPhilip Reames   }
2063dbd7e98SPhilip Reames   case Instruction::InsertElement: {
2073dbd7e98SPhilip Reames     Value *Vec = I.getOperand(0);
2087ca56c90SChristopher Tetreault     auto *VecVTy = dyn_cast<FixedVectorType>(Vec->getType());
2097ca56c90SChristopher Tetreault     if (!VecVTy)
2103dbd7e98SPhilip Reames       break;
2113dbd7e98SPhilip Reames     Value *Idx = I.getOperand(2);
2123bebf028SChristopher Tetreault     unsigned NumElts = VecVTy->getNumElements();
2133dbd7e98SPhilip Reames     Value *Check =
2143dbd7e98SPhilip Reames       B.CreateICmp(ICmpInst::ICMP_UGE, Idx,
2153dbd7e98SPhilip Reames                    ConstantInt::get(Idx->getType(), NumElts));
2163dbd7e98SPhilip Reames     Checks.push_back(Check);
2173dbd7e98SPhilip Reames     break;
2183dbd7e98SPhilip Reames   }
2193dbd7e98SPhilip Reames   };
220f47a313eSPhilip Reames }
221f47a313eSPhilip Reames 
getPoisonFor(DenseMap<Value *,Value * > & ValToPoison,Value * V)222f47a313eSPhilip Reames static Value *getPoisonFor(DenseMap<Value *, Value *> &ValToPoison, Value *V) {
223f47a313eSPhilip Reames   auto Itr = ValToPoison.find(V);
224f47a313eSPhilip Reames   if (Itr != ValToPoison.end())
225f47a313eSPhilip Reames     return Itr->second;
226f47a313eSPhilip Reames   if (isa<Constant>(V)) {
227f47a313eSPhilip Reames     return ConstantInt::getFalse(V->getContext());
228f47a313eSPhilip Reames   }
229f47a313eSPhilip Reames   // Return false for unknwon values - this implements a non-strict mode where
230f47a313eSPhilip Reames   // unhandled IR constructs are simply considered to never produce poison.  At
231f47a313eSPhilip Reames   // some point in the future, we probably want a "strict mode" for testing if
232f47a313eSPhilip Reames   // nothing else.
233f47a313eSPhilip Reames   return ConstantInt::getFalse(V->getContext());
234f47a313eSPhilip Reames }
235f47a313eSPhilip Reames 
CreateAssert(IRBuilder<> & B,Value * Cond)236f47a313eSPhilip Reames static void CreateAssert(IRBuilder<> &B, Value *Cond) {
237f47a313eSPhilip Reames   assert(Cond->getType()->isIntegerTy(1));
238f47a313eSPhilip Reames   if (auto *CI = dyn_cast<ConstantInt>(Cond))
239f47a313eSPhilip Reames     if (CI->isAllOnesValue())
240f47a313eSPhilip Reames       return;
241f47a313eSPhilip Reames 
242f47a313eSPhilip Reames   Module *M = B.GetInsertBlock()->getModule();
243f47a313eSPhilip Reames   M->getOrInsertFunction("__poison_checker_assert",
244f47a313eSPhilip Reames                          Type::getVoidTy(M->getContext()),
245f47a313eSPhilip Reames                          Type::getInt1Ty(M->getContext()));
246f47a313eSPhilip Reames   Function *TrapFunc = M->getFunction("__poison_checker_assert");
247f47a313eSPhilip Reames   B.CreateCall(TrapFunc, Cond);
248f47a313eSPhilip Reames }
249f47a313eSPhilip Reames 
CreateAssertNot(IRBuilder<> & B,Value * Cond)250f47a313eSPhilip Reames static void CreateAssertNot(IRBuilder<> &B, Value *Cond) {
251f47a313eSPhilip Reames   assert(Cond->getType()->isIntegerTy(1));
252f47a313eSPhilip Reames   CreateAssert(B, B.CreateNot(Cond));
253f47a313eSPhilip Reames }
254f47a313eSPhilip Reames 
rewrite(Function & F)255f47a313eSPhilip Reames static bool rewrite(Function &F) {
256f47a313eSPhilip Reames   auto * const Int1Ty = Type::getInt1Ty(F.getContext());
257f47a313eSPhilip Reames 
258f47a313eSPhilip Reames   DenseMap<Value *, Value *> ValToPoison;
259f47a313eSPhilip Reames 
260f47a313eSPhilip Reames   for (BasicBlock &BB : F)
261f47a313eSPhilip Reames     for (auto I = BB.begin(); isa<PHINode>(&*I); I++) {
262f47a313eSPhilip Reames       auto *OldPHI = cast<PHINode>(&*I);
263e5f602d8SJuneyoung Lee       auto *NewPHI = PHINode::Create(Int1Ty, OldPHI->getNumIncomingValues());
264f47a313eSPhilip Reames       for (unsigned i = 0; i < OldPHI->getNumIncomingValues(); i++)
265f47a313eSPhilip Reames         NewPHI->addIncoming(UndefValue::get(Int1Ty),
266f47a313eSPhilip Reames                             OldPHI->getIncomingBlock(i));
267f47a313eSPhilip Reames       NewPHI->insertBefore(OldPHI);
268f47a313eSPhilip Reames       ValToPoison[OldPHI] = NewPHI;
269f47a313eSPhilip Reames     }
270f47a313eSPhilip Reames 
271f47a313eSPhilip Reames   for (BasicBlock &BB : F)
272f47a313eSPhilip Reames     for (Instruction &I : BB) {
273f47a313eSPhilip Reames       if (isa<PHINode>(I)) continue;
274f47a313eSPhilip Reames 
275f47a313eSPhilip Reames       IRBuilder<> B(cast<Instruction>(&I));
276a6548d04SPhilip Reames 
277a6548d04SPhilip Reames       // Note: There are many more sources of documented UB, but this pass only
278a6548d04SPhilip Reames       // attempts to find UB triggered by propagation of poison.
279f753f5b0SJuneyoung Lee       SmallPtrSet<const Value *, 4> NonPoisonOps;
280f753f5b0SJuneyoung Lee       getGuaranteedNonPoisonOps(&I, NonPoisonOps);
281f753f5b0SJuneyoung Lee       for (const Value *Op : NonPoisonOps)
282f753f5b0SJuneyoung Lee         CreateAssertNot(B, getPoisonFor(ValToPoison, const_cast<Value *>(Op)));
283f47a313eSPhilip Reames 
284f47a313eSPhilip Reames       if (LocalCheck)
285f47a313eSPhilip Reames         if (auto *RI = dyn_cast<ReturnInst>(&I))
286f47a313eSPhilip Reames           if (RI->getNumOperands() != 0) {
287f47a313eSPhilip Reames             Value *Op = RI->getOperand(0);
288f47a313eSPhilip Reames             CreateAssertNot(B, getPoisonFor(ValToPoison, Op));
289f47a313eSPhilip Reames           }
290f47a313eSPhilip Reames 
291f47a313eSPhilip Reames       SmallVector<Value*, 4> Checks;
292*25ce1e04SJuneyoung Lee       if (propagatesPoison(cast<Operator>(&I)))
293f47a313eSPhilip Reames         for (Value *V : I.operands())
294f47a313eSPhilip Reames           Checks.push_back(getPoisonFor(ValToPoison, V));
295f47a313eSPhilip Reames 
2960a6aee51SJuneyoung Lee       if (canCreatePoison(cast<Operator>(&I)))
297463513e9SPhilip Reames         generateCreationChecks(I, Checks);
298f47a313eSPhilip Reames       ValToPoison[&I] = buildOrChain(B, Checks);
299f47a313eSPhilip Reames     }
300f47a313eSPhilip Reames 
301f47a313eSPhilip Reames   for (BasicBlock &BB : F)
302f47a313eSPhilip Reames     for (auto I = BB.begin(); isa<PHINode>(&*I); I++) {
303f47a313eSPhilip Reames       auto *OldPHI = cast<PHINode>(&*I);
304f47a313eSPhilip Reames       if (!ValToPoison.count(OldPHI))
305f47a313eSPhilip Reames         continue; // skip the newly inserted phis
306f47a313eSPhilip Reames       auto *NewPHI = cast<PHINode>(ValToPoison[OldPHI]);
307f47a313eSPhilip Reames       for (unsigned i = 0; i < OldPHI->getNumIncomingValues(); i++) {
308f47a313eSPhilip Reames         auto *OldVal = OldPHI->getIncomingValue(i);
309f47a313eSPhilip Reames         NewPHI->setIncomingValue(i, getPoisonFor(ValToPoison, OldVal));
310f47a313eSPhilip Reames       }
311f47a313eSPhilip Reames     }
312f47a313eSPhilip Reames   return true;
313f47a313eSPhilip Reames }
314f47a313eSPhilip Reames 
315f47a313eSPhilip Reames 
run(Module & M,ModuleAnalysisManager & AM)316f47a313eSPhilip Reames PreservedAnalyses PoisonCheckingPass::run(Module &M,
317f47a313eSPhilip Reames                                           ModuleAnalysisManager &AM) {
318f47a313eSPhilip Reames   bool Changed = false;
319f47a313eSPhilip Reames   for (auto &F : M)
320f47a313eSPhilip Reames     Changed |= rewrite(F);
321f47a313eSPhilip Reames 
322f47a313eSPhilip Reames   return Changed ? PreservedAnalyses::none() : PreservedAnalyses::all();
323f47a313eSPhilip Reames }
324f47a313eSPhilip Reames 
run(Function & F,FunctionAnalysisManager & AM)325f47a313eSPhilip Reames PreservedAnalyses PoisonCheckingPass::run(Function &F,
326f47a313eSPhilip Reames                                           FunctionAnalysisManager &AM) {
327f47a313eSPhilip Reames   return rewrite(F) ? PreservedAnalyses::none() : PreservedAnalyses::all();
328f47a313eSPhilip Reames }
329f47a313eSPhilip Reames 
330f47a313eSPhilip Reames /* Major TODO Items:
331f47a313eSPhilip Reames    - Control dependent poison UB
332f47a313eSPhilip Reames    - Strict mode - (i.e. must analyze every operand)
333f47a313eSPhilip Reames      - Poison through memory
334f47a313eSPhilip Reames      - Function ABIs
335a6548d04SPhilip Reames      - Full coverage of intrinsics, etc.. (ouch)
336f47a313eSPhilip Reames 
337a6548d04SPhilip Reames    Instructions w/Unclear Semantics:
338a6548d04SPhilip Reames    - shufflevector - It would seem reasonable for an out of bounds mask element
339a6548d04SPhilip Reames      to produce poison, but the LangRef does not state.
340a6548d04SPhilip Reames    - all binary ops w/vector operands - The likely interpretation would be that
341a6548d04SPhilip Reames      any element overflowing should produce poison for the entire result, but
342a6548d04SPhilip Reames      the LangRef does not state.
343a6548d04SPhilip Reames    - Floating point binary ops w/fmf flags other than (nnan, noinfs).  It seems
344a6548d04SPhilip Reames      strange that only certian flags should be documented as producing poison.
345a6548d04SPhilip Reames 
346a6548d04SPhilip Reames    Cases of clear poison semantics not yet implemented:
347a6548d04SPhilip Reames    - Exact flags on ashr/lshr produce poison
348a6548d04SPhilip Reames    - NSW/NUW flags on shl produce poison
349a6548d04SPhilip Reames    - Inbounds flag on getelementptr produce poison
350a6548d04SPhilip Reames    - fptosi/fptoui (out of bounds input) produce poison
351a6548d04SPhilip Reames    - Scalable vector types for insertelement/extractelement
352a6548d04SPhilip Reames    - Floating point binary ops w/fmf nnan/noinfs flags produce poison
353f47a313eSPhilip Reames  */
354