1 //===------ PPCGCodeGeneration.cpp - Polly Accelerator Code Generation. ---===//
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 // Take a scop created by ScopInfo and map it to GPU code using the ppcg
11 // GPU mapping strategy.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "polly/CodeGen/IslNodeBuilder.h"
16 #include "polly/DependenceInfo.h"
17 #include "polly/LinkAllPasses.h"
18 #include "polly/ScopInfo.h"
19 #include "llvm/Analysis/AliasAnalysis.h"
20 #include "llvm/Analysis/BasicAliasAnalysis.h"
21 #include "llvm/Analysis/GlobalsModRef.h"
22 #include "llvm/Analysis/PostDominators.h"
23 #include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h"
24 
25 extern "C" {
26 #include "gpu.h"
27 #include "ppcg.h"
28 }
29 
30 #include "llvm/Support/Debug.h"
31 
32 using namespace polly;
33 using namespace llvm;
34 
35 #define DEBUG_TYPE "polly-codegen-ppcg"
36 
37 namespace {
38 class PPCGCodeGeneration : public ScopPass {
39 public:
40   static char ID;
41 
42   /// The scop that is currently processed.
43   Scop *S;
44 
45   PPCGCodeGeneration() : ScopPass(ID) {}
46 
47   /// Construct compilation options for PPCG.
48   ///
49   /// @returns The compilation options.
50   ppcg_options *createPPCGOptions() {
51     auto DebugOptions =
52         (ppcg_debug_options *)malloc(sizeof(ppcg_debug_options));
53     auto Options = (ppcg_options *)malloc(sizeof(ppcg_options));
54 
55     DebugOptions->dump_schedule_constraints = false;
56     DebugOptions->dump_schedule = false;
57     DebugOptions->dump_final_schedule = false;
58     DebugOptions->dump_sizes = false;
59 
60     Options->debug = DebugOptions;
61 
62     Options->reschedule = true;
63     Options->scale_tile_loops = false;
64     Options->wrap = false;
65 
66     Options->non_negative_parameters = false;
67     Options->ctx = nullptr;
68     Options->sizes = nullptr;
69 
70     Options->use_private_memory = false;
71     Options->use_shared_memory = false;
72     Options->max_shared_memory = 0;
73 
74     Options->target = PPCG_TARGET_CUDA;
75     Options->openmp = false;
76     Options->linearize_device_arrays = true;
77     Options->live_range_reordering = false;
78 
79     Options->opencl_compiler_options = nullptr;
80     Options->opencl_use_gpu = false;
81     Options->opencl_n_include_file = 0;
82     Options->opencl_include_files = nullptr;
83     Options->opencl_print_kernel_types = false;
84     Options->opencl_embed_kernel_code = false;
85 
86     Options->save_schedule_file = nullptr;
87     Options->load_schedule_file = nullptr;
88 
89     return Options;
90   }
91 
92   /// Create a new PPCG scop from the current scop.
93   ///
94   /// For now the created scop is initialized to 'zero' and does not contain
95   /// any scop-specific information.
96   ///
97   /// @returns A new ppcg scop.
98   ppcg_scop *createPPCGScop() {
99     auto PPCGScop = (ppcg_scop *)malloc(sizeof(ppcg_scop));
100 
101     PPCGScop->options = createPPCGOptions();
102 
103     PPCGScop->start = 0;
104     PPCGScop->end = 0;
105 
106     PPCGScop->context = nullptr;
107     PPCGScop->domain = nullptr;
108     PPCGScop->call = nullptr;
109     PPCGScop->tagged_reads = nullptr;
110     PPCGScop->reads = nullptr;
111     PPCGScop->live_in = nullptr;
112     PPCGScop->tagged_may_writes = nullptr;
113     PPCGScop->may_writes = nullptr;
114     PPCGScop->tagged_must_writes = nullptr;
115     PPCGScop->must_writes = nullptr;
116     PPCGScop->live_out = nullptr;
117     PPCGScop->tagged_must_kills = nullptr;
118     PPCGScop->tagger = nullptr;
119 
120     PPCGScop->independence = nullptr;
121     PPCGScop->dep_flow = nullptr;
122     PPCGScop->tagged_dep_flow = nullptr;
123     PPCGScop->dep_false = nullptr;
124     PPCGScop->dep_forced = nullptr;
125     PPCGScop->dep_order = nullptr;
126     PPCGScop->tagged_dep_order = nullptr;
127 
128     PPCGScop->schedule = nullptr;
129     PPCGScop->names = nullptr;
130 
131     PPCGScop->pet = nullptr;
132 
133     return PPCGScop;
134   }
135 
136   /// Create a default-initialized PPCG GPU program.
137   ///
138   /// @returns A new gpu grogram description.
139   gpu_prog *createPPCGProg(ppcg_scop *PPCGScop) {
140 
141     if (!PPCGScop)
142       return nullptr;
143 
144     auto PPCGProg = isl_calloc_type(S->getIslCtx(), struct gpu_prog);
145 
146     PPCGProg->ctx = S->getIslCtx();
147     PPCGProg->scop = PPCGScop;
148     PPCGProg->context = nullptr;
149     PPCGProg->read = nullptr;
150     PPCGProg->may_write = nullptr;
151     PPCGProg->must_write = nullptr;
152     PPCGProg->tagged_must_kill = nullptr;
153     PPCGProg->may_persist = nullptr;
154     PPCGProg->to_outer = nullptr;
155     PPCGProg->to_inner = nullptr;
156     PPCGProg->any_to_outer = nullptr;
157     PPCGProg->array_order = nullptr;
158     PPCGProg->n_stmts = 0;
159     PPCGProg->stmts = nullptr;
160     PPCGProg->n_array = 0;
161     PPCGProg->array = nullptr;
162 
163     return PPCGProg;
164   }
165 
166   bool runOnScop(Scop &CurrentScop) override {
167     S = &CurrentScop;
168 
169     auto PPCGScop = createPPCGScop();
170     auto PPCGProg = createPPCGProg(PPCGScop);
171     gpu_prog_free(PPCGProg);
172     ppcg_scop_free(PPCGScop);
173 
174     return true;
175   }
176 
177   void printScop(raw_ostream &, Scop &) const override {}
178 
179   void getAnalysisUsage(AnalysisUsage &AU) const override {
180     AU.addRequired<DominatorTreeWrapperPass>();
181     AU.addRequired<RegionInfoPass>();
182     AU.addRequired<ScalarEvolutionWrapperPass>();
183     AU.addRequired<ScopDetection>();
184     AU.addRequired<ScopInfoRegionPass>();
185     AU.addRequired<LoopInfoWrapperPass>();
186 
187     AU.addPreserved<AAResultsWrapperPass>();
188     AU.addPreserved<BasicAAWrapperPass>();
189     AU.addPreserved<LoopInfoWrapperPass>();
190     AU.addPreserved<DominatorTreeWrapperPass>();
191     AU.addPreserved<GlobalsAAWrapperPass>();
192     AU.addPreserved<PostDominatorTreeWrapperPass>();
193     AU.addPreserved<ScopDetection>();
194     AU.addPreserved<ScalarEvolutionWrapperPass>();
195     AU.addPreserved<SCEVAAWrapperPass>();
196 
197     // FIXME: We do not yet add regions for the newly generated code to the
198     //        region tree.
199     AU.addPreserved<RegionInfoPass>();
200     AU.addPreserved<ScopInfoRegionPass>();
201   }
202 };
203 }
204 
205 char PPCGCodeGeneration::ID = 1;
206 
207 Pass *polly::createPPCGCodeGenerationPass() { return new PPCGCodeGeneration(); }
208 
209 INITIALIZE_PASS_BEGIN(PPCGCodeGeneration, "polly-codegen-ppcg",
210                       "Polly - Apply PPCG translation to SCOP", false, false)
211 INITIALIZE_PASS_DEPENDENCY(DependenceInfo);
212 INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass);
213 INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass);
214 INITIALIZE_PASS_DEPENDENCY(RegionInfoPass);
215 INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass);
216 INITIALIZE_PASS_DEPENDENCY(ScopDetection);
217 INITIALIZE_PASS_END(PPCGCodeGeneration, "polly-codegen-ppcg",
218                     "Polly - Apply PPCG translation to SCOP", false, false)
219