1 //===--------- PolyhedralInfo.cpp - Create Scops from LLVM IR-------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // An interface to the Polyhedral analysis engine(Polly) of LLVM.
11 // This pass provides an interface to the polyhedral analysis performed by
14 // This interface provides basic interface like isParallel, isVectorizable
15 // that can be used in LLVM transformation passes.
17 // 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/InitializePasses.h"
29 #include "llvm/Support/Debug.h"
30 #include "isl/union_map.h"
33 using namespace polly
;
35 #include "polly/Support/PollyDebug.h"
36 #define DEBUG_TYPE "polyhedral-info"
38 static cl::opt
<bool> CheckParallel("polly-check-parallel",
39 cl::desc("Check for parallel loops"),
40 cl::Hidden
, cl::cat(PollyCategory
));
42 static cl::opt
<bool> CheckVectorizable("polly-check-vectorizable",
43 cl::desc("Check for vectorizable loops"),
44 cl::Hidden
, cl::cat(PollyCategory
));
46 void PolyhedralInfo::getAnalysisUsage(AnalysisUsage
&AU
) const {
47 AU
.addRequiredTransitive
<DependenceInfoWrapperPass
>();
48 AU
.addRequired
<LoopInfoWrapperPass
>();
49 AU
.addRequiredTransitive
<ScopInfoWrapperPass
>();
53 bool PolyhedralInfo::runOnFunction(Function
&F
) {
54 DI
= &getAnalysis
<DependenceInfoWrapperPass
>();
55 SI
= getAnalysis
<ScopInfoWrapperPass
>().getSI();
59 void PolyhedralInfo::print(raw_ostream
&OS
, const Module
*) const {
60 auto &LI
= getAnalysis
<LoopInfoWrapperPass
>().getLoopInfo();
61 for (auto *TopLevelLoop
: LI
) {
62 for (auto *L
: depth_first(TopLevelLoop
)) {
63 OS
.indent(2) << L
->getHeader()->getName() << ":\t";
64 if (CheckParallel
&& isParallel(L
))
65 OS
<< "Loop is parallel.\n";
66 else if (CheckParallel
)
67 OS
<< "Loop is not parallel.\n";
72 bool PolyhedralInfo::checkParallel(Loop
*L
, isl_pw_aff
**MinDepDistPtr
) const {
74 const Scop
*S
= getScopContainingLoop(L
);
77 const Dependences
&D
=
78 DI
->getDependences(const_cast<Scop
*>(S
), Dependences::AL_Access
);
79 if (!D
.hasValidDependences())
81 POLLY_DEBUG(dbgs() << "Loop :\t" << L
->getHeader()->getName() << ":\n");
84 D
.getDependences(Dependences::TYPE_RAW
| Dependences::TYPE_WAW
|
85 Dependences::TYPE_WAR
| Dependences::TYPE_RED
)
88 POLLY_DEBUG(dbgs() << "Dependences :\t" << stringFromIslObj(Deps
, "null")
91 isl_union_map
*Schedule
= getScheduleForLoop(S
, L
);
92 POLLY_DEBUG(dbgs() << "Schedule: \t" << stringFromIslObj(Schedule
, "null")
95 IsParallel
= D
.isParallel(Schedule
, Deps
, MinDepDistPtr
);
96 isl_union_map_free(Schedule
);
100 bool PolyhedralInfo::isParallel(Loop
*L
) const { return checkParallel(L
); }
102 const Scop
*PolyhedralInfo::getScopContainingLoop(Loop
*L
) const {
103 assert((SI
) && "ScopInfoWrapperPass is required by PolyhedralInfo pass!\n");
104 for (auto &It
: *SI
) {
105 Region
*R
= It
.first
;
107 return It
.second
.get();
112 // Given a Loop and the containing SCoP, we compute the partial schedule
113 // by taking union of individual schedules of each ScopStmt within the loop
114 // and projecting out the inner dimensions from the range of the schedule.
115 // for (i = 0; i < n; i++)
116 // for (j = 0; j < n; j++)
119 // The original schedule will be
120 // Stmt[i0, i1] -> [i0, i1]
121 // The schedule for the outer loop will be
122 // Stmt[i0, i1] -> [i0]
123 // The schedule for the inner loop will be
124 // Stmt[i0, i1] -> [i0, i1]
125 __isl_give isl_union_map
*PolyhedralInfo::getScheduleForLoop(const Scop
*S
,
127 isl_union_map
*Schedule
= isl_union_map_empty(S
->getParamSpace().release());
128 int CurrDim
= S
->getRelativeLoopDepth(L
);
129 POLLY_DEBUG(dbgs() << "Relative loop depth:\t" << CurrDim
<< "\n");
130 assert(CurrDim
>= 0 && "Loop in region should have at least depth one");
132 for (auto &SS
: *S
) {
133 if (L
->contains(SS
.getSurroundingLoop())) {
135 unsigned int MaxDim
= SS
.getNumIterators();
136 POLLY_DEBUG(dbgs() << "Maximum depth of Stmt:\t" << MaxDim
<< "\n");
137 isl_map
*ScheduleMap
= SS
.getSchedule().release();
140 "Schedules that contain extension nodes require special handling.");
142 ScheduleMap
= isl_map_project_out(ScheduleMap
, isl_dim_out
, CurrDim
+ 1,
143 MaxDim
- CurrDim
- 1);
144 ScheduleMap
= isl_map_set_tuple_id(ScheduleMap
, isl_dim_in
,
145 SS
.getDomainId().release());
147 isl_union_map_union(Schedule
, isl_union_map_from_map(ScheduleMap
));
150 Schedule
= isl_union_map_coalesce(Schedule
);
154 char PolyhedralInfo::ID
= 0;
156 Pass
*polly::createPolyhedralInfoPass() { return new PolyhedralInfo(); }
158 INITIALIZE_PASS_BEGIN(PolyhedralInfo
, "polyhedral-info",
159 "Polly - Interface to polyhedral analysis engine", false,
161 INITIALIZE_PASS_DEPENDENCY(DependenceInfoWrapperPass
);
162 INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass
);
163 INITIALIZE_PASS_DEPENDENCY(ScopInfoWrapperPass
);
164 INITIALIZE_PASS_END(PolyhedralInfo
, "polyhedral-info",
165 "Polly - Interface to polyhedral analysis engine", false,
168 //===----------------------------------------------------------------------===//
171 /// Print result from PolyhedralInfo.
172 class PolyhedralInfoPrinterLegacyPass final
: public FunctionPass
{
176 PolyhedralInfoPrinterLegacyPass() : PolyhedralInfoPrinterLegacyPass(outs()) {}
177 explicit PolyhedralInfoPrinterLegacyPass(llvm::raw_ostream
&OS
)
178 : FunctionPass(ID
), OS(OS
) {}
180 bool runOnFunction(Function
&F
) override
{
181 PolyhedralInfo
&P
= getAnalysis
<PolyhedralInfo
>();
183 OS
<< "Printing analysis '" << P
.getPassName() << "' for function '"
184 << F
.getName() << "':\n";
190 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
191 FunctionPass::getAnalysisUsage(AU
);
192 AU
.addRequired
<PolyhedralInfo
>();
193 AU
.setPreservesAll();
197 llvm::raw_ostream
&OS
;
200 char PolyhedralInfoPrinterLegacyPass::ID
= 0;
203 Pass
*polly::createPolyhedralInfoPrinterLegacyPass(raw_ostream
&OS
) {
204 return new PolyhedralInfoPrinterLegacyPass(OS
);
207 INITIALIZE_PASS_BEGIN(
208 PolyhedralInfoPrinterLegacyPass
, "print-polyhedral-info",
209 "Polly - Print interface to polyhedral analysis engine analysis", false,
211 INITIALIZE_PASS_DEPENDENCY(PolyhedralInfo
);
213 PolyhedralInfoPrinterLegacyPass
, "print-polyhedral-info",
214 "Polly - Print interface to polyhedral analysis engine analysis", false,