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