mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-25 04:39:44 +00:00
[PM] Add pass run listeners to the pass manager.
This commit provides the necessary C/C++ APIs and infastructure to enable fine- grain progress report and safe suspension points after each pass in the pass manager. Clients can provide a callback function to the pass manager to call after each pass. This can be used in a variety of ways (progress report, dumping of IR between passes, safe suspension of threads, etc). The run listener list is maintained in the LLVMContext, which allows a multi- threaded client to be only informed for it's own thread. This of course assumes that the client created a LLVMContext for each thread. This fixes <rdar://problem/16728690> git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@207430 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
c430d3ffcd
commit
4e0cc51d79
@ -112,12 +112,23 @@ typedef struct LLVMOpaqueBuilder *LLVMBuilderRef;
|
||||
*/
|
||||
typedef struct LLVMOpaqueModuleProvider *LLVMModuleProviderRef;
|
||||
|
||||
/** @see llvm::Pass */
|
||||
typedef struct LLVMOpaquePass *LLVMPassRef;
|
||||
|
||||
/** @see llvm::PassManagerBase */
|
||||
typedef struct LLVMOpaquePassManager *LLVMPassManagerRef;
|
||||
|
||||
/** @see llvm::PassRegistry */
|
||||
typedef struct LLVMOpaquePassRegistry *LLVMPassRegistryRef;
|
||||
|
||||
/** @see llvm::PassRunListener */
|
||||
typedef struct LLVMOpaquePassRunListener *LLVMPassRunListenerRef;
|
||||
|
||||
/** @see llvm::LLVMPassRunListener */
|
||||
typedef void (*LLVMPassRunListenerHandlerTy)(LLVMContextRef, LLVMPassRef,
|
||||
LLVMModuleRef, LLVMValueRef,
|
||||
LLVMBasicBlockRef);
|
||||
|
||||
/**
|
||||
* Used to get the users and usees of a Value.
|
||||
*
|
||||
@ -515,6 +526,10 @@ unsigned LLVMGetMDKindIDInContext(LLVMContextRef C, const char* Name,
|
||||
unsigned SLen);
|
||||
unsigned LLVMGetMDKindID(const char* Name, unsigned SLen);
|
||||
|
||||
LLVMPassRunListenerRef LLVMAddPassRunListener(LLVMContextRef,
|
||||
LLVMPassRunListenerHandlerTy);
|
||||
void LLVMRemovePassRunListener(LLVMContextRef, LLVMPassRunListenerRef);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
@ -2759,6 +2774,18 @@ const char *LLVMGetBufferStart(LLVMMemoryBufferRef MemBuf);
|
||||
size_t LLVMGetBufferSize(LLVMMemoryBufferRef MemBuf);
|
||||
void LLVMDisposeMemoryBuffer(LLVMMemoryBufferRef MemBuf);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup LLVMCCorePass Pass
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
const char *LLVMGetPassName(LLVMPassRef);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
@ -21,16 +21,19 @@
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class BasicBlock;
|
||||
class DebugLoc;
|
||||
class DiagnosticInfo;
|
||||
class Function;
|
||||
class Instruction;
|
||||
class LLVMContextImpl;
|
||||
class Module;
|
||||
class Pass;
|
||||
struct PassRunListener;
|
||||
template <typename T> class SmallVectorImpl;
|
||||
class SMDiagnostic;
|
||||
class StringRef;
|
||||
class Twine;
|
||||
class Instruction;
|
||||
class Module;
|
||||
class SMDiagnostic;
|
||||
class DiagnosticInfo;
|
||||
template <typename T> class SmallVectorImpl;
|
||||
class Function;
|
||||
class DebugLoc;
|
||||
|
||||
/// This is an important class for using LLVM in a threaded context. It
|
||||
/// (opaquely) owns and manages the core "global" data of LLVM's core
|
||||
@ -136,6 +139,16 @@ public:
|
||||
void emitOptimizationRemark(const char *PassName, const Function &Fn,
|
||||
const DebugLoc &DLoc, const Twine &Msg);
|
||||
|
||||
/// \brief Notify that we finished running a pass.
|
||||
void notifyPassRun(Pass *P, Module *M, Function *F = nullptr,
|
||||
BasicBlock *BB = nullptr);
|
||||
/// \brief Register the given PassRunListener to receive notifyPassRun()
|
||||
/// callbacks whenever a pass ran. The context will take ownership of the
|
||||
/// listener and free it when the context is destroyed.
|
||||
void addRunListener(PassRunListener *L);
|
||||
/// \brief Unregister a PassRunListener so that it no longer receives
|
||||
/// notifyPassRun() callbacks. Remove and free the listener from the context.
|
||||
void removeRunListener(PassRunListener *L);
|
||||
private:
|
||||
LLVMContext(LLVMContext&) LLVM_DELETED_FUNCTION;
|
||||
void operator=(LLVMContext&) LLVM_DELETED_FUNCTION;
|
||||
|
@ -29,7 +29,9 @@
|
||||
#ifndef LLVM_PASS_H
|
||||
#define LLVM_PASS_H
|
||||
|
||||
#include "llvm/Support/CBindingWrapping.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm-c/Core.h"
|
||||
#include <string>
|
||||
|
||||
namespace llvm {
|
||||
@ -369,6 +371,9 @@ protected:
|
||||
/// @brief This is the storage for the -time-passes option.
|
||||
extern bool TimePassesIsEnabled;
|
||||
|
||||
// Create wrappers for C Binding types (see CBindingWrapping.h).
|
||||
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Pass, LLVMPassRef)
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
// Include support files that contain important APIs commonly used by Passes,
|
||||
|
@ -31,6 +31,7 @@
|
||||
namespace llvm {
|
||||
|
||||
class TargetMachine;
|
||||
class LLVMContext;
|
||||
//===---------------------------------------------------------------------------
|
||||
/// PassInfo class - An instance of this class exists for every pass known by
|
||||
/// the system, and can be obtained from a live Pass by calling its
|
||||
@ -355,6 +356,21 @@ struct PassRegistrationListener {
|
||||
virtual void passEnumerate(const PassInfo *) {}
|
||||
};
|
||||
|
||||
//===---------------------------------------------------------------------------
|
||||
/// PassRunListener class - This class is meant to be derived from by
|
||||
/// clients that are interested in which and when passes are run at runtime.
|
||||
struct PassRunListener {
|
||||
/// PassRunListener ctor - Add the current object to the list of
|
||||
/// PassRunListeners...
|
||||
PassRunListener(LLVMContext *);
|
||||
|
||||
virtual ~PassRunListener();
|
||||
|
||||
/// Callback function - This functions is invoked whenever a pass has run.
|
||||
virtual void passRun(LLVMContext *, Pass *, Module *, Function *,
|
||||
BasicBlock *) {}
|
||||
};
|
||||
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "llvm/IR/IntrinsicInst.h"
|
||||
#include "llvm/IR/LLVMContext.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/PassManager.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
@ -43,6 +44,21 @@ using namespace llvm;
|
||||
|
||||
#define DEBUG_TYPE "ir"
|
||||
|
||||
namespace {
|
||||
struct LLVMPassRunListener : PassRunListener {
|
||||
LLVMPassRunListenerHandlerTy Callback;
|
||||
|
||||
LLVMPassRunListener(LLVMContext *Context, LLVMPassRunListenerHandlerTy Fn)
|
||||
: PassRunListener(Context), Callback(Fn) {}
|
||||
void passRun(LLVMContext *C, Pass *P, Module *M, Function *F,
|
||||
BasicBlock *BB) override {
|
||||
Callback(wrap(C), wrap(P), wrap(M), wrap(F), wrap(BB));
|
||||
}
|
||||
};
|
||||
// Create wrappers for C Binding types (see CBindingWrapping.h).
|
||||
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LLVMPassRunListener, LLVMPassRunListenerRef)
|
||||
} // end anonymous namespace
|
||||
|
||||
void llvm::initializeCore(PassRegistry &Registry) {
|
||||
initializeDominatorTreeWrapperPassPass(Registry);
|
||||
initializePrintModulePassWrapperPass(Registry);
|
||||
@ -133,7 +149,15 @@ LLVMDiagnosticSeverity LLVMGetDiagInfoSeverity(LLVMDiagnosticInfoRef DI){
|
||||
return severity;
|
||||
}
|
||||
|
||||
LLVMPassRunListenerRef LLVMAddPassRunListener(LLVMContextRef Context,
|
||||
LLVMPassRunListenerHandlerTy Fn) {
|
||||
return wrap(new LLVMPassRunListener(unwrap(Context), Fn));
|
||||
}
|
||||
|
||||
void LLVMRemovePassRunListener(LLVMContextRef Context,
|
||||
LLVMPassRunListenerRef Listener) {
|
||||
unwrap(Context)->removeRunListener(unwrap(Listener));
|
||||
}
|
||||
|
||||
|
||||
/*===-- Operations on modules ---------------------------------------------===*/
|
||||
@ -2646,6 +2670,12 @@ void LLVMDisposeMemoryBuffer(LLVMMemoryBufferRef MemBuf) {
|
||||
delete unwrap(MemBuf);
|
||||
}
|
||||
|
||||
/*===-- Pass -------------------------------------------------------------===*/
|
||||
|
||||
const char *LLVMGetPassName(LLVMPassRef P) {
|
||||
return unwrap(P)->getPassName();
|
||||
}
|
||||
|
||||
/*===-- Pass Registry -----------------------------------------------------===*/
|
||||
|
||||
LLVMPassRegistryRef LLVMGetGlobalPassRegistry(void) {
|
||||
|
@ -214,3 +214,23 @@ void LLVMContext::getMDKindNames(SmallVectorImpl<StringRef> &Names) const {
|
||||
E = pImpl->CustomMDKindNames.end(); I != E; ++I)
|
||||
Names[I->second] = I->first();
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Pass Run Listeners
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// Notify that we finished running a pass.
|
||||
void LLVMContext::notifyPassRun(Pass *P, Module *M, Function *F, BasicBlock *BB)
|
||||
{
|
||||
pImpl->notifyPassRun(this, P, M, F, BB);
|
||||
}
|
||||
/// Register the given PassRunListener to receive notifyPassRun() callbacks
|
||||
/// whenever a pass ran. The context will take ownership of the listener and
|
||||
/// free it when the context is destroyed.
|
||||
void LLVMContext::addRunListener(PassRunListener *L) {
|
||||
pImpl->addRunListener(L);
|
||||
}
|
||||
/// Unregister a PassRunListener so that it no longer receives notifyPassRun()
|
||||
/// callbacks. Remove and free the listener from the context.
|
||||
void LLVMContext::removeRunListener(PassRunListener *L) {
|
||||
pImpl->removeRunListener(L);
|
||||
}
|
||||
|
@ -15,11 +15,32 @@
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/IR/Attributes.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/PassSupport.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/Regex.h"
|
||||
#include <algorithm>
|
||||
using namespace llvm;
|
||||
|
||||
/// Notify that we finished running a pass.
|
||||
void LLVMContextImpl::notifyPassRun(LLVMContext *C, Pass *P, Module *M,
|
||||
Function *F, BasicBlock *BB) {
|
||||
for (auto const &L : RunListeners)
|
||||
L->passRun(C, P, M, F, BB);
|
||||
}
|
||||
/// Register the given PassRunListener to receive notifyPassRun()
|
||||
/// callbacks whenever a pass ran.
|
||||
void LLVMContextImpl::addRunListener(PassRunListener *L) {
|
||||
RunListeners.push_back(L);
|
||||
}
|
||||
/// Unregister a PassRunListener so that it no longer receives
|
||||
/// notifyPassRun() callbacks.
|
||||
void LLVMContextImpl::removeRunListener(PassRunListener *L) {
|
||||
auto I = std::find(RunListeners.begin(), RunListeners.end(), L);
|
||||
assert(I != RunListeners.end() && "RunListener not registered!");
|
||||
delete *I;
|
||||
RunListeners.erase(I);
|
||||
}
|
||||
|
||||
LLVMContextImpl::LLVMContextImpl(LLVMContext &C)
|
||||
: TheTrueVal(nullptr), TheFalseVal(nullptr),
|
||||
VoidTy(C, Type::VoidTyID),
|
||||
@ -188,6 +209,11 @@ LLVMContextImpl::~LLVMContextImpl() {
|
||||
|
||||
// Destroy MDStrings.
|
||||
DeleteContainerSeconds(MDStringCache);
|
||||
|
||||
// Destroy all run listeners.
|
||||
for (auto &L : RunListeners)
|
||||
delete L;
|
||||
RunListeners.clear();
|
||||
}
|
||||
|
||||
// ConstantsContext anchors
|
||||
|
@ -40,6 +40,7 @@ class ConstantFP;
|
||||
class LLVMContext;
|
||||
class Type;
|
||||
class Value;
|
||||
struct PassRunListener;
|
||||
|
||||
struct DenseMapAPIntKeyInfo {
|
||||
struct KeyTy {
|
||||
@ -368,13 +369,26 @@ public:
|
||||
typedef DenseMap<const Function *, ReturnInst *> PrefixDataMapTy;
|
||||
PrefixDataMapTy PrefixDataMap;
|
||||
|
||||
/// \brief List of listeners to notify about a pass run.
|
||||
SmallVector<PassRunListener *, 4> RunListeners;
|
||||
|
||||
/// \brief Return true if the given pass name should emit optimization
|
||||
/// remarks.
|
||||
bool optimizationRemarksEnabledFor(const char *PassName) const;
|
||||
|
||||
int getOrAddScopeRecordIdxEntry(MDNode *N, int ExistingIdx);
|
||||
int getOrAddScopeInlinedAtIdxEntry(MDNode *Scope, MDNode *IA,int ExistingIdx);
|
||||
|
||||
|
||||
/// \brief Notify that we finished running a pass.
|
||||
void notifyPassRun(LLVMContext *, Pass *, Module *, Function *, BasicBlock *);
|
||||
/// \brief Register the given PassRunListener to receive notifyPassRun()
|
||||
/// callbacks whenever a pass ran. The context will take ownership of the
|
||||
/// listener and free it when the context is destroyed.
|
||||
void addRunListener(PassRunListener *);
|
||||
/// \brief Unregister a PassRunListener so that it no longer receives
|
||||
/// notifyPassRun() callbacks. Remove and free the listener from the context.
|
||||
void removeRunListener(PassRunListener *);
|
||||
|
||||
LLVMContextImpl(LLVMContext &C);
|
||||
~LLVMContextImpl();
|
||||
};
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "llvm/IR/LegacyPassManager.h"
|
||||
#include "llvm/IR/LegacyPassManagers.h"
|
||||
#include "llvm/IR/LegacyPassNameParser.h"
|
||||
#include "llvm/IR/LLVMContext.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
@ -1313,6 +1314,8 @@ bool BBPassManager::runOnFunction(Function &F) {
|
||||
TimeRegion PassTimer(getPassTimer(BP));
|
||||
|
||||
LocalChanged |= BP->runOnBasicBlock(*I);
|
||||
|
||||
F.getContext().notifyPassRun(BP, F.getParent(), &F, &*I);
|
||||
}
|
||||
|
||||
Changed |= LocalChanged;
|
||||
@ -1551,6 +1554,8 @@ bool FPPassManager::runOnFunction(Function &F) {
|
||||
removeNotPreservedAnalysis(FP);
|
||||
recordAvailableAnalysis(FP);
|
||||
removeDeadPasses(FP, F.getName(), ON_FUNCTION_MSG);
|
||||
|
||||
F.getContext().notifyPassRun(FP, F.getParent(), &F);
|
||||
}
|
||||
return Changed;
|
||||
}
|
||||
@ -1630,6 +1635,8 @@ MPPassManager::runOnModule(Module &M) {
|
||||
removeNotPreservedAnalysis(MP);
|
||||
recordAvailableAnalysis(MP);
|
||||
removeDeadPasses(MP, M.getModuleIdentifier(), ON_MODULE_MSG);
|
||||
|
||||
M.getContext().notifyPassRun(MP, &M);
|
||||
}
|
||||
|
||||
// Finalize module passes
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/IR/IRPrintingPasses.h"
|
||||
#include "llvm/IR/LegacyPassNameParser.h"
|
||||
#include "llvm/IR/LLVMContext.h"
|
||||
#include "llvm/PassRegistry.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
@ -242,6 +243,18 @@ void PassRegistrationListener::enumeratePasses() {
|
||||
PassRegistry::getPassRegistry()->enumerateWith(this);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// PassRunListener implementation
|
||||
//
|
||||
|
||||
// PassRunListener ctor - Add the current object to the list of
|
||||
// PassRunListeners...
|
||||
PassRunListener::PassRunListener(LLVMContext *C) {
|
||||
C->addRunListener(this);
|
||||
}
|
||||
|
||||
PassRunListener::~PassRunListener() {}
|
||||
|
||||
PassNameParser::~PassNameParser() {}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -28,6 +28,7 @@ using namespace llvm;
|
||||
|
||||
static bool didCallAllocateCodeSection;
|
||||
static bool didAllocateCompactUnwindSection;
|
||||
static bool didCallPassRunListener;
|
||||
|
||||
static uint8_t *roundTripAllocateCodeSection(void *object, uintptr_t size,
|
||||
unsigned alignment,
|
||||
@ -64,6 +65,12 @@ static void roundTripDestroy(void *object) {
|
||||
delete static_cast<SectionMemoryManager*>(object);
|
||||
}
|
||||
|
||||
static void passRunListenerCallback(LLVMContextRef C, LLVMPassRef P,
|
||||
LLVMModuleRef M, LLVMValueRef F,
|
||||
LLVMBasicBlockRef BB) {
|
||||
didCallPassRunListener = true;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
// memory manager to test reserve allocation space callback
|
||||
@ -142,6 +149,7 @@ protected:
|
||||
virtual void SetUp() {
|
||||
didCallAllocateCodeSection = false;
|
||||
didAllocateCompactUnwindSection = false;
|
||||
didCallPassRunListener = false;
|
||||
Module = 0;
|
||||
Function = 0;
|
||||
Engine = 0;
|
||||
@ -429,3 +437,23 @@ TEST_F(MCJITCAPITest, reserve_allocation_space) {
|
||||
EXPECT_TRUE(MM->UsedCodeSize > 0);
|
||||
EXPECT_TRUE(MM->UsedDataSizeRW > 0);
|
||||
}
|
||||
|
||||
TEST_F(MCJITCAPITest, pass_run_listener) {
|
||||
SKIP_UNSUPPORTED_PLATFORM;
|
||||
|
||||
buildSimpleFunction();
|
||||
buildMCJITOptions();
|
||||
buildMCJITEngine();
|
||||
LLVMContextRef C = LLVMGetGlobalContext();
|
||||
LLVMAddPassRunListener(C, passRunListenerCallback);
|
||||
buildAndRunPasses();
|
||||
|
||||
union {
|
||||
void *raw;
|
||||
int (*usable)();
|
||||
} functionPointer;
|
||||
functionPointer.raw = LLVMGetPointerToGlobal(Engine, Function);
|
||||
|
||||
EXPECT_EQ(42, functionPointer.usable());
|
||||
EXPECT_TRUE(didCallPassRunListener);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user