Coverage Report

Created: 2018-10-23 03:11

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/polly/lib/Support/RegisterPasses.cpp
Line
Count
Source (jump to first uncovered line)
1
//===------ RegisterPasses.cpp - Add the Polly Passes to default passes  --===//
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
// This file composes the individual LLVM-IR passes provided by Polly to a
11
// functional polyhedral optimizer. The polyhedral optimizer is automatically
12
// made available to LLVM based compilers by loading the Polly shared library
13
// into such a compiler.
14
//
15
// The Polly optimizer is made available by executing a static constructor that
16
// registers the individual Polly passes in the LLVM pass manager builder. The
17
// passes are registered such that the default behaviour of the compiler is not
18
// changed, but that the flag '-polly' provided at optimization level '-O3'
19
// enables additional polyhedral optimizations.
20
//===----------------------------------------------------------------------===//
21
22
#include "polly/RegisterPasses.h"
23
#include "polly/Canonicalization.h"
24
#include "polly/CodeGen/CodeGeneration.h"
25
#include "polly/CodeGen/CodegenCleanup.h"
26
#include "polly/CodeGen/IslAst.h"
27
#include "polly/CodeGen/PPCGCodeGeneration.h"
28
#include "polly/CodePreparation.h"
29
#include "polly/DeLICM.h"
30
#include "polly/DependenceInfo.h"
31
#include "polly/FlattenSchedule.h"
32
#include "polly/ForwardOpTree.h"
33
#include "polly/JSONExporter.h"
34
#include "polly/LinkAllPasses.h"
35
#include "polly/Options.h"
36
#include "polly/PolyhedralInfo.h"
37
#include "polly/ScopDetection.h"
38
#include "polly/ScopInfo.h"
39
#include "polly/Simplify.h"
40
#include "polly/Support/DumpModulePass.h"
41
#include "llvm/Analysis/CFGPrinter.h"
42
#include "llvm/IR/LegacyPassManager.h"
43
#include "llvm/IR/Verifier.h"
44
#include "llvm/Passes/PassBuilder.h"
45
#include "llvm/Passes/PassPlugin.h"
46
#include "llvm/Support/TargetSelect.h"
47
#include "llvm/Transforms/IPO.h"
48
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
49
#include "llvm/Transforms/Scalar.h"
50
#include "llvm/Transforms/Vectorize.h"
51
52
using namespace llvm;
53
using namespace polly;
54
55
cl::OptionCategory PollyCategory("Polly Options",
56
                                 "Configure the polly loop optimizer");
57
58
static cl::opt<bool>
59
    PollyEnabled("polly", cl::desc("Enable the polly optimizer (only at -O3)"),
60
                 cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory));
61
62
static cl::opt<bool> PollyDetectOnly(
63
    "polly-only-scop-detection",
64
    cl::desc("Only run scop detection, but no other optimizations"),
65
    cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory));
66
67
enum PassPositionChoice {
68
  POSITION_EARLY,
69
  POSITION_AFTER_LOOPOPT,
70
  POSITION_BEFORE_VECTORIZER
71
};
72
73
enum OptimizerChoice { OPTIMIZER_NONE, OPTIMIZER_ISL };
74
75
static cl::opt<PassPositionChoice> PassPosition(
76
    "polly-position", cl::desc("Where to run polly in the pass pipeline"),
77
    cl::values(
78
        clEnumValN(POSITION_EARLY, "early", "Before everything"),
79
        clEnumValN(POSITION_AFTER_LOOPOPT, "after-loopopt",
80
                   "After the loop optimizer (but within the inline cycle)"),
81
        clEnumValN(POSITION_BEFORE_VECTORIZER, "before-vectorizer",
82
                   "Right before the vectorizer")),
83
    cl::Hidden, cl::init(POSITION_BEFORE_VECTORIZER), cl::ZeroOrMore,
84
    cl::cat(PollyCategory));
85
86
static cl::opt<OptimizerChoice>
87
    Optimizer("polly-optimizer", cl::desc("Select the scheduling optimizer"),
88
              cl::values(clEnumValN(OPTIMIZER_NONE, "none", "No optimizer"),
89
                         clEnumValN(OPTIMIZER_ISL, "isl",
90
                                    "The isl scheduling optimizer")),
91
              cl::Hidden, cl::init(OPTIMIZER_ISL), cl::ZeroOrMore,
92
              cl::cat(PollyCategory));
