silvas updated this revision to Diff 64420.
silvas added a comment.

Rebase after r275507.


https://reviews.llvm.org/D21954

Files:
  include/clang/Driver/CC1Options.td
  include/clang/Frontend/CodeGenOptions.h
  lib/CodeGen/BackendUtil.cpp
  lib/CodeGen/CMakeLists.txt
  lib/Frontend/CompilerInvocation.cpp
  test/CodeGen/middle-end-passes.c

Index: test/CodeGen/middle-end-passes.c
===================================================================
--- /dev/null
+++ test/CodeGen/middle-end-passes.c
@@ -0,0 +1,26 @@
+// Check that passes get run.
+
+// RUN: %clang_cc1 %s -emit-llvm -o /dev/null -middle-end-passes=mem2reg,aa-eval 2>&1 | FileCheck %s --check-prefix=NO-AA
+
+// NO-AA: ===== Alias Analysis Evaluator Report =====
+// NO-AA: 0 must alias responses
+
+// RUN: %clang_cc1 %s -emit-llvm -o /dev/null -middle-end-passes=mem2reg,aa-eval -middle-end-aa-pipeline=basic-aa 2>&1 | FileCheck %s --check-prefix=WITH-AA
+
+// WITH-AA: ===== Alias Analysis Evaluator Report =====
+// WITH-AA: 1 must alias responses
+
+
+// The actual output with -flto or -emit-llvm is generated by running a
+// pass in the old PM. Verify that that we still get output.
+
+// RUN: %clang -flto -c %s -o - -Xclang -middle-end-passes=mem2reg 2>&1 | opt -S | FileCheck %s --check-prefix=OUTPUT-IS-GENERATED
+// RUN: %clang -emit-llvm -S %s -o - -Xclang -middle-end-passes=mem2reg 2>&1 | FileCheck %s --check-prefix=OUTPUT-IS-GENERATED
+
+// OUTPUT-IS-GENERATED: @foo
+
+int foo(int *x) {
+  int *y = x + 1;
+  int *z = y - 1;
+  return *x + *z;
+}
Index: lib/Frontend/CompilerInvocation.cpp
===================================================================
--- lib/Frontend/CompilerInvocation.cpp
+++ lib/Frontend/CompilerInvocation.cpp
@@ -845,6 +845,11 @@
   Opts.EmitCheckPathComponentsToStrip = getLastArgIntValue(
       Args, OPT_fsanitize_undefined_strip_path_components_EQ, 0, Diags);
 
+  if (Arg *A = Args.getLastArg(OPT_middle_end_passes_EQ))
+    Opts.MiddleEndPasses = A->getValue();
+  if (Arg *A = Args.getLastArg(OPT_middle_end_aa_pipeline_EQ))
+    Opts.MiddleEndAAPipeline = A->getValue();
+
   return Success;
 }
 
Index: lib/CodeGen/CMakeLists.txt
===================================================================
--- lib/CodeGen/CMakeLists.txt
+++ lib/CodeGen/CMakeLists.txt
@@ -12,6 +12,7 @@
   MC
   ObjCARCOpts
   Object
+  Passes
   ProfileData
   ScalarOpts
   Support
Index: lib/CodeGen/BackendUtil.cpp
===================================================================
--- lib/CodeGen/BackendUtil.cpp
+++ lib/CodeGen/BackendUtil.cpp
@@ -31,6 +31,7 @@
 #include "llvm/IR/Verifier.h"
 #include "llvm/MC/SubtargetFeature.h"
 #include "llvm/Object/ModuleSummaryIndexObjectFile.h"
+#include "llvm/Passes/PassBuilder.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/PrettyStackTrace.h"
 #include "llvm/Support/TargetRegistry.h"
@@ -643,6 +644,43 @@
   return true;
 }
 
