Coverage Report

Created: 2019-04-25 15:07

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