llvm.org GIT mirror llvm / 4e0cc51
[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 Juergen Ributzka 5 years ago
11 changed file(s) with 208 addition(s) and 9 deletion(s). Raw diff Collapse all Expand all
2020
2121 namespace llvm {
2222
23 class BasicBlock;
24 class DebugLoc;
25 class DiagnosticInfo;
26 class Function;
27 class Instruction;
2328 class LLVMContextImpl;
29 class Module;
30 class Pass;
31 struct PassRunListener;
32 template class SmallVectorImpl;
33 class SMDiagnostic;
2434 class StringRef;
2535 class Twine;
26 class Instruction;
27 class Module;
28 class SMDiagnostic;
29 class DiagnosticInfo;
30 template class SmallVectorImpl;
31 class Function;
32 class DebugLoc;
3336
3437 /// This is an important class for using LLVM in a threaded context. It
3538 /// (opaquely) owns and manages the core "global" data of LLVM's core
135138 void emitOptimizationRemark(const char *PassName, const Function &Fn,
136139 const DebugLoc &DLoc, const Twine &Msg);
137140
141 /// \brief Notify that we finished running a pass.
142 void notifyPassRun(Pass *P, Module *M, Function *F = nullptr,
143 BasicBlock *BB = nullptr);
144 /// \brief Register the given PassRunListener to receive notifyPassRun()
145 /// callbacks whenever a pass ran. The context will take ownership of the
146 /// listener and free it when the context is destroyed.
147 void addRunListener(PassRunListener *L);
148 /// \brief Unregister a PassRunListener so that it no longer receives
149 /// notifyPassRun() callbacks. Remove and free the listener from the context.
150 void removeRunListener(PassRunListener *L);
138151 private:
139152 LLVMContext(LLVMContext&) LLVM_DELETED_FUNCTION;
140153 void operator=(LLVMContext&) LLVM_DELETED_FUNCTION;
2828 #ifndef LLVM_PASS_H
2929 #define LLVM_PASS_H
3030
31 #include "llvm/Support/CBindingWrapping.h"
3132 #include "llvm/Support/Compiler.h"
33 #include "llvm-c/Core.h"
3234 #include
3335
3436 namespace llvm {
368370 /// @brief This is the storage for the -time-passes option.
369371 extern bool TimePassesIsEnabled;
370372
373 // Create wrappers for C Binding types (see CBindingWrapping.h).
374 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Pass, LLVMPassRef)
375
371376 } // End llvm namespace
372377
373378 // Include support files that contain important APIs commonly used by Passes,
3030 namespace llvm {
3131
3232 class TargetMachine;
33 class LLVMContext;
3334 //===---------------------------------------------------------------------------
3435 /// PassInfo class - An instance of this class exists for every pass known by
3536 /// the system, and can be obtained from a live Pass by calling its
354355 virtual void passEnumerate(const PassInfo *) {}
355356 };
356357
358 //===---------------------------------------------------------------------------
359 /// PassRunListener class - This class is meant to be derived from by
360 /// clients that are interested in which and when passes are run at runtime.
361 struct PassRunListener {
362 /// PassRunListener ctor - Add the current object to the list of
363 /// PassRunListeners...
364 PassRunListener(LLVMContext *);
365
366 virtual ~PassRunListener();
367
368 /// Callback function - This functions is invoked whenever a pass has run.
369 virtual void passRun(LLVMContext *, Pass *, Module *, Function *,
370 BasicBlock *) {}
371 };
372
357373
358374 } // End llvm namespace
359375
111111 */
112112 typedef struct LLVMOpaqueModuleProvider *LLVMModuleProviderRef;
113113
114 /** @see llvm::Pass */
115 typedef struct LLVMOpaquePass *LLVMPassRef;
116
114117 /** @see llvm::PassManagerBase */
115118 typedef struct LLVMOpaquePassManager *LLVMPassManagerRef;
116119
117120 /** @see llvm::PassRegistry */
118121 typedef struct LLVMOpaquePassRegistry *LLVMPassRegistryRef;
122
123 /** @see llvm::PassRunListener */
124 typedef struct LLVMOpaquePassRunListener *LLVMPassRunListenerRef;
125
126 /** @see llvm::LLVMPassRunListener */
127 typedef void (*LLVMPassRunListenerHandlerTy)(LLVMContextRef, LLVMPassRef,
128 LLVMModuleRef, LLVMValueRef,
129 LLVMBasicBlockRef);
119130
120131 /**
121132 * Used to get the users and usees of a Value.
513524 unsigned LLVMGetMDKindIDInContext(LLVMContextRef C, const char* Name,
514525 unsigned SLen);
515526 unsigned LLVMGetMDKindID(const char* Name, unsigned SLen);
527
528 LLVMPassRunListenerRef LLVMAddPassRunListener(LLVMContextRef,
529 LLVMPassRunListenerHandlerTy);
530 void LLVMRemovePassRunListener(LLVMContextRef, LLVMPassRunListenerRef);
516531
517532 /**
518533 * @}
27632778 */
27642779
27652780 /**
2781 * @defgroup LLVMCCorePass Pass
2782 *
2783 * @{
2784 */
2785
2786 const char *LLVMGetPassName(LLVMPassRef);
2787
2788 /**
2789 * @}
2790 */
2791
2792 /**
27662793 * @defgroup LLVMCCorePassRegistry Pass Registry
27672794 *
27682795 * @{
2626 #include "llvm/IR/IntrinsicInst.h"
2727 #include "llvm/IR/LLVMContext.h"
2828 #include "llvm/IR/Module.h"
29 #include "llvm/Pass.h"
2930 #include "llvm/PassManager.h"
3031 #include "llvm/Support/Debug.h"
3132 #include "llvm/Support/ErrorHandling.h"
4142 using namespace llvm;
4243
4344 #define DEBUG_TYPE "ir"
45
46 namespace {
47 struct LLVMPassRunListener : PassRunListener {
48 LLVMPassRunListenerHandlerTy Callback;
49
50 LLVMPassRunListener(LLVMContext *Context, LLVMPassRunListenerHandlerTy Fn)
51 : PassRunListener(Context), Callback(Fn) {}
52 void passRun(LLVMContext *C, Pass *P, Module *M, Function *F,
53 BasicBlock *BB) override {
54 Callback(wrap(C), wrap(P), wrap(M), wrap(F), wrap(BB));
55 }
56 };
57 // Create wrappers for C Binding types (see CBindingWrapping.h).
58 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LLVMPassRunListener, LLVMPassRunListenerRef)
59 } // end anonymous namespace
4460
4561 void llvm::initializeCore(PassRegistry &Registry) {
4662 initializeDominatorTreeWrapperPassPass(Registry);
132148 return severity;
133149 }
134150
135
151 LLVMPassRunListenerRef LLVMAddPassRunListener(LLVMContextRef Context,
152 LLVMPassRunListenerHandlerTy Fn) {
153 return wrap(new LLVMPassRunListener(unwrap(Context), Fn));
154 }
155
156 void LLVMRemovePassRunListener(LLVMContextRef Context,
157 LLVMPassRunListenerRef Listener) {
158 unwrap(Context)->removeRunListener(unwrap(Listener));
159 }
136160
137161
138162 /*===-- Operations on modules ---------------------------------------------===*/
26452669 delete unwrap(MemBuf);
26462670 }
26472671
2672 /*===-- Pass -------------------------------------------------------------===*/
2673
2674 const char *LLVMGetPassName(LLVMPassRef P) {
2675 return unwrap(P)->getPassName();
2676 }
2677
26482678 /*===-- Pass Registry -----------------------------------------------------===*/
26492679
26502680 LLVMPassRegistryRef LLVMGetGlobalPassRegistry(void) {
213213 E = pImpl->CustomMDKindNames.end(); I != E; ++I)
214214 Names[I->second] = I->first();
215215 }
216
217 //===----------------------------------------------------------------------===//
218 // Pass Run Listeners
219 //===----------------------------------------------------------------------===//
220 /// Notify that we finished running a pass.
221 void LLVMContext::notifyPassRun(Pass *P, Module *M, Function *F, BasicBlock *BB)
222 {
223 pImpl->notifyPassRun(this, P, M, F, BB);
224 }
225 /// Register the given PassRunListener to receive notifyPassRun() callbacks
226 /// whenever a pass ran. The context will take ownership of the listener and
227 /// free it when the context is destroyed.
228 void LLVMContext::addRunListener(PassRunListener *L) {
229 pImpl->addRunListener(L);
230 }
231 /// Unregister a PassRunListener so that it no longer receives notifyPassRun()
232 /// callbacks. Remove and free the listener from the context.
233 void LLVMContext::removeRunListener(PassRunListener *L) {
234 pImpl->removeRunListener(L);
235 }
1414 #include "llvm/ADT/STLExtras.h"
1515 #include "llvm/IR/Attributes.h"
1616 #include "llvm/IR/Module.h"
17 #include "llvm/PassSupport.h"
1718 #include "llvm/Support/CommandLine.h"
1819 #include "llvm/Support/Regex.h"
1920 #include
2021 using namespace llvm;
22
23 /// Notify that we finished running a pass.
24 void LLVMContextImpl::notifyPassRun(LLVMContext *C, Pass *P, Module *M,
25 Function *F, BasicBlock *BB) {
26 for (auto const &L : RunListeners)
27 L->passRun(C, P, M, F, BB);
28 }
29 /// Register the given PassRunListener to receive notifyPassRun()
30 /// callbacks whenever a pass ran.
31 void LLVMContextImpl::addRunListener(PassRunListener *L) {
32 RunListeners.push_back(L);
33 }
34 /// Unregister a PassRunListener so that it no longer receives
35 /// notifyPassRun() callbacks.
36 void LLVMContextImpl::removeRunListener(PassRunListener *L) {
37 auto I = std::find(RunListeners.begin(), RunListeners.end(), L);
38 assert(I != RunListeners.end() && "RunListener not registered!");
39 delete *I;
40 RunListeners.erase(I);
41 }
2142
2243 LLVMContextImpl::LLVMContextImpl(LLVMContext &C)
2344 : TheTrueVal(nullptr), TheFalseVal(nullptr),
187208
188209 // Destroy MDStrings.
189210 DeleteContainerSeconds(MDStringCache);
211
212 // Destroy all run listeners.
213 for (auto &L : RunListeners)
214 delete L;
215 RunListeners.clear();
190216 }
191217
192218 // ConstantsContext anchors
3939 class LLVMContext;
4040 class Type;
4141 class Value;
42 struct PassRunListener;
4243
4344 struct DenseMapAPIntKeyInfo {
4445 struct KeyTy {
367368 typedef DenseMap PrefixDataMapTy;
368369 PrefixDataMapTy PrefixDataMap;
369370
371 /// \brief List of listeners to notify about a pass run.
372 SmallVector RunListeners;
373
370374 /// \brief Return true if the given pass name should emit optimization
371375 /// remarks.
372376 bool optimizationRemarksEnabledFor(const char *PassName) const;
373377
374378 int getOrAddScopeRecordIdxEntry(MDNode *N, int ExistingIdx);
375379 int getOrAddScopeInlinedAtIdxEntry(MDNode *Scope, MDNode *IA,int ExistingIdx);
376
380
381 /// \brief Notify that we finished running a pass.
382 void notifyPassRun(LLVMContext *, Pass *, Module *, Function *, BasicBlock *);
383 /// \brief Register the given PassRunListener to receive notifyPassRun()
384 /// callbacks whenever a pass ran. The context will take ownership of the
385 /// listener and free it when the context is destroyed.
386 void addRunListener(PassRunListener *);
387 /// \brief Unregister a PassRunListener so that it no longer receives
388 /// notifyPassRun() callbacks. Remove and free the listener from the context.
389 void removeRunListener(PassRunListener *);
390
377391 LLVMContextImpl(LLVMContext &C);
378392 ~LLVMContextImpl();
379393 };
1515 #include "llvm/IR/LegacyPassManager.h"
1616 #include "llvm/IR/LegacyPassManagers.h"
1717 #include "llvm/IR/LegacyPassNameParser.h"
18 #include "llvm/IR/LLVMContext.h"
1819 #include "llvm/IR/Module.h"
1920 #include "llvm/Support/CommandLine.h"
2021 #include "llvm/Support/Debug.h"
13121313 TimeRegion PassTimer(getPassTimer(BP));
13131314
13141315 LocalChanged |= BP->runOnBasicBlock(*I);
1316
1317 F.getContext().notifyPassRun(BP, F.getParent(), &F, &*I);
13151318 }
13161319
13171320 Changed |= LocalChanged;
15501553 removeNotPreservedAnalysis(FP);
15511554 recordAvailableAnalysis(FP);
15521555 removeDeadPasses(FP, F.getName(), ON_FUNCTION_MSG);
1556
1557 F.getContext().notifyPassRun(FP, F.getParent(), &F);
15531558 }
15541559 return Changed;
15551560 }
16291634 removeNotPreservedAnalysis(MP);
16301635 recordAvailableAnalysis(MP);
16311636 removeDeadPasses(MP, M.getModuleIdentifier(), ON_MODULE_MSG);
1637
1638 M.getContext().notifyPassRun(MP, &M);
16321639 }
16331640
16341641 // Finalize module passes
1616 #include "llvm/IR/Function.h"
1717 #include "llvm/IR/IRPrintingPasses.h"
1818 #include "llvm/IR/LegacyPassNameParser.h"
19 #include "llvm/IR/LLVMContext.h"
1920 #include "llvm/PassRegistry.h"
2021 #include "llvm/Support/Debug.h"
2122 #include "llvm/Support/raw_ostream.h"
241242 PassRegistry::getPassRegistry()->enumerateWith(this);
242243 }
243244
245 //===----------------------------------------------------------------------===//
246 // PassRunListener implementation
247 //
248
249 // PassRunListener ctor - Add the current object to the list of
250 // PassRunListeners...
251 PassRunListener::PassRunListener(LLVMContext *C) {
252 C->addRunListener(this);
253 }
254
255 PassRunListener::~PassRunListener() {}
256
244257 PassNameParser::~PassNameParser() {}
245258
246259 //===----------------------------------------------------------------------===//
2727
2828 static bool didCallAllocateCodeSection;
2929 static bool didAllocateCompactUnwindSection;
30 static bool didCallPassRunListener;
3031
3132 static uint8_t *roundTripAllocateCodeSection(void *object, uintptr_t size,
3233 unsigned alignment,
6162
6263 static void roundTripDestroy(void *object) {
6364 delete static_cast(object);
65 }
66
67 static void passRunListenerCallback(LLVMContextRef C, LLVMPassRef P,
68 LLVMModuleRef M, LLVMValueRef F,
69 LLVMBasicBlockRef BB) {
70 didCallPassRunListener = true;
6471 }
6572
6673 namespace {
141148 virtual void SetUp() {
142149 didCallAllocateCodeSection = false;
143150 didAllocateCompactUnwindSection = false;
151 didCallPassRunListener = false;
144152 Module = 0;
145153 Function = 0;
146154 Engine = 0;
428436 EXPECT_TRUE(MM->UsedCodeSize > 0);
429437 EXPECT_TRUE(MM->UsedDataSizeRW > 0);
430438 }
439
440 TEST_F(MCJITCAPITest, pass_run_listener) {
441 SKIP_UNSUPPORTED_PLATFORM;
442
443 buildSimpleFunction();
444 buildMCJITOptions();
445 buildMCJITEngine();
446 LLVMContextRef C = LLVMGetGlobalContext();
447 LLVMAddPassRunListener(C, passRunListenerCallback);
448 buildAndRunPasses();
449
450 union {
451 void *raw;
452 int (*usable)();
453 } functionPointer;
454 functionPointer.raw = LLVMGetPointerToGlobal(Engine, Function);
455
456 EXPECT_EQ(42, functionPointer.usable());
457 EXPECT_TRUE(didCallPassRunListener);
458 }