1 //===------ FlattenSchedule.cpp --------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // Try to reduce the number of scatter dimension. Useful to make isl_union_map
11 // schedules more understandable. This is only intended for debugging and
12 // unittests, not for production use.
13 //
14 //===----------------------------------------------------------------------===//
15 
16 #include "polly/FlattenSchedule.h"
17 #include "polly/FlattenAlgo.h"
18 #include "polly/ScopInfo.h"
19 #include "polly/ScopPass.h"
20 #define DEBUG_TYPE "polly-flatten-schedule"
21 
22 using namespace polly;
23 using namespace llvm;
24 
25 namespace {
26 
27 /// Print a schedule to @p OS.
28 ///
29 /// Prints the schedule for each statements on a new line.
30 void printSchedule(raw_ostream &OS, const isl::union_map &Schedule,
31                    int indent) {
32   foreachElt(Schedule,
33              [&OS, indent](isl::map Map) { OS.indent(indent) << Map << "\n"; });
34 }
35 
36 /// Flatten the schedule stored in an polly::Scop.
37 class FlattenSchedule : public ScopPass {
38 private:
39   FlattenSchedule(const FlattenSchedule &) = delete;
40   const FlattenSchedule &operator=(const FlattenSchedule &) = delete;
41 
42   std::shared_ptr<isl_ctx> IslCtx;
43   isl::union_map OldSchedule;
44 
45 public:
46   static char ID;
47   explicit FlattenSchedule() : ScopPass(ID) {}
48 
49   virtual void getAnalysisUsage(AnalysisUsage &AU) const override {
50     AU.addRequiredTransitive<ScopInfoRegionPass>();
51     AU.setPreservesAll();
52   }
53 
54   virtual bool runOnScop(Scop &S) override {
55     // Keep a reference to isl_ctx to ensure that it is not freed before we free
56     // OldSchedule.
57     IslCtx = S.getSharedIslCtx();
58 
59     DEBUG(dbgs() << "Going to flatten old schedule:\n");
60     OldSchedule = give(S.getSchedule());
61     DEBUG(printSchedule(dbgs(), OldSchedule, 2));
62 
63     auto Domains = give(S.getDomains());
64     auto RestrictedOldSchedule = OldSchedule.intersect_domain(Domains);
65     DEBUG(dbgs() << "Old schedule with domains:\n");
66     DEBUG(printSchedule(dbgs(), RestrictedOldSchedule, 2));
67 
68     auto NewSchedule = flattenSchedule(RestrictedOldSchedule);
69 
70     DEBUG(dbgs() << "Flattened new schedule:\n");
71     DEBUG(printSchedule(dbgs(), NewSchedule, 2));
72 
73     NewSchedule = NewSchedule.gist_domain(Domains);
74     DEBUG(dbgs() << "Gisted, flattened new schedule:\n");
75     DEBUG(printSchedule(dbgs(), NewSchedule, 2));
76 
77     S.setSchedule(NewSchedule.take());
78     return false;
79   }
80 
81   virtual void printScop(raw_ostream &OS, Scop &S) const override {
82     OS << "Schedule before flattening {\n";
83     printSchedule(OS, OldSchedule, 4);
84     OS << "}\n\n";
85 
86     OS << "Schedule after flattening {\n";
87     printSchedule(OS, give(S.getSchedule()), 4);
88     OS << "}\n";
89   }
90 
91   virtual void releaseMemory() override {
92     OldSchedule = nullptr;
93     IslCtx.reset();
94   }
95 };
96 
97 char FlattenSchedule::ID;
98 } // anonymous namespace
99 
100 Pass *polly::createFlattenSchedulePass() { return new FlattenSchedule(); }
101 
102 INITIALIZE_PASS_BEGIN(FlattenSchedule, "polly-flatten-schedule",
103                       "Polly - Flatten schedule", false, false)
104 INITIALIZE_PASS_END(FlattenSchedule, "polly-flatten-schedule",
105                     "Polly - Flatten schedule", false, false)
106