VLLM 中的module PASS 和FUN PASS

LLVM Module Pass 与 Function Pass 详解

一、核心区别与作用范围

特性 Module Pass Function Pass
作用粒度 作用于整个编译单元(Module),可访问模块内所有函数、全局变量、元数据等 [[4]] 作用于单个函数(Function),仅能访问当前函数的IR结构 [[2]]
执行顺序 在整个Module级别执行一次 对Module中的每个函数独立执行一次 [[2]]
依赖关系 可请求并使用Function Pass的分析结果(通过getAnalysis接口) [[35]] 不能依赖Module Pass(Legacy PM中存在此限制) [[6]]
行为特性 具有全局视角,可进行跨函数优化、内联决策、全局符号分析等 具有局部可预测性,系统可预期其行为仅影响当前函数 [[2]]

二、典型应用场景

Module Pass 适用场景:

  • 全局优化:函数内联(需分析调用图)、死函数消除
  • 链接时优化(LTO):跨编译单元的符号合并与优化
  • 全局变量初始化分析、模块级元数据处理
  • 构建和维护全局数据结构(如调用图CallGraph)

Function Pass 适用场景:

  • 函数内优化:常量传播、死代码消除、指令组合
  • 基本块级分析:支配树(DominatorTree)、循环识别
  • 局部寄存器分配前的指令调度
  • 函数内特定模式匹配与转换

三、Pass 实现与注册(New Pass Manager)

LLVM 11+ 推荐使用 New Pass Manager(优化管线默认采用),其核心改进是分离Pass与Analysis,支持更灵活的pipeline组合 [[18]]。

1. Function Pass 实现示例
cpp 复制代码
#include "llvm/Passes/PassBuilder.h"
#include "llvm/Passes/PassPlugin.h"

namespace {

struct HelloFunctionPass : public llvm::PassInfoMixin<HelloFunctionPass> {
  llvm::PreservedAnalyses run(llvm::Function &F,
                              llvm::FunctionAnalysisManager &AM) {
    llvm::errs() << "Hello from function: " << F.getName() << "\n";
    return llvm::PreservedAnalyses::none(); // 表示未保留任何分析结果
  }
};

// 静态注册(用于opt工具)
llvm::PassPluginLibraryInfo getHelloFunctionPassPluginInfo() {
  return {
    LLVM_PLUGIN_API_VERSION, "HelloFunctionPass", LLVM_VERSION_STRING,
    [](llvm::PassBuilder &PB) {
      // 注册到默认优化管线的EarlyCSE阶段后
      PB.registerPipelineParsingCallback(
        [](llvm::StringRef Name, llvm::FunctionPassManager &FPM,
           llvm::ArrayRef<llvm::PassBuilder::PipelineElement>) {
          if (Name == "hello-function") {
            FPM.addPass(HelloFunctionPass());
            return true;
          }
          return false;
        });
    }
  };
}

} // namespace

extern "C" LLVM_ATTRIBUTE_WEAK ::llvm::PassPluginLibraryInfo
llvmGetPassPluginInfo() {
  return getHelloFunctionPassPluginInfo();
}
2. Module Pass 实现示例
cpp 复制代码
struct HelloModulePass : public llvm::PassInfoMixin<HelloModulePass> {
  llvm::PreservedAnalyses run(llvm::Module &M,
                              llvm::ModuleAnalysisManager &AM) {
    llvm::errs() << "Module: " << M.getName() << " has " 
                 << M.size() << " functions\n";
    
    // 可在Module Pass中请求Function级分析
    auto &FAM = AM.getResult<llvm::FunctionAnalysisManagerModuleProxy>(M).getManager();
    for (auto &F : M) {
      if (!F.isDeclaration()) {
        auto &DT = FAM.getResult<llvm::DominatorTreeAnalysis>(F);
        // 使用支配树分析...
      }
    }
    return llvm::PreservedAnalyses::none();
  }
};

四、Pipeline 注册机制

1. 命令行使用(opt工具)
bash 复制代码
# 运行Function Pass(自动包装在ModulePassManager中)
opt -passes='hello-function' input.ll -o output.ll

# 混合Module Pass与Function Pass
# 注意:Function Pass需用module作用域包装
opt -passes='no-op-module,function(hello-function),no-op-module' input.ll

