xref: /llvm-project/polly/lib/Analysis/PolyhedralInfo.cpp (revision 601d7eab0665ba298d81952da11593124fd893a0)
180312380SJohannes Doerfert //===--------- PolyhedralInfo.cpp  - Create Scops from LLVM IR-------------===//
23d80264fSMichal Gorny //
33d80264fSMichal Gorny // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
43d80264fSMichal Gorny // See https://llvm.org/LICENSE.txt for license information.
53d80264fSMichal Gorny // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63d80264fSMichal Gorny //
780312380SJohannes Doerfert //===----------------------------------------------------------------------===//
83d80264fSMichal Gorny //
93d80264fSMichal Gorny // An interface to the Polyhedral analysis engine(Polly) of LLVM.
103d80264fSMichal Gorny //
113d80264fSMichal Gorny // This pass provides an interface to the polyhedral analysis performed by
123d80264fSMichal Gorny // Polly.
133d80264fSMichal Gorny //
143d80264fSMichal Gorny // This interface provides basic interface like isParallel, isVectorizable
153d80264fSMichal Gorny // that can be used in LLVM transformation passes.
163d80264fSMichal Gorny //
173d80264fSMichal Gorny // Work in progress, this file is subject to change.
183d80264fSMichal Gorny //
1980312380SJohannes Doerfert //===----------------------------------------------------------------------===//
2080312380SJohannes Doerfert 
2180312380SJohannes Doerfert #include "polly/PolyhedralInfo.h"
2280312380SJohannes Doerfert #include "polly/DependenceInfo.h"
2380312380SJohannes Doerfert #include "polly/LinkAllPasses.h"
2480312380SJohannes Doerfert #include "polly/Options.h"
2580312380SJohannes Doerfert #include "polly/ScopInfo.h"
2680312380SJohannes Doerfert #include "polly/Support/GICHelper.h"
2780312380SJohannes Doerfert #include "llvm/Analysis/LoopInfo.h"
2805da2fe5SReid Kleckner #include "llvm/InitializePasses.h"
2980312380SJohannes Doerfert #include "llvm/Support/Debug.h"
30031bb165SMichael Kruse #include "isl/union_map.h"
3180312380SJohannes Doerfert 
3280312380SJohannes Doerfert using namespace llvm;
3380312380SJohannes Doerfert using namespace polly;
3480312380SJohannes Doerfert 
35*601d7eabSKarthika Devi C #include "polly/Support/PollyDebug.h"
3680312380SJohannes Doerfert #define DEBUG_TYPE "polyhedral-info"
3780312380SJohannes Doerfert 
3880312380SJohannes Doerfert static cl::opt<bool> CheckParallel("polly-check-parallel",
3980312380SJohannes Doerfert                                    cl::desc("Check for parallel loops"),
4036c7d79dSFangrui Song                                    cl::Hidden, cl::cat(PollyCategory));
4180312380SJohannes Doerfert 
4280312380SJohannes Doerfert static cl::opt<bool> CheckVectorizable("polly-check-vectorizable",
4380312380SJohannes Doerfert                                        cl::desc("Check for vectorizable loops"),
44d86a206fSFangrui Song                                        cl::Hidden, cl::cat(PollyCategory));
4580312380SJohannes Doerfert 
getAnalysisUsage(AnalysisUsage & AU) const4680312380SJohannes Doerfert void PolyhedralInfo::getAnalysisUsage(AnalysisUsage &AU) const {
4780312380SJohannes Doerfert   AU.addRequiredTransitive<DependenceInfoWrapperPass>();
4880312380SJohannes Doerfert   AU.addRequired<LoopInfoWrapperPass>();
4980312380SJohannes Doerfert   AU.addRequiredTransitive<ScopInfoWrapperPass>();
5080312380SJohannes Doerfert   AU.setPreservesAll();
5180312380SJohannes Doerfert }
5280312380SJohannes Doerfert 
runOnFunction(Function & F)5380312380SJohannes Doerfert bool PolyhedralInfo::runOnFunction(Function &F) {
5480312380SJohannes Doerfert   DI = &getAnalysis<DependenceInfoWrapperPass>();
55838e0884SPhilip Pfaffe   SI = getAnalysis<ScopInfoWrapperPass>().getSI();
5680312380SJohannes Doerfert   return false;
5780312380SJohannes Doerfert }
5880312380SJohannes Doerfert 
print(raw_ostream & OS,const Module *) const5980312380SJohannes Doerfert void PolyhedralInfo::print(raw_ostream &OS, const Module *) const {
6080312380SJohannes Doerfert   auto &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
6180312380SJohannes Doerfert   for (auto *TopLevelLoop : LI) {
6280312380SJohannes Doerfert     for (auto *L : depth_first(TopLevelLoop)) {
6380312380SJohannes Doerfert       OS.indent(2) << L->getHeader()->getName() << ":\t";
6480312380SJohannes Doerfert       if (CheckParallel && isParallel(L))
6580312380SJohannes Doerfert         OS << "Loop is parallel.\n";
6680312380SJohannes Doerfert       else if (CheckParallel)
6780312380SJohannes Doerfert         OS << "Loop is not parallel.\n";
6880312380SJohannes Doerfert     }
6980312380SJohannes Doerfert   }
7080312380SJohannes Doerfert }
7180312380SJohannes Doerfert 
checkParallel(Loop * L,isl_pw_aff ** MinDepDistPtr) const7280312380SJohannes Doerfert bool PolyhedralInfo::checkParallel(Loop *L, isl_pw_aff **MinDepDistPtr) const {
7380312380SJohannes Doerfert   bool IsParallel;
7480312380SJohannes Doerfert   const Scop *S = getScopContainingLoop(L);
7580312380SJohannes Doerfert   if (!S)
7680312380SJohannes Doerfert     return false;
7780312380SJohannes Doerfert   const Dependences &D =
7880312380SJohannes Doerfert       DI->getDependences(const_cast<Scop *>(S), Dependences::AL_Access);
7980312380SJohannes Doerfert   if (!D.hasValidDependences())
8080312380SJohannes Doerfert     return false;
81*601d7eabSKarthika Devi C   POLLY_DEBUG(dbgs() << "Loop :\t" << L->getHeader()->getName() << ":\n");
8280312380SJohannes Doerfert 
8380312380SJohannes Doerfert   isl_union_map *Deps =
8480312380SJohannes Doerfert       D.getDependences(Dependences::TYPE_RAW | Dependences::TYPE_WAW |
856a6d9df7STobias Grosser                        Dependences::TYPE_WAR | Dependences::TYPE_RED)
866a6d9df7STobias Grosser           .release();
876a6d9df7STobias Grosser 
88*601d7eabSKarthika Devi C   POLLY_DEBUG(dbgs() << "Dependences :\t" << stringFromIslObj(Deps, "null")
89cfe117deSpatacca                      << "\n");
9080312380SJohannes Doerfert 
9180312380SJohannes Doerfert   isl_union_map *Schedule = getScheduleForLoop(S, L);
92*601d7eabSKarthika Devi C   POLLY_DEBUG(dbgs() << "Schedule: \t" << stringFromIslObj(Schedule, "null")
93cfe117deSpatacca                      << "\n");
9480312380SJohannes Doerfert 
9580312380SJohannes Doerfert   IsParallel = D.isParallel(Schedule, Deps, MinDepDistPtr);
9680312380SJohannes Doerfert   isl_union_map_free(Schedule);
9780312380SJohannes Doerfert   return IsParallel;
9880312380SJohannes Doerfert }
9980312380SJohannes Doerfert 
isParallel(Loop * L) const10080312380SJohannes Doerfert bool PolyhedralInfo::isParallel(Loop *L) const { return checkParallel(L); }
10180312380SJohannes Doerfert 
getScopContainingLoop(Loop * L) const10280312380SJohannes Doerfert const Scop *PolyhedralInfo::getScopContainingLoop(Loop *L) const {
10380312380SJohannes Doerfert   assert((SI) && "ScopInfoWrapperPass is required by PolyhedralInfo pass!\n");
10480312380SJohannes Doerfert   for (auto &It : *SI) {
10580312380SJohannes Doerfert     Region *R = It.first;
10680312380SJohannes Doerfert     if (R->contains(L))
10780312380SJohannes Doerfert       return It.second.get();
10880312380SJohannes Doerfert   }
10980312380SJohannes Doerfert   return nullptr;
11080312380SJohannes Doerfert }
11180312380SJohannes Doerfert 
11280312380SJohannes Doerfert //  Given a Loop and the containing SCoP, we compute the partial schedule
11380312380SJohannes Doerfert //  by taking union of individual schedules of each ScopStmt within the loop
11480312380SJohannes Doerfert //  and projecting out the inner dimensions from the range of the schedule.
11580312380SJohannes Doerfert //   for (i = 0; i < n; i++)
11680312380SJohannes Doerfert //      for (j = 0; j < n; j++)
11780312380SJohannes Doerfert //        A[j] = 1;  //Stmt
11880312380SJohannes Doerfert //
11980312380SJohannes Doerfert //  The original schedule will be
12080312380SJohannes Doerfert //    Stmt[i0, i1] -> [i0, i1]
12180312380SJohannes Doerfert //  The schedule for the outer loop will be
12280312380SJohannes Doerfert //    Stmt[i0, i1] -> [i0]
12380312380SJohannes Doerfert //  The schedule for the inner loop will be
12480312380SJohannes Doerfert //    Stmt[i0, i1] -> [i0, i1]
getScheduleForLoop(const Scop * S,Loop * L) const12580312380SJohannes Doerfert __isl_give isl_union_map *PolyhedralInfo::getScheduleForLoop(const Scop *S,
12680312380SJohannes Doerfert                                                              Loop *L) const {
127b65ccc43STobias Grosser   isl_union_map *Schedule = isl_union_map_empty(S->getParamSpace().release());
12880312380SJohannes Doerfert   int CurrDim = S->getRelativeLoopDepth(L);
129*601d7eabSKarthika Devi C   POLLY_DEBUG(dbgs() << "Relative loop depth:\t" << CurrDim << "\n");
13080312380SJohannes Doerfert   assert(CurrDim >= 0 && "Loop in region should have at least depth one");
13180312380SJohannes Doerfert 
13266e38a84STobias Grosser   for (auto &SS : *S) {
13366e38a84STobias Grosser     if (L->contains(SS.getSurroundingLoop())) {
13480312380SJohannes Doerfert 
13566e38a84STobias Grosser       unsigned int MaxDim = SS.getNumIterators();
136*601d7eabSKarthika Devi C       POLLY_DEBUG(dbgs() << "Maximum depth of Stmt:\t" << MaxDim << "\n");
1376ad1640aSTobias Grosser       isl_map *ScheduleMap = SS.getSchedule().release();
13866e38a84STobias Grosser       assert(
13966e38a84STobias Grosser           ScheduleMap &&
140b3224adfSRoman Gareev           "Schedules that contain extension nodes require special handling.");
14180312380SJohannes Doerfert 
14280312380SJohannes Doerfert       ScheduleMap = isl_map_project_out(ScheduleMap, isl_dim_out, CurrDim + 1,
14380312380SJohannes Doerfert                                         MaxDim - CurrDim - 1);
144dcf8d696STobias Grosser       ScheduleMap = isl_map_set_tuple_id(ScheduleMap, isl_dim_in,
145dcf8d696STobias Grosser                                          SS.getDomainId().release());
14680312380SJohannes Doerfert       Schedule =
14780312380SJohannes Doerfert           isl_union_map_union(Schedule, isl_union_map_from_map(ScheduleMap));
14880312380SJohannes Doerfert     }
14966e38a84STobias Grosser   }
15080312380SJohannes Doerfert   Schedule = isl_union_map_coalesce(Schedule);
15180312380SJohannes Doerfert   return Schedule;
15280312380SJohannes Doerfert }
15380312380SJohannes Doerfert 
15480312380SJohannes Doerfert char PolyhedralInfo::ID = 0;
15580312380SJohannes Doerfert 
createPolyhedralInfoPass()15680312380SJohannes Doerfert Pass *polly::createPolyhedralInfoPass() { return new PolyhedralInfo(); }
15780312380SJohannes Doerfert 
15880312380SJohannes Doerfert INITIALIZE_PASS_BEGIN(PolyhedralInfo, "polyhedral-info",
15980312380SJohannes Doerfert                       "Polly - Interface to polyhedral analysis engine", false,
16080312380SJohannes Doerfert                       false);
16180312380SJohannes Doerfert INITIALIZE_PASS_DEPENDENCY(DependenceInfoWrapperPass);
16280312380SJohannes Doerfert INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass);
16380312380SJohannes Doerfert INITIALIZE_PASS_DEPENDENCY(ScopInfoWrapperPass);
16480312380SJohannes Doerfert INITIALIZE_PASS_END(PolyhedralInfo, "polyhedral-info",
16580312380SJohannes Doerfert                     "Polly - Interface to polyhedral analysis engine", false,
16680312380SJohannes Doerfert                     false)
1675c028081SMichael Kruse 
1685c028081SMichael Kruse //===----------------------------------------------------------------------===//
1695c028081SMichael Kruse 
1705c028081SMichael Kruse namespace {
1715c028081SMichael Kruse /// Print result from PolyhedralInfo.
172bd93df93SMichael Kruse class PolyhedralInfoPrinterLegacyPass final : public FunctionPass {
1735c028081SMichael Kruse public:
1745c028081SMichael Kruse   static char ID;
1755c028081SMichael Kruse 
PolyhedralInfoPrinterLegacyPass()1765c028081SMichael Kruse   PolyhedralInfoPrinterLegacyPass() : PolyhedralInfoPrinterLegacyPass(outs()) {}
PolyhedralInfoPrinterLegacyPass(llvm::raw_ostream & OS)1775c028081SMichael Kruse   explicit PolyhedralInfoPrinterLegacyPass(llvm::raw_ostream &OS)
1785c028081SMichael Kruse       : FunctionPass(ID), OS(OS) {}
1795c028081SMichael Kruse 
runOnFunction(Function & F)1805c028081SMichael Kruse   bool runOnFunction(Function &F) override {
1815c028081SMichael Kruse     PolyhedralInfo &P = getAnalysis<PolyhedralInfo>();
1825c028081SMichael Kruse 
1835c028081SMichael Kruse     OS << "Printing analysis '" << P.getPassName() << "' for function '"
1845c028081SMichael Kruse        << F.getName() << "':\n";
1855c028081SMichael Kruse     P.print(OS);
1865c028081SMichael Kruse 
1875c028081SMichael Kruse     return false;
1885c028081SMichael Kruse   }
1895c028081SMichael Kruse 
getAnalysisUsage(AnalysisUsage & AU) const1905c028081SMichael Kruse   void getAnalysisUsage(AnalysisUsage &AU) const override {
1915c028081SMichael Kruse     FunctionPass::getAnalysisUsage(AU);
1925c028081SMichael Kruse     AU.addRequired<PolyhedralInfo>();
1935c028081SMichael Kruse     AU.setPreservesAll();
1945c028081SMichael Kruse   }
1955c028081SMichael Kruse 
1965c028081SMichael Kruse private:
1975c028081SMichael Kruse   llvm::raw_ostream &OS;
1985c028081SMichael Kruse };
1995c028081SMichael Kruse 
2005c028081SMichael Kruse char PolyhedralInfoPrinterLegacyPass::ID = 0;
2015c028081SMichael Kruse } // namespace
2025c028081SMichael Kruse 
createPolyhedralInfoPrinterLegacyPass(raw_ostream & OS)2035c028081SMichael Kruse Pass *polly::createPolyhedralInfoPrinterLegacyPass(raw_ostream &OS) {
2045c028081SMichael Kruse   return new PolyhedralInfoPrinterLegacyPass(OS);
2055c028081SMichael Kruse }
2065c028081SMichael Kruse 
2075c028081SMichael Kruse INITIALIZE_PASS_BEGIN(
2085c028081SMichael Kruse     PolyhedralInfoPrinterLegacyPass, "print-polyhedral-info",
2095c028081SMichael Kruse     "Polly - Print interface to polyhedral analysis engine analysis", false,
2105c028081SMichael Kruse     false);
2115c028081SMichael Kruse INITIALIZE_PASS_DEPENDENCY(PolyhedralInfo);
2125c028081SMichael Kruse INITIALIZE_PASS_END(
2135c028081SMichael Kruse     PolyhedralInfoPrinterLegacyPass, "print-polyhedral-info",
2145c028081SMichael Kruse     "Polly - Print interface to polyhedral analysis engine analysis", false,
2155c028081SMichael Kruse     false)
216