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