93
94
enum CodeGenChoice { CODEGEN_FULL, CODEGEN_AST, CODEGEN_NONE };
95
static cl::opt<CodeGenChoice> CodeGeneration(
96
    "polly-code-generation", cl::desc("How much code-generation to perform"),
97
    cl::values(clEnumValN(CODEGEN_FULL, "full", "AST and IR generation"),
98
               clEnumValN(CODEGEN_AST, "ast", "Only AST generation"),
99
               clEnumValN(CODEGEN_NONE, "none", "No code generation")),
100
    cl::Hidden, cl::init(CODEGEN_FULL), cl::ZeroOrMore, cl::cat(PollyCategory));
101
102
enum TargetChoice { TARGET_CPU, TARGET_GPU, TARGET_HYBRID };
103
static cl::opt<TargetChoice>
104
    Target("polly-target", cl::desc("The hardware to target"),
105
           cl::values(clEnumValN(TARGET_CPU, "cpu", "generate CPU code")
106
#ifdef GPU_CODEGEN
107
                          ,
108
                      clEnumValN(TARGET_GPU, "gpu", "generate GPU code"),
109
                      clEnumValN(TARGET_HYBRID, "hybrid",
110
                                 "generate GPU code (preferably) or CPU code")
111
#endif
112
                          ),
113
           cl::init(TARGET_CPU), cl::ZeroOrMore, cl::cat(PollyCategory));
114
115
#ifdef GPU_CODEGEN
116
static cl::opt<GPURuntime> GPURuntimeChoice(
117
    "polly-gpu-runtime", cl::desc("The GPU Runtime API to target"),
118
    cl::values(clEnumValN(GPURuntime::CUDA, "libcudart",
119
                          "use the CUDA Runtime API"),
120
               clEnumValN(GPURuntime::OpenCL, "libopencl",
121
                          "use the OpenCL Runtime API")),
122
    cl::init(GPURuntime::CUDA), cl::ZeroOrMore, cl::cat(PollyCategory));
123
124
static cl::opt<GPUArch>
125
    GPUArchChoice("polly-gpu-arch", cl::desc("The GPU Architecture to target"),
126
                  cl::values(clEnumValN(GPUArch::NVPTX64, "nvptx64",
127
                                        "target NVIDIA 64-bit architecture"),
128
                             clEnumValN(GPUArch::SPIR32, "spir32",
129
                                        "target SPIR 32-bit architecture"),
130
                             clEnumValN(GPUArch::SPIR64, "spir64",
131
                                        "target SPIR 64-bit architecture")),
132
                  cl::init(GPUArch::NVPTX64), cl::ZeroOrMore,
133
                  cl::cat(PollyCategory));
134
#endif
135
136
VectorizerChoice polly::PollyVectorizerChoice;
137
static cl::opt<polly::VectorizerChoice, true> Vectorizer(
138
    "polly-vectorizer", cl::desc("Select the vectorization strategy"),
139
    cl::values(
140
        clEnumValN(polly::VECTORIZER_NONE, "none", "No Vectorization"),
141
        clEnumValN(polly::VECTORIZER_POLLY, "polly",
142
                   "Polly internal vectorizer"),
143
        clEnumValN(
144
            polly::VECTORIZER_STRIPMINE, "stripmine",
145
            "Strip-mine outer loops for the loop-vectorizer to trigger")),
146
    cl::location(PollyVectorizerChoice), cl::init(polly::VECTORIZER_NONE),
147
    cl::ZeroOrMore, cl::cat(PollyCategory));
148
149
static cl::opt<bool> ImportJScop(
150
    "polly-import",
151
    cl::desc("Import the polyhedral description of the detected Scops"),
152
    cl::Hidden, cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory));
153
154
static cl::opt<bool> FullyIndexedStaticExpansion(
155
    "polly-enable-mse",
156
    cl::desc("Fully expand the memory accesses of the detected Scops"),
157
    cl::Hidden, cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory));
158
159
static cl::opt<bool> ExportJScop(
160
    "polly-export",
161
    cl::desc("Export the polyhedral description of the detected Scops"),
162
    cl::Hidden, cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory));
163
164
static cl::opt<bool> DeadCodeElim("polly-run-dce",
165
                                  cl::desc("Run the dead code elimination"),
166
                                  cl::Hidden, cl::init(false), cl::ZeroOrMore,
167
                                  cl::cat(PollyCategory));
168
169
static cl::opt<bool> PollyViewer(
170
    "polly-show",
171
    cl::desc("Highlight the code regions that will be optimized in a "
172
             "(CFG BBs and LLVM-IR instructions)"),
173
    cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory));
