1*9880d681SAndroid Build Coastguard Worker //===- LoopLoadElimination.cpp - Loop Load Elimination Pass ---------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This file implement a loop-aware load elimination pass.
11*9880d681SAndroid Build Coastguard Worker //
12*9880d681SAndroid Build Coastguard Worker // It uses LoopAccessAnalysis to identify loop-carried dependences with a
13*9880d681SAndroid Build Coastguard Worker // distance of one between stores and loads. These form the candidates for the
14*9880d681SAndroid Build Coastguard Worker // transformation. The source value of each store then propagated to the user
15*9880d681SAndroid Build Coastguard Worker // of the corresponding load. This makes the load dead.
16*9880d681SAndroid Build Coastguard Worker //
17*9880d681SAndroid Build Coastguard Worker // The pass can also version the loop and add memchecks in order to prove that
18*9880d681SAndroid Build Coastguard Worker // may-aliasing stores can't change the value in memory before it's read by the
19*9880d681SAndroid Build Coastguard Worker // load.
20*9880d681SAndroid Build Coastguard Worker //
21*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
22*9880d681SAndroid Build Coastguard Worker
23*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/Statistic.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/LoopAccessAnalysis.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/LoopInfo.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/ScalarEvolutionExpander.h"
27*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Dominators.h"
28*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Module.h"
29*9880d681SAndroid Build Coastguard Worker #include "llvm/Pass.h"
30*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Debug.h"
31*9880d681SAndroid Build Coastguard Worker #include "llvm/Transforms/Scalar.h"
32*9880d681SAndroid Build Coastguard Worker #include "llvm/Transforms/Utils/LoopVersioning.h"
33*9880d681SAndroid Build Coastguard Worker #include <forward_list>
34*9880d681SAndroid Build Coastguard Worker
35*9880d681SAndroid Build Coastguard Worker #define LLE_OPTION "loop-load-elim"
36*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE LLE_OPTION
37*9880d681SAndroid Build Coastguard Worker
38*9880d681SAndroid Build Coastguard Worker using namespace llvm;
39*9880d681SAndroid Build Coastguard Worker
40*9880d681SAndroid Build Coastguard Worker static cl::opt<unsigned> CheckPerElim(
41*9880d681SAndroid Build Coastguard Worker "runtime-check-per-loop-load-elim", cl::Hidden,
42*9880d681SAndroid Build Coastguard Worker cl::desc("Max number of memchecks allowed per eliminated load on average"),
43*9880d681SAndroid Build Coastguard Worker cl::init(1));
44*9880d681SAndroid Build Coastguard Worker
45*9880d681SAndroid Build Coastguard Worker static cl::opt<unsigned> LoadElimSCEVCheckThreshold(
46*9880d681SAndroid Build Coastguard Worker "loop-load-elimination-scev-check-threshold", cl::init(8), cl::Hidden,
47*9880d681SAndroid Build Coastguard Worker cl::desc("The maximum number of SCEV checks allowed for Loop "
48*9880d681SAndroid Build Coastguard Worker "Load Elimination"));
49*9880d681SAndroid Build Coastguard Worker
50*9880d681SAndroid Build Coastguard Worker
51*9880d681SAndroid Build Coastguard Worker STATISTIC(NumLoopLoadEliminted, "Number of loads eliminated by LLE");
52*9880d681SAndroid Build Coastguard Worker
53*9880d681SAndroid Build Coastguard Worker namespace {
54*9880d681SAndroid Build Coastguard Worker
55*9880d681SAndroid Build Coastguard Worker /// \brief Represent a store-to-forwarding candidate.
56*9880d681SAndroid Build Coastguard Worker struct StoreToLoadForwardingCandidate {
57*9880d681SAndroid Build Coastguard Worker LoadInst *Load;
58*9880d681SAndroid Build Coastguard Worker StoreInst *Store;
59*9880d681SAndroid Build Coastguard Worker
StoreToLoadForwardingCandidate__anon3b45aabe0111::StoreToLoadForwardingCandidate60*9880d681SAndroid Build Coastguard Worker StoreToLoadForwardingCandidate(LoadInst *Load, StoreInst *Store)
61*9880d681SAndroid Build Coastguard Worker : Load(Load), Store(Store) {}
62*9880d681SAndroid Build Coastguard Worker
63*9880d681SAndroid Build Coastguard Worker /// \brief Return true if the dependence from the store to the load has a
64*9880d681SAndroid Build Coastguard Worker /// distance of one. E.g. A[i+1] = A[i]
isDependenceDistanceOfOne__anon3b45aabe0111::StoreToLoadForwardingCandidate65*9880d681SAndroid Build Coastguard Worker bool isDependenceDistanceOfOne(PredicatedScalarEvolution &PSE,
66*9880d681SAndroid Build Coastguard Worker Loop *L) const {
67*9880d681SAndroid Build Coastguard Worker Value *LoadPtr = Load->getPointerOperand();
68*9880d681SAndroid Build Coastguard Worker Value *StorePtr = Store->getPointerOperand();
69*9880d681SAndroid Build Coastguard Worker Type *LoadPtrType = LoadPtr->getType();
70*9880d681SAndroid Build Coastguard Worker Type *LoadType = LoadPtrType->getPointerElementType();
71*9880d681SAndroid Build Coastguard Worker
72*9880d681SAndroid Build Coastguard Worker assert(LoadPtrType->getPointerAddressSpace() ==
73*9880d681SAndroid Build Coastguard Worker StorePtr->getType()->getPointerAddressSpace() &&
74*9880d681SAndroid Build Coastguard Worker LoadType == StorePtr->getType()->getPointerElementType() &&
75*9880d681SAndroid Build Coastguard Worker "Should be a known dependence");
76*9880d681SAndroid Build Coastguard Worker
77*9880d681SAndroid Build Coastguard Worker // Currently we only support accesses with unit stride. FIXME: we should be
78*9880d681SAndroid Build Coastguard Worker // able to handle non unit stirde as well as long as the stride is equal to
79*9880d681SAndroid Build Coastguard Worker // the dependence distance.
80*9880d681SAndroid Build Coastguard Worker if (getPtrStride(PSE, LoadPtr, L) != 1 ||
81*9880d681SAndroid Build Coastguard Worker getPtrStride(PSE, StorePtr, L) != 1)
82*9880d681SAndroid Build Coastguard Worker return false;
83*9880d681SAndroid Build Coastguard Worker
84*9880d681SAndroid Build Coastguard Worker auto &DL = Load->getParent()->getModule()->getDataLayout();
85*9880d681SAndroid Build Coastguard Worker unsigned TypeByteSize = DL.getTypeAllocSize(const_cast<Type *>(LoadType));
86*9880d681SAndroid Build Coastguard Worker
87*9880d681SAndroid Build Coastguard Worker auto *LoadPtrSCEV = cast<SCEVAddRecExpr>(PSE.getSCEV(LoadPtr));
88*9880d681SAndroid Build Coastguard Worker auto *StorePtrSCEV = cast<SCEVAddRecExpr>(PSE.getSCEV(StorePtr));
89*9880d681SAndroid Build Coastguard Worker
90*9880d681SAndroid Build Coastguard Worker // We don't need to check non-wrapping here because forward/backward
91*9880d681SAndroid Build Coastguard Worker // dependence wouldn't be valid if these weren't monotonic accesses.
92*9880d681SAndroid Build Coastguard Worker auto *Dist = cast<SCEVConstant>(
93*9880d681SAndroid Build Coastguard Worker PSE.getSE()->getMinusSCEV(StorePtrSCEV, LoadPtrSCEV));
94*9880d681SAndroid Build Coastguard Worker const APInt &Val = Dist->getAPInt();
95*9880d681SAndroid Build Coastguard Worker return Val == TypeByteSize;
96*9880d681SAndroid Build Coastguard Worker }
97*9880d681SAndroid Build Coastguard Worker
getLoadPtr__anon3b45aabe0111::StoreToLoadForwardingCandidate98*9880d681SAndroid Build Coastguard Worker Value *getLoadPtr() const { return Load->getPointerOperand(); }
99*9880d681SAndroid Build Coastguard Worker
100*9880d681SAndroid Build Coastguard Worker #ifndef NDEBUG
operator <<(raw_ostream & OS,const StoreToLoadForwardingCandidate & Cand)101*9880d681SAndroid Build Coastguard Worker friend raw_ostream &operator<<(raw_ostream &OS,
102*9880d681SAndroid Build Coastguard Worker const StoreToLoadForwardingCandidate &Cand) {
103*9880d681SAndroid Build Coastguard Worker OS << *Cand.Store << " -->\n";
104*9880d681SAndroid Build Coastguard Worker OS.indent(2) << *Cand.Load << "\n";
105*9880d681SAndroid Build Coastguard Worker return OS;
106*9880d681SAndroid Build Coastguard Worker }
107*9880d681SAndroid Build Coastguard Worker #endif
108*9880d681SAndroid Build Coastguard Worker };
109*9880d681SAndroid Build Coastguard Worker
110*9880d681SAndroid Build Coastguard Worker /// \brief Check if the store dominates all latches, so as long as there is no
111*9880d681SAndroid Build Coastguard Worker /// intervening store this value will be loaded in the next iteration.
doesStoreDominatesAllLatches(BasicBlock * StoreBlock,Loop * L,DominatorTree * DT)112*9880d681SAndroid Build Coastguard Worker bool doesStoreDominatesAllLatches(BasicBlock *StoreBlock, Loop *L,
113*9880d681SAndroid Build Coastguard Worker DominatorTree *DT) {
114*9880d681SAndroid Build Coastguard Worker SmallVector<BasicBlock *, 8> Latches;
115*9880d681SAndroid Build Coastguard Worker L->getLoopLatches(Latches);
116*9880d681SAndroid Build Coastguard Worker return std::all_of(Latches.begin(), Latches.end(),
117*9880d681SAndroid Build Coastguard Worker [&](const BasicBlock *Latch) {
118*9880d681SAndroid Build Coastguard Worker return DT->dominates(StoreBlock, Latch);
119*9880d681SAndroid Build Coastguard Worker });
120*9880d681SAndroid Build Coastguard Worker }
121*9880d681SAndroid Build Coastguard Worker
122*9880d681SAndroid Build Coastguard Worker /// \brief Return true if the load is not executed on all paths in the loop.
isLoadConditional(LoadInst * Load,Loop * L)123*9880d681SAndroid Build Coastguard Worker static bool isLoadConditional(LoadInst *Load, Loop *L) {
124*9880d681SAndroid Build Coastguard Worker return Load->getParent() != L->getHeader();
125*9880d681SAndroid Build Coastguard Worker }
126*9880d681SAndroid Build Coastguard Worker
127*9880d681SAndroid Build Coastguard Worker /// \brief The per-loop class that does most of the work.
128*9880d681SAndroid Build Coastguard Worker class LoadEliminationForLoop {
129*9880d681SAndroid Build Coastguard Worker public:
LoadEliminationForLoop(Loop * L,LoopInfo * LI,const LoopAccessInfo & LAI,DominatorTree * DT)130*9880d681SAndroid Build Coastguard Worker LoadEliminationForLoop(Loop *L, LoopInfo *LI, const LoopAccessInfo &LAI,
131*9880d681SAndroid Build Coastguard Worker DominatorTree *DT)
132*9880d681SAndroid Build Coastguard Worker : L(L), LI(LI), LAI(LAI), DT(DT), PSE(LAI.getPSE()) {}
133*9880d681SAndroid Build Coastguard Worker
134*9880d681SAndroid Build Coastguard Worker /// \brief Look through the loop-carried and loop-independent dependences in
135*9880d681SAndroid Build Coastguard Worker /// this loop and find store->load dependences.
136*9880d681SAndroid Build Coastguard Worker ///
137*9880d681SAndroid Build Coastguard Worker /// Note that no candidate is returned if LAA has failed to analyze the loop
138*9880d681SAndroid Build Coastguard Worker /// (e.g. if it's not bottom-tested, contains volatile memops, etc.)
139*9880d681SAndroid Build Coastguard Worker std::forward_list<StoreToLoadForwardingCandidate>
findStoreToLoadDependences(const LoopAccessInfo & LAI)140*9880d681SAndroid Build Coastguard Worker findStoreToLoadDependences(const LoopAccessInfo &LAI) {
141*9880d681SAndroid Build Coastguard Worker std::forward_list<StoreToLoadForwardingCandidate> Candidates;
142*9880d681SAndroid Build Coastguard Worker
143*9880d681SAndroid Build Coastguard Worker const auto *Deps = LAI.getDepChecker().getDependences();
144*9880d681SAndroid Build Coastguard Worker if (!Deps)
145*9880d681SAndroid Build Coastguard Worker return Candidates;
146*9880d681SAndroid Build Coastguard Worker
147*9880d681SAndroid Build Coastguard Worker // Find store->load dependences (consequently true dep). Both lexically
148*9880d681SAndroid Build Coastguard Worker // forward and backward dependences qualify. Disqualify loads that have
149*9880d681SAndroid Build Coastguard Worker // other unknown dependences.
150*9880d681SAndroid Build Coastguard Worker
151*9880d681SAndroid Build Coastguard Worker SmallSet<Instruction *, 4> LoadsWithUnknownDepedence;
152*9880d681SAndroid Build Coastguard Worker
153*9880d681SAndroid Build Coastguard Worker for (const auto &Dep : *Deps) {
154*9880d681SAndroid Build Coastguard Worker Instruction *Source = Dep.getSource(LAI);
155*9880d681SAndroid Build Coastguard Worker Instruction *Destination = Dep.getDestination(LAI);
156*9880d681SAndroid Build Coastguard Worker
157*9880d681SAndroid Build Coastguard Worker if (Dep.Type == MemoryDepChecker::Dependence::Unknown) {
158*9880d681SAndroid Build Coastguard Worker if (isa<LoadInst>(Source))
159*9880d681SAndroid Build Coastguard Worker LoadsWithUnknownDepedence.insert(Source);
160*9880d681SAndroid Build Coastguard Worker if (isa<LoadInst>(Destination))
161*9880d681SAndroid Build Coastguard Worker LoadsWithUnknownDepedence.insert(Destination);
162*9880d681SAndroid Build Coastguard Worker continue;
163*9880d681SAndroid Build Coastguard Worker }
164*9880d681SAndroid Build Coastguard Worker
165*9880d681SAndroid Build Coastguard Worker if (Dep.isBackward())
166*9880d681SAndroid Build Coastguard Worker // Note that the designations source and destination follow the program
167*9880d681SAndroid Build Coastguard Worker // order, i.e. source is always first. (The direction is given by the
168*9880d681SAndroid Build Coastguard Worker // DepType.)
169*9880d681SAndroid Build Coastguard Worker std::swap(Source, Destination);
170*9880d681SAndroid Build Coastguard Worker else
171*9880d681SAndroid Build Coastguard Worker assert(Dep.isForward() && "Needs to be a forward dependence");
172*9880d681SAndroid Build Coastguard Worker
173*9880d681SAndroid Build Coastguard Worker auto *Store = dyn_cast<StoreInst>(Source);
174*9880d681SAndroid Build Coastguard Worker if (!Store)
175*9880d681SAndroid Build Coastguard Worker continue;
176*9880d681SAndroid Build Coastguard Worker auto *Load = dyn_cast<LoadInst>(Destination);
177*9880d681SAndroid Build Coastguard Worker if (!Load)
178*9880d681SAndroid Build Coastguard Worker continue;
179*9880d681SAndroid Build Coastguard Worker
180*9880d681SAndroid Build Coastguard Worker // Only progagate the value if they are of the same type.
181*9880d681SAndroid Build Coastguard Worker if (Store->getPointerOperand()->getType() !=
182*9880d681SAndroid Build Coastguard Worker Load->getPointerOperand()->getType())
183*9880d681SAndroid Build Coastguard Worker continue;
184*9880d681SAndroid Build Coastguard Worker
185*9880d681SAndroid Build Coastguard Worker Candidates.emplace_front(Load, Store);
186*9880d681SAndroid Build Coastguard Worker }
187*9880d681SAndroid Build Coastguard Worker
188*9880d681SAndroid Build Coastguard Worker if (!LoadsWithUnknownDepedence.empty())
189*9880d681SAndroid Build Coastguard Worker Candidates.remove_if([&](const StoreToLoadForwardingCandidate &C) {
190*9880d681SAndroid Build Coastguard Worker return LoadsWithUnknownDepedence.count(C.Load);
191*9880d681SAndroid Build Coastguard Worker });
192*9880d681SAndroid Build Coastguard Worker
193*9880d681SAndroid Build Coastguard Worker return Candidates;
194*9880d681SAndroid Build Coastguard Worker }
195*9880d681SAndroid Build Coastguard Worker
196*9880d681SAndroid Build Coastguard Worker /// \brief Return the index of the instruction according to program order.
getInstrIndex(Instruction * Inst)197*9880d681SAndroid Build Coastguard Worker unsigned getInstrIndex(Instruction *Inst) {
198*9880d681SAndroid Build Coastguard Worker auto I = InstOrder.find(Inst);
199*9880d681SAndroid Build Coastguard Worker assert(I != InstOrder.end() && "No index for instruction");
200*9880d681SAndroid Build Coastguard Worker return I->second;
201*9880d681SAndroid Build Coastguard Worker }
202*9880d681SAndroid Build Coastguard Worker
203*9880d681SAndroid Build Coastguard Worker /// \brief If a load has multiple candidates associated (i.e. different
204*9880d681SAndroid Build Coastguard Worker /// stores), it means that it could be forwarding from multiple stores
205*9880d681SAndroid Build Coastguard Worker /// depending on control flow. Remove these candidates.
206*9880d681SAndroid Build Coastguard Worker ///
207*9880d681SAndroid Build Coastguard Worker /// Here, we rely on LAA to include the relevant loop-independent dependences.
208*9880d681SAndroid Build Coastguard Worker /// LAA is known to omit these in the very simple case when the read and the
209*9880d681SAndroid Build Coastguard Worker /// write within an alias set always takes place using the *same* pointer.
210*9880d681SAndroid Build Coastguard Worker ///
211*9880d681SAndroid Build Coastguard Worker /// However, we know that this is not the case here, i.e. we can rely on LAA
212*9880d681SAndroid Build Coastguard Worker /// to provide us with loop-independent dependences for the cases we're
213*9880d681SAndroid Build Coastguard Worker /// interested. Consider the case for example where a loop-independent
214*9880d681SAndroid Build Coastguard Worker /// dependece S1->S2 invalidates the forwarding S3->S2.
215*9880d681SAndroid Build Coastguard Worker ///
216*9880d681SAndroid Build Coastguard Worker /// A[i] = ... (S1)
217*9880d681SAndroid Build Coastguard Worker /// ... = A[i] (S2)
218*9880d681SAndroid Build Coastguard Worker /// A[i+1] = ... (S3)
219*9880d681SAndroid Build Coastguard Worker ///
220*9880d681SAndroid Build Coastguard Worker /// LAA will perform dependence analysis here because there are two
221*9880d681SAndroid Build Coastguard Worker /// *different* pointers involved in the same alias set (&A[i] and &A[i+1]).
removeDependencesFromMultipleStores(std::forward_list<StoreToLoadForwardingCandidate> & Candidates)222*9880d681SAndroid Build Coastguard Worker void removeDependencesFromMultipleStores(
223*9880d681SAndroid Build Coastguard Worker std::forward_list<StoreToLoadForwardingCandidate> &Candidates) {
224*9880d681SAndroid Build Coastguard Worker // If Store is nullptr it means that we have multiple stores forwarding to
225*9880d681SAndroid Build Coastguard Worker // this store.
226*9880d681SAndroid Build Coastguard Worker typedef DenseMap<LoadInst *, const StoreToLoadForwardingCandidate *>
227*9880d681SAndroid Build Coastguard Worker LoadToSingleCandT;
228*9880d681SAndroid Build Coastguard Worker LoadToSingleCandT LoadToSingleCand;
229*9880d681SAndroid Build Coastguard Worker
230*9880d681SAndroid Build Coastguard Worker for (const auto &Cand : Candidates) {
231*9880d681SAndroid Build Coastguard Worker bool NewElt;
232*9880d681SAndroid Build Coastguard Worker LoadToSingleCandT::iterator Iter;
233*9880d681SAndroid Build Coastguard Worker
234*9880d681SAndroid Build Coastguard Worker std::tie(Iter, NewElt) =
235*9880d681SAndroid Build Coastguard Worker LoadToSingleCand.insert(std::make_pair(Cand.Load, &Cand));
236*9880d681SAndroid Build Coastguard Worker if (!NewElt) {
237*9880d681SAndroid Build Coastguard Worker const StoreToLoadForwardingCandidate *&OtherCand = Iter->second;
238*9880d681SAndroid Build Coastguard Worker // Already multiple stores forward to this load.
239*9880d681SAndroid Build Coastguard Worker if (OtherCand == nullptr)
240*9880d681SAndroid Build Coastguard Worker continue;
241*9880d681SAndroid Build Coastguard Worker
242*9880d681SAndroid Build Coastguard Worker // Handle the very basic case when the two stores are in the same block
243*9880d681SAndroid Build Coastguard Worker // so deciding which one forwards is easy. The later one forwards as
244*9880d681SAndroid Build Coastguard Worker // long as they both have a dependence distance of one to the load.
245*9880d681SAndroid Build Coastguard Worker if (Cand.Store->getParent() == OtherCand->Store->getParent() &&
246*9880d681SAndroid Build Coastguard Worker Cand.isDependenceDistanceOfOne(PSE, L) &&
247*9880d681SAndroid Build Coastguard Worker OtherCand->isDependenceDistanceOfOne(PSE, L)) {
248*9880d681SAndroid Build Coastguard Worker // They are in the same block, the later one will forward to the load.
249*9880d681SAndroid Build Coastguard Worker if (getInstrIndex(OtherCand->Store) < getInstrIndex(Cand.Store))
250*9880d681SAndroid Build Coastguard Worker OtherCand = &Cand;
251*9880d681SAndroid Build Coastguard Worker } else
252*9880d681SAndroid Build Coastguard Worker OtherCand = nullptr;
253*9880d681SAndroid Build Coastguard Worker }
254*9880d681SAndroid Build Coastguard Worker }
255*9880d681SAndroid Build Coastguard Worker
256*9880d681SAndroid Build Coastguard Worker Candidates.remove_if([&](const StoreToLoadForwardingCandidate &Cand) {
257*9880d681SAndroid Build Coastguard Worker if (LoadToSingleCand[Cand.Load] != &Cand) {
258*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Removing from candidates: \n" << Cand
259*9880d681SAndroid Build Coastguard Worker << " The load may have multiple stores forwarding to "
260*9880d681SAndroid Build Coastguard Worker << "it\n");
261*9880d681SAndroid Build Coastguard Worker return true;
262*9880d681SAndroid Build Coastguard Worker }
263*9880d681SAndroid Build Coastguard Worker return false;
264*9880d681SAndroid Build Coastguard Worker });
265*9880d681SAndroid Build Coastguard Worker }
266*9880d681SAndroid Build Coastguard Worker
267*9880d681SAndroid Build Coastguard Worker /// \brief Given two pointers operations by their RuntimePointerChecking
268*9880d681SAndroid Build Coastguard Worker /// indices, return true if they require an alias check.
269*9880d681SAndroid Build Coastguard Worker ///
270*9880d681SAndroid Build Coastguard Worker /// We need a check if one is a pointer for a candidate load and the other is
271*9880d681SAndroid Build Coastguard Worker /// a pointer for a possibly intervening store.
needsChecking(unsigned PtrIdx1,unsigned PtrIdx2,const SmallSet<Value *,4> & PtrsWrittenOnFwdingPath,const std::set<Value * > & CandLoadPtrs)272*9880d681SAndroid Build Coastguard Worker bool needsChecking(unsigned PtrIdx1, unsigned PtrIdx2,
273*9880d681SAndroid Build Coastguard Worker const SmallSet<Value *, 4> &PtrsWrittenOnFwdingPath,
274*9880d681SAndroid Build Coastguard Worker const std::set<Value *> &CandLoadPtrs) {
275*9880d681SAndroid Build Coastguard Worker Value *Ptr1 =
276*9880d681SAndroid Build Coastguard Worker LAI.getRuntimePointerChecking()->getPointerInfo(PtrIdx1).PointerValue;
277*9880d681SAndroid Build Coastguard Worker Value *Ptr2 =
278*9880d681SAndroid Build Coastguard Worker LAI.getRuntimePointerChecking()->getPointerInfo(PtrIdx2).PointerValue;
279*9880d681SAndroid Build Coastguard Worker return ((PtrsWrittenOnFwdingPath.count(Ptr1) && CandLoadPtrs.count(Ptr2)) ||
280*9880d681SAndroid Build Coastguard Worker (PtrsWrittenOnFwdingPath.count(Ptr2) && CandLoadPtrs.count(Ptr1)));
281*9880d681SAndroid Build Coastguard Worker }
282*9880d681SAndroid Build Coastguard Worker
283*9880d681SAndroid Build Coastguard Worker /// \brief Return pointers that are possibly written to on the path from a
284*9880d681SAndroid Build Coastguard Worker /// forwarding store to a load.
285*9880d681SAndroid Build Coastguard Worker ///
286*9880d681SAndroid Build Coastguard Worker /// These pointers need to be alias-checked against the forwarding candidates.
findPointersWrittenOnForwardingPath(const SmallVectorImpl<StoreToLoadForwardingCandidate> & Candidates)287*9880d681SAndroid Build Coastguard Worker SmallSet<Value *, 4> findPointersWrittenOnForwardingPath(
288*9880d681SAndroid Build Coastguard Worker const SmallVectorImpl<StoreToLoadForwardingCandidate> &Candidates) {
289*9880d681SAndroid Build Coastguard Worker // From FirstStore to LastLoad neither of the elimination candidate loads
290*9880d681SAndroid Build Coastguard Worker // should overlap with any of the stores.
291*9880d681SAndroid Build Coastguard Worker //
292*9880d681SAndroid Build Coastguard Worker // E.g.:
293*9880d681SAndroid Build Coastguard Worker //
294*9880d681SAndroid Build Coastguard Worker // st1 C[i]
295*9880d681SAndroid Build Coastguard Worker // ld1 B[i] <-------,
296*9880d681SAndroid Build Coastguard Worker // ld0 A[i] <----, | * LastLoad
297*9880d681SAndroid Build Coastguard Worker // ... | |
298*9880d681SAndroid Build Coastguard Worker // st2 E[i] | |
299*9880d681SAndroid Build Coastguard Worker // st3 B[i+1] -- | -' * FirstStore
300*9880d681SAndroid Build Coastguard Worker // st0 A[i+1] ---'
301*9880d681SAndroid Build Coastguard Worker // st4 D[i]
302*9880d681SAndroid Build Coastguard Worker //
303*9880d681SAndroid Build Coastguard Worker // st0 forwards to ld0 if the accesses in st4 and st1 don't overlap with
304*9880d681SAndroid Build Coastguard Worker // ld0.
305*9880d681SAndroid Build Coastguard Worker
306*9880d681SAndroid Build Coastguard Worker LoadInst *LastLoad =
307*9880d681SAndroid Build Coastguard Worker std::max_element(Candidates.begin(), Candidates.end(),
308*9880d681SAndroid Build Coastguard Worker [&](const StoreToLoadForwardingCandidate &A,
309*9880d681SAndroid Build Coastguard Worker const StoreToLoadForwardingCandidate &B) {
310*9880d681SAndroid Build Coastguard Worker return getInstrIndex(A.Load) < getInstrIndex(B.Load);
311*9880d681SAndroid Build Coastguard Worker })
312*9880d681SAndroid Build Coastguard Worker ->Load;
313*9880d681SAndroid Build Coastguard Worker StoreInst *FirstStore =
314*9880d681SAndroid Build Coastguard Worker std::min_element(Candidates.begin(), Candidates.end(),
315*9880d681SAndroid Build Coastguard Worker [&](const StoreToLoadForwardingCandidate &A,
316*9880d681SAndroid Build Coastguard Worker const StoreToLoadForwardingCandidate &B) {
317*9880d681SAndroid Build Coastguard Worker return getInstrIndex(A.Store) <
318*9880d681SAndroid Build Coastguard Worker getInstrIndex(B.Store);
319*9880d681SAndroid Build Coastguard Worker })
320*9880d681SAndroid Build Coastguard Worker ->Store;
321*9880d681SAndroid Build Coastguard Worker
322*9880d681SAndroid Build Coastguard Worker // We're looking for stores after the first forwarding store until the end
323*9880d681SAndroid Build Coastguard Worker // of the loop, then from the beginning of the loop until the last
324*9880d681SAndroid Build Coastguard Worker // forwarded-to load. Collect the pointer for the stores.
325*9880d681SAndroid Build Coastguard Worker SmallSet<Value *, 4> PtrsWrittenOnFwdingPath;
326*9880d681SAndroid Build Coastguard Worker
327*9880d681SAndroid Build Coastguard Worker auto InsertStorePtr = [&](Instruction *I) {
328*9880d681SAndroid Build Coastguard Worker if (auto *S = dyn_cast<StoreInst>(I))
329*9880d681SAndroid Build Coastguard Worker PtrsWrittenOnFwdingPath.insert(S->getPointerOperand());
330*9880d681SAndroid Build Coastguard Worker };
331*9880d681SAndroid Build Coastguard Worker const auto &MemInstrs = LAI.getDepChecker().getMemoryInstructions();
332*9880d681SAndroid Build Coastguard Worker std::for_each(MemInstrs.begin() + getInstrIndex(FirstStore) + 1,
333*9880d681SAndroid Build Coastguard Worker MemInstrs.end(), InsertStorePtr);
334*9880d681SAndroid Build Coastguard Worker std::for_each(MemInstrs.begin(), &MemInstrs[getInstrIndex(LastLoad)],
335*9880d681SAndroid Build Coastguard Worker InsertStorePtr);
336*9880d681SAndroid Build Coastguard Worker
337*9880d681SAndroid Build Coastguard Worker return PtrsWrittenOnFwdingPath;
338*9880d681SAndroid Build Coastguard Worker }
339*9880d681SAndroid Build Coastguard Worker
340*9880d681SAndroid Build Coastguard Worker /// \brief Determine the pointer alias checks to prove that there are no
341*9880d681SAndroid Build Coastguard Worker /// intervening stores.
collectMemchecks(const SmallVectorImpl<StoreToLoadForwardingCandidate> & Candidates)342*9880d681SAndroid Build Coastguard Worker SmallVector<RuntimePointerChecking::PointerCheck, 4> collectMemchecks(
343*9880d681SAndroid Build Coastguard Worker const SmallVectorImpl<StoreToLoadForwardingCandidate> &Candidates) {
344*9880d681SAndroid Build Coastguard Worker
345*9880d681SAndroid Build Coastguard Worker SmallSet<Value *, 4> PtrsWrittenOnFwdingPath =
346*9880d681SAndroid Build Coastguard Worker findPointersWrittenOnForwardingPath(Candidates);
347*9880d681SAndroid Build Coastguard Worker
348*9880d681SAndroid Build Coastguard Worker // Collect the pointers of the candidate loads.
349*9880d681SAndroid Build Coastguard Worker // FIXME: SmallSet does not work with std::inserter.
350*9880d681SAndroid Build Coastguard Worker std::set<Value *> CandLoadPtrs;
351*9880d681SAndroid Build Coastguard Worker std::transform(Candidates.begin(), Candidates.end(),
352*9880d681SAndroid Build Coastguard Worker std::inserter(CandLoadPtrs, CandLoadPtrs.begin()),
353*9880d681SAndroid Build Coastguard Worker std::mem_fn(&StoreToLoadForwardingCandidate::getLoadPtr));
354*9880d681SAndroid Build Coastguard Worker
355*9880d681SAndroid Build Coastguard Worker const auto &AllChecks = LAI.getRuntimePointerChecking()->getChecks();
356*9880d681SAndroid Build Coastguard Worker SmallVector<RuntimePointerChecking::PointerCheck, 4> Checks;
357*9880d681SAndroid Build Coastguard Worker
358*9880d681SAndroid Build Coastguard Worker std::copy_if(AllChecks.begin(), AllChecks.end(), std::back_inserter(Checks),
359*9880d681SAndroid Build Coastguard Worker [&](const RuntimePointerChecking::PointerCheck &Check) {
360*9880d681SAndroid Build Coastguard Worker for (auto PtrIdx1 : Check.first->Members)
361*9880d681SAndroid Build Coastguard Worker for (auto PtrIdx2 : Check.second->Members)
362*9880d681SAndroid Build Coastguard Worker if (needsChecking(PtrIdx1, PtrIdx2,
363*9880d681SAndroid Build Coastguard Worker PtrsWrittenOnFwdingPath, CandLoadPtrs))
364*9880d681SAndroid Build Coastguard Worker return true;
365*9880d681SAndroid Build Coastguard Worker return false;
366*9880d681SAndroid Build Coastguard Worker });
367*9880d681SAndroid Build Coastguard Worker
368*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "\nPointer Checks (count: " << Checks.size() << "):\n");
369*9880d681SAndroid Build Coastguard Worker DEBUG(LAI.getRuntimePointerChecking()->printChecks(dbgs(), Checks));
370*9880d681SAndroid Build Coastguard Worker
371*9880d681SAndroid Build Coastguard Worker return Checks;
372*9880d681SAndroid Build Coastguard Worker }
373*9880d681SAndroid Build Coastguard Worker
374*9880d681SAndroid Build Coastguard Worker /// \brief Perform the transformation for a candidate.
375*9880d681SAndroid Build Coastguard Worker void
propagateStoredValueToLoadUsers(const StoreToLoadForwardingCandidate & Cand,SCEVExpander & SEE)376*9880d681SAndroid Build Coastguard Worker propagateStoredValueToLoadUsers(const StoreToLoadForwardingCandidate &Cand,
377*9880d681SAndroid Build Coastguard Worker SCEVExpander &SEE) {
378*9880d681SAndroid Build Coastguard Worker //
379*9880d681SAndroid Build Coastguard Worker // loop:
380*9880d681SAndroid Build Coastguard Worker // %x = load %gep_i
381*9880d681SAndroid Build Coastguard Worker // = ... %x
382*9880d681SAndroid Build Coastguard Worker // store %y, %gep_i_plus_1
383*9880d681SAndroid Build Coastguard Worker //
384*9880d681SAndroid Build Coastguard Worker // =>
385*9880d681SAndroid Build Coastguard Worker //
386*9880d681SAndroid Build Coastguard Worker // ph:
387*9880d681SAndroid Build Coastguard Worker // %x.initial = load %gep_0
388*9880d681SAndroid Build Coastguard Worker // loop:
389*9880d681SAndroid Build Coastguard Worker // %x.storeforward = phi [%x.initial, %ph] [%y, %loop]
390*9880d681SAndroid Build Coastguard Worker // %x = load %gep_i <---- now dead
391*9880d681SAndroid Build Coastguard Worker // = ... %x.storeforward
392*9880d681SAndroid Build Coastguard Worker // store %y, %gep_i_plus_1
393*9880d681SAndroid Build Coastguard Worker
394*9880d681SAndroid Build Coastguard Worker Value *Ptr = Cand.Load->getPointerOperand();
395*9880d681SAndroid Build Coastguard Worker auto *PtrSCEV = cast<SCEVAddRecExpr>(PSE.getSCEV(Ptr));
396*9880d681SAndroid Build Coastguard Worker auto *PH = L->getLoopPreheader();
397*9880d681SAndroid Build Coastguard Worker Value *InitialPtr = SEE.expandCodeFor(PtrSCEV->getStart(), Ptr->getType(),
398*9880d681SAndroid Build Coastguard Worker PH->getTerminator());
399*9880d681SAndroid Build Coastguard Worker Value *Initial =
400*9880d681SAndroid Build Coastguard Worker new LoadInst(InitialPtr, "load_initial", PH->getTerminator());
401*9880d681SAndroid Build Coastguard Worker PHINode *PHI = PHINode::Create(Initial->getType(), 2, "store_forwarded",
402*9880d681SAndroid Build Coastguard Worker &L->getHeader()->front());
403*9880d681SAndroid Build Coastguard Worker PHI->addIncoming(Initial, PH);
404*9880d681SAndroid Build Coastguard Worker PHI->addIncoming(Cand.Store->getOperand(0), L->getLoopLatch());
405*9880d681SAndroid Build Coastguard Worker
406*9880d681SAndroid Build Coastguard Worker Cand.Load->replaceAllUsesWith(PHI);
407*9880d681SAndroid Build Coastguard Worker }
408*9880d681SAndroid Build Coastguard Worker
409*9880d681SAndroid Build Coastguard Worker /// \brief Top-level driver for each loop: find store->load forwarding
410*9880d681SAndroid Build Coastguard Worker /// candidates, add run-time checks and perform transformation.
processLoop()411*9880d681SAndroid Build Coastguard Worker bool processLoop() {
412*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "\nIn \"" << L->getHeader()->getParent()->getName()
413*9880d681SAndroid Build Coastguard Worker << "\" checking " << *L << "\n");
414*9880d681SAndroid Build Coastguard Worker // Look for store-to-load forwarding cases across the
415*9880d681SAndroid Build Coastguard Worker // backedge. E.g.:
416*9880d681SAndroid Build Coastguard Worker //
417*9880d681SAndroid Build Coastguard Worker // loop:
418*9880d681SAndroid Build Coastguard Worker // %x = load %gep_i
419*9880d681SAndroid Build Coastguard Worker // = ... %x
420*9880d681SAndroid Build Coastguard Worker // store %y, %gep_i_plus_1
421*9880d681SAndroid Build Coastguard Worker //
422*9880d681SAndroid Build Coastguard Worker // =>
423*9880d681SAndroid Build Coastguard Worker //
424*9880d681SAndroid Build Coastguard Worker // ph:
425*9880d681SAndroid Build Coastguard Worker // %x.initial = load %gep_0
426*9880d681SAndroid Build Coastguard Worker // loop:
427*9880d681SAndroid Build Coastguard Worker // %x.storeforward = phi [%x.initial, %ph] [%y, %loop]
428*9880d681SAndroid Build Coastguard Worker // %x = load %gep_i <---- now dead
429*9880d681SAndroid Build Coastguard Worker // = ... %x.storeforward
430*9880d681SAndroid Build Coastguard Worker // store %y, %gep_i_plus_1
431*9880d681SAndroid Build Coastguard Worker
432*9880d681SAndroid Build Coastguard Worker // First start with store->load dependences.
433*9880d681SAndroid Build Coastguard Worker auto StoreToLoadDependences = findStoreToLoadDependences(LAI);
434*9880d681SAndroid Build Coastguard Worker if (StoreToLoadDependences.empty())
435*9880d681SAndroid Build Coastguard Worker return false;
436*9880d681SAndroid Build Coastguard Worker
437*9880d681SAndroid Build Coastguard Worker // Generate an index for each load and store according to the original
438*9880d681SAndroid Build Coastguard Worker // program order. This will be used later.
439*9880d681SAndroid Build Coastguard Worker InstOrder = LAI.getDepChecker().generateInstructionOrderMap();
440*9880d681SAndroid Build Coastguard Worker
441*9880d681SAndroid Build Coastguard Worker // To keep things simple for now, remove those where the load is potentially
442*9880d681SAndroid Build Coastguard Worker // fed by multiple stores.
443*9880d681SAndroid Build Coastguard Worker removeDependencesFromMultipleStores(StoreToLoadDependences);
444*9880d681SAndroid Build Coastguard Worker if (StoreToLoadDependences.empty())
445*9880d681SAndroid Build Coastguard Worker return false;
446*9880d681SAndroid Build Coastguard Worker
447*9880d681SAndroid Build Coastguard Worker // Filter the candidates further.
448*9880d681SAndroid Build Coastguard Worker SmallVector<StoreToLoadForwardingCandidate, 4> Candidates;
449*9880d681SAndroid Build Coastguard Worker unsigned NumForwarding = 0;
450*9880d681SAndroid Build Coastguard Worker for (const StoreToLoadForwardingCandidate Cand : StoreToLoadDependences) {
451*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Candidate " << Cand);
452*9880d681SAndroid Build Coastguard Worker
453*9880d681SAndroid Build Coastguard Worker // Make sure that the stored values is available everywhere in the loop in
454*9880d681SAndroid Build Coastguard Worker // the next iteration.
455*9880d681SAndroid Build Coastguard Worker if (!doesStoreDominatesAllLatches(Cand.Store->getParent(), L, DT))
456*9880d681SAndroid Build Coastguard Worker continue;
457*9880d681SAndroid Build Coastguard Worker
458*9880d681SAndroid Build Coastguard Worker // If the load is conditional we can't hoist its 0-iteration instance to
459*9880d681SAndroid Build Coastguard Worker // the preheader because that would make it unconditional. Thus we would
460*9880d681SAndroid Build Coastguard Worker // access a memory location that the original loop did not access.
461*9880d681SAndroid Build Coastguard Worker if (isLoadConditional(Cand.Load, L))
462*9880d681SAndroid Build Coastguard Worker continue;
463*9880d681SAndroid Build Coastguard Worker
464*9880d681SAndroid Build Coastguard Worker // Check whether the SCEV difference is the same as the induction step,
465*9880d681SAndroid Build Coastguard Worker // thus we load the value in the next iteration.
466*9880d681SAndroid Build Coastguard Worker if (!Cand.isDependenceDistanceOfOne(PSE, L))
467*9880d681SAndroid Build Coastguard Worker continue;
468*9880d681SAndroid Build Coastguard Worker
469*9880d681SAndroid Build Coastguard Worker ++NumForwarding;
470*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs()
471*9880d681SAndroid Build Coastguard Worker << NumForwarding
472*9880d681SAndroid Build Coastguard Worker << ". Valid store-to-load forwarding across the loop backedge\n");
473*9880d681SAndroid Build Coastguard Worker Candidates.push_back(Cand);
474*9880d681SAndroid Build Coastguard Worker }
475*9880d681SAndroid Build Coastguard Worker if (Candidates.empty())
476*9880d681SAndroid Build Coastguard Worker return false;
477*9880d681SAndroid Build Coastguard Worker
478*9880d681SAndroid Build Coastguard Worker // Check intervening may-alias stores. These need runtime checks for alias
479*9880d681SAndroid Build Coastguard Worker // disambiguation.
480*9880d681SAndroid Build Coastguard Worker SmallVector<RuntimePointerChecking::PointerCheck, 4> Checks =
481*9880d681SAndroid Build Coastguard Worker collectMemchecks(Candidates);
482*9880d681SAndroid Build Coastguard Worker
483*9880d681SAndroid Build Coastguard Worker // Too many checks are likely to outweigh the benefits of forwarding.
484*9880d681SAndroid Build Coastguard Worker if (Checks.size() > Candidates.size() * CheckPerElim) {
485*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Too many run-time checks needed.\n");
486*9880d681SAndroid Build Coastguard Worker return false;
487*9880d681SAndroid Build Coastguard Worker }
488*9880d681SAndroid Build Coastguard Worker
489*9880d681SAndroid Build Coastguard Worker if (LAI.getPSE().getUnionPredicate().getComplexity() >
490*9880d681SAndroid Build Coastguard Worker LoadElimSCEVCheckThreshold) {
491*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Too many SCEV run-time checks needed.\n");
492*9880d681SAndroid Build Coastguard Worker return false;
493*9880d681SAndroid Build Coastguard Worker }
494*9880d681SAndroid Build Coastguard Worker
495*9880d681SAndroid Build Coastguard Worker if (!Checks.empty() || !LAI.getPSE().getUnionPredicate().isAlwaysTrue()) {
496*9880d681SAndroid Build Coastguard Worker if (L->getHeader()->getParent()->optForSize()) {
497*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Versioning is needed but not allowed when optimizing "
498*9880d681SAndroid Build Coastguard Worker "for size.\n");
499*9880d681SAndroid Build Coastguard Worker return false;
500*9880d681SAndroid Build Coastguard Worker }
501*9880d681SAndroid Build Coastguard Worker
502*9880d681SAndroid Build Coastguard Worker // Point of no-return, start the transformation. First, version the loop
503*9880d681SAndroid Build Coastguard Worker // if necessary.
504*9880d681SAndroid Build Coastguard Worker
505*9880d681SAndroid Build Coastguard Worker LoopVersioning LV(LAI, L, LI, DT, PSE.getSE(), false);
506*9880d681SAndroid Build Coastguard Worker LV.setAliasChecks(std::move(Checks));
507*9880d681SAndroid Build Coastguard Worker LV.setSCEVChecks(LAI.getPSE().getUnionPredicate());
508*9880d681SAndroid Build Coastguard Worker LV.versionLoop();
509*9880d681SAndroid Build Coastguard Worker }
510*9880d681SAndroid Build Coastguard Worker
511*9880d681SAndroid Build Coastguard Worker // Next, propagate the value stored by the store to the users of the load.
512*9880d681SAndroid Build Coastguard Worker // Also for the first iteration, generate the initial value of the load.
513*9880d681SAndroid Build Coastguard Worker SCEVExpander SEE(*PSE.getSE(), L->getHeader()->getModule()->getDataLayout(),
514*9880d681SAndroid Build Coastguard Worker "storeforward");
515*9880d681SAndroid Build Coastguard Worker for (const auto &Cand : Candidates)
516*9880d681SAndroid Build Coastguard Worker propagateStoredValueToLoadUsers(Cand, SEE);
517*9880d681SAndroid Build Coastguard Worker NumLoopLoadEliminted += NumForwarding;
518*9880d681SAndroid Build Coastguard Worker
519*9880d681SAndroid Build Coastguard Worker return true;
520*9880d681SAndroid Build Coastguard Worker }
521*9880d681SAndroid Build Coastguard Worker
522*9880d681SAndroid Build Coastguard Worker private:
523*9880d681SAndroid Build Coastguard Worker Loop *L;
524*9880d681SAndroid Build Coastguard Worker
525*9880d681SAndroid Build Coastguard Worker /// \brief Maps the load/store instructions to their index according to
526*9880d681SAndroid Build Coastguard Worker /// program order.
527*9880d681SAndroid Build Coastguard Worker DenseMap<Instruction *, unsigned> InstOrder;
528*9880d681SAndroid Build Coastguard Worker
529*9880d681SAndroid Build Coastguard Worker // Analyses used.
530*9880d681SAndroid Build Coastguard Worker LoopInfo *LI;
531*9880d681SAndroid Build Coastguard Worker const LoopAccessInfo &LAI;
532*9880d681SAndroid Build Coastguard Worker DominatorTree *DT;
533*9880d681SAndroid Build Coastguard Worker PredicatedScalarEvolution PSE;
534*9880d681SAndroid Build Coastguard Worker };
535*9880d681SAndroid Build Coastguard Worker
536*9880d681SAndroid Build Coastguard Worker /// \brief The pass. Most of the work is delegated to the per-loop
537*9880d681SAndroid Build Coastguard Worker /// LoadEliminationForLoop class.
538*9880d681SAndroid Build Coastguard Worker class LoopLoadElimination : public FunctionPass {
539*9880d681SAndroid Build Coastguard Worker public:
LoopLoadElimination()540*9880d681SAndroid Build Coastguard Worker LoopLoadElimination() : FunctionPass(ID) {
541*9880d681SAndroid Build Coastguard Worker initializeLoopLoadEliminationPass(*PassRegistry::getPassRegistry());
542*9880d681SAndroid Build Coastguard Worker }
543*9880d681SAndroid Build Coastguard Worker
runOnFunction(Function & F)544*9880d681SAndroid Build Coastguard Worker bool runOnFunction(Function &F) override {
545*9880d681SAndroid Build Coastguard Worker if (skipFunction(F))
546*9880d681SAndroid Build Coastguard Worker return false;
547*9880d681SAndroid Build Coastguard Worker
548*9880d681SAndroid Build Coastguard Worker auto *LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
549*9880d681SAndroid Build Coastguard Worker auto *LAA = &getAnalysis<LoopAccessLegacyAnalysis>();
550*9880d681SAndroid Build Coastguard Worker auto *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
551*9880d681SAndroid Build Coastguard Worker
552*9880d681SAndroid Build Coastguard Worker // Build up a worklist of inner-loops to vectorize. This is necessary as the
553*9880d681SAndroid Build Coastguard Worker // act of distributing a loop creates new loops and can invalidate iterators
554*9880d681SAndroid Build Coastguard Worker // across the loops.
555*9880d681SAndroid Build Coastguard Worker SmallVector<Loop *, 8> Worklist;
556*9880d681SAndroid Build Coastguard Worker
557*9880d681SAndroid Build Coastguard Worker for (Loop *TopLevelLoop : *LI)
558*9880d681SAndroid Build Coastguard Worker for (Loop *L : depth_first(TopLevelLoop))
559*9880d681SAndroid Build Coastguard Worker // We only handle inner-most loops.
560*9880d681SAndroid Build Coastguard Worker if (L->empty())
561*9880d681SAndroid Build Coastguard Worker Worklist.push_back(L);
562*9880d681SAndroid Build Coastguard Worker
563*9880d681SAndroid Build Coastguard Worker // Now walk the identified inner loops.
564*9880d681SAndroid Build Coastguard Worker bool Changed = false;
565*9880d681SAndroid Build Coastguard Worker for (Loop *L : Worklist) {
566*9880d681SAndroid Build Coastguard Worker const LoopAccessInfo &LAI = LAA->getInfo(L);
567*9880d681SAndroid Build Coastguard Worker // The actual work is performed by LoadEliminationForLoop.
568*9880d681SAndroid Build Coastguard Worker LoadEliminationForLoop LEL(L, LI, LAI, DT);
569*9880d681SAndroid Build Coastguard Worker Changed |= LEL.processLoop();
570*9880d681SAndroid Build Coastguard Worker }
571*9880d681SAndroid Build Coastguard Worker
572*9880d681SAndroid Build Coastguard Worker // Process each loop nest in the function.
573*9880d681SAndroid Build Coastguard Worker return Changed;
574*9880d681SAndroid Build Coastguard Worker }
575*9880d681SAndroid Build Coastguard Worker
getAnalysisUsage(AnalysisUsage & AU) const576*9880d681SAndroid Build Coastguard Worker void getAnalysisUsage(AnalysisUsage &AU) const override {
577*9880d681SAndroid Build Coastguard Worker AU.addRequiredID(LoopSimplifyID);
578*9880d681SAndroid Build Coastguard Worker AU.addRequired<LoopInfoWrapperPass>();
579*9880d681SAndroid Build Coastguard Worker AU.addPreserved<LoopInfoWrapperPass>();
580*9880d681SAndroid Build Coastguard Worker AU.addRequired<LoopAccessLegacyAnalysis>();
581*9880d681SAndroid Build Coastguard Worker AU.addRequired<ScalarEvolutionWrapperPass>();
582*9880d681SAndroid Build Coastguard Worker AU.addRequired<DominatorTreeWrapperPass>();
583*9880d681SAndroid Build Coastguard Worker AU.addPreserved<DominatorTreeWrapperPass>();
584*9880d681SAndroid Build Coastguard Worker }
585*9880d681SAndroid Build Coastguard Worker
586*9880d681SAndroid Build Coastguard Worker static char ID;
587*9880d681SAndroid Build Coastguard Worker };
588*9880d681SAndroid Build Coastguard Worker }
589*9880d681SAndroid Build Coastguard Worker
590*9880d681SAndroid Build Coastguard Worker char LoopLoadElimination::ID;
591*9880d681SAndroid Build Coastguard Worker static const char LLE_name[] = "Loop Load Elimination";
592*9880d681SAndroid Build Coastguard Worker
593*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_BEGIN(LoopLoadElimination, LLE_OPTION, LLE_name, false, false)
594*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
595*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_DEPENDENCY(LoopAccessLegacyAnalysis)
596*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
597*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass)
598*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_DEPENDENCY(LoopSimplify)
599*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_END(LoopLoadElimination, LLE_OPTION, LLE_name, false, false)
600*9880d681SAndroid Build Coastguard Worker
601*9880d681SAndroid Build Coastguard Worker namespace llvm {
createLoopLoadEliminationPass()602*9880d681SAndroid Build Coastguard Worker FunctionPass *createLoopLoadEliminationPass() {
603*9880d681SAndroid Build Coastguard Worker return new LoopLoadElimination();
604*9880d681SAndroid Build Coastguard Worker }
605*9880d681SAndroid Build Coastguard Worker }
606