Towards a minimal compiling example (1): PassContext

Yuanbo LiYuanbo Li
3 min read

What Is PassContext?

A PassContext is a contextual object that exists during the execution of IR passes. It acts as a shared environment to configure and control the behavior of optimization passes without hard-coding logic into each one.

If you’re familiar with TVM or LLVM, you’ll recognize that compiler passes often need to access global or per-run configurations such as:

  • Optimization level (e.g., 0, 1, 2)

  • Debugging flags (e.g., whether to trace each pass)

  • Custom behavior toggles (e.g., enabling/disabling certain transformations)

Rather than pass these settings explicitly through every function, PassContext provides a clean and centralized way to manage them. It’s especially useful in large, modular pipelines where passes are composed dynamically.

IRModule

Previously, my ONNX translator in myTVM directly returned a RelayFunction, which captured the core computational graph but lacked the structural metadata needed for further compiler passes. As part of improving modularity and aligning more closely with TVM’s architecture, I’ve now updated the translator to wrap the RelayFunction inside an IRModule. This allows the function to be registered under a global symbol and provides a unified container for compiler analyses and transformations, making it easier to extend the system with features like module-level passes and function inlining in the future.

using namespace mytvm::relay;
class IRModule {
    public:
    /*! \brief The functions in the module, keyed by function name */
    std::unordered_map<std::string, std::shared_ptr<RelayFunction>> functions;

    IRModule() {}
};
}

Implementing PassContext

  • Originally PassContext is include/tvm/ir/transform.h

class PassContextNode : public Object {
 public:
  /*! \brief The default optimization level. */
  int opt_level{2};

  /*! \brief The list of required passes. */
  Array<String> required_pass;
  /*! \brief The list of disabled passes. */
  Array<String> disabled_pass;
  /*! \brief The diagnostic context. */
  mutable Optional<DiagnosticContext> diag_ctx;
  /*! \brief Pass specific configurations. */
  Map<String, ObjectRef> config;

  /*! \brief A list of pass instrument implementations. */
  Array<instrument::PassInstrument> instruments;
  // TODO(@sunggg): Fix dependency issue in the header file and correct the types
  // e.g., relax::trace, relax::database in tvm/relax/tuning_api.h
  /*! \brief Trace stack for relax pass infra. */
  mutable Array<ObjectRef> trace_stack;
  /*! \brief List of passes to be traced. If not defined, make every pass traceable. */
  Optional<Map<String, Bool>> make_traceable;
  /*! \brief Number of evaluations conducted in the pass pipeline. */
  mutable int num_evals{0};
  /*! \brief Database for tuning API. */
  Optional<ObjectRef> tuning_api_database;
......
}

Breakdown of PassContextNode Fields in Original TVM

  • int opt_level {2}

    • Optimization level for the pass pipeline.

    • Higher levels enable more aggressive optimizations.

  • Array<String> required_pass

    • A list of passes that must be executed, regardless of optimization level.

    • Forces specific passes into the pipeline.

  • Array<String> disabled_pass

    • A list of passes that should be skipped, even if normally included.

    • Useful for debugging or custom pipelines.

  • mutable Optional<DiagnosticContext> diag_ctx

    • Context for diagnostics (e.g., errors, warnings, source locations).

    • mutable allows it to be updated even in a const context.

    • Used to enrich error messages with IR source span info.

  • Map<String, ObjectRef> config

    • A flexible key-value store for pass-specific settings.

    • Allows custom flags or tuning parameters to be passed into passes.

  • Array<instrument::PassInstrument> instruments

    • Instruments to hook into pass execution for logging, profiling, etc.

    • Enables observability without modifying core pass logic.

  • mutable Array<ObjectRef> trace_stack

    • Stack for Relax-specific trace data during pass execution.

    • Records transformation events for replay or introspection.

  • etc……

Let’s first implement the basic ones in our TVM projects such as

  • int opt_level {2}

  • Array<String> required_pass

  • Array<String> disabled_pass

If we need additional functionality, we add others on-the-fly.

0
Subscribe to my newsletter

Read articles from Yuanbo Li directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Yuanbo Li
Yuanbo Li