1 //===--------- PolyhedralInfo.cpp - Create Scops from LLVM IR-------------===//
3 /// The LLVM Compiler Infrastructure
5 /// This file is distributed under the University of Illinois Open Source
6 /// License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 /// An interface to the Polyhedral analysis engine(Polly) of LLVM.
12 /// This pass provides an interface to the polyhedral analysis performed by
15 /// This interface provides basic interface like isParallel, isVectorizable
16 /// that can be used in LLVM transformation passes.
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"
30 #include <isl/union_map.h>
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
>();
54 bool PolyhedralInfo::runOnFunction(Function
&F
) {
55 DI
= &getAnalysis
<DependenceInfoWrapperPass
>();
56 SI
= &getAnalysis
<ScopInfoWrapperPass
>();
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 {
75 const Scop
*S
= getScopContainingLoop(L
);
78 const Dependences
&D
=
79 DI
->getDependences(const_cast<Scop
*>(S
), Dependences::AL_Access
);
80 if (!D
.hasValidDependences())
82 DEBUG(dbgs() << "Loop :\t" << L
->getHeader()->getName() << ":\n");
85 D
.getDependences(Dependences::TYPE_RAW
| Dependences::TYPE_WAW
|
86 Dependences::TYPE_WAR
| Dependences::TYPE_RED
);
87 DEBUG(dbgs() << "Dependences :\t" << stringFromIslObj(Deps
) << "\n");
89 isl_union_map
*Schedule
= getScheduleForLoop(S
, L
);
90 DEBUG(dbgs() << "Schedule: \t" << stringFromIslObj(Schedule
) << "\n");
92 IsParallel
= D
.isParallel(Schedule
, Deps
, MinDepDistPtr
);
93 isl_union_map_free(Schedule
);
97 bool PolyhedralInfo::isParallel(Loop
*L
) const { return checkParallel(L
); }
99 const Scop
*PolyhedralInfo::getScopContainingLoop(Loop
*L
) const {
100 assert((SI
) && "ScopInfoWrapperPass is required by PolyhedralInfo pass!\n");
101 for (auto &It
: *SI
) {
102 Region
*R
= It
.first
;
104 return It
.second
.get();
109 // Given a Loop and the containing SCoP, we compute the partial schedule
110 // by taking union of individual schedules of each ScopStmt within the loop
111 // and projecting out the inner dimensions from the range of the schedule.
112 // for (i = 0; i < n; i++)
113 // for (j = 0; j < n; j++)
116 // The original schedule will be
117 // Stmt[i0, i1] -> [i0, i1]
118 // The schedule for the outer loop will be
119 // Stmt[i0, i1] -> [i0]
120 // The schedule for the inner loop will be
121 // Stmt[i0, i1] -> [i0, i1]
122 __isl_give isl_union_map
*PolyhedralInfo::getScheduleForLoop(const Scop
*S
,
124 isl_union_map
*Schedule
= isl_union_map_empty(S
->getParamSpace());
125 int CurrDim
= S
->getRelativeLoopDepth(L
);
126 DEBUG(dbgs() << "Relative loop depth:\t" << CurrDim
<< "\n");
127 assert(CurrDim
>= 0 && "Loop in region should have at least depth one");
129 for (auto *BB
: L
->blocks()) {
130 auto *SS
= S
->getStmtFor(BB
);
134 unsigned int MaxDim
= SS
->getNumIterators();
135 DEBUG(dbgs() << "Maximum depth of Stmt:\t" << MaxDim
<< "\n");
136 auto *ScheduleMap
= SS
->getSchedule();
137 assert(ScheduleMap
&&
138 "Schedules that contain extension nodes require special handling.");
140 ScheduleMap
= isl_map_project_out(ScheduleMap
, isl_dim_out
, CurrDim
+ 1,
141 MaxDim
- CurrDim
- 1);
143 isl_map_set_tuple_id(ScheduleMap
, isl_dim_in
, SS
->getDomainId());
145 isl_union_map_union(Schedule
, isl_union_map_from_map(ScheduleMap
));
148 Schedule
= isl_union_map_coalesce(Schedule
);
152 char PolyhedralInfo::ID
= 0;
154 Pass
*polly::createPolyhedralInfoPass() { return new PolyhedralInfo(); }
156 INITIALIZE_PASS_BEGIN(PolyhedralInfo
, "polyhedral-info",
157 "Polly - Interface to polyhedral analysis engine", false,
159 INITIALIZE_PASS_DEPENDENCY(DependenceInfoWrapperPass
);
160 INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass
);
161 INITIALIZE_PASS_DEPENDENCY(ScopInfoWrapperPass
);
162 INITIALIZE_PASS_END(PolyhedralInfo
, "polyhedral-info",
163 "Polly - Interface to polyhedral analysis engine", false,