xref: /freebsd-src/contrib/llvm-project/llvm/lib/Transforms/Utils/AssumeBundleBuilder.cpp (revision 5ffd83dbcc34f10e07f6d3e968ae6365869615f4)
1*5ffd83dbSDimitry Andric //===- AssumeBundleBuilder.cpp - tools to preserve informations -*- C++ -*-===//
2*5ffd83dbSDimitry Andric //
3*5ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*5ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*5ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*5ffd83dbSDimitry Andric //
7*5ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
8*5ffd83dbSDimitry Andric 
9*5ffd83dbSDimitry Andric #define DEBUG_TYPE "assume-builder"
10*5ffd83dbSDimitry Andric 
11*5ffd83dbSDimitry Andric #include "llvm/Transforms/Utils/AssumeBundleBuilder.h"
12*5ffd83dbSDimitry Andric #include "llvm/ADT/DepthFirstIterator.h"
13*5ffd83dbSDimitry Andric #include "llvm/ADT/MapVector.h"
14*5ffd83dbSDimitry Andric #include "llvm/ADT/Statistic.h"
15*5ffd83dbSDimitry Andric #include "llvm/Analysis/AssumeBundleQueries.h"
16*5ffd83dbSDimitry Andric #include "llvm/Analysis/AssumptionCache.h"
17*5ffd83dbSDimitry Andric #include "llvm/Analysis/ValueTracking.h"
18*5ffd83dbSDimitry Andric #include "llvm/IR/Dominators.h"
19*5ffd83dbSDimitry Andric #include "llvm/IR/Function.h"
20*5ffd83dbSDimitry Andric #include "llvm/IR/InstIterator.h"
21*5ffd83dbSDimitry Andric #include "llvm/IR/IntrinsicInst.h"
22*5ffd83dbSDimitry Andric #include "llvm/IR/Module.h"
23*5ffd83dbSDimitry Andric #include "llvm/InitializePasses.h"
24*5ffd83dbSDimitry Andric #include "llvm/Support/CommandLine.h"
25*5ffd83dbSDimitry Andric #include "llvm/Support/DebugCounter.h"
26*5ffd83dbSDimitry Andric #include "llvm/Transforms/Utils/Local.h"
27*5ffd83dbSDimitry Andric 
28*5ffd83dbSDimitry Andric using namespace llvm;
29*5ffd83dbSDimitry Andric 
30*5ffd83dbSDimitry Andric cl::opt<bool> ShouldPreserveAllAttributes(
31*5ffd83dbSDimitry Andric     "assume-preserve-all", cl::init(false), cl::Hidden,
32*5ffd83dbSDimitry Andric     cl::desc("enable preservation of all attrbitues. even those that are "
33*5ffd83dbSDimitry Andric              "unlikely to be usefull"));
34*5ffd83dbSDimitry Andric 
35*5ffd83dbSDimitry Andric cl::opt<bool> EnableKnowledgeRetention(
36*5ffd83dbSDimitry Andric     "enable-knowledge-retention", cl::init(false), cl::Hidden,
37*5ffd83dbSDimitry Andric     cl::desc(
38*5ffd83dbSDimitry Andric         "enable preservation of attributes throughout code transformation"));
39*5ffd83dbSDimitry Andric 
40*5ffd83dbSDimitry Andric STATISTIC(NumAssumeBuilt, "Number of assume built by the assume builder");
41*5ffd83dbSDimitry Andric STATISTIC(NumBundlesInAssumes, "Total number of Bundles in the assume built");
42*5ffd83dbSDimitry Andric STATISTIC(NumAssumesMerged,
43*5ffd83dbSDimitry Andric           "Number of assume merged by the assume simplify pass");
44*5ffd83dbSDimitry Andric STATISTIC(NumAssumesRemoved,
45*5ffd83dbSDimitry Andric           "Number of assume removed by the assume simplify pass");
46*5ffd83dbSDimitry Andric 
47*5ffd83dbSDimitry Andric DEBUG_COUNTER(BuildAssumeCounter, "assume-builder-counter",
48*5ffd83dbSDimitry Andric               "Controls which assumes gets created");
49*5ffd83dbSDimitry Andric 
50*5ffd83dbSDimitry Andric namespace {
51*5ffd83dbSDimitry Andric 
52*5ffd83dbSDimitry Andric bool isUsefullToPreserve(Attribute::AttrKind Kind) {
53*5ffd83dbSDimitry Andric   switch (Kind) {
54*5ffd83dbSDimitry Andric     case Attribute::NonNull:
55*5ffd83dbSDimitry Andric     case Attribute::Alignment:
56*5ffd83dbSDimitry Andric     case Attribute::Dereferenceable:
57*5ffd83dbSDimitry Andric     case Attribute::DereferenceableOrNull:
58*5ffd83dbSDimitry Andric     case Attribute::Cold:
59*5ffd83dbSDimitry Andric       return true;
60*5ffd83dbSDimitry Andric     default:
61*5ffd83dbSDimitry Andric       return false;
62*5ffd83dbSDimitry Andric   }
63*5ffd83dbSDimitry Andric }
64*5ffd83dbSDimitry Andric 
65*5ffd83dbSDimitry Andric /// This function will try to transform the given knowledge into a more
66*5ffd83dbSDimitry Andric /// canonical one. the canonical knowledge maybe the given one.
67*5ffd83dbSDimitry Andric RetainedKnowledge canonicalizedKnowledge(RetainedKnowledge RK, Module *M) {
68*5ffd83dbSDimitry Andric   switch (RK.AttrKind) {
69*5ffd83dbSDimitry Andric   default:
70*5ffd83dbSDimitry Andric     return RK;
71*5ffd83dbSDimitry Andric   case Attribute::NonNull:
72*5ffd83dbSDimitry Andric     RK.WasOn = GetUnderlyingObject(RK.WasOn, M->getDataLayout());
73*5ffd83dbSDimitry Andric     return RK;
74*5ffd83dbSDimitry Andric   case Attribute::Alignment: {
75*5ffd83dbSDimitry Andric     Value *V = RK.WasOn->stripInBoundsOffsets([&](const Value *Strip) {
76*5ffd83dbSDimitry Andric       if (auto *GEP = dyn_cast<GEPOperator>(Strip))
77*5ffd83dbSDimitry Andric         RK.ArgValue =
78*5ffd83dbSDimitry Andric             MinAlign(RK.ArgValue,
79*5ffd83dbSDimitry Andric                      GEP->getMaxPreservedAlignment(M->getDataLayout()).value());
80*5ffd83dbSDimitry Andric     });
81*5ffd83dbSDimitry Andric     RK.WasOn = V;
82*5ffd83dbSDimitry Andric     return RK;
83*5ffd83dbSDimitry Andric   }
84*5ffd83dbSDimitry Andric   case Attribute::Dereferenceable:
85*5ffd83dbSDimitry Andric   case Attribute::DereferenceableOrNull: {
86*5ffd83dbSDimitry Andric     int64_t Offset = 0;
87*5ffd83dbSDimitry Andric     Value *V = GetPointerBaseWithConstantOffset(
88*5ffd83dbSDimitry Andric         RK.WasOn, Offset, M->getDataLayout(), /*AllowNonInBounds*/ false);
89*5ffd83dbSDimitry Andric     if (Offset < 0)
90*5ffd83dbSDimitry Andric       return RK;
91*5ffd83dbSDimitry Andric     RK.ArgValue = RK.ArgValue + Offset;
92*5ffd83dbSDimitry Andric     RK.WasOn = V;
93*5ffd83dbSDimitry Andric   }
94*5ffd83dbSDimitry Andric   }
95*5ffd83dbSDimitry Andric   return RK;
96*5ffd83dbSDimitry Andric }
97*5ffd83dbSDimitry Andric 
98*5ffd83dbSDimitry Andric /// This class contain all knowledge that have been gather while building an
99*5ffd83dbSDimitry Andric /// llvm.assume and the function to manipulate it.
100*5ffd83dbSDimitry Andric struct AssumeBuilderState {
101*5ffd83dbSDimitry Andric   Module *M;
102*5ffd83dbSDimitry Andric 
103*5ffd83dbSDimitry Andric   using MapKey = std::pair<Value *, Attribute::AttrKind>;
104*5ffd83dbSDimitry Andric   SmallMapVector<MapKey, unsigned, 8> AssumedKnowledgeMap;
105*5ffd83dbSDimitry Andric   Instruction *InstBeingRemoved = nullptr;
106*5ffd83dbSDimitry Andric   AssumptionCache* AC = nullptr;
107*5ffd83dbSDimitry Andric   DominatorTree* DT = nullptr;
108*5ffd83dbSDimitry Andric 
109*5ffd83dbSDimitry Andric   AssumeBuilderState(Module *M, Instruction *I = nullptr,
110*5ffd83dbSDimitry Andric                      AssumptionCache *AC = nullptr, DominatorTree *DT = nullptr)
111*5ffd83dbSDimitry Andric       : M(M), InstBeingRemoved(I), AC(AC), DT(DT) {}
112*5ffd83dbSDimitry Andric 
113*5ffd83dbSDimitry Andric   bool tryToPreserveWithoutAddingAssume(RetainedKnowledge RK) {
114*5ffd83dbSDimitry Andric     if (!InstBeingRemoved || !RK.WasOn)
115*5ffd83dbSDimitry Andric       return false;
116*5ffd83dbSDimitry Andric     bool HasBeenPreserved = false;
117*5ffd83dbSDimitry Andric     Use* ToUpdate = nullptr;
118*5ffd83dbSDimitry Andric     getKnowledgeForValue(
119*5ffd83dbSDimitry Andric         RK.WasOn, {RK.AttrKind}, AC,
120*5ffd83dbSDimitry Andric         [&](RetainedKnowledge RKOther, Instruction *Assume,
121*5ffd83dbSDimitry Andric             const CallInst::BundleOpInfo *Bundle) {
122*5ffd83dbSDimitry Andric           if (!isValidAssumeForContext(Assume, InstBeingRemoved, DT))
123*5ffd83dbSDimitry Andric             return false;
124*5ffd83dbSDimitry Andric           if (RKOther.ArgValue >= RK.ArgValue) {
125*5ffd83dbSDimitry Andric             HasBeenPreserved = true;
126*5ffd83dbSDimitry Andric             return true;
127*5ffd83dbSDimitry Andric           } else if (isValidAssumeForContext(InstBeingRemoved, Assume,
128*5ffd83dbSDimitry Andric                                              DT)) {
129*5ffd83dbSDimitry Andric             HasBeenPreserved = true;
130*5ffd83dbSDimitry Andric             IntrinsicInst *Intr = cast<IntrinsicInst>(Assume);
131*5ffd83dbSDimitry Andric             ToUpdate = &Intr->op_begin()[Bundle->Begin + ABA_Argument];
132*5ffd83dbSDimitry Andric             return true;
133*5ffd83dbSDimitry Andric           }
134*5ffd83dbSDimitry Andric           return false;
135*5ffd83dbSDimitry Andric         });
136*5ffd83dbSDimitry Andric     if (ToUpdate)
137*5ffd83dbSDimitry Andric       ToUpdate->set(
138*5ffd83dbSDimitry Andric           ConstantInt::get(Type::getInt64Ty(M->getContext()), RK.ArgValue));
139*5ffd83dbSDimitry Andric     return HasBeenPreserved;
140*5ffd83dbSDimitry Andric   }
141*5ffd83dbSDimitry Andric 
142*5ffd83dbSDimitry Andric   bool isKnowledgeWorthPreserving(RetainedKnowledge RK) {
143*5ffd83dbSDimitry Andric     if (!RK)
144*5ffd83dbSDimitry Andric       return false;
145*5ffd83dbSDimitry Andric     if (!RK.WasOn)
146*5ffd83dbSDimitry Andric       return true;
147*5ffd83dbSDimitry Andric     if (RK.WasOn->getType()->isPointerTy()) {
148*5ffd83dbSDimitry Andric       Value *UnderlyingPtr = GetUnderlyingObject(RK.WasOn, M->getDataLayout());
149*5ffd83dbSDimitry Andric       if (isa<AllocaInst>(UnderlyingPtr) || isa<GlobalValue>(UnderlyingPtr))
150*5ffd83dbSDimitry Andric         return false;
151*5ffd83dbSDimitry Andric     }
152*5ffd83dbSDimitry Andric     if (auto *Arg = dyn_cast<Argument>(RK.WasOn)) {
153*5ffd83dbSDimitry Andric       if (Arg->hasAttribute(RK.AttrKind) &&
154*5ffd83dbSDimitry Andric           (!Attribute::doesAttrKindHaveArgument(RK.AttrKind) ||
155*5ffd83dbSDimitry Andric            Arg->getAttribute(RK.AttrKind).getValueAsInt() >= RK.ArgValue))
156*5ffd83dbSDimitry Andric         return false;
157*5ffd83dbSDimitry Andric       return true;
158*5ffd83dbSDimitry Andric     }
159*5ffd83dbSDimitry Andric     if (auto *Inst = dyn_cast<Instruction>(RK.WasOn))
160*5ffd83dbSDimitry Andric       if (wouldInstructionBeTriviallyDead(Inst)) {
161*5ffd83dbSDimitry Andric         if (RK.WasOn->use_empty())
162*5ffd83dbSDimitry Andric           return false;
163*5ffd83dbSDimitry Andric         Use *SingleUse = RK.WasOn->getSingleUndroppableUse();
164*5ffd83dbSDimitry Andric         if (SingleUse && SingleUse->getUser() == InstBeingRemoved)
165*5ffd83dbSDimitry Andric           return false;
166*5ffd83dbSDimitry Andric       }
167*5ffd83dbSDimitry Andric     return true;
168*5ffd83dbSDimitry Andric   }
169*5ffd83dbSDimitry Andric 
170*5ffd83dbSDimitry Andric   void addKnowledge(RetainedKnowledge RK) {
171*5ffd83dbSDimitry Andric     RK = canonicalizedKnowledge(RK, M);
172*5ffd83dbSDimitry Andric 
173*5ffd83dbSDimitry Andric     if (!isKnowledgeWorthPreserving(RK))
174*5ffd83dbSDimitry Andric       return;
175*5ffd83dbSDimitry Andric 
176*5ffd83dbSDimitry Andric     if (tryToPreserveWithoutAddingAssume(RK))
177*5ffd83dbSDimitry Andric       return;
178*5ffd83dbSDimitry Andric     MapKey Key{RK.WasOn, RK.AttrKind};
179*5ffd83dbSDimitry Andric     auto Lookup = AssumedKnowledgeMap.find(Key);
180*5ffd83dbSDimitry Andric     if (Lookup == AssumedKnowledgeMap.end()) {
181*5ffd83dbSDimitry Andric       AssumedKnowledgeMap[Key] = RK.ArgValue;
182*5ffd83dbSDimitry Andric       return;
183*5ffd83dbSDimitry Andric     }
184*5ffd83dbSDimitry Andric     assert(((Lookup->second == 0 && RK.ArgValue == 0) ||
185*5ffd83dbSDimitry Andric             (Lookup->second != 0 && RK.ArgValue != 0)) &&
186*5ffd83dbSDimitry Andric            "inconsistent argument value");
187*5ffd83dbSDimitry Andric 
188*5ffd83dbSDimitry Andric     /// This is only desirable because for all attributes taking an argument
189*5ffd83dbSDimitry Andric     /// higher is better.
190*5ffd83dbSDimitry Andric     Lookup->second = std::max(Lookup->second, RK.ArgValue);
191*5ffd83dbSDimitry Andric   }
192*5ffd83dbSDimitry Andric 
193*5ffd83dbSDimitry Andric   void addAttribute(Attribute Attr, Value *WasOn) {
194*5ffd83dbSDimitry Andric     if (Attr.isTypeAttribute() || Attr.isStringAttribute() ||
195*5ffd83dbSDimitry Andric         (!ShouldPreserveAllAttributes &&
196*5ffd83dbSDimitry Andric          !isUsefullToPreserve(Attr.getKindAsEnum())))
197*5ffd83dbSDimitry Andric       return;
198*5ffd83dbSDimitry Andric     unsigned AttrArg = 0;
199*5ffd83dbSDimitry Andric     if (Attr.isIntAttribute())
200*5ffd83dbSDimitry Andric       AttrArg = Attr.getValueAsInt();
201*5ffd83dbSDimitry Andric     addKnowledge({Attr.getKindAsEnum(), AttrArg, WasOn});
202*5ffd83dbSDimitry Andric   }
203*5ffd83dbSDimitry Andric 
204*5ffd83dbSDimitry Andric   void addCall(const CallBase *Call) {
205*5ffd83dbSDimitry Andric     auto addAttrList = [&](AttributeList AttrList) {
206*5ffd83dbSDimitry Andric       for (unsigned Idx = AttributeList::FirstArgIndex;
207*5ffd83dbSDimitry Andric            Idx < AttrList.getNumAttrSets(); Idx++)
208*5ffd83dbSDimitry Andric         for (Attribute Attr : AttrList.getAttributes(Idx))
209*5ffd83dbSDimitry Andric           addAttribute(Attr, Call->getArgOperand(Idx - 1));
210*5ffd83dbSDimitry Andric       for (Attribute Attr : AttrList.getFnAttributes())
211*5ffd83dbSDimitry Andric         addAttribute(Attr, nullptr);
212*5ffd83dbSDimitry Andric     };
213*5ffd83dbSDimitry Andric     addAttrList(Call->getAttributes());
214*5ffd83dbSDimitry Andric     if (Function *Fn = Call->getCalledFunction())
215*5ffd83dbSDimitry Andric       addAttrList(Fn->getAttributes());
216*5ffd83dbSDimitry Andric   }
217*5ffd83dbSDimitry Andric 
218*5ffd83dbSDimitry Andric   IntrinsicInst *build() {
219*5ffd83dbSDimitry Andric     if (AssumedKnowledgeMap.empty())
220*5ffd83dbSDimitry Andric       return nullptr;
221*5ffd83dbSDimitry Andric     if (!DebugCounter::shouldExecute(BuildAssumeCounter))
222*5ffd83dbSDimitry Andric       return nullptr;
223*5ffd83dbSDimitry Andric     Function *FnAssume = Intrinsic::getDeclaration(M, Intrinsic::assume);
224*5ffd83dbSDimitry Andric     LLVMContext &C = M->getContext();
225*5ffd83dbSDimitry Andric     SmallVector<OperandBundleDef, 8> OpBundle;
226*5ffd83dbSDimitry Andric     for (auto &MapElem : AssumedKnowledgeMap) {
227*5ffd83dbSDimitry Andric       SmallVector<Value *, 2> Args;
228*5ffd83dbSDimitry Andric       if (MapElem.first.first)
229*5ffd83dbSDimitry Andric         Args.push_back(MapElem.first.first);
230*5ffd83dbSDimitry Andric 
231*5ffd83dbSDimitry Andric       /// This is only valid because for all attribute that currently exist a
232*5ffd83dbSDimitry Andric       /// value of 0 is useless. and should not be preserved.
233*5ffd83dbSDimitry Andric       if (MapElem.second)
234*5ffd83dbSDimitry Andric         Args.push_back(ConstantInt::get(Type::getInt64Ty(M->getContext()),
235*5ffd83dbSDimitry Andric                                         MapElem.second));
236*5ffd83dbSDimitry Andric       OpBundle.push_back(OperandBundleDefT<Value *>(
237*5ffd83dbSDimitry Andric           std::string(Attribute::getNameFromAttrKind(MapElem.first.second)),
238*5ffd83dbSDimitry Andric           Args));
239*5ffd83dbSDimitry Andric       NumBundlesInAssumes++;
240*5ffd83dbSDimitry Andric     }
241*5ffd83dbSDimitry Andric     NumAssumeBuilt++;
242*5ffd83dbSDimitry Andric     return cast<IntrinsicInst>(CallInst::Create(
243*5ffd83dbSDimitry Andric         FnAssume, ArrayRef<Value *>({ConstantInt::getTrue(C)}), OpBundle));
244*5ffd83dbSDimitry Andric   }
245*5ffd83dbSDimitry Andric 
246*5ffd83dbSDimitry Andric   void addAccessedPtr(Instruction *MemInst, Value *Pointer, Type *AccType,
247*5ffd83dbSDimitry Andric                       MaybeAlign MA) {
248*5ffd83dbSDimitry Andric     unsigned DerefSize = MemInst->getModule()
249*5ffd83dbSDimitry Andric                              ->getDataLayout()
250*5ffd83dbSDimitry Andric                              .getTypeStoreSize(AccType)
251*5ffd83dbSDimitry Andric                              .getKnownMinSize();
252*5ffd83dbSDimitry Andric     if (DerefSize != 0) {
253*5ffd83dbSDimitry Andric       addKnowledge({Attribute::Dereferenceable, DerefSize, Pointer});
254*5ffd83dbSDimitry Andric       if (!NullPointerIsDefined(MemInst->getFunction(),
255*5ffd83dbSDimitry Andric                                 Pointer->getType()->getPointerAddressSpace()))
256*5ffd83dbSDimitry Andric         addKnowledge({Attribute::NonNull, 0u, Pointer});
257*5ffd83dbSDimitry Andric     }
258*5ffd83dbSDimitry Andric     if (MA.valueOrOne() > 1)
259*5ffd83dbSDimitry Andric       addKnowledge(
260*5ffd83dbSDimitry Andric           {Attribute::Alignment, unsigned(MA.valueOrOne().value()), Pointer});
261*5ffd83dbSDimitry Andric   }
262*5ffd83dbSDimitry Andric 
263*5ffd83dbSDimitry Andric   void addInstruction(Instruction *I) {
264*5ffd83dbSDimitry Andric     if (auto *Call = dyn_cast<CallBase>(I))
265*5ffd83dbSDimitry Andric       return addCall(Call);
266*5ffd83dbSDimitry Andric     if (auto *Load = dyn_cast<LoadInst>(I))
267*5ffd83dbSDimitry Andric       return addAccessedPtr(I, Load->getPointerOperand(), Load->getType(),
268*5ffd83dbSDimitry Andric                             Load->getAlign());
269*5ffd83dbSDimitry Andric     if (auto *Store = dyn_cast<StoreInst>(I))
270*5ffd83dbSDimitry Andric       return addAccessedPtr(I, Store->getPointerOperand(),
271*5ffd83dbSDimitry Andric                             Store->getValueOperand()->getType(),
272*5ffd83dbSDimitry Andric                             Store->getAlign());
273*5ffd83dbSDimitry Andric     // TODO: Add support for the other Instructions.
274*5ffd83dbSDimitry Andric     // TODO: Maybe we should look around and merge with other llvm.assume.
275*5ffd83dbSDimitry Andric   }
276*5ffd83dbSDimitry Andric };
277*5ffd83dbSDimitry Andric 
278*5ffd83dbSDimitry Andric } // namespace
279*5ffd83dbSDimitry Andric 
280*5ffd83dbSDimitry Andric IntrinsicInst *llvm::buildAssumeFromInst(Instruction *I) {
281*5ffd83dbSDimitry Andric   if (!EnableKnowledgeRetention)
282*5ffd83dbSDimitry Andric     return nullptr;
283*5ffd83dbSDimitry Andric   AssumeBuilderState Builder(I->getModule());
284*5ffd83dbSDimitry Andric   Builder.addInstruction(I);
285*5ffd83dbSDimitry Andric   return Builder.build();
286*5ffd83dbSDimitry Andric }
287*5ffd83dbSDimitry Andric 
288*5ffd83dbSDimitry Andric void llvm::salvageKnowledge(Instruction *I, AssumptionCache *AC,
289*5ffd83dbSDimitry Andric                             DominatorTree *DT) {
290*5ffd83dbSDimitry Andric   if (!EnableKnowledgeRetention || I->isTerminator())
291*5ffd83dbSDimitry Andric     return;
292*5ffd83dbSDimitry Andric   AssumeBuilderState Builder(I->getModule(), I, AC, DT);
293*5ffd83dbSDimitry Andric   Builder.addInstruction(I);
294*5ffd83dbSDimitry Andric   if (IntrinsicInst *Intr = Builder.build()) {
295*5ffd83dbSDimitry Andric     Intr->insertBefore(I);
296*5ffd83dbSDimitry Andric     if (AC)
297*5ffd83dbSDimitry Andric       AC->registerAssumption(Intr);
298*5ffd83dbSDimitry Andric   }
299*5ffd83dbSDimitry Andric }
300*5ffd83dbSDimitry Andric 
301*5ffd83dbSDimitry Andric namespace {
302*5ffd83dbSDimitry Andric 
303*5ffd83dbSDimitry Andric struct AssumeSimplify {
304*5ffd83dbSDimitry Andric   Function &F;
305*5ffd83dbSDimitry Andric   AssumptionCache &AC;
306*5ffd83dbSDimitry Andric   DominatorTree *DT;
307*5ffd83dbSDimitry Andric   LLVMContext &C;
308*5ffd83dbSDimitry Andric   SmallDenseSet<IntrinsicInst *> CleanupToDo;
309*5ffd83dbSDimitry Andric   StringMapEntry<uint32_t> *IgnoreTag;
310*5ffd83dbSDimitry Andric   SmallDenseMap<BasicBlock *, SmallVector<IntrinsicInst *, 4>, 8> BBToAssume;
311*5ffd83dbSDimitry Andric   bool MadeChange = false;
312*5ffd83dbSDimitry Andric 
313*5ffd83dbSDimitry Andric   AssumeSimplify(Function &F, AssumptionCache &AC, DominatorTree *DT,
314*5ffd83dbSDimitry Andric                  LLVMContext &C)
315*5ffd83dbSDimitry Andric       : F(F), AC(AC), DT(DT), C(C),
316*5ffd83dbSDimitry Andric         IgnoreTag(C.getOrInsertBundleTag(IgnoreBundleTag)) {}
317*5ffd83dbSDimitry Andric 
318*5ffd83dbSDimitry Andric   void buildMapping(bool FilterBooleanArgument) {
319*5ffd83dbSDimitry Andric     BBToAssume.clear();
320*5ffd83dbSDimitry Andric     for (Value *V : AC.assumptions()) {
321*5ffd83dbSDimitry Andric       if (!V)
322*5ffd83dbSDimitry Andric         continue;
323*5ffd83dbSDimitry Andric       IntrinsicInst *Assume = cast<IntrinsicInst>(V);
324*5ffd83dbSDimitry Andric       if (FilterBooleanArgument) {
325*5ffd83dbSDimitry Andric         auto *Arg = dyn_cast<ConstantInt>(Assume->getOperand(0));
326*5ffd83dbSDimitry Andric         if (!Arg || Arg->isZero())
327*5ffd83dbSDimitry Andric           continue;
328*5ffd83dbSDimitry Andric       }
329*5ffd83dbSDimitry Andric       BBToAssume[Assume->getParent()].push_back(Assume);
330*5ffd83dbSDimitry Andric     }
331*5ffd83dbSDimitry Andric 
332*5ffd83dbSDimitry Andric     for (auto &Elem : BBToAssume) {
333*5ffd83dbSDimitry Andric       llvm::sort(Elem.second,
334*5ffd83dbSDimitry Andric                  [](const IntrinsicInst *LHS, const IntrinsicInst *RHS) {
335*5ffd83dbSDimitry Andric                    return LHS->comesBefore(RHS);
336*5ffd83dbSDimitry Andric                  });
337*5ffd83dbSDimitry Andric     }
338*5ffd83dbSDimitry Andric   }
339*5ffd83dbSDimitry Andric 
340*5ffd83dbSDimitry Andric   /// Remove all asumes in CleanupToDo if there boolean argument is true and
341*5ffd83dbSDimitry Andric   /// ForceCleanup is set or the assume doesn't hold valuable knowledge.
342*5ffd83dbSDimitry Andric   void RunCleanup(bool ForceCleanup) {
343*5ffd83dbSDimitry Andric     for (IntrinsicInst *Assume : CleanupToDo) {
344*5ffd83dbSDimitry Andric       auto *Arg = dyn_cast<ConstantInt>(Assume->getOperand(0));
345*5ffd83dbSDimitry Andric       if (!Arg || Arg->isZero() ||
346*5ffd83dbSDimitry Andric           (!ForceCleanup && !isAssumeWithEmptyBundle(*Assume)))
347*5ffd83dbSDimitry Andric         continue;
348*5ffd83dbSDimitry Andric       MadeChange = true;
349*5ffd83dbSDimitry Andric       if (ForceCleanup)
350*5ffd83dbSDimitry Andric         NumAssumesMerged++;
351*5ffd83dbSDimitry Andric       else
352*5ffd83dbSDimitry Andric         NumAssumesRemoved++;
353*5ffd83dbSDimitry Andric       Assume->eraseFromParent();
354*5ffd83dbSDimitry Andric     }
355*5ffd83dbSDimitry Andric     CleanupToDo.clear();
356*5ffd83dbSDimitry Andric   }
357*5ffd83dbSDimitry Andric 
358*5ffd83dbSDimitry Andric   /// Remove knowledge stored in assume when it is already know by an attribute
359*5ffd83dbSDimitry Andric   /// or an other assume. This can when valid update an existing knowledge in an
360*5ffd83dbSDimitry Andric   /// attribute or an other assume.
361*5ffd83dbSDimitry Andric   void dropRedundantKnowledge() {
362*5ffd83dbSDimitry Andric     struct MapValue {
363*5ffd83dbSDimitry Andric       IntrinsicInst *Assume;
364*5ffd83dbSDimitry Andric       unsigned ArgValue;
365*5ffd83dbSDimitry Andric       CallInst::BundleOpInfo *BOI;
366*5ffd83dbSDimitry Andric     };
367*5ffd83dbSDimitry Andric     buildMapping(false);
368*5ffd83dbSDimitry Andric     SmallDenseMap<std::pair<Value *, Attribute::AttrKind>,
369*5ffd83dbSDimitry Andric                   SmallVector<MapValue, 2>, 16>
370*5ffd83dbSDimitry Andric         Knowledge;
371*5ffd83dbSDimitry Andric     for (BasicBlock *BB : depth_first(&F))
372*5ffd83dbSDimitry Andric       for (Value *V : BBToAssume[BB]) {
373*5ffd83dbSDimitry Andric         if (!V)
374*5ffd83dbSDimitry Andric           continue;
375*5ffd83dbSDimitry Andric         IntrinsicInst *Assume = cast<IntrinsicInst>(V);
376*5ffd83dbSDimitry Andric         for (CallInst::BundleOpInfo &BOI : Assume->bundle_op_infos()) {
377*5ffd83dbSDimitry Andric           auto RemoveFromAssume = [&]() {
378*5ffd83dbSDimitry Andric             CleanupToDo.insert(Assume);
379*5ffd83dbSDimitry Andric             if (BOI.Begin != BOI.End) {
380*5ffd83dbSDimitry Andric               Use *U = &Assume->op_begin()[BOI.Begin + ABA_WasOn];
381*5ffd83dbSDimitry Andric               U->set(UndefValue::get(U->get()->getType()));
382*5ffd83dbSDimitry Andric             }
383*5ffd83dbSDimitry Andric             BOI.Tag = IgnoreTag;
384*5ffd83dbSDimitry Andric           };
385*5ffd83dbSDimitry Andric           if (BOI.Tag == IgnoreTag) {
386*5ffd83dbSDimitry Andric             CleanupToDo.insert(Assume);
387*5ffd83dbSDimitry Andric             continue;
388*5ffd83dbSDimitry Andric           }
389*5ffd83dbSDimitry Andric           RetainedKnowledge RK = getKnowledgeFromBundle(*Assume, BOI);
390*5ffd83dbSDimitry Andric           if (auto *Arg = dyn_cast_or_null<Argument>(RK.WasOn)) {
391*5ffd83dbSDimitry Andric             bool HasSameKindAttr = Arg->hasAttribute(RK.AttrKind);
392*5ffd83dbSDimitry Andric             if (HasSameKindAttr)
393*5ffd83dbSDimitry Andric               if (!Attribute::doesAttrKindHaveArgument(RK.AttrKind) ||
394*5ffd83dbSDimitry Andric                   Arg->getAttribute(RK.AttrKind).getValueAsInt() >=
395*5ffd83dbSDimitry Andric                       RK.ArgValue) {
396*5ffd83dbSDimitry Andric                 RemoveFromAssume();
397*5ffd83dbSDimitry Andric                 continue;
398*5ffd83dbSDimitry Andric               }
399*5ffd83dbSDimitry Andric             if (isValidAssumeForContext(
400*5ffd83dbSDimitry Andric                     Assume, &*F.getEntryBlock().getFirstInsertionPt()) ||
401*5ffd83dbSDimitry Andric                 Assume == &*F.getEntryBlock().getFirstInsertionPt()) {
402*5ffd83dbSDimitry Andric               if (HasSameKindAttr)
403*5ffd83dbSDimitry Andric                 Arg->removeAttr(RK.AttrKind);
404*5ffd83dbSDimitry Andric               Arg->addAttr(Attribute::get(C, RK.AttrKind, RK.ArgValue));
405*5ffd83dbSDimitry Andric               MadeChange = true;
406*5ffd83dbSDimitry Andric               RemoveFromAssume();
407*5ffd83dbSDimitry Andric               continue;
408*5ffd83dbSDimitry Andric             }
409*5ffd83dbSDimitry Andric           }
410*5ffd83dbSDimitry Andric           auto &Lookup = Knowledge[{RK.WasOn, RK.AttrKind}];
411*5ffd83dbSDimitry Andric           for (MapValue &Elem : Lookup) {
412*5ffd83dbSDimitry Andric             if (!isValidAssumeForContext(Elem.Assume, Assume, DT))
413*5ffd83dbSDimitry Andric               continue;
414*5ffd83dbSDimitry Andric             if (Elem.ArgValue >= RK.ArgValue) {
415*5ffd83dbSDimitry Andric               RemoveFromAssume();
416*5ffd83dbSDimitry Andric               continue;
417*5ffd83dbSDimitry Andric             } else if (isValidAssumeForContext(Assume, Elem.Assume, DT)) {
418*5ffd83dbSDimitry Andric               Elem.Assume->op_begin()[Elem.BOI->Begin + ABA_Argument].set(
419*5ffd83dbSDimitry Andric                   ConstantInt::get(Type::getInt64Ty(C), RK.ArgValue));
420*5ffd83dbSDimitry Andric               MadeChange = true;
421*5ffd83dbSDimitry Andric               RemoveFromAssume();
422*5ffd83dbSDimitry Andric               continue;
423*5ffd83dbSDimitry Andric             }
424*5ffd83dbSDimitry Andric           }
425*5ffd83dbSDimitry Andric           Lookup.push_back({Assume, RK.ArgValue, &BOI});
426*5ffd83dbSDimitry Andric         }
427*5ffd83dbSDimitry Andric       }
428*5ffd83dbSDimitry Andric   }
429*5ffd83dbSDimitry Andric 
430*5ffd83dbSDimitry Andric   using MergeIterator = SmallVectorImpl<IntrinsicInst *>::iterator;
431*5ffd83dbSDimitry Andric 
432*5ffd83dbSDimitry Andric   /// Merge all Assumes from Begin to End in and insert the resulting assume as
433*5ffd83dbSDimitry Andric   /// high as possible in the basicblock.
434*5ffd83dbSDimitry Andric   void mergeRange(BasicBlock *BB, MergeIterator Begin, MergeIterator End) {
435*5ffd83dbSDimitry Andric     if (Begin == End || std::next(Begin) == End)
436*5ffd83dbSDimitry Andric       return;
437*5ffd83dbSDimitry Andric     /// Provide no additional information so that AssumeBuilderState doesn't
438*5ffd83dbSDimitry Andric     /// try to do any punning since it already has been done better.
439*5ffd83dbSDimitry Andric     AssumeBuilderState Builder(F.getParent());
440*5ffd83dbSDimitry Andric 
441*5ffd83dbSDimitry Andric     /// For now it is initialized to the best value it could have
442*5ffd83dbSDimitry Andric     Instruction *InsertPt = BB->getFirstNonPHI();
443*5ffd83dbSDimitry Andric     if (isa<LandingPadInst>(InsertPt))
444*5ffd83dbSDimitry Andric       InsertPt = InsertPt->getNextNode();
445*5ffd83dbSDimitry Andric     for (IntrinsicInst *I : make_range(Begin, End)) {
446*5ffd83dbSDimitry Andric       CleanupToDo.insert(I);
447*5ffd83dbSDimitry Andric       for (CallInst::BundleOpInfo &BOI : I->bundle_op_infos()) {
448*5ffd83dbSDimitry Andric         RetainedKnowledge RK = getKnowledgeFromBundle(*I, BOI);
449*5ffd83dbSDimitry Andric         if (!RK)
450*5ffd83dbSDimitry Andric           continue;
451*5ffd83dbSDimitry Andric         Builder.addKnowledge(RK);
452*5ffd83dbSDimitry Andric         if (auto *I = dyn_cast_or_null<Instruction>(RK.WasOn))
453*5ffd83dbSDimitry Andric           if (I->getParent() == InsertPt->getParent() &&
454*5ffd83dbSDimitry Andric               (InsertPt->comesBefore(I) || InsertPt == I))
455*5ffd83dbSDimitry Andric             InsertPt = I->getNextNode();
456*5ffd83dbSDimitry Andric       }
457*5ffd83dbSDimitry Andric     }
458*5ffd83dbSDimitry Andric 
459*5ffd83dbSDimitry Andric     /// Adjust InsertPt if it is before Begin, since mergeAssumes only
460*5ffd83dbSDimitry Andric     /// guarantees we can place the resulting assume between Begin and End.
461*5ffd83dbSDimitry Andric     if (InsertPt->comesBefore(*Begin))
462*5ffd83dbSDimitry Andric       for (auto It = (*Begin)->getIterator(), E = InsertPt->getIterator();
463*5ffd83dbSDimitry Andric            It != E; --It)
464*5ffd83dbSDimitry Andric         if (!isGuaranteedToTransferExecutionToSuccessor(&*It)) {
465*5ffd83dbSDimitry Andric           InsertPt = It->getNextNode();
466*5ffd83dbSDimitry Andric           break;
467*5ffd83dbSDimitry Andric         }
468*5ffd83dbSDimitry Andric     IntrinsicInst *MergedAssume = Builder.build();
469*5ffd83dbSDimitry Andric     if (!MergedAssume)
470*5ffd83dbSDimitry Andric       return;
471*5ffd83dbSDimitry Andric     MadeChange = true;
472*5ffd83dbSDimitry Andric     MergedAssume->insertBefore(InsertPt);
473*5ffd83dbSDimitry Andric     AC.registerAssumption(MergedAssume);
474*5ffd83dbSDimitry Andric   }
475*5ffd83dbSDimitry Andric 
476*5ffd83dbSDimitry Andric   /// Merge assume when they are in the same BasicBlock and for all instruction
477*5ffd83dbSDimitry Andric   /// between them isGuaranteedToTransferExecutionToSuccessor returns true.
478*5ffd83dbSDimitry Andric   void mergeAssumes() {
479*5ffd83dbSDimitry Andric     buildMapping(true);
480*5ffd83dbSDimitry Andric 
481*5ffd83dbSDimitry Andric     SmallVector<MergeIterator, 4> SplitPoints;
482*5ffd83dbSDimitry Andric     for (auto &Elem : BBToAssume) {
483*5ffd83dbSDimitry Andric       SmallVectorImpl<IntrinsicInst *> &AssumesInBB = Elem.second;
484*5ffd83dbSDimitry Andric       if (AssumesInBB.size() < 2)
485*5ffd83dbSDimitry Andric         continue;
486*5ffd83dbSDimitry Andric       /// AssumesInBB is already sorted by order in the block.
487*5ffd83dbSDimitry Andric 
488*5ffd83dbSDimitry Andric       BasicBlock::iterator It = AssumesInBB.front()->getIterator();
489*5ffd83dbSDimitry Andric       BasicBlock::iterator E = AssumesInBB.back()->getIterator();
490*5ffd83dbSDimitry Andric       SplitPoints.push_back(AssumesInBB.begin());
491*5ffd83dbSDimitry Andric       MergeIterator LastSplit = AssumesInBB.begin();
492*5ffd83dbSDimitry Andric       for (; It != E; ++It)
493*5ffd83dbSDimitry Andric         if (!isGuaranteedToTransferExecutionToSuccessor(&*It)) {
494*5ffd83dbSDimitry Andric           for (; (*LastSplit)->comesBefore(&*It); ++LastSplit)
495*5ffd83dbSDimitry Andric             ;
496*5ffd83dbSDimitry Andric           if (SplitPoints.back() != LastSplit)
497*5ffd83dbSDimitry Andric             SplitPoints.push_back(LastSplit);
498*5ffd83dbSDimitry Andric         }
499*5ffd83dbSDimitry Andric       SplitPoints.push_back(AssumesInBB.end());
500*5ffd83dbSDimitry Andric       for (auto SplitIt = SplitPoints.begin();
501*5ffd83dbSDimitry Andric            SplitIt != std::prev(SplitPoints.end()); SplitIt++) {
502*5ffd83dbSDimitry Andric         mergeRange(Elem.first, *SplitIt, *(SplitIt + 1));
503*5ffd83dbSDimitry Andric       }
504*5ffd83dbSDimitry Andric       SplitPoints.clear();
505*5ffd83dbSDimitry Andric     }
506*5ffd83dbSDimitry Andric   }
507*5ffd83dbSDimitry Andric };
508*5ffd83dbSDimitry Andric 
509*5ffd83dbSDimitry Andric bool simplifyAssumes(Function &F, AssumptionCache *AC, DominatorTree *DT) {
510*5ffd83dbSDimitry Andric   AssumeSimplify AS(F, *AC, DT, F.getContext());
511*5ffd83dbSDimitry Andric 
512*5ffd83dbSDimitry Andric   /// Remove knowledge that is already known by a dominating other assume or an
513*5ffd83dbSDimitry Andric   /// attribute.
514*5ffd83dbSDimitry Andric   AS.dropRedundantKnowledge();
515*5ffd83dbSDimitry Andric 
516*5ffd83dbSDimitry Andric   /// Remove assume that are empty.
517*5ffd83dbSDimitry Andric   AS.RunCleanup(false);
518*5ffd83dbSDimitry Andric 
519*5ffd83dbSDimitry Andric   /// Merge assume in the same basicblock when possible.
520*5ffd83dbSDimitry Andric   AS.mergeAssumes();
521*5ffd83dbSDimitry Andric 
522*5ffd83dbSDimitry Andric   /// Remove assume that were merged.
523*5ffd83dbSDimitry Andric   AS.RunCleanup(true);
524*5ffd83dbSDimitry Andric   return AS.MadeChange;
525*5ffd83dbSDimitry Andric }
526*5ffd83dbSDimitry Andric 
527*5ffd83dbSDimitry Andric } // namespace
528*5ffd83dbSDimitry Andric 
529*5ffd83dbSDimitry Andric PreservedAnalyses AssumeSimplifyPass::run(Function &F,
530*5ffd83dbSDimitry Andric                                           FunctionAnalysisManager &AM) {
531*5ffd83dbSDimitry Andric   if (!EnableKnowledgeRetention)
532*5ffd83dbSDimitry Andric     return PreservedAnalyses::all();
533*5ffd83dbSDimitry Andric   simplifyAssumes(F, &AM.getResult<AssumptionAnalysis>(F),
534*5ffd83dbSDimitry Andric                   AM.getCachedResult<DominatorTreeAnalysis>(F));
535*5ffd83dbSDimitry Andric   return PreservedAnalyses::all();
536*5ffd83dbSDimitry Andric }
537*5ffd83dbSDimitry Andric 
538*5ffd83dbSDimitry Andric namespace {
539*5ffd83dbSDimitry Andric class AssumeSimplifyPassLegacyPass : public FunctionPass {
540*5ffd83dbSDimitry Andric public:
541*5ffd83dbSDimitry Andric   static char ID;
542*5ffd83dbSDimitry Andric 
543*5ffd83dbSDimitry Andric   AssumeSimplifyPassLegacyPass() : FunctionPass(ID) {
544*5ffd83dbSDimitry Andric     initializeAssumeSimplifyPassLegacyPassPass(
545*5ffd83dbSDimitry Andric         *PassRegistry::getPassRegistry());
546*5ffd83dbSDimitry Andric   }
547*5ffd83dbSDimitry Andric   bool runOnFunction(Function &F) override {
548*5ffd83dbSDimitry Andric     if (skipFunction(F) || !EnableKnowledgeRetention)
549*5ffd83dbSDimitry Andric       return false;
550*5ffd83dbSDimitry Andric     AssumptionCache &AC =
551*5ffd83dbSDimitry Andric         getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F);
552*5ffd83dbSDimitry Andric     DominatorTreeWrapperPass *DTWP =
553*5ffd83dbSDimitry Andric         getAnalysisIfAvailable<DominatorTreeWrapperPass>();
554*5ffd83dbSDimitry Andric     return simplifyAssumes(F, &AC, DTWP ? &DTWP->getDomTree() : nullptr);
555*5ffd83dbSDimitry Andric   }
556*5ffd83dbSDimitry Andric 
557*5ffd83dbSDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {
558*5ffd83dbSDimitry Andric     AU.addRequired<AssumptionCacheTracker>();
559*5ffd83dbSDimitry Andric 
560*5ffd83dbSDimitry Andric     AU.setPreservesAll();
561*5ffd83dbSDimitry Andric   }
562*5ffd83dbSDimitry Andric };
563*5ffd83dbSDimitry Andric } // namespace
564*5ffd83dbSDimitry Andric 
565*5ffd83dbSDimitry Andric char AssumeSimplifyPassLegacyPass::ID = 0;
566*5ffd83dbSDimitry Andric 
567*5ffd83dbSDimitry Andric INITIALIZE_PASS_BEGIN(AssumeSimplifyPassLegacyPass, "assume-simplify",
568*5ffd83dbSDimitry Andric                       "Assume Simplify", false, false)
569*5ffd83dbSDimitry Andric INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
570*5ffd83dbSDimitry Andric INITIALIZE_PASS_END(AssumeSimplifyPassLegacyPass, "assume-simplify",
571*5ffd83dbSDimitry Andric                     "Assume Simplify", false, false)
572*5ffd83dbSDimitry Andric 
573*5ffd83dbSDimitry Andric FunctionPass *llvm::createAssumeSimplifyPass() {
574*5ffd83dbSDimitry Andric   return new AssumeSimplifyPassLegacyPass();
575*5ffd83dbSDimitry Andric }
576*5ffd83dbSDimitry Andric 
577*5ffd83dbSDimitry Andric PreservedAnalyses AssumeBuilderPass::run(Function &F,
578*5ffd83dbSDimitry Andric                                          FunctionAnalysisManager &AM) {
579*5ffd83dbSDimitry Andric   AssumptionCache *AC = &AM.getResult<AssumptionAnalysis>(F);
580*5ffd83dbSDimitry Andric   DominatorTree* DT = AM.getCachedResult<DominatorTreeAnalysis>(F);
581*5ffd83dbSDimitry Andric   for (Instruction &I : instructions(F))
582*5ffd83dbSDimitry Andric     salvageKnowledge(&I, AC, DT);
583*5ffd83dbSDimitry Andric   return PreservedAnalyses::all();
584*5ffd83dbSDimitry Andric }
585*5ffd83dbSDimitry Andric 
586*5ffd83dbSDimitry Andric namespace {
587*5ffd83dbSDimitry Andric class AssumeBuilderPassLegacyPass : public FunctionPass {
588*5ffd83dbSDimitry Andric public:
589*5ffd83dbSDimitry Andric   static char ID;
590*5ffd83dbSDimitry Andric 
591*5ffd83dbSDimitry Andric   AssumeBuilderPassLegacyPass() : FunctionPass(ID) {
592*5ffd83dbSDimitry Andric     initializeAssumeBuilderPassLegacyPassPass(*PassRegistry::getPassRegistry());
593*5ffd83dbSDimitry Andric   }
594*5ffd83dbSDimitry Andric   bool runOnFunction(Function &F) override {
595*5ffd83dbSDimitry Andric     AssumptionCache &AC =
596*5ffd83dbSDimitry Andric         getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F);
597*5ffd83dbSDimitry Andric     DominatorTreeWrapperPass *DTWP =
598*5ffd83dbSDimitry Andric         getAnalysisIfAvailable<DominatorTreeWrapperPass>();
599*5ffd83dbSDimitry Andric     for (Instruction &I : instructions(F))
600*5ffd83dbSDimitry Andric       salvageKnowledge(&I, &AC, DTWP ? &DTWP->getDomTree() : nullptr);
601*5ffd83dbSDimitry Andric     return true;
602*5ffd83dbSDimitry Andric   }
603*5ffd83dbSDimitry Andric 
604*5ffd83dbSDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {
605*5ffd83dbSDimitry Andric     AU.addRequired<AssumptionCacheTracker>();
606*5ffd83dbSDimitry Andric 
607*5ffd83dbSDimitry Andric     AU.setPreservesAll();
608*5ffd83dbSDimitry Andric   }
609*5ffd83dbSDimitry Andric };
610*5ffd83dbSDimitry Andric } // namespace
611*5ffd83dbSDimitry Andric 
612*5ffd83dbSDimitry Andric char AssumeBuilderPassLegacyPass::ID = 0;
613*5ffd83dbSDimitry Andric 
614*5ffd83dbSDimitry Andric INITIALIZE_PASS_BEGIN(AssumeBuilderPassLegacyPass, "assume-builder",
615*5ffd83dbSDimitry Andric                       "Assume Builder", false, false)
616*5ffd83dbSDimitry Andric INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
617*5ffd83dbSDimitry Andric INITIALIZE_PASS_END(AssumeBuilderPassLegacyPass, "assume-builder",
618*5ffd83dbSDimitry Andric                     "Assume Builder", false, false)
619