174
175
static cl::opt<bool> PollyOnlyViewer(
176
    "polly-show-only",
177
    cl::desc("Highlight the code regions that will be optimized in "
178
             "a (CFG only BBs)"),
179
    cl::init(false), cl::cat(PollyCategory));
180
181
static cl::opt<bool>
182
    PollyPrinter("polly-dot", cl::desc("Enable the Polly DOT printer in -O3"),
183
                 cl::Hidden, cl::value_desc("Run the Polly DOT printer at -O3"),
184
                 cl::init(false), cl::cat(PollyCategory));
185
186
static cl::opt<bool> PollyOnlyPrinter(
187
    "polly-dot-only",
188
    cl::desc("Enable the Polly DOT printer in -O3 (no BB content)"), cl::Hidden,
189
    cl::value_desc("Run the Polly DOT printer at -O3 (no BB content"),
190
    cl::init(false), cl::cat(PollyCategory));
191
192
static cl::opt<bool>
193
    CFGPrinter("polly-view-cfg",
194
               cl::desc("Show the Polly CFG right after code generation"),
195
               cl::Hidden, cl::init(false), cl::cat(PollyCategory));
196
197
static cl::opt<bool>
198
    EnablePolyhedralInfo("polly-enable-polyhedralinfo",
199
                         cl::desc("Enable polyhedral interface of Polly"),
200
                         cl::Hidden, cl::init(false), cl::cat(PollyCategory));
201
202
static cl::opt<bool>
203
    EnableForwardOpTree("polly-enable-optree",
204
                        cl::desc("Enable operand tree forwarding"), cl::Hidden,
205
                        cl::init(true), cl::cat(PollyCategory));
206
207
static cl::opt<bool>
208
    DumpBefore("polly-dump-before",
209
               cl::desc("Dump module before Polly transformations into a file "
210
                        "suffixed with \"-before\""),
211
               cl::init(false), cl::cat(PollyCategory));
212
213
static cl::list<std::string> DumpBeforeFile(
214
    "polly-dump-before-file",
215
    cl::desc("Dump module before Polly transformations to the given file"),
216
    cl::cat(PollyCategory));
217
218
static cl::opt<bool>
219
    DumpAfter("polly-dump-after",
220
              cl::desc("Dump module after Polly transformations into a file "
221
                       "suffixed with \"-after\""),
222
              cl::init(false), cl::cat(PollyCategory));
223
224
static cl::list<std::string> DumpAfterFile(
225
    "polly-dump-after-file",
226
    cl::desc("Dump module after Polly transformations to the given file"),
227
    cl::ZeroOrMore, cl::cat(PollyCategory));
228
229
static cl::opt<bool>
230
    EnableDeLICM("polly-enable-delicm",
231
                 cl::desc("Eliminate scalar loop carried dependences"),
232
                 cl::Hidden, cl::init(true), cl::cat(PollyCategory));
233
234
static cl::opt<bool>
235
    EnableSimplify("polly-enable-simplify",
236
                   cl::desc("Simplify SCoP after optimizations"),
237
                   cl::init(true), cl::cat(PollyCategory));
238
239
static cl::opt<bool> EnablePruneUnprofitable(
240
    "polly-enable-prune-unprofitable",
241
    cl::desc("Bail out on unprofitable SCoPs before rescheduling"), cl::Hidden,
242
    cl::init(true), cl::cat(PollyCategory));
