1 | //===------ FlattenSchedule.cpp --------------------------------*- C++ -*-===// |
2 | // |
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 |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // Try to reduce the number of scatter dimension. Useful to make isl_union_map |
10 | // schedules more understandable. This is only intended for debugging and |
11 | // unittests, not for production use. |
12 | // |
13 | //===----------------------------------------------------------------------===// |
14 | |
15 | #include "polly/FlattenSchedule.h" |
16 | #include "polly/FlattenAlgo.h" |
17 | #include "polly/ScopInfo.h" |
18 | #include "polly/ScopPass.h" |
19 | #include "polly/Support/ISLOStream.h" |
20 | #include "polly/Support/ISLTools.h" |
21 | #include "polly/Support/PollyDebug.h" |
22 | #define DEBUG_TYPE "polly-flatten-schedule" |
23 | |
24 | using namespace polly; |
25 | using namespace llvm; |
26 | |
27 | namespace { |
28 | |
29 | /// Print a schedule to @p OS. |
30 | /// |
31 | /// Prints the schedule for each statements on a new line. |
32 | void printSchedule(raw_ostream &OS, const isl::union_map &Schedule, |
33 | int indent) { |
34 | for (isl::map Map : Schedule.get_map_list()) |
35 | OS.indent(NumSpaces: indent) << Map << "\n" ; |
36 | } |
37 | |
38 | /// Flatten the schedule stored in an polly::Scop. |
39 | class FlattenSchedule final : public ScopPass { |
40 | private: |
41 | FlattenSchedule(const FlattenSchedule &) = delete; |
42 | const FlattenSchedule &operator=(const FlattenSchedule &) = delete; |
43 | |
44 | std::shared_ptr<isl_ctx> IslCtx; |
45 | isl::union_map OldSchedule; |
46 | |
47 | public: |
48 | static char ID; |
49 | explicit FlattenSchedule() : ScopPass(ID) {} |
50 | |
51 | void getAnalysisUsage(AnalysisUsage &AU) const override { |
52 | AU.addRequiredTransitive<ScopInfoRegionPass>(); |
53 | AU.setPreservesAll(); |
54 | } |
55 | |
56 | bool runOnScop(Scop &S) override { |
57 | // Keep a reference to isl_ctx to ensure that it is not freed before we free |
58 | // OldSchedule. |
59 | IslCtx = S.getSharedIslCtx(); |
60 | |
61 | POLLY_DEBUG(dbgs() << "Going to flatten old schedule:\n" ); |
62 | OldSchedule = S.getSchedule(); |
63 | POLLY_DEBUG(printSchedule(dbgs(), OldSchedule, 2)); |
64 | |
65 | auto Domains = S.getDomains(); |
66 | auto RestrictedOldSchedule = OldSchedule.intersect_domain(uset: Domains); |
67 | POLLY_DEBUG(dbgs() << "Old schedule with domains:\n" ); |
68 | POLLY_DEBUG(printSchedule(dbgs(), RestrictedOldSchedule, 2)); |
69 | |
70 | auto NewSchedule = flattenSchedule(Schedule: RestrictedOldSchedule); |
71 | |
72 | POLLY_DEBUG(dbgs() << "Flattened new schedule:\n" ); |
73 | POLLY_DEBUG(printSchedule(dbgs(), NewSchedule, 2)); |
74 | |
75 | NewSchedule = NewSchedule.gist_domain(uset: Domains); |
76 | POLLY_DEBUG(dbgs() << "Gisted, flattened new schedule:\n" ); |
77 | POLLY_DEBUG(printSchedule(dbgs(), NewSchedule, 2)); |
78 | |
79 | S.setSchedule(NewSchedule); |
80 | return false; |
81 | } |
82 | |
83 | void printScop(raw_ostream &OS, Scop &S) const override { |
84 | OS << "Schedule before flattening {\n" ; |
85 | printSchedule(OS, Schedule: OldSchedule, indent: 4); |
86 | OS << "}\n\n" ; |
87 | |
88 | OS << "Schedule after flattening {\n" ; |
89 | printSchedule(OS, Schedule: S.getSchedule(), indent: 4); |
90 | OS << "}\n" ; |
91 | } |
92 | |
93 | void releaseMemory() override { |
94 | OldSchedule = {}; |
95 | IslCtx.reset(); |
96 | } |
97 | }; |
98 | |
99 | char FlattenSchedule::ID; |
100 | |
101 | /// Print result from FlattenSchedule. |
102 | class FlattenSchedulePrinterLegacyPass final : public ScopPass { |
103 | public: |
104 | static char ID; |
105 | |
106 | FlattenSchedulePrinterLegacyPass() |
107 | : FlattenSchedulePrinterLegacyPass(outs()) {} |
108 | explicit FlattenSchedulePrinterLegacyPass(llvm::raw_ostream &OS) |
109 | : ScopPass(ID), OS(OS) {} |
110 | |
111 | bool runOnScop(Scop &S) override { |
112 | FlattenSchedule &P = getAnalysis<FlattenSchedule>(); |
113 | |
114 | OS << "Printing analysis '" << P.getPassName() << "' for region: '" |
115 | << S.getRegion().getNameStr() << "' in function '" |
116 | << S.getFunction().getName() << "':\n" ; |
117 | P.printScop(OS, S); |
118 | |
119 | return false; |
120 | } |
121 | |
122 | void getAnalysisUsage(AnalysisUsage &AU) const override { |
123 | ScopPass::getAnalysisUsage(AU); |
124 | AU.addRequired<FlattenSchedule>(); |
125 | AU.setPreservesAll(); |
126 | } |
127 | |
128 | private: |
129 | llvm::raw_ostream &OS; |
130 | }; |
131 | |
132 | char FlattenSchedulePrinterLegacyPass::ID = 0; |
133 | } // anonymous namespace |
134 | |
135 | Pass *polly::createFlattenSchedulePass() { return new FlattenSchedule(); } |
136 | |
137 | Pass *polly::createFlattenSchedulePrinterLegacyPass(llvm::raw_ostream &OS) { |
138 | return new FlattenSchedulePrinterLegacyPass(OS); |
139 | } |
140 | |
141 | INITIALIZE_PASS_BEGIN(FlattenSchedule, "polly-flatten-schedule" , |
142 | "Polly - Flatten schedule" , false, false) |
143 | INITIALIZE_PASS_END(FlattenSchedule, "polly-flatten-schedule" , |
144 | "Polly - Flatten schedule" , false, false) |
145 | |
146 | INITIALIZE_PASS_BEGIN(FlattenSchedulePrinterLegacyPass, |
147 | "polly-print-flatten-schedule" , |
148 | "Polly - Print flattened schedule" , false, false) |
149 | INITIALIZE_PASS_DEPENDENCY(FlattenSchedule) |
150 | INITIALIZE_PASS_END(FlattenSchedulePrinterLegacyPass, |
151 | "polly-print-flatten-schedule" , |
152 | "Polly - Print flattened schedule" , false, false) |
153 | |