1938d3d63SAdam Nemet //===- LoopDistribute.cpp - Loop Distribution Pass ------------------------===//
2938d3d63SAdam Nemet //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6938d3d63SAdam Nemet //
7938d3d63SAdam Nemet //===----------------------------------------------------------------------===//
8938d3d63SAdam Nemet //
9938d3d63SAdam Nemet // This file implements the Loop Distribution Pass.  Its main focus is to
10938d3d63SAdam Nemet // distribute loops that cannot be vectorized due to dependence cycles.  It
11938d3d63SAdam Nemet // tries to isolate the offending dependences into a new loop allowing
12938d3d63SAdam Nemet // vectorization of the remaining parts.
13938d3d63SAdam Nemet //
14938d3d63SAdam Nemet // For dependence analysis, the pass uses the LoopVectorizer's
15938d3d63SAdam Nemet // LoopAccessAnalysis.  Because this analysis presumes no change in the order of
16938d3d63SAdam Nemet // memory operations, special care is taken to preserve the lexical order of
17938d3d63SAdam Nemet // these operations.
18938d3d63SAdam Nemet //
19938d3d63SAdam Nemet // Similarly to the Vectorizer, the pass also supports loop versioning to
20938d3d63SAdam Nemet // run-time disambiguate potentially overlapping arrays.
21938d3d63SAdam Nemet //
22938d3d63SAdam Nemet //===----------------------------------------------------------------------===//
23938d3d63SAdam Nemet 
24b2593f78SAdam Nemet #include "llvm/Transforms/Scalar/LoopDistribute.h"
25dd40f5e7SEugene Zelenko #include "llvm/ADT/DenseMap.h"
26938d3d63SAdam Nemet #include "llvm/ADT/DepthFirstIterator.h"
27938d3d63SAdam Nemet #include "llvm/ADT/EquivalenceClasses.h"
28dd40f5e7SEugene Zelenko #include "llvm/ADT/Optional.h"
29938d3d63SAdam Nemet #include "llvm/ADT/STLExtras.h"
30dd40f5e7SEugene Zelenko #include "llvm/ADT/SmallPtrSet.h"
31dd40f5e7SEugene Zelenko #include "llvm/ADT/SmallVector.h"
32938d3d63SAdam Nemet #include "llvm/ADT/Statistic.h"
33dd40f5e7SEugene Zelenko #include "llvm/ADT/StringRef.h"
34dd40f5e7SEugene Zelenko #include "llvm/ADT/Twine.h"
35dd40f5e7SEugene Zelenko #include "llvm/ADT/iterator_range.h"
36dd40f5e7SEugene Zelenko #include "llvm/Analysis/AssumptionCache.h"
3766fdba87SEli Friedman #include "llvm/Analysis/GlobalsModRef.h"
38938d3d63SAdam Nemet #include "llvm/Analysis/LoopAccessAnalysis.h"
39dd40f5e7SEugene Zelenko #include "llvm/Analysis/LoopAnalysisManager.h"
40938d3d63SAdam Nemet #include "llvm/Analysis/LoopInfo.h"
410965da20SAdam Nemet #include "llvm/Analysis/OptimizationRemarkEmitter.h"
42dd40f5e7SEugene Zelenko #include "llvm/Analysis/ScalarEvolution.h"
43dd40f5e7SEugene Zelenko #include "llvm/Analysis/TargetLibraryInfo.h"
44dd40f5e7SEugene Zelenko #include "llvm/Analysis/TargetTransformInfo.h"
45dd40f5e7SEugene Zelenko #include "llvm/IR/BasicBlock.h"
46dd40f5e7SEugene Zelenko #include "llvm/IR/Constants.h"
470ba164bbSAdam Nemet #include "llvm/IR/DiagnosticInfo.h"
48938d3d63SAdam Nemet #include "llvm/IR/Dominators.h"
49dd40f5e7SEugene Zelenko #include "llvm/IR/Function.h"
50dd40f5e7SEugene Zelenko #include "llvm/IR/Instruction.h"
51dd40f5e7SEugene Zelenko #include "llvm/IR/Instructions.h"
52dd40f5e7SEugene Zelenko #include "llvm/IR/LLVMContext.h"
53dd40f5e7SEugene Zelenko #include "llvm/IR/Metadata.h"
54dd40f5e7SEugene Zelenko #include "llvm/IR/PassManager.h"
55dd40f5e7SEugene Zelenko #include "llvm/IR/Value.h"
5605da2fe5SReid Kleckner #include "llvm/InitializePasses.h"
57938d3d63SAdam Nemet #include "llvm/Pass.h"
58dd40f5e7SEugene Zelenko #include "llvm/Support/Casting.h"
59938d3d63SAdam Nemet #include "llvm/Support/CommandLine.h"
60938d3d63SAdam Nemet #include "llvm/Support/Debug.h"
61dd40f5e7SEugene Zelenko #include "llvm/Support/raw_ostream.h"
62dd40f5e7SEugene Zelenko #include "llvm/Transforms/Scalar.h"
63938d3d63SAdam Nemet #include "llvm/Transforms/Utils/BasicBlockUtils.h"
64938d3d63SAdam Nemet #include "llvm/Transforms/Utils/Cloning.h"
65c5b7b555SAshutosh Nema #include "llvm/Transforms/Utils/LoopUtils.h"
66215746b4SAdam Nemet #include "llvm/Transforms/Utils/LoopVersioning.h"
67dd40f5e7SEugene Zelenko #include "llvm/Transforms/Utils/ValueMapper.h"
68dd40f5e7SEugene Zelenko #include <cassert>
69dd40f5e7SEugene Zelenko #include <functional>
70938d3d63SAdam Nemet #include <list>
71dd40f5e7SEugene Zelenko #include <tuple>
72dd40f5e7SEugene Zelenko #include <utility>
73dd40f5e7SEugene Zelenko 
74dd40f5e7SEugene Zelenko using namespace llvm;
75938d3d63SAdam Nemet 
76938d3d63SAdam Nemet #define LDIST_NAME "loop-distribute"
77938d3d63SAdam Nemet #define DEBUG_TYPE LDIST_NAME
78938d3d63SAdam Nemet 
7972448525SMichael Kruse /// @{
8072448525SMichael Kruse /// Metadata attribute names
8172448525SMichael Kruse static const char *const LLVMLoopDistributeFollowupAll =
8272448525SMichael Kruse     "llvm.loop.distribute.followup_all";
8372448525SMichael Kruse static const char *const LLVMLoopDistributeFollowupCoincident =
8472448525SMichael Kruse     "llvm.loop.distribute.followup_coincident";
8572448525SMichael Kruse static const char *const LLVMLoopDistributeFollowupSequential =
8672448525SMichael Kruse     "llvm.loop.distribute.followup_sequential";
8772448525SMichael Kruse static const char *const LLVMLoopDistributeFollowupFallback =
8872448525SMichael Kruse     "llvm.loop.distribute.followup_fallback";
8972448525SMichael Kruse /// @}
9072448525SMichael Kruse 
91938d3d63SAdam Nemet static cl::opt<bool>
92938d3d63SAdam Nemet     LDistVerify("loop-distribute-verify", cl::Hidden,
93938d3d63SAdam Nemet                 cl::desc("Turn on DominatorTree and LoopInfo verification "
94938d3d63SAdam Nemet                          "after Loop Distribution"),
95938d3d63SAdam Nemet                 cl::init(false));
96938d3d63SAdam Nemet 
97938d3d63SAdam Nemet static cl::opt<bool> DistributeNonIfConvertible(
98938d3d63SAdam Nemet     "loop-distribute-non-if-convertible", cl::Hidden,
99938d3d63SAdam Nemet     cl::desc("Whether to distribute into a loop that may not be "
100938d3d63SAdam Nemet              "if-convertible by the loop vectorizer"),
101938d3d63SAdam Nemet     cl::init(false));
102938d3d63SAdam Nemet 
1032910a4f6SSilviu Baranga static cl::opt<unsigned> DistributeSCEVCheckThreshold(
1042910a4f6SSilviu Baranga     "loop-distribute-scev-check-threshold", cl::init(8), cl::Hidden,
1052910a4f6SSilviu Baranga     cl::desc("The maximum number of SCEV checks allowed for Loop "
1062910a4f6SSilviu Baranga              "Distribution"));
1072910a4f6SSilviu Baranga 
108d2fa4147SAdam Nemet static cl::opt<unsigned> PragmaDistributeSCEVCheckThreshold(
109d2fa4147SAdam Nemet     "loop-distribute-scev-check-threshold-with-pragma", cl::init(128),
110d2fa4147SAdam Nemet     cl::Hidden,
111d2fa4147SAdam Nemet     cl::desc(
112d2fa4147SAdam Nemet         "The maximum number of SCEV checks allowed for Loop "
113d2fa4147SAdam Nemet         "Distribution for loop marked with #pragma loop distribute(enable)"));
114d2fa4147SAdam Nemet 
115d2fa4147SAdam Nemet static cl::opt<bool> EnableLoopDistribute(
116d2fa4147SAdam Nemet     "enable-loop-distribute", cl::Hidden,
11732e6a34cSAdam Nemet     cl::desc("Enable the new, experimental LoopDistribution Pass"),
11832e6a34cSAdam Nemet     cl::init(false));
119d2fa4147SAdam Nemet 
120938d3d63SAdam Nemet STATISTIC(NumLoopsDistributed, "Number of loops distributed");
121938d3d63SAdam Nemet 
1222f85b737SAdam Nemet namespace {
123dd40f5e7SEugene Zelenko 
1245f8f34e4SAdrian Prantl /// Maintains the set of instructions of the loop for a partition before
125938d3d63SAdam Nemet /// cloning.  After cloning, it hosts the new loop.
126938d3d63SAdam Nemet class InstPartition {
127dd40f5e7SEugene Zelenko   using InstructionSet = SmallPtrSet<Instruction *, 8>;
128938d3d63SAdam Nemet 
129938d3d63SAdam Nemet public:
InstPartition(Instruction * I,Loop * L,bool DepCycle=false)130938d3d63SAdam Nemet   InstPartition(Instruction *I, Loop *L, bool DepCycle = false)
131dd40f5e7SEugene Zelenko       : DepCycle(DepCycle), OrigLoop(L) {
132938d3d63SAdam Nemet     Set.insert(I);
133938d3d63SAdam Nemet   }
134938d3d63SAdam Nemet 
1355f8f34e4SAdrian Prantl   /// Returns whether this partition contains a dependence cycle.
hasDepCycle() const136938d3d63SAdam Nemet   bool hasDepCycle() const { return DepCycle; }
137938d3d63SAdam Nemet 
1385f8f34e4SAdrian Prantl   /// Adds an instruction to this partition.
add(Instruction * I)139938d3d63SAdam Nemet   void add(Instruction *I) { Set.insert(I); }
140938d3d63SAdam Nemet 
1415f8f34e4SAdrian Prantl   /// Collection accessors.
begin()142938d3d63SAdam Nemet   InstructionSet::iterator begin() { return Set.begin(); }
end()143938d3d63SAdam Nemet   InstructionSet::iterator end() { return Set.end(); }
begin() const144938d3d63SAdam Nemet   InstructionSet::const_iterator begin() const { return Set.begin(); }
end() const145938d3d63SAdam Nemet   InstructionSet::const_iterator end() const { return Set.end(); }
empty() const146938d3d63SAdam Nemet   bool empty() const { return Set.empty(); }
147938d3d63SAdam Nemet 
1485f8f34e4SAdrian Prantl   /// Moves this partition into \p Other.  This partition becomes empty
149938d3d63SAdam Nemet   /// after this.
moveTo(InstPartition & Other)150938d3d63SAdam Nemet   void moveTo(InstPartition &Other) {
151938d3d63SAdam Nemet     Other.Set.insert(Set.begin(), Set.end());
152938d3d63SAdam Nemet     Set.clear();
153938d3d63SAdam Nemet     Other.DepCycle |= DepCycle;
154938d3d63SAdam Nemet   }
155938d3d63SAdam Nemet 
1565f8f34e4SAdrian Prantl   /// Populates the partition with a transitive closure of all the
157938d3d63SAdam Nemet   /// instructions that the seeded instructions dependent on.
populateUsedSet()158938d3d63SAdam Nemet   void populateUsedSet() {
159938d3d63SAdam Nemet     // FIXME: We currently don't use control-dependence but simply include all
160938d3d63SAdam Nemet     // blocks (possibly empty at the end) and let simplifycfg mostly clean this
161938d3d63SAdam Nemet     // up.
162938d3d63SAdam Nemet     for (auto *B : OrigLoop->getBlocks())
163938d3d63SAdam Nemet       Set.insert(B->getTerminator());
164938d3d63SAdam Nemet 
165938d3d63SAdam Nemet     // Follow the use-def chains to form a transitive closure of all the
166938d3d63SAdam Nemet     // instructions that the originally seeded instructions depend on.
167938d3d63SAdam Nemet     SmallVector<Instruction *, 8> Worklist(Set.begin(), Set.end());
168938d3d63SAdam Nemet     while (!Worklist.empty()) {
169938d3d63SAdam Nemet       Instruction *I = Worklist.pop_back_val();
170938d3d63SAdam Nemet       // Insert instructions from the loop that we depend on.
171938d3d63SAdam Nemet       for (Value *V : I->operand_values()) {
172938d3d63SAdam Nemet         auto *I = dyn_cast<Instruction>(V);
173938d3d63SAdam Nemet         if (I && OrigLoop->contains(I->getParent()) && Set.insert(I).second)
174938d3d63SAdam Nemet           Worklist.push_back(I);
175938d3d63SAdam Nemet       }
176938d3d63SAdam Nemet     }
177938d3d63SAdam Nemet   }
178938d3d63SAdam Nemet 
1795f8f34e4SAdrian Prantl   /// Clones the original loop.
180938d3d63SAdam Nemet   ///
181938d3d63SAdam Nemet   /// Updates LoopInfo and DominatorTree using the information that block \p
182938d3d63SAdam Nemet   /// LoopDomBB dominates the loop.
cloneLoopWithPreheader(BasicBlock * InsertBefore,BasicBlock * LoopDomBB,unsigned Index,LoopInfo * LI,DominatorTree * DT)183938d3d63SAdam Nemet   Loop *cloneLoopWithPreheader(BasicBlock *InsertBefore, BasicBlock *LoopDomBB,
184938d3d63SAdam Nemet                                unsigned Index, LoopInfo *LI,
185938d3d63SAdam Nemet                                DominatorTree *DT) {
186938d3d63SAdam Nemet     ClonedLoop = ::cloneLoopWithPreheader(InsertBefore, LoopDomBB, OrigLoop,
187938d3d63SAdam Nemet                                           VMap, Twine(".ldist") + Twine(Index),
188938d3d63SAdam Nemet                                           LI, DT, ClonedLoopBlocks);
189938d3d63SAdam Nemet     return ClonedLoop;
190938d3d63SAdam Nemet   }
191938d3d63SAdam Nemet 
1925f8f34e4SAdrian Prantl   /// The cloned loop.  If this partition is mapped to the original loop,
193938d3d63SAdam Nemet   /// this is null.
getClonedLoop() const194938d3d63SAdam Nemet   const Loop *getClonedLoop() const { return ClonedLoop; }
195938d3d63SAdam Nemet 
1965f8f34e4SAdrian Prantl   /// Returns the loop where this partition ends up after distribution.
197938d3d63SAdam Nemet   /// If this partition is mapped to the original loop then use the block from
198938d3d63SAdam Nemet   /// the loop.
getDistributedLoop() const19972448525SMichael Kruse   Loop *getDistributedLoop() const {
200938d3d63SAdam Nemet     return ClonedLoop ? ClonedLoop : OrigLoop;
201938d3d63SAdam Nemet   }
202938d3d63SAdam Nemet 
2035f8f34e4SAdrian Prantl   /// The VMap that is populated by cloning and then used in
204938d3d63SAdam Nemet   /// remapinstruction to remap the cloned instructions.
getVMap()205938d3d63SAdam Nemet   ValueToValueMapTy &getVMap() { return VMap; }
206938d3d63SAdam Nemet 
2075f8f34e4SAdrian Prantl   /// Remaps the cloned instructions using VMap.
remapInstructions()2081a689188SAdam Nemet   void remapInstructions() {
2091a689188SAdam Nemet     remapInstructionsInBlocks(ClonedLoopBlocks, VMap);
2101a689188SAdam Nemet   }
211938d3d63SAdam Nemet 
2125f8f34e4SAdrian Prantl   /// Based on the set of instructions selected for this partition,
213938d3d63SAdam Nemet   /// removes the unnecessary ones.
removeUnusedInsts()214938d3d63SAdam Nemet   void removeUnusedInsts() {
215938d3d63SAdam Nemet     SmallVector<Instruction *, 8> Unused;
216938d3d63SAdam Nemet 
217938d3d63SAdam Nemet     for (auto *Block : OrigLoop->getBlocks())
218938d3d63SAdam Nemet       for (auto &Inst : *Block)
219938d3d63SAdam Nemet         if (!Set.count(&Inst)) {
220938d3d63SAdam Nemet           Instruction *NewInst = &Inst;
221938d3d63SAdam Nemet           if (!VMap.empty())
222938d3d63SAdam Nemet             NewInst = cast<Instruction>(VMap[NewInst]);
223938d3d63SAdam Nemet 
224938d3d63SAdam Nemet           assert(!isa<BranchInst>(NewInst) &&
225938d3d63SAdam Nemet                  "Branches are marked used early on");
226938d3d63SAdam Nemet           Unused.push_back(NewInst);
227938d3d63SAdam Nemet         }
228938d3d63SAdam Nemet 
229938d3d63SAdam Nemet     // Delete the instructions backwards, as it has a reduced likelihood of
230938d3d63SAdam Nemet     // having to update as many def-use and use-def chains.
231d7708773SDavid Majnemer     for (auto *Inst : reverse(Unused)) {
232938d3d63SAdam Nemet       if (!Inst->use_empty())
23353dc0f10SNuno Lopes         Inst->replaceAllUsesWith(PoisonValue::get(Inst->getType()));
234938d3d63SAdam Nemet       Inst->eraseFromParent();
235938d3d63SAdam Nemet     }
236938d3d63SAdam Nemet   }
237938d3d63SAdam Nemet 
print() const238e6987bf3SBenjamin Kramer   void print() const {
239938d3d63SAdam Nemet     if (DepCycle)
240938d3d63SAdam Nemet       dbgs() << "  (cycle)\n";
241938d3d63SAdam Nemet     for (auto *I : Set)
242938d3d63SAdam Nemet       // Prefix with the block name.
243938d3d63SAdam Nemet       dbgs() << "  " << I->getParent()->getName() << ":" << *I << "\n";
244938d3d63SAdam Nemet   }
245938d3d63SAdam Nemet 
printBlocks() const246938d3d63SAdam Nemet   void printBlocks() const {
247938d3d63SAdam Nemet     for (auto *BB : getDistributedLoop()->getBlocks())
248938d3d63SAdam Nemet       dbgs() << *BB;
249938d3d63SAdam Nemet   }
250938d3d63SAdam Nemet 
251938d3d63SAdam Nemet private:
2525f8f34e4SAdrian Prantl   /// Instructions from OrigLoop selected for this partition.
253938d3d63SAdam Nemet   InstructionSet Set;
254938d3d63SAdam Nemet 
2555f8f34e4SAdrian Prantl   /// Whether this partition contains a dependence cycle.
256938d3d63SAdam Nemet   bool DepCycle;
257938d3d63SAdam Nemet 
2585f8f34e4SAdrian Prantl   /// The original loop.
259938d3d63SAdam Nemet   Loop *OrigLoop;
260938d3d63SAdam Nemet 
2615f8f34e4SAdrian Prantl   /// The cloned loop.  If this partition is mapped to the original loop,
262938d3d63SAdam Nemet   /// this is null.
263dd40f5e7SEugene Zelenko   Loop *ClonedLoop = nullptr;
264938d3d63SAdam Nemet 
2655f8f34e4SAdrian Prantl   /// The blocks of ClonedLoop including the preheader.  If this
266938d3d63SAdam Nemet   /// partition is mapped to the original loop, this is empty.
267938d3d63SAdam Nemet   SmallVector<BasicBlock *, 8> ClonedLoopBlocks;
268938d3d63SAdam Nemet 
2695f8f34e4SAdrian Prantl   /// These gets populated once the set of instructions have been
270938d3d63SAdam Nemet   /// finalized. If this partition is mapped to the original loop, these are not
271938d3d63SAdam Nemet   /// set.
272938d3d63SAdam Nemet   ValueToValueMapTy VMap;
273938d3d63SAdam Nemet };
274938d3d63SAdam Nemet 
2755f8f34e4SAdrian Prantl /// Holds the set of Partitions.  It populates them, merges them and then
276938d3d63SAdam Nemet /// clones the loops.
277938d3d63SAdam Nemet class InstPartitionContainer {
278dd40f5e7SEugene Zelenko   using InstToPartitionIdT = DenseMap<Instruction *, int>;
279938d3d63SAdam Nemet 
280938d3d63SAdam Nemet public:
InstPartitionContainer(Loop * L,LoopInfo * LI,DominatorTree * DT)281938d3d63SAdam Nemet   InstPartitionContainer(Loop *L, LoopInfo *LI, DominatorTree *DT)
282938d3d63SAdam Nemet       : L(L), LI(LI), DT(DT) {}
283938d3d63SAdam Nemet 
2845f8f34e4SAdrian Prantl   /// Returns the number of partitions.
getSize() const285938d3d63SAdam Nemet   unsigned getSize() const { return PartitionContainer.size(); }
286938d3d63SAdam Nemet 
2875f8f34e4SAdrian Prantl   /// Adds \p Inst into the current partition if that is marked to
288938d3d63SAdam Nemet   /// contain cycles.  Otherwise start a new partition for it.
addToCyclicPartition(Instruction * Inst)289938d3d63SAdam Nemet   void addToCyclicPartition(Instruction *Inst) {
290938d3d63SAdam Nemet     // If the current partition is non-cyclic.  Start a new one.
291e6987bf3SBenjamin Kramer     if (PartitionContainer.empty() || !PartitionContainer.back().hasDepCycle())
292e6987bf3SBenjamin Kramer       PartitionContainer.emplace_back(Inst, L, /*DepCycle=*/true);
293938d3d63SAdam Nemet     else
294e6987bf3SBenjamin Kramer       PartitionContainer.back().add(Inst);
295938d3d63SAdam Nemet   }
296938d3d63SAdam Nemet 
2975f8f34e4SAdrian Prantl   /// Adds \p Inst into a partition that is not marked to contain
298938d3d63SAdam Nemet   /// dependence cycles.
299938d3d63SAdam Nemet   ///
300938d3d63SAdam Nemet   //  Initially we isolate memory instructions into as many partitions as
301938d3d63SAdam Nemet   //  possible, then later we may merge them back together.
addToNewNonCyclicPartition(Instruction * Inst)302938d3d63SAdam Nemet   void addToNewNonCyclicPartition(Instruction *Inst) {
303e6987bf3SBenjamin Kramer     PartitionContainer.emplace_back(Inst, L);
304938d3d63SAdam Nemet   }
305938d3d63SAdam Nemet 
3065f8f34e4SAdrian Prantl   /// Merges adjacent non-cyclic partitions.
307938d3d63SAdam Nemet   ///
308938d3d63SAdam Nemet   /// The idea is that we currently only want to isolate the non-vectorizable
309938d3d63SAdam Nemet   /// partition.  We could later allow more distribution among these partition
310938d3d63SAdam Nemet   /// too.
mergeAdjacentNonCyclic()311938d3d63SAdam Nemet   void mergeAdjacentNonCyclic() {
312938d3d63SAdam Nemet     mergeAdjacentPartitionsIf(
313938d3d63SAdam Nemet         [](const InstPartition *P) { return !P->hasDepCycle(); });
314938d3d63SAdam Nemet   }
315938d3d63SAdam Nemet 
3165f8f34e4SAdrian Prantl   /// If a partition contains only conditional stores, we won't vectorize
317938d3d63SAdam Nemet   /// it.  Try to merge it with a previous cyclic partition.
mergeNonIfConvertible()318938d3d63SAdam Nemet   void mergeNonIfConvertible() {
319938d3d63SAdam Nemet     mergeAdjacentPartitionsIf([&](const InstPartition *Partition) {
320938d3d63SAdam Nemet       if (Partition->hasDepCycle())
321938d3d63SAdam Nemet         return true;
322938d3d63SAdam Nemet 
323938d3d63SAdam Nemet       // Now, check if all stores are conditional in this partition.
324938d3d63SAdam Nemet       bool seenStore = false;
325938d3d63SAdam Nemet 
326938d3d63SAdam Nemet       for (auto *Inst : *Partition)
327938d3d63SAdam Nemet         if (isa<StoreInst>(Inst)) {
328938d3d63SAdam Nemet           seenStore = true;
329938d3d63SAdam Nemet           if (!LoopAccessInfo::blockNeedsPredication(Inst->getParent(), L, DT))
330938d3d63SAdam Nemet             return false;
331938d3d63SAdam Nemet         }
332938d3d63SAdam Nemet       return seenStore;
333938d3d63SAdam Nemet     });
334938d3d63SAdam Nemet   }
335938d3d63SAdam Nemet 
3365f8f34e4SAdrian Prantl   /// Merges the partitions according to various heuristics.
mergeBeforePopulating()337938d3d63SAdam Nemet   void mergeBeforePopulating() {
338938d3d63SAdam Nemet     mergeAdjacentNonCyclic();
339938d3d63SAdam Nemet     if (!DistributeNonIfConvertible)
340938d3d63SAdam Nemet       mergeNonIfConvertible();
341938d3d63SAdam Nemet   }
342938d3d63SAdam Nemet 
3435f8f34e4SAdrian Prantl   /// Merges partitions in order to ensure that no loads are duplicated.
344938d3d63SAdam Nemet   ///
345938d3d63SAdam Nemet   /// We can't duplicate loads because that could potentially reorder them.
346938d3d63SAdam Nemet   /// LoopAccessAnalysis provides dependency information with the context that
347938d3d63SAdam Nemet   /// the order of memory operation is preserved.
348938d3d63SAdam Nemet   ///
349938d3d63SAdam Nemet   /// Return if any partitions were merged.
mergeToAvoidDuplicatedLoads()350938d3d63SAdam Nemet   bool mergeToAvoidDuplicatedLoads() {
351dd40f5e7SEugene Zelenko     using LoadToPartitionT = DenseMap<Instruction *, InstPartition *>;
352dd40f5e7SEugene Zelenko     using ToBeMergedT = EquivalenceClasses<InstPartition *>;
353938d3d63SAdam Nemet 
354938d3d63SAdam Nemet     LoadToPartitionT LoadToPartition;
355938d3d63SAdam Nemet     ToBeMergedT ToBeMerged;
356938d3d63SAdam Nemet 
357938d3d63SAdam Nemet     // Step through the partitions and create equivalence between partitions
358938d3d63SAdam Nemet     // that contain the same load.  Also put partitions in between them in the
359938d3d63SAdam Nemet     // same equivalence class to avoid reordering of memory operations.
360938d3d63SAdam Nemet     for (PartitionContainerT::iterator I = PartitionContainer.begin(),
361938d3d63SAdam Nemet                                        E = PartitionContainer.end();
362938d3d63SAdam Nemet          I != E; ++I) {
363e6987bf3SBenjamin Kramer       auto *PartI = &*I;
364938d3d63SAdam Nemet 
365938d3d63SAdam Nemet       // If a load occurs in two partitions PartI and PartJ, merge all
366938d3d63SAdam Nemet       // partitions (PartI, PartJ] into PartI.
367938d3d63SAdam Nemet       for (Instruction *Inst : *PartI)
368938d3d63SAdam Nemet         if (isa<LoadInst>(Inst)) {
369938d3d63SAdam Nemet           bool NewElt;
370938d3d63SAdam Nemet           LoadToPartitionT::iterator LoadToPart;
371938d3d63SAdam Nemet 
372938d3d63SAdam Nemet           std::tie(LoadToPart, NewElt) =
373938d3d63SAdam Nemet               LoadToPartition.insert(std::make_pair(Inst, PartI));
374938d3d63SAdam Nemet           if (!NewElt) {
375d34e60caSNicola Zaghen             LLVM_DEBUG(dbgs()
376d34e60caSNicola Zaghen                        << "Merging partitions due to this load in multiple "
377d34e60caSNicola Zaghen                        << "partitions: " << PartI << ", " << LoadToPart->second
378d34e60caSNicola Zaghen                        << "\n"
379d34e60caSNicola Zaghen                        << *Inst << "\n");
380938d3d63SAdam Nemet 
381938d3d63SAdam Nemet             auto PartJ = I;
382938d3d63SAdam Nemet             do {
383938d3d63SAdam Nemet               --PartJ;
384e6987bf3SBenjamin Kramer               ToBeMerged.unionSets(PartI, &*PartJ);
385e6987bf3SBenjamin Kramer             } while (&*PartJ != LoadToPart->second);
386938d3d63SAdam Nemet           }
387938d3d63SAdam Nemet         }
388938d3d63SAdam Nemet     }
389938d3d63SAdam Nemet     if (ToBeMerged.empty())
390938d3d63SAdam Nemet       return false;
391938d3d63SAdam Nemet 
392938d3d63SAdam Nemet     // Merge the member of an equivalence class into its class leader.  This
393938d3d63SAdam Nemet     // makes the members empty.
394938d3d63SAdam Nemet     for (ToBeMergedT::iterator I = ToBeMerged.begin(), E = ToBeMerged.end();
395938d3d63SAdam Nemet          I != E; ++I) {
396938d3d63SAdam Nemet       if (!I->isLeader())
397938d3d63SAdam Nemet         continue;
398938d3d63SAdam Nemet 
399938d3d63SAdam Nemet       auto PartI = I->getData();
400938d3d63SAdam Nemet       for (auto PartJ : make_range(std::next(ToBeMerged.member_begin(I)),
401938d3d63SAdam Nemet                                    ToBeMerged.member_end())) {
402938d3d63SAdam Nemet         PartJ->moveTo(*PartI);
403938d3d63SAdam Nemet       }
404938d3d63SAdam Nemet     }
405938d3d63SAdam Nemet 
406938d3d63SAdam Nemet     // Remove the empty partitions.
407e6987bf3SBenjamin Kramer     PartitionContainer.remove_if(
408e6987bf3SBenjamin Kramer         [](const InstPartition &P) { return P.empty(); });
409938d3d63SAdam Nemet 
410938d3d63SAdam Nemet     return true;
411938d3d63SAdam Nemet   }
412938d3d63SAdam Nemet 
4135f8f34e4SAdrian Prantl   /// Sets up the mapping between instructions to partitions.  If the
414938d3d63SAdam Nemet   /// instruction is duplicated across multiple partitions, set the entry to -1.
setupPartitionIdOnInstructions()415938d3d63SAdam Nemet   void setupPartitionIdOnInstructions() {
416938d3d63SAdam Nemet     int PartitionID = 0;
417e6987bf3SBenjamin Kramer     for (const auto &Partition : PartitionContainer) {
418e6987bf3SBenjamin Kramer       for (Instruction *Inst : Partition) {
419938d3d63SAdam Nemet         bool NewElt;
420938d3d63SAdam Nemet         InstToPartitionIdT::iterator Iter;
421938d3d63SAdam Nemet 
422938d3d63SAdam Nemet         std::tie(Iter, NewElt) =
423938d3d63SAdam Nemet             InstToPartitionId.insert(std::make_pair(Inst, PartitionID));
424938d3d63SAdam Nemet         if (!NewElt)
425938d3d63SAdam Nemet           Iter->second = -1;
426938d3d63SAdam Nemet       }
427938d3d63SAdam Nemet       ++PartitionID;
428938d3d63SAdam Nemet     }
429938d3d63SAdam Nemet   }
430938d3d63SAdam Nemet 
4315f8f34e4SAdrian Prantl   /// Populates the partition with everything that the seeding
432938d3d63SAdam Nemet   /// instructions require.
populateUsedSet()433938d3d63SAdam Nemet   void populateUsedSet() {
434938d3d63SAdam Nemet     for (auto &P : PartitionContainer)
435e6987bf3SBenjamin Kramer       P.populateUsedSet();
436938d3d63SAdam Nemet   }
437938d3d63SAdam Nemet 
4385f8f34e4SAdrian Prantl   /// This performs the main chunk of the work of cloning the loops for
439938d3d63SAdam Nemet   /// the partitions.
cloneLoops()440843fb204SJustin Bogner   void cloneLoops() {
441938d3d63SAdam Nemet     BasicBlock *OrigPH = L->getLoopPreheader();
442938d3d63SAdam Nemet     // At this point the predecessor of the preheader is either the memcheck
443938d3d63SAdam Nemet     // block or the top part of the original preheader.
444938d3d63SAdam Nemet     BasicBlock *Pred = OrigPH->getSinglePredecessor();
445938d3d63SAdam Nemet     assert(Pred && "Preheader does not have a single predecessor");
446938d3d63SAdam Nemet     BasicBlock *ExitBlock = L->getExitBlock();
447938d3d63SAdam Nemet     assert(ExitBlock && "No single exit block");
448938d3d63SAdam Nemet     Loop *NewLoop;
449938d3d63SAdam Nemet 
450938d3d63SAdam Nemet     assert(!PartitionContainer.empty() && "at least two partitions expected");
451938d3d63SAdam Nemet     // We're cloning the preheader along with the loop so we already made sure
452938d3d63SAdam Nemet     // it was empty.
453938d3d63SAdam Nemet     assert(&*OrigPH->begin() == OrigPH->getTerminator() &&
454938d3d63SAdam Nemet            "preheader not empty");
455938d3d63SAdam Nemet 
45672448525SMichael Kruse     // Preserve the original loop ID for use after the transformation.
45772448525SMichael Kruse     MDNode *OrigLoopID = L->getLoopID();
45872448525SMichael Kruse 
459938d3d63SAdam Nemet     // Create a loop for each partition except the last.  Clone the original
460938d3d63SAdam Nemet     // loop before PH along with adding a preheader for the cloned loop.  Then
461938d3d63SAdam Nemet     // update PH to point to the newly added preheader.
462938d3d63SAdam Nemet     BasicBlock *TopPH = OrigPH;
463938d3d63SAdam Nemet     unsigned Index = getSize() - 1;
464e6987bf3SBenjamin Kramer     for (auto I = std::next(PartitionContainer.rbegin()),
465e6987bf3SBenjamin Kramer               E = PartitionContainer.rend();
466938d3d63SAdam Nemet          I != E; ++I, --Index, TopPH = NewLoop->getLoopPreheader()) {
467e6987bf3SBenjamin Kramer       auto *Part = &*I;
468938d3d63SAdam Nemet 
469938d3d63SAdam Nemet       NewLoop = Part->cloneLoopWithPreheader(TopPH, Pred, Index, LI, DT);
470938d3d63SAdam Nemet 
471938d3d63SAdam Nemet       Part->getVMap()[ExitBlock] = TopPH;
472938d3d63SAdam Nemet       Part->remapInstructions();
47372448525SMichael Kruse       setNewLoopID(OrigLoopID, Part);
474938d3d63SAdam Nemet     }
475938d3d63SAdam Nemet     Pred->getTerminator()->replaceUsesOfWith(OrigPH, TopPH);
476938d3d63SAdam Nemet 
47772448525SMichael Kruse     // Also set a new loop ID for the last loop.
47872448525SMichael Kruse     setNewLoopID(OrigLoopID, &PartitionContainer.back());
47972448525SMichael Kruse 
480938d3d63SAdam Nemet     // Now go in forward order and update the immediate dominator for the
481938d3d63SAdam Nemet     // preheaders with the exiting block of the previous loop.  Dominance
482938d3d63SAdam Nemet     // within the loop is updated in cloneLoopWithPreheader.
483938d3d63SAdam Nemet     for (auto Curr = PartitionContainer.cbegin(),
484938d3d63SAdam Nemet               Next = std::next(PartitionContainer.cbegin()),
485938d3d63SAdam Nemet               E = PartitionContainer.cend();
486938d3d63SAdam Nemet          Next != E; ++Curr, ++Next)
487938d3d63SAdam Nemet       DT->changeImmediateDominator(
488e6987bf3SBenjamin Kramer           Next->getDistributedLoop()->getLoopPreheader(),
489e6987bf3SBenjamin Kramer           Curr->getDistributedLoop()->getExitingBlock());
490938d3d63SAdam Nemet   }
491938d3d63SAdam Nemet 
4925f8f34e4SAdrian Prantl   /// Removes the dead instructions from the cloned loops.
removeUnusedInsts()493938d3d63SAdam Nemet   void removeUnusedInsts() {
494e6987bf3SBenjamin Kramer     for (auto &Partition : PartitionContainer)
495e6987bf3SBenjamin Kramer       Partition.removeUnusedInsts();
496938d3d63SAdam Nemet   }
497938d3d63SAdam Nemet 
4985f8f34e4SAdrian Prantl   /// For each memory pointer, it computes the partitionId the pointer is
499938d3d63SAdam Nemet   /// used in.
500938d3d63SAdam Nemet   ///
501938d3d63SAdam Nemet   /// This returns an array of int where the I-th entry corresponds to I-th
502938d3d63SAdam Nemet   /// entry in LAI.getRuntimePointerCheck().  If the pointer is used in multiple
503938d3d63SAdam Nemet   /// partitions its entry is set to -1.
504938d3d63SAdam Nemet   SmallVector<int, 8>
computePartitionSetForPointers(const LoopAccessInfo & LAI)505938d3d63SAdam Nemet   computePartitionSetForPointers(const LoopAccessInfo &LAI) {
5067cdebac0SAdam Nemet     const RuntimePointerChecking *RtPtrCheck = LAI.getRuntimePointerChecking();
507938d3d63SAdam Nemet 
508938d3d63SAdam Nemet     unsigned N = RtPtrCheck->Pointers.size();
509938d3d63SAdam Nemet     SmallVector<int, 8> PtrToPartitions(N);
510938d3d63SAdam Nemet     for (unsigned I = 0; I < N; ++I) {
5119f7dedc3SAdam Nemet       Value *Ptr = RtPtrCheck->Pointers[I].PointerValue;
512938d3d63SAdam Nemet       auto Instructions =
5139f7dedc3SAdam Nemet           LAI.getInstructionsForAccess(Ptr, RtPtrCheck->Pointers[I].IsWritePtr);
514938d3d63SAdam Nemet 
515938d3d63SAdam Nemet       int &Partition = PtrToPartitions[I];
516938d3d63SAdam Nemet       // First set it to uninitialized.
517938d3d63SAdam Nemet       Partition = -2;
518938d3d63SAdam Nemet       for (Instruction *Inst : Instructions) {
519938d3d63SAdam Nemet         // Note that this could be -1 if Inst is duplicated across multiple
520938d3d63SAdam Nemet         // partitions.
521938d3d63SAdam Nemet         int ThisPartition = this->InstToPartitionId[Inst];
522938d3d63SAdam Nemet         if (Partition == -2)
523938d3d63SAdam Nemet           Partition = ThisPartition;
524938d3d63SAdam Nemet         // -1 means belonging to multiple partitions.
525938d3d63SAdam Nemet         else if (Partition == -1)
526938d3d63SAdam Nemet           break;
527938d3d63SAdam Nemet         else if (Partition != (int)ThisPartition)
528938d3d63SAdam Nemet           Partition = -1;
529938d3d63SAdam Nemet       }
530938d3d63SAdam Nemet       assert(Partition != -2 && "Pointer not belonging to any partition");
531938d3d63SAdam Nemet     }
532938d3d63SAdam Nemet 
533938d3d63SAdam Nemet     return PtrToPartitions;
534938d3d63SAdam Nemet   }
535938d3d63SAdam Nemet 
print(raw_ostream & OS) const536938d3d63SAdam Nemet   void print(raw_ostream &OS) const {
537938d3d63SAdam Nemet     unsigned Index = 0;
538e6987bf3SBenjamin Kramer     for (const auto &P : PartitionContainer) {
539e6987bf3SBenjamin Kramer       OS << "Partition " << Index++ << " (" << &P << "):\n";
540e6987bf3SBenjamin Kramer       P.print();
541938d3d63SAdam Nemet     }
542938d3d63SAdam Nemet   }
543938d3d63SAdam Nemet 
dump() const544938d3d63SAdam Nemet   void dump() const { print(dbgs()); }
545938d3d63SAdam Nemet 
546938d3d63SAdam Nemet #ifndef NDEBUG
operator <<(raw_ostream & OS,const InstPartitionContainer & Partitions)547938d3d63SAdam Nemet   friend raw_ostream &operator<<(raw_ostream &OS,
548938d3d63SAdam Nemet                                  const InstPartitionContainer &Partitions) {
549938d3d63SAdam Nemet     Partitions.print(OS);
550938d3d63SAdam Nemet     return OS;
551938d3d63SAdam Nemet   }
552938d3d63SAdam Nemet #endif
553938d3d63SAdam Nemet 
printBlocks() const554938d3d63SAdam Nemet   void printBlocks() const {
555938d3d63SAdam Nemet     unsigned Index = 0;
556e6987bf3SBenjamin Kramer     for (const auto &P : PartitionContainer) {
557e6987bf3SBenjamin Kramer       dbgs() << "\nPartition " << Index++ << " (" << &P << "):\n";
558e6987bf3SBenjamin Kramer       P.printBlocks();
559938d3d63SAdam Nemet     }
560938d3d63SAdam Nemet   }
561938d3d63SAdam Nemet 
562938d3d63SAdam Nemet private:
563dd40f5e7SEugene Zelenko   using PartitionContainerT = std::list<InstPartition>;
564938d3d63SAdam Nemet 
5655f8f34e4SAdrian Prantl   /// List of partitions.
566938d3d63SAdam Nemet   PartitionContainerT PartitionContainer;
567938d3d63SAdam Nemet 
5685f8f34e4SAdrian Prantl   /// Mapping from Instruction to partition Id.  If the instruction
569938d3d63SAdam Nemet   /// belongs to multiple partitions the entry contains -1.
570938d3d63SAdam Nemet   InstToPartitionIdT InstToPartitionId;
571938d3d63SAdam Nemet 
572938d3d63SAdam Nemet   Loop *L;
573938d3d63SAdam Nemet   LoopInfo *LI;
574938d3d63SAdam Nemet   DominatorTree *DT;
575938d3d63SAdam Nemet 
5765f8f34e4SAdrian Prantl   /// The control structure to merge adjacent partitions if both satisfy
577938d3d63SAdam Nemet   /// the \p Predicate.
578938d3d63SAdam Nemet   template <class UnaryPredicate>
mergeAdjacentPartitionsIf(UnaryPredicate Predicate)579938d3d63SAdam Nemet   void mergeAdjacentPartitionsIf(UnaryPredicate Predicate) {
580938d3d63SAdam Nemet     InstPartition *PrevMatch = nullptr;
581938d3d63SAdam Nemet     for (auto I = PartitionContainer.begin(); I != PartitionContainer.end();) {
582e6987bf3SBenjamin Kramer       auto DoesMatch = Predicate(&*I);
583938d3d63SAdam Nemet       if (PrevMatch == nullptr && DoesMatch) {
584e6987bf3SBenjamin Kramer         PrevMatch = &*I;
585938d3d63SAdam Nemet         ++I;
586938d3d63SAdam Nemet       } else if (PrevMatch != nullptr && DoesMatch) {
587e6987bf3SBenjamin Kramer         I->moveTo(*PrevMatch);
588938d3d63SAdam Nemet         I = PartitionContainer.erase(I);
589938d3d63SAdam Nemet       } else {
590938d3d63SAdam Nemet         PrevMatch = nullptr;
591938d3d63SAdam Nemet         ++I;
592938d3d63SAdam Nemet       }
593938d3d63SAdam Nemet     }
594938d3d63SAdam Nemet   }
59572448525SMichael Kruse 
59672448525SMichael Kruse   /// Assign new LoopIDs for the partition's cloned loop.
setNewLoopID(MDNode * OrigLoopID,InstPartition * Part)59772448525SMichael Kruse   void setNewLoopID(MDNode *OrigLoopID, InstPartition *Part) {
59872448525SMichael Kruse     Optional<MDNode *> PartitionID = makeFollowupLoopID(
59972448525SMichael Kruse         OrigLoopID,
60072448525SMichael Kruse         {LLVMLoopDistributeFollowupAll,
60172448525SMichael Kruse          Part->hasDepCycle() ? LLVMLoopDistributeFollowupSequential
60272448525SMichael Kruse                              : LLVMLoopDistributeFollowupCoincident});
603a7938c74SKazu Hirata     if (PartitionID) {
60472448525SMichael Kruse       Loop *NewLoop = Part->getDistributedLoop();
605*611ffcf4SKazu Hirata       NewLoop->setLoopID(PartitionID.value());
60672448525SMichael Kruse     }
60772448525SMichael Kruse   }
608938d3d63SAdam Nemet };
609938d3d63SAdam Nemet 
6105f8f34e4SAdrian Prantl /// For each memory instruction, this class maintains difference of the
611938d3d63SAdam Nemet /// number of unsafe dependences that start out from this instruction minus
612938d3d63SAdam Nemet /// those that end here.
613938d3d63SAdam Nemet ///
614938d3d63SAdam Nemet /// By traversing the memory instructions in program order and accumulating this
615938d3d63SAdam Nemet /// number, we know whether any unsafe dependence crosses over a program point.
616938d3d63SAdam Nemet class MemoryInstructionDependences {
617dd40f5e7SEugene Zelenko   using Dependence = MemoryDepChecker::Dependence;
618938d3d63SAdam Nemet 
619938d3d63SAdam Nemet public:
620938d3d63SAdam Nemet   struct Entry {
621938d3d63SAdam Nemet     Instruction *Inst;
622dd40f5e7SEugene Zelenko     unsigned NumUnsafeDependencesStartOrEnd = 0;
623938d3d63SAdam Nemet 
Entry__anon4e01e93c0111::MemoryInstructionDependences::Entry624dd40f5e7SEugene Zelenko     Entry(Instruction *Inst) : Inst(Inst) {}
625938d3d63SAdam Nemet   };
626938d3d63SAdam Nemet 
627dd40f5e7SEugene Zelenko   using AccessesType = SmallVector<Entry, 8>;
628938d3d63SAdam Nemet 
begin() const629938d3d63SAdam Nemet   AccessesType::const_iterator begin() const { return Accesses.begin(); }
end() const630938d3d63SAdam Nemet   AccessesType::const_iterator end() const { return Accesses.end(); }
631938d3d63SAdam Nemet 
MemoryInstructionDependences(const SmallVectorImpl<Instruction * > & Instructions,const SmallVectorImpl<Dependence> & Dependences)632938d3d63SAdam Nemet   MemoryInstructionDependences(
633938d3d63SAdam Nemet       const SmallVectorImpl<Instruction *> &Instructions,
634a2df750fSAdam Nemet       const SmallVectorImpl<Dependence> &Dependences) {
635e6987bf3SBenjamin Kramer     Accesses.append(Instructions.begin(), Instructions.end());
636938d3d63SAdam Nemet 
637d34e60caSNicola Zaghen     LLVM_DEBUG(dbgs() << "Backward dependences:\n");
638a2df750fSAdam Nemet     for (auto &Dep : Dependences)
639938d3d63SAdam Nemet       if (Dep.isPossiblyBackward()) {
640938d3d63SAdam Nemet         // Note that the designations source and destination follow the program
641938d3d63SAdam Nemet         // order, i.e. source is always first.  (The direction is given by the
642938d3d63SAdam Nemet         // DepType.)
643938d3d63SAdam Nemet         ++Accesses[Dep.Source].NumUnsafeDependencesStartOrEnd;
644938d3d63SAdam Nemet         --Accesses[Dep.Destination].NumUnsafeDependencesStartOrEnd;
645938d3d63SAdam Nemet 
646d34e60caSNicola Zaghen         LLVM_DEBUG(Dep.print(dbgs(), 2, Instructions));
647938d3d63SAdam Nemet       }
648938d3d63SAdam Nemet   }
649938d3d63SAdam Nemet 
650938d3d63SAdam Nemet private:
651938d3d63SAdam Nemet   AccessesType Accesses;
652938d3d63SAdam Nemet };
653938d3d63SAdam Nemet 
6545f8f34e4SAdrian Prantl /// The actual class performing the per-loop work.
65561399ac4SAdam Nemet class LoopDistributeForLoop {
656938d3d63SAdam Nemet public:
LoopDistributeForLoop(Loop * L,Function * F,LoopInfo * LI,DominatorTree * DT,ScalarEvolution * SE,OptimizationRemarkEmitter * ORE)657eff76646SAdam Nemet   LoopDistributeForLoop(Loop *L, Function *F, LoopInfo *LI, DominatorTree *DT,
658aad81608SAdam Nemet                         ScalarEvolution *SE, OptimizationRemarkEmitter *ORE)
659dd40f5e7SEugene Zelenko       : L(L), F(F), LI(LI), DT(DT), SE(SE), ORE(ORE) {
660d2fa4147SAdam Nemet     setForced();
661d2fa4147SAdam Nemet   }
662c75ad69cSAdam Nemet 
6635f8f34e4SAdrian Prantl   /// Try to distribute an inner-most loop.
processLoop(std::function<const LoopAccessInfo & (Loop &)> & GetLAA)664b2593f78SAdam Nemet   bool processLoop(std::function<const LoopAccessInfo &(Loop &)> &GetLAA) {
66589c1e35fSStefanos Baziotis     assert(L->isInnermost() && "Only process inner loops.");
666938d3d63SAdam Nemet 
667d34e60caSNicola Zaghen     LLVM_DEBUG(dbgs() << "\nLDist: In \""
668d34e60caSNicola Zaghen                       << L->getHeader()->getParent()->getName()
669938d3d63SAdam Nemet                       << "\" checking " << *L << "\n");
670938d3d63SAdam Nemet 
671f5fe8493SPhilip Reames     // Having a single exit block implies there's also one exiting block.
6727f38e119SAdam Nemet     if (!L->getExitBlock())
673f744ad78SAdam Nemet       return fail("MultipleExitBlocks", "multiple exit blocks");
6742e03213fSFlorian Hahn     if (!L->isLoopSimplifyForm())
6752e03213fSFlorian Hahn       return fail("NotLoopSimplifyForm",
6762e03213fSFlorian Hahn                   "loop is not in loop-simplify form");
677f5fe8493SPhilip Reames     if (!L->isRotatedForm())
678f5fe8493SPhilip Reames       return fail("NotBottomTested", "loop is not bottom tested");
6792e03213fSFlorian Hahn 
6802e03213fSFlorian Hahn     BasicBlock *PH = L->getLoopPreheader();
681eff76646SAdam Nemet 
682b2593f78SAdam Nemet     LAI = &GetLAA(*L);
683938d3d63SAdam Nemet 
684938d3d63SAdam Nemet     // Currently, we only distribute to isolate the part of the loop with
685938d3d63SAdam Nemet     // dependence cycles to enable partial vectorization.
686eff76646SAdam Nemet     if (LAI->canVectorizeMemory())
687f744ad78SAdam Nemet       return fail("MemOpsCanBeVectorized",
688f744ad78SAdam Nemet                   "memory operations are safe for vectorization");
6897f38e119SAdam Nemet 
690eff76646SAdam Nemet     auto *Dependences = LAI->getDepChecker().getDependences();
6917f38e119SAdam Nemet     if (!Dependences || Dependences->empty())
692f744ad78SAdam Nemet       return fail("NoUnsafeDeps", "no unsafe dependences to isolate");
693938d3d63SAdam Nemet 
694938d3d63SAdam Nemet     InstPartitionContainer Partitions(L, LI, DT);
695938d3d63SAdam Nemet 
696938d3d63SAdam Nemet     // First, go through each memory operation and assign them to consecutive
697938d3d63SAdam Nemet     // partitions (the order of partitions follows program order).  Put those
698938d3d63SAdam Nemet     // with unsafe dependences into "cyclic" partition otherwise put each store
699938d3d63SAdam Nemet     // in its own "non-cyclic" partition (we'll merge these later).
700938d3d63SAdam Nemet     //
701938d3d63SAdam Nemet     // Note that a memory operation (e.g. Load2 below) at a program point that
702938d3d63SAdam Nemet     // has an unsafe dependence (Store3->Load1) spanning over it must be
703938d3d63SAdam Nemet     // included in the same cyclic partition as the dependent operations.  This
704938d3d63SAdam Nemet     // is to preserve the original program order after distribution.  E.g.:
705938d3d63SAdam Nemet     //
706938d3d63SAdam Nemet     //                NumUnsafeDependencesStartOrEnd  NumUnsafeDependencesActive
707938d3d63SAdam Nemet     //  Load1   -.                     1                       0->1
708938d3d63SAdam Nemet     //  Load2    | /Unsafe/            0                       1
709938d3d63SAdam Nemet     //  Store3  -'                    -1                       1->0
710938d3d63SAdam Nemet     //  Load4                          0                       0
711938d3d63SAdam Nemet     //
712938d3d63SAdam Nemet     // NumUnsafeDependencesActive > 0 indicates this situation and in this case
713938d3d63SAdam Nemet     // we just keep assigning to the same cyclic partition until
714938d3d63SAdam Nemet     // NumUnsafeDependencesActive reaches 0.
715eff76646SAdam Nemet     const MemoryDepChecker &DepChecker = LAI->getDepChecker();
716938d3d63SAdam Nemet     MemoryInstructionDependences MID(DepChecker.getMemoryInstructions(),
717a2df750fSAdam Nemet                                      *Dependences);
718938d3d63SAdam Nemet 
719938d3d63SAdam Nemet     int NumUnsafeDependencesActive = 0;
720938d3d63SAdam Nemet     for (auto &InstDep : MID) {
721938d3d63SAdam Nemet       Instruction *I = InstDep.Inst;
722938d3d63SAdam Nemet       // We update NumUnsafeDependencesActive post-instruction, catch the
723938d3d63SAdam Nemet       // start of a dependence directly via NumUnsafeDependencesStartOrEnd.
724938d3d63SAdam Nemet       if (NumUnsafeDependencesActive ||
725938d3d63SAdam Nemet           InstDep.NumUnsafeDependencesStartOrEnd > 0)
726938d3d63SAdam Nemet         Partitions.addToCyclicPartition(I);
727938d3d63SAdam Nemet       else
728938d3d63SAdam Nemet         Partitions.addToNewNonCyclicPartition(I);
729938d3d63SAdam Nemet       NumUnsafeDependencesActive += InstDep.NumUnsafeDependencesStartOrEnd;
730938d3d63SAdam Nemet       assert(NumUnsafeDependencesActive >= 0 &&
731938d3d63SAdam Nemet              "Negative number of dependences active");
732938d3d63SAdam Nemet     }
733938d3d63SAdam Nemet 
734938d3d63SAdam Nemet     // Add partitions for values used outside.  These partitions can be out of
735938d3d63SAdam Nemet     // order from the original program order.  This is OK because if the
736938d3d63SAdam Nemet     // partition uses a load we will merge this partition with the original
737938d3d63SAdam Nemet     // partition of the load that we set up in the previous loop (see
738938d3d63SAdam Nemet     // mergeToAvoidDuplicatedLoads).
739938d3d63SAdam Nemet     auto DefsUsedOutside = findDefsUsedOutsideOfLoop(L);
740938d3d63SAdam Nemet     for (auto *Inst : DefsUsedOutside)
741938d3d63SAdam Nemet       Partitions.addToNewNonCyclicPartition(Inst);
742938d3d63SAdam Nemet 
743d34e60caSNicola Zaghen     LLVM_DEBUG(dbgs() << "Seeded partitions:\n" << Partitions);
744938d3d63SAdam Nemet     if (Partitions.getSize() < 2)
745f744ad78SAdam Nemet       return fail("CantIsolateUnsafeDeps",
746f744ad78SAdam Nemet                   "cannot isolate unsafe dependencies");
747938d3d63SAdam Nemet 
748938d3d63SAdam Nemet     // Run the merge heuristics: Merge non-cyclic adjacent partitions since we
749938d3d63SAdam Nemet     // should be able to vectorize these together.
750938d3d63SAdam Nemet     Partitions.mergeBeforePopulating();
751d34e60caSNicola Zaghen     LLVM_DEBUG(dbgs() << "\nMerged partitions:\n" << Partitions);
752938d3d63SAdam Nemet     if (Partitions.getSize() < 2)
753f744ad78SAdam Nemet       return fail("CantIsolateUnsafeDeps",
754f744ad78SAdam Nemet                   "cannot isolate unsafe dependencies");
755938d3d63SAdam Nemet 
756938d3d63SAdam Nemet     // Now, populate the partitions with non-memory operations.
757938d3d63SAdam Nemet     Partitions.populateUsedSet();
758d34e60caSNicola Zaghen     LLVM_DEBUG(dbgs() << "\nPopulated partitions:\n" << Partitions);
759938d3d63SAdam Nemet 
760938d3d63SAdam Nemet     // In order to preserve original lexical order for loads, keep them in the
761938d3d63SAdam Nemet     // partition that we set up in the MemoryInstructionDependences loop.
762938d3d63SAdam Nemet     if (Partitions.mergeToAvoidDuplicatedLoads()) {
763d34e60caSNicola Zaghen       LLVM_DEBUG(dbgs() << "\nPartitions merged to ensure unique loads:\n"
764938d3d63SAdam Nemet                         << Partitions);
765938d3d63SAdam Nemet       if (Partitions.getSize() < 2)
766f744ad78SAdam Nemet         return fail("CantIsolateUnsafeDeps",
767f744ad78SAdam Nemet                     "cannot isolate unsafe dependencies");
768938d3d63SAdam Nemet     }
769938d3d63SAdam Nemet 
7702466ba97SMatt Arsenault     // Don't distribute the loop if we need too many SCEV run-time checks, or
7712466ba97SMatt Arsenault     // any if it's illegal.
7725ba11503SPhilip Reames     const SCEVPredicate &Pred = LAI->getPSE().getPredicate();
7732466ba97SMatt Arsenault     if (LAI->hasConvergentOp() && !Pred.isAlwaysTrue()) {
7742466ba97SMatt Arsenault       return fail("RuntimeCheckWithConvergent",
7752466ba97SMatt Arsenault                   "may not insert runtime check with convergent operation");
7762466ba97SMatt Arsenault     }
7772466ba97SMatt Arsenault 
778129b531cSKazu Hirata     if (Pred.getComplexity() > (IsForced.value_or(false)
779d2fa4147SAdam Nemet                                     ? PragmaDistributeSCEVCheckThreshold
7807f38e119SAdam Nemet                                     : DistributeSCEVCheckThreshold))
781f744ad78SAdam Nemet       return fail("TooManySCEVRuntimeChecks",
782f744ad78SAdam Nemet                   "too many SCEV run-time checks needed.\n");
7832910a4f6SSilviu Baranga 
784129b531cSKazu Hirata     if (!IsForced.value_or(false) && hasDisableAllTransformsHint(L))
78572448525SMichael Kruse       return fail("HeuristicDisabled", "distribution heuristic disabled");
78672448525SMichael Kruse 
787d34e60caSNicola Zaghen     LLVM_DEBUG(dbgs() << "\nDistributing loop: " << *L << "\n");
788938d3d63SAdam Nemet     // We're done forming the partitions set up the reverse mapping from
789938d3d63SAdam Nemet     // instructions to partitions.
790938d3d63SAdam Nemet     Partitions.setupPartitionIdOnInstructions();
791938d3d63SAdam Nemet 
7922910a4f6SSilviu Baranga     // If we need run-time checks, version the loop now.
793eff76646SAdam Nemet     auto PtrToPartition = Partitions.computePartitionSetForPointers(*LAI);
794eff76646SAdam Nemet     const auto *RtPtrChecking = LAI->getRuntimePointerChecking();
79515840393SAdam Nemet     const auto &AllChecks = RtPtrChecking->getChecks();
796c75ad69cSAdam Nemet     auto Checks = includeOnlyCrossPartitionChecks(AllChecks, PtrToPartition,
797c75ad69cSAdam Nemet                                                   RtPtrChecking);
7982910a4f6SSilviu Baranga 
7992466ba97SMatt Arsenault     if (LAI->hasConvergentOp() && !Checks.empty()) {
8002466ba97SMatt Arsenault       return fail("RuntimeCheckWithConvergent",
8012466ba97SMatt Arsenault                   "may not insert runtime check with convergent operation");
8022466ba97SMatt Arsenault     }
8032466ba97SMatt Arsenault 
8044dd33272Sserge-sans-paille     // To keep things simple have an empty preheader before we version or clone
8054dd33272Sserge-sans-paille     // the loop.  (Also split if this has no predecessor, i.e. entry, because we
8064dd33272Sserge-sans-paille     // rely on PH having a predecessor.)
8074dd33272Sserge-sans-paille     if (!PH->getSinglePredecessor() || &*PH->begin() != PH->getTerminator())
8084dd33272Sserge-sans-paille       SplitBlock(PH, PH->getTerminator(), DT, LI);
8094dd33272Sserge-sans-paille 
8102910a4f6SSilviu Baranga     if (!Pred.isAlwaysTrue() || !Checks.empty()) {
8112466ba97SMatt Arsenault       assert(!LAI->hasConvergentOp() && "inserting illegal loop versioning");
8122466ba97SMatt Arsenault 
81372448525SMichael Kruse       MDNode *OrigLoopID = L->getLoopID();
81472448525SMichael Kruse 
815d34e60caSNicola Zaghen       LLVM_DEBUG(dbgs() << "\nPointers:\n");
816d34e60caSNicola Zaghen       LLVM_DEBUG(LAI->getRuntimePointerChecking()->printChecks(dbgs(), Checks));
81789c01242SFlorian Hahn       LoopVersioning LVer(*LAI, Checks, L, LI, DT, SE);
818e4813409SAdam Nemet       LVer.versionLoop(DefsUsedOutside);
8195eccf07dSAdam Nemet       LVer.annotateLoopWithNoAlias();
82072448525SMichael Kruse 
82172448525SMichael Kruse       // The unversioned loop will not be changed, so we inherit all attributes
82272448525SMichael Kruse       // from the original loop, but remove the loop distribution metadata to
82372448525SMichael Kruse       // avoid to distribute it again.
8243b7c3a65SKazu Hirata       MDNode *UnversionedLoopID =
8253b7c3a65SKazu Hirata           makeFollowupLoopID(OrigLoopID,
8263b7c3a65SKazu Hirata                              {LLVMLoopDistributeFollowupAll,
8273b7c3a65SKazu Hirata                               LLVMLoopDistributeFollowupFallback},
8283b7c3a65SKazu Hirata                              "llvm.loop.distribute.", true)
829*611ffcf4SKazu Hirata               .value();
83072448525SMichael Kruse       LVer.getNonVersionedLoop()->setLoopID(UnversionedLoopID);
831938d3d63SAdam Nemet     }
832938d3d63SAdam Nemet 
833938d3d63SAdam Nemet     // Create identical copies of the original loop for each partition and hook
834938d3d63SAdam Nemet     // them up sequentially.
835843fb204SJustin Bogner     Partitions.cloneLoops();
836938d3d63SAdam Nemet 
837938d3d63SAdam Nemet     // Now, we remove the instruction from each loop that don't belong to that
838938d3d63SAdam Nemet     // partition.
839938d3d63SAdam Nemet     Partitions.removeUnusedInsts();
840d34e60caSNicola Zaghen     LLVM_DEBUG(dbgs() << "\nAfter removing unused Instrs:\n");
841d34e60caSNicola Zaghen     LLVM_DEBUG(Partitions.printBlocks());
842938d3d63SAdam Nemet 
843938d3d63SAdam Nemet     if (LDistVerify) {
844e0b2d97bSMichael Zolotukhin       LI->verify(*DT);
8457c35de12SDavid Green       assert(DT->verify(DominatorTree::VerificationLevel::Fast));
846938d3d63SAdam Nemet     }
847938d3d63SAdam Nemet 
848938d3d63SAdam Nemet     ++NumLoopsDistributed;
84988ec4918SAdam Nemet     // Report the success.
8509590658fSVivek Pandya     ORE->emit([&]() {
8519590658fSVivek Pandya       return OptimizationRemark(LDIST_NAME, "Distribute", L->getStartLoc(),
852f744ad78SAdam Nemet                                 L->getHeader())
8539590658fSVivek Pandya              << "distributed loop";
8549590658fSVivek Pandya     });
855938d3d63SAdam Nemet     return true;
856938d3d63SAdam Nemet   }
857938d3d63SAdam Nemet 
8585f8f34e4SAdrian Prantl   /// Provide diagnostics then \return with false.
fail(StringRef RemarkName,StringRef Message)859f744ad78SAdam Nemet   bool fail(StringRef RemarkName, StringRef Message) {
8600ba164bbSAdam Nemet     LLVMContext &Ctx = F->getContext();
861129b531cSKazu Hirata     bool Forced = isForced().value_or(false);
8620ba164bbSAdam Nemet 
863d34e60caSNicola Zaghen     LLVM_DEBUG(dbgs() << "Skipping; " << Message << "\n");
8640ba164bbSAdam Nemet 
8650ba164bbSAdam Nemet     // With Rpass-missed report that distribution failed.
8669590658fSVivek Pandya     ORE->emit([&]() {
8679590658fSVivek Pandya       return OptimizationRemarkMissed(LDIST_NAME, "NotDistributed",
8689590658fSVivek Pandya                                       L->getStartLoc(), L->getHeader())
8699590658fSVivek Pandya              << "loop not distributed: use -Rpass-analysis=loop-distribute for "
8709590658fSVivek Pandya                 "more "
8719590658fSVivek Pandya                 "info";
8729590658fSVivek Pandya     });
8730ba164bbSAdam Nemet 
8740ba164bbSAdam Nemet     // With Rpass-analysis report why.  This is on by default if distribution
8750ba164bbSAdam Nemet     // was requested explicitly.
876f744ad78SAdam Nemet     ORE->emit(OptimizationRemarkAnalysis(
877f744ad78SAdam Nemet                   Forced ? OptimizationRemarkAnalysis::AlwaysPrint : LDIST_NAME,
878f744ad78SAdam Nemet                   RemarkName, L->getStartLoc(), L->getHeader())
879f744ad78SAdam Nemet               << "loop not distributed: " << Message);
8800ba164bbSAdam Nemet 
8810ba164bbSAdam Nemet     // Also issue a warning if distribution was requested explicitly but it
8820ba164bbSAdam Nemet     // failed.
8830ba164bbSAdam Nemet     if (Forced)
8840ba164bbSAdam Nemet       Ctx.diagnose(DiagnosticInfoOptimizationFailure(
88574730d9aSAdam Nemet           *F, L->getStartLoc(), "loop not distributed: failed "
8860ba164bbSAdam Nemet                                 "explicitly specified loop distribution"));
8870ba164bbSAdam Nemet 
8887f38e119SAdam Nemet     return false;
8897f38e119SAdam Nemet   }
8907f38e119SAdam Nemet 
8915f8f34e4SAdrian Prantl   /// Return if distribution forced to be enabled/disabled for the loop.
892d2fa4147SAdam Nemet   ///
893d2fa4147SAdam Nemet   /// If the optional has a value, it indicates whether distribution was forced
894d2fa4147SAdam Nemet   /// to be enabled (true) or disabled (false).  If the optional has no value
895d2fa4147SAdam Nemet   /// distribution was not forced either way.
isForced() const896d2fa4147SAdam Nemet   const Optional<bool> &isForced() const { return IsForced; }
897d2fa4147SAdam Nemet 
89861399ac4SAdam Nemet private:
8995f8f34e4SAdrian Prantl   /// Filter out checks between pointers from the same partition.
90061399ac4SAdam Nemet   ///
90161399ac4SAdam Nemet   /// \p PtrToPartition contains the partition number for pointers.  Partition
90261399ac4SAdam Nemet   /// number -1 means that the pointer is used in multiple partitions.  In this
90361399ac4SAdam Nemet   /// case we can't safely omit the check.
includeOnlyCrossPartitionChecks(const SmallVectorImpl<RuntimePointerCheck> & AllChecks,const SmallVectorImpl<int> & PtrToPartition,const RuntimePointerChecking * RtPtrChecking)904616657b3SFlorian Hahn   SmallVector<RuntimePointerCheck, 4> includeOnlyCrossPartitionChecks(
905616657b3SFlorian Hahn       const SmallVectorImpl<RuntimePointerCheck> &AllChecks,
90661399ac4SAdam Nemet       const SmallVectorImpl<int> &PtrToPartition,
90761399ac4SAdam Nemet       const RuntimePointerChecking *RtPtrChecking) {
908616657b3SFlorian Hahn     SmallVector<RuntimePointerCheck, 4> Checks;
90961399ac4SAdam Nemet 
91090208720SSanjoy Das     copy_if(AllChecks, std::back_inserter(Checks),
911616657b3SFlorian Hahn             [&](const RuntimePointerCheck &Check) {
91261399ac4SAdam Nemet               for (unsigned PtrIdx1 : Check.first->Members)
91361399ac4SAdam Nemet                 for (unsigned PtrIdx2 : Check.second->Members)
91461399ac4SAdam Nemet                   // Only include this check if there is a pair of pointers
91561399ac4SAdam Nemet                   // that require checking and the pointers fall into
91661399ac4SAdam Nemet                   // separate partitions.
91761399ac4SAdam Nemet                   //
91861399ac4SAdam Nemet                   // (Note that we already know at this point that the two
91961399ac4SAdam Nemet                   // pointer groups need checking but it doesn't follow
92061399ac4SAdam Nemet                   // that each pair of pointers within the two groups need
92161399ac4SAdam Nemet                   // checking as well.
92261399ac4SAdam Nemet                   //
92361399ac4SAdam Nemet                   // In other words we don't want to include a check just
92461399ac4SAdam Nemet                   // because there is a pair of pointers between the two
92561399ac4SAdam Nemet                   // pointer groups that require checks and a different
92661399ac4SAdam Nemet                   // pair whose pointers fall into different partitions.)
92761399ac4SAdam Nemet                   if (RtPtrChecking->needsChecking(PtrIdx1, PtrIdx2) &&
92861399ac4SAdam Nemet                       !RuntimePointerChecking::arePointersInSamePartition(
92961399ac4SAdam Nemet                           PtrToPartition, PtrIdx1, PtrIdx2))
93061399ac4SAdam Nemet                     return true;
93161399ac4SAdam Nemet               return false;
93261399ac4SAdam Nemet             });
93361399ac4SAdam Nemet 
93461399ac4SAdam Nemet     return Checks;
93561399ac4SAdam Nemet   }
93661399ac4SAdam Nemet 
9375f8f34e4SAdrian Prantl   /// Check whether the loop metadata is forcing distribution to be
938d2fa4147SAdam Nemet   /// enabled/disabled.
setForced()939d2fa4147SAdam Nemet   void setForced() {
940d2fa4147SAdam Nemet     Optional<const MDOperand *> Value =
941d2fa4147SAdam Nemet         findStringMetadataForLoop(L, "llvm.loop.distribute.enable");
942d2fa4147SAdam Nemet     if (!Value)
943d2fa4147SAdam Nemet       return;
944d2fa4147SAdam Nemet 
945d2fa4147SAdam Nemet     const MDOperand *Op = *Value;
946d2fa4147SAdam Nemet     assert(Op && mdconst::hasa<ConstantInt>(*Op) && "invalid metadata");
947d2fa4147SAdam Nemet     IsForced = mdconst::extract<ConstantInt>(*Op)->getZExtValue();
948d2fa4147SAdam Nemet   }
949d2fa4147SAdam Nemet 
95061399ac4SAdam Nemet   Loop *L;
9514338d676SAdam Nemet   Function *F;
9524338d676SAdam Nemet 
9534338d676SAdam Nemet   // Analyses used.
954938d3d63SAdam Nemet   LoopInfo *LI;
955dd40f5e7SEugene Zelenko   const LoopAccessInfo *LAI = nullptr;
956938d3d63SAdam Nemet   DominatorTree *DT;
9572910a4f6SSilviu Baranga   ScalarEvolution *SE;
958aad81608SAdam Nemet   OptimizationRemarkEmitter *ORE;
959d2fa4147SAdam Nemet 
9605f8f34e4SAdrian Prantl   /// Indicates whether distribution is forced to be enabled/disabled for
961d2fa4147SAdam Nemet   /// the loop.
962d2fa4147SAdam Nemet   ///
963d2fa4147SAdam Nemet   /// If the optional has a value, it indicates whether distribution was forced
964d2fa4147SAdam Nemet   /// to be enabled (true) or disabled (false).  If the optional has no value
965d2fa4147SAdam Nemet   /// distribution was not forced either way.
966d2fa4147SAdam Nemet   Optional<bool> IsForced;
967938d3d63SAdam Nemet };
96861399ac4SAdam Nemet 
969dd40f5e7SEugene Zelenko } // end anonymous namespace
970dd40f5e7SEugene Zelenko 
971b2593f78SAdam Nemet /// Shared implementation between new and old PMs.
runImpl(Function & F,LoopInfo * LI,DominatorTree * DT,ScalarEvolution * SE,OptimizationRemarkEmitter * ORE,std::function<const LoopAccessInfo & (Loop &)> & GetLAA)972b2593f78SAdam Nemet static bool runImpl(Function &F, LoopInfo *LI, DominatorTree *DT,
973b2593f78SAdam Nemet                     ScalarEvolution *SE, OptimizationRemarkEmitter *ORE,
97432e6a34cSAdam Nemet                     std::function<const LoopAccessInfo &(Loop &)> &GetLAA) {
97561399ac4SAdam Nemet   // Build up a worklist of inner-loops to vectorize. This is necessary as the
97661399ac4SAdam Nemet   // act of distributing a loop creates new loops and can invalidate iterators
97761399ac4SAdam Nemet   // across the loops.
97861399ac4SAdam Nemet   SmallVector<Loop *, 8> Worklist;
97961399ac4SAdam Nemet 
98061399ac4SAdam Nemet   for (Loop *TopLevelLoop : *LI)
98161399ac4SAdam Nemet     for (Loop *L : depth_first(TopLevelLoop))
98261399ac4SAdam Nemet       // We only handle inner-most loops.
98389c1e35fSStefanos Baziotis       if (L->isInnermost())
98461399ac4SAdam Nemet         Worklist.push_back(L);
98561399ac4SAdam Nemet 
98661399ac4SAdam Nemet   // Now walk the identified inner loops.
98761399ac4SAdam Nemet   bool Changed = false;
98861399ac4SAdam Nemet   for (Loop *L : Worklist) {
989aad81608SAdam Nemet     LoopDistributeForLoop LDL(L, &F, LI, DT, SE, ORE);
990d2fa4147SAdam Nemet 
991d2fa4147SAdam Nemet     // If distribution was forced for the specific loop to be
992d2fa4147SAdam Nemet     // enabled/disabled, follow that.  Otherwise use the global flag.
993129b531cSKazu Hirata     if (LDL.isForced().value_or(EnableLoopDistribute))
994b2593f78SAdam Nemet       Changed |= LDL.processLoop(GetLAA);
99561399ac4SAdam Nemet   }
99661399ac4SAdam Nemet 
99761399ac4SAdam Nemet   // Process each loop nest in the function.
99861399ac4SAdam Nemet   return Changed;
99961399ac4SAdam Nemet }
100061399ac4SAdam Nemet 
1001dd40f5e7SEugene Zelenko namespace {
1002dd40f5e7SEugene Zelenko 
10035f8f34e4SAdrian Prantl /// The pass class.
1004b2593f78SAdam Nemet class LoopDistributeLegacy : public FunctionPass {
1005b2593f78SAdam Nemet public:
1006dd40f5e7SEugene Zelenko   static char ID;
1007dd40f5e7SEugene Zelenko 
LoopDistributeLegacy()100832e6a34cSAdam Nemet   LoopDistributeLegacy() : FunctionPass(ID) {
1009b2593f78SAdam Nemet     // The default is set by the caller.
1010b2593f78SAdam Nemet     initializeLoopDistributeLegacyPass(*PassRegistry::getPassRegistry());
1011b2593f78SAdam Nemet   }
1012b2593f78SAdam Nemet 
runOnFunction(Function & F)1013b2593f78SAdam Nemet   bool runOnFunction(Function &F) override {
1014b2593f78SAdam Nemet     if (skipFunction(F))
1015b2593f78SAdam Nemet       return false;
1016b2593f78SAdam Nemet 
1017b2593f78SAdam Nemet     auto *LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
1018b2593f78SAdam Nemet     auto *LAA = &getAnalysis<LoopAccessLegacyAnalysis>();
1019b2593f78SAdam Nemet     auto *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
1020b2593f78SAdam Nemet     auto *SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
1021b2593f78SAdam Nemet     auto *ORE = &getAnalysis<OptimizationRemarkEmitterWrapperPass>().getORE();
1022b2593f78SAdam Nemet     std::function<const LoopAccessInfo &(Loop &)> GetLAA =
1023b2593f78SAdam Nemet         [&](Loop &L) -> const LoopAccessInfo & { return LAA->getInfo(&L); };
1024b2593f78SAdam Nemet 
102532e6a34cSAdam Nemet     return runImpl(F, LI, DT, SE, ORE, GetLAA);
1026b2593f78SAdam Nemet   }
1027b2593f78SAdam Nemet 
getAnalysisUsage(AnalysisUsage & AU) const102861399ac4SAdam Nemet   void getAnalysisUsage(AnalysisUsage &AU) const override {
102961399ac4SAdam Nemet     AU.addRequired<ScalarEvolutionWrapperPass>();
103061399ac4SAdam Nemet     AU.addRequired<LoopInfoWrapperPass>();
103161399ac4SAdam Nemet     AU.addPreserved<LoopInfoWrapperPass>();
10327853c1ddSXinliang David Li     AU.addRequired<LoopAccessLegacyAnalysis>();
103361399ac4SAdam Nemet     AU.addRequired<DominatorTreeWrapperPass>();
103461399ac4SAdam Nemet     AU.addPreserved<DominatorTreeWrapperPass>();
103579ac42a5SAdam Nemet     AU.addRequired<OptimizationRemarkEmitterWrapperPass>();
103666fdba87SEli Friedman     AU.addPreserved<GlobalsAAWrapperPass>();
103761399ac4SAdam Nemet   }
103861399ac4SAdam Nemet };
1039dd40f5e7SEugene Zelenko 
1040dd40f5e7SEugene Zelenko } // end anonymous namespace
1041938d3d63SAdam Nemet 
run(Function & F,FunctionAnalysisManager & AM)1042b2593f78SAdam Nemet PreservedAnalyses LoopDistributePass::run(Function &F,
1043b2593f78SAdam Nemet                                           FunctionAnalysisManager &AM) {
1044b2593f78SAdam Nemet   auto &LI = AM.getResult<LoopAnalysis>(F);
1045b2593f78SAdam Nemet   auto &DT = AM.getResult<DominatorTreeAnalysis>(F);
1046b2593f78SAdam Nemet   auto &SE = AM.getResult<ScalarEvolutionAnalysis>(F);
1047b2593f78SAdam Nemet   auto &ORE = AM.getResult<OptimizationRemarkEmitterAnalysis>(F);
1048b2593f78SAdam Nemet 
1049410eaeb0SChandler Carruth   // We don't directly need these analyses but they're required for loop
1050410eaeb0SChandler Carruth   // analyses so provide them below.
1051410eaeb0SChandler Carruth   auto &AA = AM.getResult<AAManager>(F);
1052410eaeb0SChandler Carruth   auto &AC = AM.getResult<AssumptionAnalysis>(F);
1053410eaeb0SChandler Carruth   auto &TTI = AM.getResult<TargetIRAnalysis>(F);
1054410eaeb0SChandler Carruth   auto &TLI = AM.getResult<TargetLibraryAnalysis>(F);
1055410eaeb0SChandler Carruth 
1056b2593f78SAdam Nemet   auto &LAM = AM.getResult<LoopAnalysisManagerFunctionProxy>(F).getManager();
1057b2593f78SAdam Nemet   std::function<const LoopAccessInfo &(Loop &)> GetLAA =
1058b2593f78SAdam Nemet       [&](Loop &L) -> const LoopAccessInfo & {
10592ea4c2c5SWenlei He     LoopStandardAnalysisResults AR = {AA,  AC,  DT,      LI,      SE,
1060452714f8SAnna Thomas                                       TLI, TTI, nullptr, nullptr, nullptr};
1061410eaeb0SChandler Carruth     return LAM.getResult<LoopAccessAnalysis>(L, AR);
1062b2593f78SAdam Nemet   };
1063b2593f78SAdam Nemet 
106432e6a34cSAdam Nemet   bool Changed = runImpl(F, &LI, &DT, &SE, &ORE, GetLAA);
1065b2593f78SAdam Nemet   if (!Changed)
1066b2593f78SAdam Nemet     return PreservedAnalyses::all();
1067b2593f78SAdam Nemet   PreservedAnalyses PA;
1068b2593f78SAdam Nemet   PA.preserve<LoopAnalysis>();
1069b2593f78SAdam Nemet   PA.preserve<DominatorTreeAnalysis>();
1070b2593f78SAdam Nemet   return PA;
1071b2593f78SAdam Nemet }
1072b2593f78SAdam Nemet 
1073b2593f78SAdam Nemet char LoopDistributeLegacy::ID;
1074dd40f5e7SEugene Zelenko 
10755cda89adSMichael Zolotukhin static const char ldist_name[] = "Loop Distribution";
1076938d3d63SAdam Nemet 
INITIALIZE_PASS_BEGIN(LoopDistributeLegacy,LDIST_NAME,ldist_name,false,false)1077b2593f78SAdam Nemet INITIALIZE_PASS_BEGIN(LoopDistributeLegacy, LDIST_NAME, ldist_name, false,
1078b2593f78SAdam Nemet                       false)
1079938d3d63SAdam Nemet INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
10807853c1ddSXinliang David Li INITIALIZE_PASS_DEPENDENCY(LoopAccessLegacyAnalysis)
1081938d3d63SAdam Nemet INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
10822910a4f6SSilviu Baranga INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass)
108379ac42a5SAdam Nemet INITIALIZE_PASS_DEPENDENCY(OptimizationRemarkEmitterWrapperPass)
1084b2593f78SAdam Nemet INITIALIZE_PASS_END(LoopDistributeLegacy, LDIST_NAME, ldist_name, false, false)
1085938d3d63SAdam Nemet 
1086dd40f5e7SEugene Zelenko FunctionPass *llvm::createLoopDistributePass() { return new LoopDistributeLegacy(); }
1087