Coverage Report

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