243
244
namespace polly {
245
45.1k
void initializePollyPasses(PassRegistry &Registry) {
246
45.1k
  initializeCodeGenerationPass(Registry);
247
45.1k
248
#ifdef GPU_CODEGEN
249
  initializePPCGCodeGenerationPass(Registry);
250
  initializeManagedMemoryRewritePassPass(Registry);
251
  LLVMInitializeNVPTXTarget();
252
  LLVMInitializeNVPTXTargetInfo();
253
  LLVMInitializeNVPTXTargetMC();
254
  LLVMInitializeNVPTXAsmPrinter();
255
#endif
256
  initializeCodePreparationPass(Registry);
257
45.1k
  initializeDeadCodeElimPass(Registry);
258
45.1k
  initializeDependenceInfoPass(Registry);
259
45.1k
  initializeDependenceInfoWrapperPassPass(Registry);
260
45.1k
  initializeJSONExporterPass(Registry);
261
45.1k
  initializeJSONImporterPass(Registry);
262
45.1k
  initializeMaximalStaticExpanderPass(Registry);
263
45.1k
  initializeIslAstInfoWrapperPassPass(Registry);
264
45.1k
  initializeIslScheduleOptimizerPass(Registry);
265
45.1k
  initializePollyCanonicalizePass(Registry);
266
45.1k
  initializePolyhedralInfoPass(Registry);
267
45.1k
  initializeScopDetectionWrapperPassPass(Registry);
268
45.1k
  initializeScopInlinerPass(Registry);
269
45.1k
  initializeScopInfoRegionPassPass(Registry);
270
45.1k
  initializeScopInfoWrapperPassPass(Registry);
271
45.1k
  initializeRewriteByrefParamsPass(Registry);
272
45.1k
  initializeCodegenCleanupPass(Registry);
273
45.1k
  initializeFlattenSchedulePass(Registry);
274
45.1k
  initializeForwardOpTreePass(Registry);
275
45.1k
  initializeDeLICMPass(Registry);
276
45.1k
  initializeSimplifyPass(Registry);
277
45.1k
  initializeDumpModulePass(Registry);
278
45.1k
  initializePruneUnprofitablePass(Registry);
279
45.1k
}
280
281
/// Register Polly passes such that they form a polyhedral optimizer.
282
///
283
/// The individual Polly passes are registered in the pass manager such that
284
/// they form a full polyhedral optimizer. The flow of the optimizer starts with
285
/// a set of preparing transformations that canonicalize the LLVM-IR such that
286
/// the LLVM-IR is easier for us to understand and to optimizes. On the
287
/// canonicalized LLVM-IR we first run the ScopDetection pass, which detects
288
/// static control flow regions. Those regions are then translated by the
289
/// ScopInfo pass into a polyhedral representation. As a next step, a scheduling
290
/// optimizer is run on the polyhedral representation and finally the optimized
291
/// polyhedral representation is code generated back to LLVM-IR.
292
///
293
/// Besides this core functionality, we optionally schedule passes that provide
294
/// a graphical view of the scops (Polly[Only]Viewer, Polly[Only]Printer), that
295
/// allow the export/import of the polyhedral representation
296
/// (JSCON[Exporter|Importer]) or that show the cfg after code generation.
297
///
298
/// For certain parts of the Polly optimizer, several alternatives are provided:
299
///
300
/// As scheduling optimizer we support the isl scheduling optimizer
301
/// (http://freecode.com/projects/isl).
302
/// It is also possible to run Polly with no optimizer. This mode is mainly
303
/// provided to analyze the run and compile time changes caused by the
304
/// scheduling optimizer.
305
///
306
/// Polly supports the isl internal code generator.
307
0
void registerPollyPasses(llvm::legacy::PassManagerBase &PM) {
308
0
  if (DumpBefore)
309
0
    PM.add(polly::createDumpModulePass("-before", true));
310
0
  for (auto &Filename : DumpBeforeFile)
311
0
    PM.add(polly::createDumpModulePass(Filename, false));
312
0
313
0
  PM.add(polly::createScopDetectionWrapperPassPass());
314
0
315
0
  if (PollyDetectOnly)
316
0
    return;
317
0
318
0
  if (PollyViewer)
319
0
    PM.add(polly::createDOTViewerPass());
320
0
  if (PollyOnlyViewer)
321
0
    PM.add(polly::createDOTOnlyViewerPass());
322
0
  if (PollyPrinter)
323
0
    PM.add(polly::createDOTPrinterPass());
324
0
  if (PollyOnlyPrinter)
325
0
    PM.add(polly::createDOTOnlyPrinterPass());
326
0
327
0
  PM.add(polly::createScopInfoRegionPassPass());
328
0
  if (EnablePolyhedralInfo)
329
0
    PM.add(polly::createPolyhedralInfoPass());
330
0
331
0
  if (EnableSimplify)
332
0
    PM.add(polly::createSimplifyPass(0));
333
0
  if (EnableForwardOpTree)
334
0
    PM.add(polly::createForwardOpTreePass());
335
0
  if (EnableDeLICM)
336
0
    PM.add(polly::createDeLICMPass());
337
0
  if (EnableSimplify)
338
0
    PM.add(polly::createSimplifyPass(1));
339
0
340
0
  if (ImportJScop)
341
0
    PM.add(polly::createJSONImporterPass());
342
0
343
0
  if (DeadCodeElim)
344
0
    PM.add(polly::createDeadCodeElimPass());
345
0
346
0
  if (FullyIndexedStaticExpansion)
347
0
    PM.add(polly::createMaximalStaticExpansionPass());
348
0
349
0
  if (EnablePruneUnprofitable)
350
0
    PM.add(polly::createPruneUnprofitablePass());
351
0
352
#ifdef GPU_CODEGEN
353
  if (Target == TARGET_HYBRID) {
354
    PM.add(
355
        polly::createPPCGCodeGenerationPass(GPUArchChoice, GPURuntimeChoice));
356
    PM.add(polly::createManagedMemoryRewritePassPass(GPUArchChoice,
357
                                                     GPURuntimeChoice));
358
  }
359
#endif
360
0
  if (Target == TARGET_CPU || Target == TARGET_HYBRID)
361
0
    switch (Optimizer) {
362
0
    case OPTIMIZER_NONE:
363
0
      break; /* Do nothing */
364
0
365
0
    case OPTIMIZER_ISL:
366
0
      PM.add(polly::createIslScheduleOptimizerPass());
367
0
      break;
368
0
    }
369
0
370
0
  if (ExportJScop)
371
0
    PM.add(polly::createJSONExporterPass());
372
0
373
0
  if (Target == TARGET_CPU || Target == TARGET_HYBRID)
374
0
    switch (CodeGeneration) {
375
0
    case CODEGEN_AST:
376
0
      PM.add(polly::createIslAstInfoWrapperPassPass());
377
0
      break;
378
0
    case CODEGEN_FULL:
379
0
      PM.add(polly::createCodeGenerationPass());
380
0
      break;
381
0
    case CODEGEN_NONE:
382
0
      break;
383
0
    }
384
#ifdef GPU_CODEGEN
385
  else {
386
    PM.add(
387
        polly::createPPCGCodeGenerationPass(GPUArchChoice, GPURuntimeChoice));
388
    PM.add(polly::createManagedMemoryRewritePassPass());
389
  }
390
#endif
391
392
0
  // FIXME: This dummy ModulePass keeps some programs from miscompiling,
393
0
  // probably some not correctly preserved analyses. It acts as a barrier to
394
0
  // force all analysis results to be recomputed.
395
0
  PM.add(createBarrierNoopPass());
396
0
397
0
  if (DumpAfter)
398
0
    PM.add(polly::createDumpModulePass("-after", true));
399
0
  for (auto &Filename : DumpAfterFile)
400
0
    PM.add(polly::createDumpModulePass(Filename, false));
401
0
402
0
  if (CFGPrinter)
403
0
    PM.add(llvm::createCFGPrinterLegacyPassPass());
404
0
}
405
406
38.3k
static bool shouldEnablePolly() {
407
38.3k
  if (PollyOnlyPrinter || PollyPrinter || PollyOnlyViewer || PollyViewer)
408
0
    PollyTrackFailures = true;
409
38.3k
410
38.3k
  if (PollyOnlyPrinter || PollyPrinter || PollyOnlyViewer || PollyViewer ||
411
38.3k
      ExportJScop || ImportJScop)
412
0
    PollyEnabled = true;
413
38.3k
414
38.3k
  return PollyEnabled;
415
38.3k
}
416
417
static void
418
registerPollyEarlyAsPossiblePasses(const llvm::PassManagerBuilder &Builder,
419
12.7k
                                   llvm::legacy::PassManagerBase &PM) {
420
12.7k
  if (!polly::shouldEnablePolly())
421
12.7k
    return;
422
0
423
0
  if (PassPosition != POSITION_EARLY)
424
0
    return;
425
0
426
0
  registerCanonicalicationPasses(PM);
427
0
  polly::registerPollyPasses(PM);
428
0
}
429
430
static void
431
registerPollyLoopOptimizerEndPasses(const llvm::PassManagerBuilder &Builder,
432
12.7k
                                    llvm::legacy::PassManagerBase &PM) {
433
12.7k
  if (!polly::shouldEnablePolly())
434
12.7k
    return;
435
0
436
0
  if (PassPosition != POSITION_AFTER_LOOPOPT)
437
0
    return;
438
0
439
0
  PM.add(polly::createCodePreparationPass());
440
0
  polly::registerPollyPasses(PM);
441
0
  PM.add(createCodegenCleanupPass());
442
0
}
443
444
static void
445
registerPollyScalarOptimizerLatePasses(const llvm::PassManagerBuilder &Builder,
446
12.7k
                                       llvm::legacy::PassManagerBase &PM) {
447
12.7k
  if (!polly::shouldEnablePolly())
448
12.7k
    return;
449
0
450
0
  if (PassPosition != POSITION_BEFORE_VECTORIZER)
451
0
    return;
452
0
453
0
  PM.add(polly::createCodePreparationPass());
454
0
  polly::registerPollyPasses(PM);
455
0
  PM.add(createCodegenCleanupPass());
456
0
}
457
458
static void buildDefaultPollyPipeline(FunctionPassManager &PM,
459
30
                                      PassBuilder::OptimizationLevel Level) {
460
30
  if (!polly::shouldEnablePolly())
461
30
    return;
462
0
  PassBuilder PB;
463
0
  ScopPassManager SPM;
464
0
465
0
  // TODO add utility passes for the various command line options, once they're
466
0
  // ported
467
0
  assert(!DumpBefore && "This option is not implemented");
468
0
  assert(DumpBeforeFile.empty() && "This option is not implemented");
469
0
470
0
  if (PollyDetectOnly)
471
0
    return;
472
0
473
0
  assert(!PollyViewer && "This option is not implemented");
474
0
  assert(!PollyOnlyViewer && "This option is not implemented");
475
0
  assert(!PollyPrinter && "This option is not implemented");
476
0
  assert(!PollyOnlyPrinter && "This option is not implemented");
477
0
  assert(!EnablePolyhedralInfo && "This option is not implemented");
478
0
  assert(!EnableDeLICM && "This option is not implemented");
479
0
  assert(!EnableSimplify && "This option is not implemented");
480
0
  if (ImportJScop)
481
0
    SPM.addPass(JSONImportPass());
482
0
  assert(!DeadCodeElim && "This option is not implemented");
483
0
  assert(!EnablePruneUnprofitable && "This option is not implemented");
484
0
  if (Target == TARGET_CPU || Target == TARGET_HYBRID)
485
0
    switch (Optimizer) {
486
0
    case OPTIMIZER_NONE:
487
0
      break; /* Do nothing */
488
0
    case OPTIMIZER_ISL:
489
0
      llvm_unreachable("ISL optimizer is not implemented");
490
0
      break;
491
0
    }
492
0
493
0
  assert(!ExportJScop && "This option is not implemented");
494
0
495
0
  if (Target == TARGET_CPU || Target == TARGET_HYBRID) {
496
0
    switch (CodeGeneration) {
497
0
    case CODEGEN_FULL:
498
0
      SPM.addPass(polly::CodeGenerationPass());
499
0
      break;
500
0
    case CODEGEN_AST:
501
0
    default: // Does it actually make sense to distinguish IslAst codegen?
502
0
      break;
503
0
    }
504
0
  }
505
#ifdef GPU_CODEGEN
506
  else
507
    llvm_unreachable("Hybrid Target with GPU support is not implemented");
508
#endif
509
510
0
  PM.addPass(CodePreparationPass());
511
0
  PM.addPass(createFunctionToScopPassAdaptor(std::move(SPM)));
512
0
  PM.addPass(PB.buildFunctionSimplificationPipeline(
513
0
      Level, PassBuilder::ThinLTOPhase::None)); // Cleanup
514
0
515
0
  assert(!DumpAfter && "This option is not implemented");
516
0
  assert(DumpAfterFile.empty() && "This option is not implemented");
517
0
518
0
  if (CFGPrinter)
519
0
    PM.addPass(llvm::CFGPrinterPass());
520
0
}
521
522
/// Register Polly to be available as an optimizer
523
///
524
///
525
/// We can currently run Polly at three different points int the pass manager.
526
/// a) very early, b) after the canonicalizing loop transformations and c) right
527
/// before the vectorizer.
528
///
529
/// The default is currently a), to register Polly such that it runs as early as
530
/// possible. This has several implications:
531
///
532
///   1) We need to schedule more canonicalization passes
533
///
534
///   As nothing is run before Polly, it is necessary to run a set of preparing
535
///   transformations before Polly to canonicalize the LLVM-IR and to allow
536
///   Polly to detect and understand the code.
537
///
538
///   2) LICM and LoopIdiom pass have not yet been run
539
///
540
///   Loop invariant code motion as well as the loop idiom recognition pass make
541
///   it more difficult for Polly to transform code. LICM may introduce
542
///   additional data dependences that are hard to eliminate and the loop idiom
543
///   recognition pass may introduce calls to memset that we currently do not
544
///   understand. By running Polly early enough (meaning before these passes) we
545
///   avoid difficulties that may be introduced by these passes.
546
///
547
///   3) We get the full -O3 optimization sequence after Polly
548
///
549
///   The LLVM-IR that is generated by Polly has been optimized on a high level,
550
///   but it may be rather inefficient on the lower/scalar level. By scheduling
551
///   Polly before all other passes, we have the full sequence of -O3
552
///   optimizations behind us, such that inefficiencies on the low level can
553
///   be optimized away.
554
///
555
/// We are currently evaluating the benefit or running Polly at position b) or
556
/// c). b) is likely too early as it interacts with the inliner. c) is nice
557
/// as everything is fully inlined and canonicalized, but we need to be able
558
/// to handle LICMed code to make it useful.
559
static llvm::RegisterStandardPasses RegisterPollyOptimizerEarly(
560
    llvm::PassManagerBuilder::EP_ModuleOptimizerEarly,
561
    registerPollyEarlyAsPossiblePasses);
562
563
static llvm::RegisterStandardPasses
564
    RegisterPollyOptimizerLoopEnd(llvm::PassManagerBuilder::EP_LoopOptimizerEnd,
565
                                  registerPollyLoopOptimizerEndPasses);
566
567
static llvm::RegisterStandardPasses RegisterPollyOptimizerScalarLate(
568
    llvm::PassManagerBuilder::EP_VectorizerStart,
569
    registerPollyScalarOptimizerLatePasses);
570
571
static OwningScopAnalysisManagerFunctionProxy
572
934
createScopAnalyses(FunctionAnalysisManager &FAM) {
573
934
  OwningScopAnalysisManagerFunctionProxy Proxy;
574
934
#define SCOP_ANALYSIS(NAME, CREATE_PASS)                                       \
575
1.86k
  Proxy.getManager().registerPass([] { return CREATE_PASS; });
RegisterPasses.cpp:polly::createScopAnalyses(llvm::AnalysisManager<llvm::Function>&)::$_0::operator()() const
Line
Count
Source
575
934
  Proxy.getManager().registerPass([] { return CREATE_PASS; });
RegisterPasses.cpp:polly::createScopAnalyses(llvm::AnalysisManager<llvm::Function>&)::$_1::operator()() const
Line
Count
Source
575
934
  Proxy.getManager().registerPass([] { return CREATE_PASS; });
576
934
577
934
#include "PollyPasses.def"
578
934
579
934
  Proxy.getManager().registerPass(
580
934
      [&FAM] { return FunctionAnalysisManagerScopProxy(FAM); });
581
934
  return Proxy;
582
934
}
583
584
934
static void registerFunctionAnalyses(FunctionAnalysisManager &FAM) {
585
934
#define FUNCTION_ANALYSIS(NAME, CREATE_PASS)                                   \
586
1.86k
  FAM.registerPass([] { return CREATE_PASS; });
RegisterPasses.cpp:polly::registerFunctionAnalyses(llvm::AnalysisManager<llvm::Function>&)::$_3::operator()() const
Line
Count
Source
586
934
  FAM.registerPass([] { return CREATE_PASS; });
RegisterPasses.cpp:polly::registerFunctionAnalyses(llvm::AnalysisManager<llvm::Function>&)::$_4::operator()() const
Line
Count
Source
586
934
  FAM.registerPass([] { return CREATE_PASS; });
587
934
588
934
#include "PollyPasses.def"
589
934
590
934
  FAM.registerPass([&FAM] { return createScopAnalyses(FAM); });
591
934
}
592
593
static bool
594
parseFunctionPipeline(StringRef Name, FunctionPassManager &FPM,
595
27
                      ArrayRef<PassBuilder::PipelineElement> Pipeline) {
596
27
  if (parseAnalysisUtilityPasses<OwningScopAnalysisManagerFunctionProxy>(
597
27
          "polly-scop-analyses", Name, FPM))
598
0
    return true;
599
27
600
27
#define FUNCTION_ANALYSIS(NAME, CREATE_PASS)                                   \
601
81
  if (parseAnalysisUtilityPasses<                                              \
602
54
          std::remove_reference<decltype(CREATE_PASS)>::type>(NAME, Name,      \
603
54
                                                              FPM))            \
604
81
    
return true0
;
605
27
606
27
#define FUNCTION_PASS(NAME, CREATE_PASS)                                       \
607
77
  if (Name == NAME) {                                                          \
608
2
    FPM.addPass(CREATE_PASS);                                                  \
609
2
    return true;                                                               \
610
2
  }
611
27
612
131
#include 
"PollyPasses.def"27
613
131
  
return false25
;
614
131
}
615
616
1
static bool parseScopPass(StringRef Name, ScopPassManager &SPM) {
617
1
#define SCOP_ANALYSIS(NAME, CREATE_PASS)                                       \
618
2
  if (parseAnalysisUtilityPasses<                                              \
619
2
          std::remove_reference<decltype(CREATE_PASS)>::type>(NAME, Name,      \
620
2
                                                              SPM))            \
621
2
    
return true0
;
622
1
623
1
#define SCOP_PASS(NAME, CREATE_PASS)                                           \
624
3
  if (Name == NAME) {                                                          \
625
1
    SPM.addPass(CREATE_PASS);                                                  \
626
1
    return true;                                                               \
627
1
  }
628
1
629
4
#include 
"PollyPasses.def"1
630
4
631
4
  
return false0
;
632
4
}
633
634
static bool parseScopPipeline(StringRef Name, FunctionPassManager &FPM,
635
25
                              ArrayRef<PassBuilder::PipelineElement> Pipeline) {
636
25
  if (Name != "scop")
637
24
    return false;
638
1
  if (!Pipeline.empty()) {
639
1
    ScopPassManager SPM;
640
1
    for (const auto &E : Pipeline)
641
1
      if (!parseScopPass(E.Name, SPM))
642
0
        return false;
643
1
    FPM.addPass(createFunctionToScopPassAdaptor(std::move(SPM)));
644
1
  }
645
1
  return true;
646
1
}
647
648
0
static bool isScopPassName(StringRef Name) {
649
0
#define SCOP_ANALYSIS(NAME, CREATE_PASS)                                       \
650
0
  if (Name == "require<" NAME ">")                                             \
651
0
    return true;                                                               \
652
0
  if (Name == "invalidate<" NAME ">")                                          \
653
0
    return true;
654
0
655
0
#define SCOP_PASS(NAME, CREATE_PASS)                                           \
656
0
  if (Name == NAME)                                                            \
657
0
    return true;
658
0
659
0
#include "PollyPasses.def"
660
0
661
0
  return false;
662
0
}
663
664
static bool
665
parseTopLevelPipeline(ModulePassManager &MPM,
666
                      ArrayRef<PassBuilder::PipelineElement> Pipeline,
667
0
                      bool VerifyEachPass, bool DebugLogging) {
668
0
  std::vector<PassBuilder::PipelineElement> FullPipeline;
669
0
  StringRef FirstName = Pipeline.front().Name;
670
0
671
0
  if (!isScopPassName(FirstName))
672
0
    return false;
673
0
674
0
  FunctionPassManager FPM(DebugLogging);
675
0
  ScopPassManager SPM(DebugLogging);
676
0
677
0
  for (auto &Element : Pipeline) {
678
0
    auto &Name = Element.Name;
679
0
    auto &InnerPipeline = Element.InnerPipeline;
680
0
    if (!InnerPipeline.empty()) // Scop passes don't have inner pipelines
681
0
      return false;
682
0
    if (!parseScopPass(Name, SPM))
683
0
      return false;
684
0
  }
685
0
686
0
  FPM.addPass(createFunctionToScopPassAdaptor(std::move(SPM)));
687
0
  if (VerifyEachPass)
688
0
    FPM.addPass(VerifierPass());
689
0
  MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
690
0
  if (VerifyEachPass)
691
0
    MPM.addPass(VerifierPass());
692
0
693
0
  return true;
694
0
}
695
696
935
void RegisterPollyPasses(PassBuilder &PB) {
697
935
  PB.registerAnalysisRegistrationCallback(registerFunctionAnalyses);
698
935
  PB.registerPipelineParsingCallback(parseFunctionPipeline);
699
935
  PB.registerPipelineParsingCallback(parseScopPipeline);
700
935
  PB.registerParseTopLevelPipelineCallback(parseTopLevelPipeline);
701
935
702
935
  if (PassPosition == POSITION_BEFORE_VECTORIZER)
703
935
    PB.registerVectorizerStartEPCallback(buildDefaultPollyPipeline);
704
935
  // FIXME else Error?
705
935
}
706
} // namespace polly
707
708
// Plugin Entrypoint:
709
extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK
710
1
llvmGetPassPluginInfo() {
711
1
  return {LLVM_PLUGIN_API_VERSION, "Polly", LLVM_VERSION_STRING,
712
1
          polly::RegisterPollyPasses};
713
1
}