xref: /aosp_15_r20/external/llvm/lib/Transforms/Scalar/LoopLoadElimination.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
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