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
>().getSI();
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 LLVM_DEBUG(dbgs() << "Loop :\t" << L
->getHeader()->getName() << ":\n");
85 D
.getDependences(Dependences::TYPE_RAW
| Dependences::TYPE_WAW
|
86 Dependences::TYPE_WAR
| Dependences::TYPE_RED
)
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
);
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
;
106 return It
.second
.get();
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++)
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
,
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();
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());
146 isl_union_map_union(Schedule
, isl_union_map_from_map(ScheduleMap
));
149 Schedule
= isl_union_map_coalesce(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,
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,