[PM] Port TTI to the new pass manager, introducing a TargetIRAnalysis to

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.

llvm-svn: 227721
This commit is contained in:
Chandler Carruth 2015-02-01 10:11:22 +00:00
parent 2844ca7319
commit e038552c8a
11 changed files with 150 additions and 14 deletions

View File

@ -32,6 +32,7 @@ namespace llvm {
class Function; class Function;
class GlobalValue; class GlobalValue;
class Loop; class Loop;
class PreservedAnalyses;
class Type; class Type;
class User; class User;
class Value; class Value;
@ -76,6 +77,17 @@ public:
// out-of-line. // out-of-line.
~TargetTransformInfo(); ~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 /// \name Generic Target Information
/// @{ /// @{
@ -706,6 +718,74 @@ template <typename T>
TargetTransformInfo::TargetTransformInfo(T Impl) TargetTransformInfo::TargetTransformInfo(T Impl)
: TTIImpl(new Model<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. /// \brief Wrapper pass for TargetTransformInfo.
/// ///
/// This pass can be constructed from a TTI object which it stores internally /// This pass can be constructed from a TTI object which it stores internally

View File

@ -34,6 +34,7 @@ class Target;
class DataLayout; class DataLayout;
class TargetLibraryInfo; class TargetLibraryInfo;
class TargetFrameLowering; class TargetFrameLowering;
class TargetIRAnalysis;
class TargetIntrinsicInfo; class TargetIntrinsicInfo;
class TargetLowering; class TargetLowering;
class TargetPassConfig; class TargetPassConfig;
@ -187,6 +188,12 @@ public:
/// sections. /// sections.
void setFunctionSections(bool); 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. /// \brief Get a TTI implementation for the target.
/// ///
/// Targets should override this method to provide target-accurate /// Targets should override this method to provide target-accurate

View File

@ -14,6 +14,7 @@
#include "llvm/IR/Instruction.h" #include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h" #include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Operator.h" #include "llvm/IR/Operator.h"
#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ErrorHandling.h"
@ -255,6 +256,22 @@ Value *TargetTransformInfo::getOrCreateResultFromMemIntrinsic(
TargetTransformInfo::Concept::~Concept() {} 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. // Register the basic pass.
INITIALIZE_PASS(TargetTransformInfoWrapperPass, "tti", INITIALIZE_PASS(TargetTransformInfoWrapperPass, "tti",
"Target Transform Information", false, true) "Target Transform Information", false, true)

View File

@ -172,6 +172,13 @@ void TargetMachine::setDataSections(bool V) {
Options.DataSections = 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() { TargetTransformInfo TargetMachine::getTTI() {
return TargetTransformInfo(getDataLayout()); return TargetTransformInfo(getDataLayout());
} }

View File

@ -278,6 +278,18 @@
; CHECK-TLI-NOT: Running analysis: TargetLibraryAnalysis ; CHECK-TLI-NOT: Running analysis: TargetLibraryAnalysis
; CHECK-TLI: Finished pass manager ; 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() { define void @foo() {
ret void ret void
} }

View File

@ -27,6 +27,7 @@
#include "llvm/Support/CommandLine.h" #include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ToolOutputFile.h" #include "llvm/Support/ToolOutputFile.h"
#include "llvm/Target/TargetMachine.h"
using namespace llvm; using namespace llvm;
using namespace opt_tool; using namespace opt_tool;
@ -36,9 +37,10 @@ static cl::opt<bool>
cl::desc("Print pass management debugging information")); cl::desc("Print pass management debugging information"));
bool llvm::runPassPipeline(StringRef Arg0, LLVMContext &Context, Module &M, bool llvm::runPassPipeline(StringRef Arg0, LLVMContext &Context, Module &M,
tool_output_file *Out, StringRef PassPipeline, TargetMachine *TM, tool_output_file *Out,
OutputKind OK, VerifierKind VK) { StringRef PassPipeline, OutputKind OK,
Passes P; VerifierKind VK) {
Passes P(TM);
FunctionAnalysisManager FAM(DebugPM); FunctionAnalysisManager FAM(DebugPM);
CGSCCAnalysisManager CGAM(DebugPM); CGSCCAnalysisManager CGAM(DebugPM);

View File

@ -26,6 +26,7 @@
namespace llvm { namespace llvm {
class LLVMContext; class LLVMContext;
class Module; class Module;
class TargetMachine;
class tool_output_file; class tool_output_file;
namespace opt_tool { namespace opt_tool {
@ -48,8 +49,9 @@ enum VerifierKind {
/// file. It's interface is consequentially somewhat ad-hoc, but will go away /// file. It's interface is consequentially somewhat ad-hoc, but will go away
/// when the transition finishes. /// when the transition finishes.
bool runPassPipeline(StringRef Arg0, LLVMContext &Context, Module &M, bool runPassPipeline(StringRef Arg0, LLVMContext &Context, Module &M,
tool_output_file *Out, StringRef PassPipeline, TargetMachine *TM, tool_output_file *Out,
opt_tool::OutputKind OK, opt_tool::VerifierKind VK); StringRef PassPipeline, opt_tool::OutputKind OK,
opt_tool::VerifierKind VK);
} }
#endif #endif

View File

@ -55,6 +55,8 @@ FUNCTION_ANALYSIS("domtree", DominatorTreeAnalysis())
FUNCTION_ANALYSIS("loops", LoopAnalysis()) FUNCTION_ANALYSIS("loops", LoopAnalysis())
FUNCTION_ANALYSIS("no-op-function", NoOpFunctionAnalysis()) FUNCTION_ANALYSIS("no-op-function", NoOpFunctionAnalysis())
FUNCTION_ANALYSIS("targetlibinfo", TargetLibraryAnalysis()) FUNCTION_ANALYSIS("targetlibinfo", TargetLibraryAnalysis())
FUNCTION_ANALYSIS("targetir",
TM ? TM->getTargetIRAnalysis() : TargetIRAnalysis())
#undef FUNCTION_ANALYSIS #undef FUNCTION_ANALYSIS
#ifndef FUNCTION_PASS #ifndef FUNCTION_PASS

View File

@ -20,11 +20,13 @@
#include "llvm/Analysis/LazyCallGraph.h" #include "llvm/Analysis/LazyCallGraph.h"
#include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/IR/Dominators.h" #include "llvm/IR/Dominators.h"
#include "llvm/IR/IRPrintingPasses.h" #include "llvm/IR/IRPrintingPasses.h"
#include "llvm/IR/PassManager.h" #include "llvm/IR/PassManager.h"
#include "llvm/IR/Verifier.h" #include "llvm/IR/Verifier.h"
#include "llvm/Support/Debug.h" #include "llvm/Support/Debug.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Transforms/InstCombine/InstCombine.h" #include "llvm/Transforms/InstCombine/InstCombine.h"
#include "llvm/Transforms/Scalar/LowerExpectIntrinsic.h" #include "llvm/Transforms/Scalar/LowerExpectIntrinsic.h"

View File

@ -21,6 +21,7 @@
#include "llvm/IR/PassManager.h" #include "llvm/IR/PassManager.h"
namespace llvm { namespace llvm {
class TargetMachine;
/// \brief This class provides access to all of LLVM's passes. /// \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 /// of the built-in passes, and those may reference these members during
/// construction. /// construction.
class Passes { class Passes {
TargetMachine *TM;
public: public:
explicit Passes(TargetMachine *TM = nullptr) : TM(TM) {}
/// \brief Registers all available module analysis passes. /// \brief Registers all available module analysis passes.
/// ///
/// This is an interface that can be used to populate a \c /// This is an interface that can be used to populate a \c

View 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 // 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 // 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. // 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 // 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 // string. Hand off the rest of the functionality to the new code for that
// layer. // layer.
return runPassPipeline(argv[0], Context, *M, Out.get(), PassPipeline, return runPassPipeline(argv[0], Context, *M, TM.get(), Out.get(),
OK, VK) PassPipeline, OK, VK)
? 0 ? 0
: 1; : 1;
} }
@ -403,7 +409,7 @@ int main(int argc, char **argv) {
PassManager Passes; PassManager Passes;
// Add an appropriate TargetLibraryInfo pass for the module's triple. // 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. // The -disable-simplify-libcalls flag actually disables all builtin optzns.
if (DisableSimplifyLibCalls) if (DisableSimplifyLibCalls)
@ -420,12 +426,6 @@ int main(int argc, char **argv) {
if (DL) if (DL)
Passes.add(new DataLayoutPass()); 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. // Add internal analysis passes from the target machine.
Passes.add(createTargetTransformInfoWrapperPass( Passes.add(createTargetTransformInfoWrapperPass(
TM ? TM->getTTI() : TargetTransformInfo(DL))); TM ? TM->getTTI() : TargetTransformInfo(DL)));