[PM] Port TTI to the new pass manager, introducing a TargetIRAnalysis to
authorChandler Carruth <chandlerc@gmail.com>
Sun, 1 Feb 2015 10:11:22 +0000 (10:11 +0000)
committerChandler Carruth <chandlerc@gmail.com>
Sun, 1 Feb 2015 10:11:22 +0000 (10:11 +0000)
produce it.

This adds a function to the TargetMachine that produces this analysis
via a callback for each function. This in turn faves the way to produce
a *different* TTI per-function with the correct subtarget cached.

I've also done the necessary wiring in the opt tool to thread the target
machine down and make it available to the pass registry so that we can
construct this analysis from a target machine when available.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@227721 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Analysis/TargetTransformInfo.h
include/llvm/Target/TargetMachine.h
lib/Analysis/TargetTransformInfo.cpp
lib/Target/TargetMachine.cpp
test/Other/new-pass-manager.ll
tools/opt/NewPMDriver.cpp
tools/opt/NewPMDriver.h
tools/opt/PassRegistry.def
tools/opt/Passes.cpp
tools/opt/Passes.h
tools/opt/opt.cpp

index 20bc70dfd66ae00e924cc0cd1829796bf6ae3d90..9908853bc49a16f233d52a6abaf6582ad16bd926 100644 (file)
@@ -32,6 +32,7 @@ namespace llvm {
 class Function;
 class GlobalValue;
 class Loop;
+class PreservedAnalyses;
 class Type;
 class User;
 class Value;
@@ -76,6 +77,17 @@ public:
   // out-of-line.
   ~TargetTransformInfo();
 
+  /// \brief Handle the invalidation of this information.
+  ///
+  /// When used as a result of \c TargetIRAnalysis this method will be called
+  /// when the function this was computed for changes. When it returns false,
+  /// the information is preserved across those changes.
+  bool invalidate(Function &, const PreservedAnalyses &) {
+    // FIXME: We should probably in some way ensure that the subtarget
+    // information for a function hasn't changed.
+    return false;
+  }
+
   /// \name Generic Target Information
   /// @{
 
@@ -706,6 +718,74 @@ template <typename T>
 TargetTransformInfo::TargetTransformInfo(T Impl)
     : TTIImpl(new Model<T>(Impl)) {}
 
+/// \brief Analysis pass providing the \c TargetTransformInfo.
+///
+/// The core idea of the TargetIRAnalysis is to expose an interface through
+/// which LLVM targets can analyze and provide information about the middle
+/// end's target-independent IR. This supports use cases such as target-aware
+/// cost modeling of IR constructs.
+///
+/// This is a function analysis because much of the cost modeling for targets
+/// is done in a subtarget specific way and LLVM supports compiling different
+/// functions targeting different subtargets in order to support runtime
+/// dispatch according to the observed subtarget.
+class TargetIRAnalysis {
+public:
+  typedef TargetTransformInfo Result;
+
+  /// \brief Opaque, unique identifier for this analysis pass.
+  static void *ID() { return (void *)&PassID; }
+
+  /// \brief Provide access to a name for this pass for debugging purposes.
+  static StringRef name() { return "TargetIRAnalysis"; }
+
+  /// \brief Default construct a target IR analysis.
+  ///
+  /// This will use the module's datalayout to construct a baseline
+  /// conservative TTI result.
+  TargetIRAnalysis();
+
+  /// \brief Construct an IR analysis pass around a target-provide callback.
+  ///
+  /// The callback will be called with a particular function for which the TTI
+  /// is needed and must return a TTI object for that function.
+  TargetIRAnalysis(std::function<Result(Function &)> TTICallback);
+
+  // Value semantics. We spell out the constructors for MSVC.
+  TargetIRAnalysis(const TargetIRAnalysis &Arg)
+      : TTICallback(Arg.TTICallback) {}
+  TargetIRAnalysis(TargetIRAnalysis &&Arg)
+      : TTICallback(std::move(Arg.TTICallback)) {}
+  TargetIRAnalysis &operator=(const TargetIRAnalysis &RHS) {
+    TTICallback = RHS.TTICallback;
+    return *this;
+  }
+  TargetIRAnalysis &operator=(TargetIRAnalysis &&RHS) {
+    TTICallback = std::move(RHS.TTICallback);
+    return *this;
+  }
+
+  Result run(Function &F);
+
+private:
+  static char PassID;
+
+  /// \brief The callback used to produce a result.
+  ///
+  /// We use a completely opaque callback so that targets can provide whatever
+  /// mechanism they desire for constructing the TTI for a given function.
+  ///
+  /// FIXME: Should we really use std::function? It's relatively inefficient.
+  /// It might be possible to arrange for even stateful callbacks to outlive
+  /// the analysis and thus use a function_ref which would be lighter weight.
+  /// This may also be less error prone as the callback is likely to reference
+  /// the external TargetMachine, and that reference needs to never dangle.
+  std::function<Result(Function &)> TTICallback;
+
+  /// \brief Helper function used as the callback in the default constructor.
+  static Result getDefaultTTI(Function &F);
+};
+
 /// \brief Wrapper pass for TargetTransformInfo.
 ///
 /// This pass can be constructed from a TTI object which it stores internally
index 109985abb1e50aca88d2e951e01b3ed91e161e6d..dd61c0ab05728449250907045cf11e63353d00b4 100644 (file)
@@ -34,6 +34,7 @@ class Target;
 class DataLayout;
 class TargetLibraryInfo;
 class TargetFrameLowering;
+class TargetIRAnalysis;
 class TargetIntrinsicInfo;
 class TargetLowering;
 class TargetPassConfig;
@@ -187,6 +188,12 @@ public:
   /// sections.
   void setFunctionSections(bool);
 
+  /// \brief Get a \c TargetIRAnalysis appropriate for the target.
+  ///
+  /// This is used to construct the new pass manager's target IR analysis pass,
+  /// set up appropriately for this target machine.
+  virtual TargetIRAnalysis getTargetIRAnalysis();
+
   /// \brief Get a TTI implementation for the target.
   ///
   /// Targets should override this method to provide target-accurate
index a78d1db396abfd3c7b053ae9193d23e891e59750..6bd79f667b48cb6b992d8e44b8d53407856e443d 100644 (file)
@@ -14,6 +14,7 @@
 #include "llvm/IR/Instruction.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/Module.h"
 #include "llvm/IR/Operator.h"
 #include "llvm/Support/ErrorHandling.h"
 
@@ -255,6 +256,22 @@ Value *TargetTransformInfo::getOrCreateResultFromMemIntrinsic(
 
 TargetTransformInfo::Concept::~Concept() {}
 
+TargetIRAnalysis::TargetIRAnalysis() : TTICallback(&getDefaultTTI) {}
+
+TargetIRAnalysis::TargetIRAnalysis(
+    std::function<Result(Function &)> TTICallback)
+    : TTICallback(TTICallback) {}
+
+TargetIRAnalysis::Result TargetIRAnalysis::run(Function &F) {
+  return TTICallback(F);
+}
+
+char TargetIRAnalysis::PassID;
+
+TargetIRAnalysis::Result TargetIRAnalysis::getDefaultTTI(Function &F) {
+  return Result(F.getParent()->getDataLayout());
+}
+
 // Register the basic pass.
 INITIALIZE_PASS(TargetTransformInfoWrapperPass, "tti",
                 "Target Transform Information", false, true)
index a8c877f848a9e49185241d21c8370f4308911fc2..1e5bfb247293205dc02f1fb871d879f5bd316dbc 100644 (file)
@@ -172,6 +172,13 @@ void TargetMachine::setDataSections(bool V) {
   Options.DataSections = V;
 }
 
+TargetIRAnalysis TargetMachine::getTargetIRAnalysis() {
+  // While targets are free to just override getTTI and rely on this analysis,
+  // it would be more efficient to override and provide an analysis that could
+  // directly construct that target's TTI without the virtual call.
+  return TargetIRAnalysis([this](Function &) { return getTTI(); });
+}
+
 TargetTransformInfo TargetMachine::getTTI() {
   return TargetTransformInfo(getDataLayout());
 }
index 2cb54ba49a80e9ffc2ac440f9493f60fdbedee3a..a1bffe4d63d346e92bf3330c6e27dad0b6404b77 100644 (file)
 ; CHECK-TLI-NOT: Running analysis: TargetLibraryAnalysis
 ; CHECK-TLI: Finished pass manager
 
+; RUN: opt -disable-output -disable-verify -debug-pass-manager %s 2>&1 \
+; RUN:     -passes='require<targetir>,invalidate<all>,require<targetir>' \
+; RUN:     | FileCheck %s --check-prefix=CHECK-TIRA
+; CHECK-TIRA: Starting pass manager
+; CHECK-TIRA: Running pass: RequireAnalysisPass
+; CHECK-TIRA: Running analysis: TargetIRAnalysis
+; CHECK-TIRA: Running pass: InvalidateAllAnalysesPass
+; CHECK-TIRA-NOT: Invalidating analysis: TargetIRAnalysis
+; CHECK-TIRA: Running pass: RequireAnalysisPass
+; CHECK-TIRA-NOT: Running analysis: TargetIRAnalysis
+; CHECK-TIRA: Finished pass manager
+
 define void @foo() {
   ret void
 }
index b0845c7b1f5ed39e9bb6a4ce3f7f1d1598bc0a28..a73750dd4920c50dcccec8f751c847a44abb2a55 100644 (file)
@@ -27,6 +27,7 @@
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/ToolOutputFile.h"
+#include "llvm/Target/TargetMachine.h"
 
 using namespace llvm;
 using namespace opt_tool;
@@ -36,9 +37,10 @@ static cl::opt<bool>
             cl::desc("Print pass management debugging information"));
 
 bool llvm::runPassPipeline(StringRef Arg0, LLVMContext &Context, Module &M,
-                           tool_output_file *Out, StringRef PassPipeline,
-                           OutputKind OK, VerifierKind VK) {
-  Passes P;
+                           TargetMachine *TM, tool_output_file *Out,
+                           StringRef PassPipeline, OutputKind OK,
+                           VerifierKind VK) {
+  Passes P(TM);
 
   FunctionAnalysisManager FAM(DebugPM);
   CGSCCAnalysisManager CGAM(DebugPM);
index f977baca7f83017434a1929762ef703ec79f5ba3..5384fe295e132641656260ad1f735557c8b6a54f 100644 (file)
@@ -26,6 +26,7 @@
 namespace llvm {
 class LLVMContext;
 class Module;
+class TargetMachine;
 class tool_output_file;
 
 namespace opt_tool {
@@ -48,8 +49,9 @@ enum VerifierKind {
 /// file. It's interface is consequentially somewhat ad-hoc, but will go away
 /// when the transition finishes.
 bool runPassPipeline(StringRef Arg0, LLVMContext &Context, Module &M,
-                     tool_output_file *Out, StringRef PassPipeline,
-                     opt_tool::OutputKind OK, opt_tool::VerifierKind VK);
+                     TargetMachine *TM, tool_output_file *Out,
+                     StringRef PassPipeline, opt_tool::OutputKind OK,
+                     opt_tool::VerifierKind VK);
 }
 
 #endif
index 9361d98c9a5f618aaec2ef670a65979d41b1454e..4ee9e97158e2d339d5549f14abe38e69097545f6 100644 (file)
@@ -55,6 +55,8 @@ FUNCTION_ANALYSIS("domtree", DominatorTreeAnalysis())
 FUNCTION_ANALYSIS("loops", LoopAnalysis())
 FUNCTION_ANALYSIS("no-op-function", NoOpFunctionAnalysis())
 FUNCTION_ANALYSIS("targetlibinfo", TargetLibraryAnalysis())
+FUNCTION_ANALYSIS("targetir",
+                  TM ? TM->getTargetIRAnalysis() : TargetIRAnalysis())
 #undef FUNCTION_ANALYSIS
 
 #ifndef FUNCTION_PASS
index 46c165abc03fe88a974a80db1f94def97d3320ce..b098a7c23518b96e00b3af1da985149c4c96c1b5 100644 (file)
 #include "llvm/Analysis/LazyCallGraph.h"
 #include "llvm/Analysis/LoopInfo.h"
 #include "llvm/Analysis/TargetLibraryInfo.h"
+#include "llvm/Analysis/TargetTransformInfo.h"
 #include "llvm/IR/Dominators.h"
 #include "llvm/IR/IRPrintingPasses.h"
 #include "llvm/IR/PassManager.h"
 #include "llvm/IR/Verifier.h"
 #include "llvm/Support/Debug.h"
+#include "llvm/Target/TargetMachine.h"
 #include "llvm/Transforms/InstCombine/InstCombine.h"
 #include "llvm/Transforms/Scalar/LowerExpectIntrinsic.h"
 
index 90a6c6b871d3b48472ea74ab365f238f6e4ed4f9..d3cb628469b89ef49328f5359acf167d3a5cef32 100644 (file)
@@ -21,6 +21,7 @@
 #include "llvm/IR/PassManager.h"
 
 namespace llvm {
+class TargetMachine;
 
 /// \brief This class provides access to all of LLVM's passes.
 ///
@@ -29,7 +30,11 @@ namespace llvm {
 /// of the built-in passes, and those may reference these members during
 /// construction.
 class Passes {
+  TargetMachine *TM;
+
 public:
+  explicit Passes(TargetMachine *TM = nullptr) : TM(TM) {}
+
   /// \brief Registers all available module analysis passes.
   ///
   /// This is an interface that can be used to populate a \c
index 93b44d4f7f42ebf43c0aacbe630fd610a0a90222..af2cdd824609a4bc4607affdc029919df9a534d8 100644 (file)
@@ -370,6 +370,12 @@ int main(int argc, char **argv) {
     }
   }
 
+  Triple ModuleTriple(M->getTargetTriple());
+  TargetMachine *Machine = nullptr;
+  if (ModuleTriple.getArch())
+    Machine = GetTargetMachine(ModuleTriple);
+  std::unique_ptr<TargetMachine> TM(Machine);
+
   // If the output is set to be emitted to standard out, and standard out is a
   // console, print out a warning message and refuse to do it.  We don't
   // impress anyone by spewing tons of binary goo to a terminal.
@@ -391,8 +397,8 @@ int main(int argc, char **argv) {
     // The user has asked to use the new pass manager and provided a pipeline
     // string. Hand off the rest of the functionality to the new code for that
     // layer.
-    return runPassPipeline(argv[0], Context, *M, Out.get(), PassPipeline,
-                           OK, VK)
+    return runPassPipeline(argv[0], Context, *M, TM.get(), Out.get(),
+                           PassPipeline, OK, VK)
                ? 0
                : 1;
   }
@@ -403,7 +409,7 @@ int main(int argc, char **argv) {
   PassManager Passes;
 
   // Add an appropriate TargetLibraryInfo pass for the module's triple.
-  TargetLibraryInfoImpl TLII(Triple(M->getTargetTriple()));
+  TargetLibraryInfoImpl TLII(ModuleTriple);
 
   // The -disable-simplify-libcalls flag actually disables all builtin optzns.
   if (DisableSimplifyLibCalls)
@@ -420,12 +426,6 @@ int main(int argc, char **argv) {
   if (DL)
     Passes.add(new DataLayoutPass());
 
-  Triple ModuleTriple(M->getTargetTriple());
-  TargetMachine *Machine = nullptr;
-  if (ModuleTriple.getArch())
-    Machine = GetTargetMachine(Triple(ModuleTriple));
-  std::unique_ptr<TargetMachine> TM(Machine);
-
   // Add internal analysis passes from the target machine.
   Passes.add(createTargetTransformInfoWrapperPass(
       TM ? TM->getTTI() : TargetTransformInfo(DL)));