[llvm-dev] RFC: Pass Execution Instrumentation interface

Fedor Sergeev via llvm-dev llvm-dev at lists.llvm.org
Wed Jun 6 17:00:01 PDT 2018


TL;DR
====

This RFC suggests an API to enable customizable instrumentation of pass 
execution.
The intent is to have a common machinery to implement all the 
pass-execution-debugging
features mentioned here.

Prime target of the interface is the new pass manager.
The overall approach and most of the implementation details should be 
equially applicable
to the legacy one though.


Background
==========

There are quite a few important debugging facilities in LLVM that affect
pass execution sequence:

    -print-after/-print-before[-all]
        execute IR-print pass before or after a particularly 
insteresting pass
        (or all passes)

    -verify-each
        execute verifier pass after each

    -opt-bisect-limit
        execute passes only up to a selected "pass-counter"

    -time-passes
        track execution time for each pass

There are also quite a few similar ideas floating around, i.e:
    -git-commit-after-all
    -debugify-each

All these facilities essentially require instrumentation of pass 
execution points
in the pass manager, each being implemented in a legacy pass manager 
through their
own custom way, e.g:
   * -time-passes has a bunch of dedicated code in each of the pass managers

   * -print-before/after/verify-each insert additional passes before/after
     the passes in the pipeline

And there is no implementation of any of these features for the new pass 
manager,
which obviously is a problem for new pass manager transition.

Proposal
========

Main idea:
   - introduce an API that allows to instrument points of pass execution
   - access through LLVM Context (allows to control life-time and scope 
in multi-context execution)
   - wrap it into an analysis for easier access from pass managers


Details:
   1. introduce llvm::PassInstrumentation

      This is the main interface that handles the customization and 
provides instrumentation calls

      - resides in IR
      - is accessible through LLVMContext::getPassInstrumentation()
        (with context owning this object).

   2. every single point of Pass execution in the (new) PassManager(s) 
will query
      this analysis and run instrumentation call specific to a 
particular point.

      Instrumentation points:

         bool BeforePass (PassID, PassExecutionCounter);
         void AfterPass (PassID, PassExecutionCounter);

          Run before/after a particular pass execution
              BeforePass instrumentation call returns true if this 
execution is allowed to run.

             'PassID'
                  certain unique identifier for a pass (pass name?).

             'PassExecutionCounter'
                  a number that uniquely identifies this particular pass 
execution
                  in current pipeline, as tracked by Pass Manager.

         void StartPipeline()
         void EndPipeline()

          Run at the start/end of a pass pipeline execution.
          (useful for initialization/finalization purposes)


   3. custom callbacks are registered with 
PassInstrumentation::register* interfaces

      A sequence of registered callbacks is called at each 
instrumentation point as appropriate.

   4. introduce llvm::ExecutionCounter to track execution of passes

      (akin to DebugCounter, yet enabled in Release mode as well?)

      Note: it is somewhat nontrivial to uniquely track pass executions 
with counters in new pass
      manager as its pipeline schedule can be dynamic. Ideas are welcome 
on how to efficiently
      implement unique execution tracking that does not break in 
presence of fixed-point iteration
      passes like RepeatedPass/DevirtSCCRepeatedPass

      Also, the intent is for execution counters to be able provide 
thread-safety in multi-threaded
      pipeline execution (though no work planned for it yet).

   5. introduce a new analysis llvm::PassInstrumentationAnalysis

      This is a convenience wrapper to provide an access to 
PassInstrumentation via analysis framework.
      If using analysis is not convenient (?legacy) then 
PassInstrumentation can be queried
      directly from LLVMContext.


Additional goals
================

   - layering problem
     Currently OptBisect/OptPassGate has layering issue - interface 
dependencies on all the "IR units",
     even those that are analyses - Loop, CallGraphSCC.

     Generic PassInstrumentation facilitiy allows to inject arbitrary 
call-backs in run-time,
     removing any compile-time interface dependencies on internals of 
those callbacks,
     effectively solving this layering issue.

   - life-time/scope control for multi-context execution

     Currently there are issues with multi-context execution of, say, 
-time-passes which store
     their data in global maps.

     With LLVMContext owning PassInstrumentation there should be no 
problem with multi-context execution
     (callbacks can be made owning the instrumentation data).

Open Questions
==============

   - whats the best way to handle ownership of PassInstrumentation

     Any problems with owning by LLVMContext?
     Something similar to TargetLibraryInfo (owned by 
TargetLibraryAnalysis/TargetLibraryInfoWrapperPass)?

   - using PassInstrumentationAnalysis or directly querying LLVMContext

     PassInstrumentationAnalysis appeared to be a nice idea, only until 
I tried querying it
     in new pass manager framework, and amount of hooplas to jump over 
makes me shiver a bit...

     Querying LLVMContext is plain and straightforward, but we do not 
have a generic way to access LLVMContext
     from a PassManager template (need to introduce generic 
IRUnit::getContext?)

Implementation
==============

PassInstrumentationAnalysis proof-of-concept unfinished prototype 
implementation:
(Heavily under construction, do not enter without wearing a hard hat...)

    https://reviews.llvm.org/D47858



More information about the llvm-dev mailing list