+static void runMiddleEndPasses(Module &M, TargetMachine *TM, StringRef Passes,
+                               StringRef AAPipeline) {
+  // This is a really low-level internal developer option.
+  // Use report_fatal_error if anything goes wrong.
+
+  PassBuilder PB(TM);
+  AAManager AA;
+  if (!PB.parseAAPipeline(AA, AAPipeline))
+    report_fatal_error("Unable to parse AA pipeline description: " +
+                       AAPipeline);
+
+  LoopAnalysisManager LAM;
+  FunctionAnalysisManager FAM;
+  CGSCCAnalysisManager CGAM;
+  ModuleAnalysisManager MAM;
+
+  // Register the AA manager first so that our version is the one used.
+  FAM.registerPass([&] { return std::move(AA); });
+
+  // Register all the basic analyses with the managers.
+  PB.registerModuleAnalyses(MAM);
+  PB.registerCGSCCAnalyses(CGAM);
+  PB.registerFunctionAnalyses(FAM);
+  PB.registerLoopAnalyses(LAM);
+  PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
+
+  ModulePassManager MPM;
+  MPM.addPass(VerifierPass());
+
+  // Now, add all the passes we've been requested to.
+  if (!PB.parsePassPipeline(MPM, Passes))
+    report_fatal_error("Unable to parse pass pipeline description: " + Passes);
+
+  MPM.addPass(VerifierPass());
+  MPM.run(M, MAM);
+}
+
 void EmitAssemblyHelper::EmitAssembly(BackendAction Action,
                                       std::unique_ptr<raw_pwrite_stream> OS) {
   TimeRegion Region(llvm::TimePassesIsEnabled ? &CodeGenerationTime : nullptr);
@@ -687,7 +725,11 @@
   PerFunctionPasses.add(
       createTargetTransformInfoWrapperPass(getTargetIRAnalysis()));
 
-  CreatePasses(PerModulePasses, PerFunctionPasses, ModuleSummary.get());
+  bool UseCustomMiddleEndPasses = !CodeGenOpts.MiddleEndPasses.empty();
+  // If we are going to use a custom middle-end pass pipeline, don't add
+  // any of the usual passes.
+  if (!UseCustomMiddleEndPasses)
+    CreatePasses(PerModulePasses, PerFunctionPasses, ModuleSummary.get());
 
   legacy::PassManager CodeGenPasses;
   CodeGenPasses.add(
@@ -716,6 +758,18 @@
   // Before executing passes, print the final values of the LLVM options.
   cl::PrintOptionValues();
 
+  if (UseCustomMiddleEndPasses) {
+    // Override the middle-end pass pipeline.
+    // Note that we still run the old PM managers later because they
+    // contain e.g. the passes for printing out a BC or LL file (e.g. for
+    // -flto).
+    // But these passes don't affect the actual optimization because there
+    // is nothing else run in the old PM except for the printing passes.
+
+    runMiddleEndPasses(*TheModule, TM.get(), CodeGenOpts.MiddleEndPasses,
+                       CodeGenOpts.MiddleEndAAPipeline);
+  }
+
   // Run passes. For now we do all passes at once, but eventually we
   // would like to have the option of streaming code generation.
 
Index: include/clang/Frontend/CodeGenOptions.h
===================================================================
--- include/clang/Frontend/CodeGenOptions.h
+++ include/clang/Frontend/CodeGenOptions.h
@@ -107,6 +107,24 @@
   /// Enable additional debugging information.
   std::string DebugPass;
 
+  /// Pass description string to override the middle-end pass pipeline.
+  /// This is primarily for developers experimenting with different
+  /// optimization pipelines.
+  /// This will completely replace the middle-end pass pipeline, so
+  /// features that depend on changes to the pipeline (e.g. sanitizers) may
+  /// not work as expected in conjunction with this option.
+  /// The string has the same format as the string passed to opt's
+  /// `-passes=` flag.
+  std::string MiddleEndPasses;
+
+  /// Alias analysis description string to use with MiddleEndPasses.
+  /// This is primarily for developers experimenting with different
+  /// optimization pipelines.
+  /// This option only affects passes run by MiddleEndPasses.
+  /// The string has the same format as the string passed to opt's
+  /// `-aa-pipeline=` flag.
+  std::string MiddleEndAAPipeline;
+
   /// The string to embed in debug information as the current working directory.
   std::string DebugCompilationDir;
 
Index: include/clang/Driver/CC1Options.td
===================================================================
--- include/clang/Driver/CC1Options.td
+++ include/clang/Driver/CC1Options.td
@@ -157,6 +157,13 @@
   HelpText<"Disable implicit builtin knowledge of math functions">;
 }
 
+def middle_end_passes_EQ
+    : Joined<[ "-" ], "middle-end-passes=">,
+      HelpText<"Override the middle-end passes that are run">;
+def middle_end_aa_pipeline_EQ
+    : Joined<[ "-" ], "middle-end-aa-pipeline=">,
+      HelpText<"Alias analysis pipeline to use with -middle-end-passes=">;
+
 def disable_llvm_optzns : Flag<["-"], "disable-llvm-optzns">,
   HelpText<"Don't run LLVM optimization passes">;
 def disable_llvm_verifier : Flag<["-"], "disable-llvm-verifier">,
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to