# 显式使用module adaptor包装Function Pass
opt -passes='module(function(hello-function))' input.ll
2. Pipeline 构建层次结构

New Pass Manager 的IR层次为:Module → (CGSCC) → Function → Loop [[31]]

cpp 复制代码
// C++代码中构建pipeline
llvm::PassBuilder PB;
llvm::ModulePassManager MPM;

// 添加Module Pass
MPM.addPass(HelloModulePass());

// 添加Function Pass序列(自动创建FunctionPassManager)
MPM.addPass(llvm::createModuleToFunctionPassAdaptor(
  llvm::FunctionPassManager(
    HelloFunctionPass(),
    AnotherFunctionPass()
  )
));

// 运行pipeline
llvm::ModuleAnalysisManager MAM;
MPM.run(*M, MAM);
3. 注册到Clang默认优化管线
cpp 复制代码
PB.registerOptimizerLastEPCallback(
  [](llvm::ModulePassManager &MPM, llvm::OptimizationLevel Level) {
    if (Level.getSpeedupLevel() >= 2) {
      MPM.addPass(HelloModulePass());
    }
  });

PB.registerPeepholeEPCallback(
  [](llvm::FunctionPassManager &FPM, llvm::OptimizationLevel Level) {
    FPM.addPass(HelloFunctionPass());
  });

五、Legacy Pass Manager 对比(已逐步淘汰)

Legacy PM 使用虚函数接口,注册方式不同:

cpp 复制代码
// Legacy Function Pass
struct LegacyHelloPass : public llvm::FunctionPass {
  static char ID;
  LegacyHelloPass() : FunctionPass(ID) {}
  bool runOnFunction(llvm::Function &F) override {
    llvm::errs() << "Hello: " << F.getName() << "\n";
    return false; // 未修改IR
  }
};
char LegacyHelloPass::ID = 0;
static llvm::RegisterPass<LegacyHelloPass> X("hello", "Hello Pass");

// 使用:opt -load libHello.so -hello input.bc

重要提示:LLVM 16+ 已全面转向New Pass Manager,建议新开发直接采用New PM。代码生成后端(CodeGen)目前仍部分使用Legacy PM [[17]]。

六、关键设计原则

  1. 作用域隔离:Function Pass不应产生跨函数副作用,保证可并行执行
  2. 分析复用:通过AnalysisManager避免重复计算(如多次请求DominatorTree)
  3. Pipeline组合:Module Pass可包含嵌套的FunctionPassManager,实现层次化优化
  4. PreservedAnalyses:精确声明保留的分析结果,避免不必要的重新计算

此设计使LLVM能够灵活组合不同粒度的优化,在保证正确性的同时最大化编译性能。

在使用FUN PASS的时候,如果涉及到整个module 的更改,应将其转换为module PASS

相关推荐
hhzz16 小时前
云服务器ECS的高可用部署方案----弹性公网IP和负载均衡的操作
服务器·tcp/ip·负载均衡·ecs·云服务器
饮长安千年月16 小时前
一带一路暨金砖国家技能发展与技术创新大赛网络安全防护与治理-Linux应急响应手册
linux·运维·web安全·ctf·应急响应
SmartBrain16 小时前
技术总结:VLLM部署Qwen3模型的详解
开发语言·人工智能·算法·vllm
济61716 小时前
ARM Linux 驱动开发篇--- 设备树下的 LED 驱动实验-- Ubuntu20.04
linux·嵌入式·嵌入式linux驱动开发
济61716 小时前
ARM Linux 驱动开发篇---Linux 设备树之查找节点的 OF 函数-- Ubuntu20.04
linux·嵌入式·嵌入式linux驱动开发
奇特認16 小时前
LVS(Linux virual server)四层负载均衡实验
linux·运维·lvs
cyber_两只龙宝16 小时前
Keepalived+LVS--实现IPVS的高可用+高性能的双主双业务架构详细配置流程及解析
linux·运维·集群·lvs·高性能·keepalived·高可用
吕司16 小时前
Linux——System V 共享内存
linux·运维·服务器
陈 洪 伟16 小时前
大模型推理引擎vLLM(10): vLLM 分布式推理源码结构解析
分布式·vllm
芥子沫16 小时前
Windows 命令行和 Linux 差在哪里?
linux·命令行