[ScopInfo] Move splitAliasGroupsByDomain and getAccessDomain to isl++ [NFCI]
[polly-mirror.git] / lib / Analysis / PolyhedralInfo.cpp
blobe9179c78909c441e08bab42dcb04cfc43236d7c7
1 //===--------- PolyhedralInfo.cpp - Create Scops from LLVM IR-------------===//
2 ///
3 /// The LLVM Compiler Infrastructure
4 ///
5 /// This file is distributed under the University of Illinois Open Source
6 /// License. See LICENSE.TXT for details.
7 ///
8 //===----------------------------------------------------------------------===//
9 ///
10 /// An interface to the Polyhedral analysis engine(Polly) of LLVM.
11 ///
12 /// This pass provides an interface to the polyhedral analysis performed by
13 /// Polly.
14 ///
15 /// This interface provides basic interface like isParallel, isVectorizable
16 /// that can be used in LLVM transformation passes.
17 ///
18 /// Work in progress, this file is subject to change.
19 //===----------------------------------------------------------------------===//
21 #include "polly/PolyhedralInfo.h"
22 #include "polly/DependenceInfo.h"
23 #include "polly/LinkAllPasses.h"
24 #include "polly/Options.h"
25 #include "polly/ScopInfo.h"
26 #include "polly/Support/GICHelper.h"
27 #include "llvm/Analysis/LoopInfo.h"
28 #include "llvm/Support/Debug.h"
29 #include <isl/map.h>
30 #include <isl/union_map.h>
32 using namespace llvm;
33 using namespace polly;
35 #define DEBUG_TYPE "polyhedral-info"
37 static cl::opt<bool> CheckParallel("polly-check-parallel",
38 cl::desc("Check for parallel loops"),
39 cl::Hidden, cl::init(false), cl::ZeroOrMore,
40 cl::cat(PollyCategory));
42 static cl::opt<bool> CheckVectorizable("polly-check-vectorizable",
43 cl::desc("Check for vectorizable loops"),
44 cl::Hidden, cl::init(false),
45 cl::ZeroOrMore, cl::cat(PollyCategory));
47 void PolyhedralInfo::getAnalysisUsage(AnalysisUsage &AU) const {
48 AU.addRequiredTransitive<DependenceInfoWrapperPass>();
49 AU.addRequired<LoopInfoWrapperPass>();
50 AU.addRequiredTransitive<ScopInfoWrapperPass>();
51 AU.setPreservesAll();
54 bool PolyhedralInfo::runOnFunction(Function &F) {
55 DI = &getAnalysis<DependenceInfoWrapperPass>();
56 SI = getAnalysis<ScopInfoWrapperPass>().getSI();
57 return false;
60 void PolyhedralInfo::print(raw_ostream &OS, const Module *) const {
61 auto &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
62 for (auto *TopLevelLoop : LI) {
63 for (auto *L : depth_first(TopLevelLoop)) {
64 OS.indent(2) << L->getHeader()->getName() << ":\t";
65 if (CheckParallel && isParallel(L))
66 OS << "Loop is parallel.\n";
67 else if (CheckParallel)
68 OS << "Loop is not parallel.\n";
73 bool PolyhedralInfo::checkParallel(Loop *L, isl_pw_aff **MinDepDistPtr) const {
74 bool IsParallel;
75 const Scop *S = getScopContainingLoop(L);
76 if (!S)
77 return false;
78 const Dependences &D =
79 DI->getDependences(const_cast<Scop *>(S), Dependences::AL_Access);
80 if (!D.hasValidDependences())
81 return false;
82 LLVM_DEBUG(dbgs() << "Loop :\t" << L->getHeader()->getName() << ":\n");
84 isl_union_map *Deps =
85 D.getDependences(Dependences::TYPE_RAW | Dependences::TYPE_WAW |
86 Dependences::TYPE_WAR | Dependences::TYPE_RED)
87 .release();
89 LLVM_DEBUG(dbgs() << "Dependences :\t" << stringFromIslObj(Deps) << "\n");
91 isl_union_map *Schedule = getScheduleForLoop(S, L);
92 LLVM_DEBUG(dbgs() << "Schedule: \t" << stringFromIslObj(Schedule) << "\n");
94 IsParallel = D.isParallel(Schedule, Deps, MinDepDistPtr);
95 isl_union_map_free(Schedule);
96 return IsParallel;
99 bool PolyhedralInfo::isParallel(Loop *L) const { return checkParallel(L); }
101 const Scop *PolyhedralInfo::getScopContainingLoop(Loop *L) const {
102 assert((SI) && "ScopInfoWrapperPass is required by PolyhedralInfo pass!\n");
103 for (auto &It : *SI) {
104 Region *R = It.first;
105 if (R->contains(L))
106 return It.second.get();
108 return nullptr;
111 // Given a Loop and the containing SCoP, we compute the partial schedule
112 // by taking union of individual schedules of each ScopStmt within the loop
113 // and projecting out the inner dimensions from the range of the schedule.
114 // for (i = 0; i < n; i++)
115 // for (j = 0; j < n; j++)
116 // A[j] = 1; //Stmt
118 // The original schedule will be
119 // Stmt[i0, i1] -> [i0, i1]
120 // The schedule for the outer loop will be
121 // Stmt[i0, i1] -> [i0]
122 // The schedule for the inner loop will be
123 // Stmt[i0, i1] -> [i0, i1]
124 __isl_give isl_union_map *PolyhedralInfo::getScheduleForLoop(const Scop *S,
125 Loop *L) const {
126 isl_union_map *Schedule = isl_union_map_empty(S->getParamSpace().release());
127 int CurrDim = S->getRelativeLoopDepth(L);
128 LLVM_DEBUG(dbgs() << "Relative loop depth:\t" << CurrDim << "\n");
129 assert(CurrDim >= 0 && "Loop in region should have at least depth one");
131 for (auto &SS : *S) {
132 if (L->contains(SS.getSurroundingLoop())) {
134 unsigned int MaxDim = SS.getNumIterators();
135 LLVM_DEBUG(dbgs() << "Maximum depth of Stmt:\t" << MaxDim << "\n");
136 isl_map *ScheduleMap = SS.getSchedule().release();
137 assert(
138 ScheduleMap &&
139 "Schedules that contain extension nodes require special handling.");
141 ScheduleMap = isl_map_project_out(ScheduleMap, isl_dim_out, CurrDim + 1,
142 MaxDim - CurrDim - 1);
143 ScheduleMap = isl_map_set_tuple_id(ScheduleMap, isl_dim_in,
144 SS.getDomainId().release());
145 Schedule =
146 isl_union_map_union(Schedule, isl_union_map_from_map(ScheduleMap));
149 Schedule = isl_union_map_coalesce(Schedule);
150 return Schedule;
153 char PolyhedralInfo::ID = 0;
155 Pass *polly::createPolyhedralInfoPass() { return new PolyhedralInfo(); }
157 INITIALIZE_PASS_BEGIN(PolyhedralInfo, "polyhedral-info",
158 "Polly - Interface to polyhedral analysis engine", false,
159 false);
160 INITIALIZE_PASS_DEPENDENCY(DependenceInfoWrapperPass);
161 INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass);
162 INITIALIZE_PASS_DEPENDENCY(ScopInfoWrapperPass);
163 INITIALIZE_PASS_END(PolyhedralInfo, "polyhedral-info",
164 "Polly - Interface to polyhedral analysis engine", false,
165 false)