强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

JIT 编译与业务结合实战教程 / 第6章:LLVM JIT

第6章:LLVM JIT

“LLVM 不仅是编译器框架,更是构建 JIT 编译系统的最佳基础设施。”

6.1 LLVM 概述

LLVM(Low Level Virtual Machine)是一个模块化、可重用的编译器和工具链技术集合。它提供了从源代码到机器码的完整编译基础设施,特别适合构建自定义 JIT 编译系统。

6.1.1 LLVM 架构

┌─────────────────────────────────────────────────────────────────┐
│                      LLVM 架构                                   │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  源代码 (C/C++/Rust/自定义语言)                                  │
│       │                                                         │
│       ▼                                                         │
│  ┌─────────────────┐                                            │
│  │   Frontend      │  ← Clang (C/C++), rustc (Rust)            │
│  │  (前端)         │                                            │
│  └──────┬──────────┘                                            │
│         ▼                                                       │
│  ┌─────────────────┐                                            │
│  │  LLVM IR        │  ← 中间表示(文本或二进制)                 │
│  │  (中间层)       │                                            │
│  └──────┬──────────┘                                            │
│         ▼                                                       │
│  ┌─────────────────┐                                            │
│  │  Optimizer      │  ← 多趟优化                               │
│  │  (优化器)       │                                            │
│  └──────┬──────────┘                                            │
│         ▼                                                       │
│  ┌─────────────────┐                                            │
│  │  Backend        │  ← 目标代码生成                           │
│  │  (后端)         │     x86, ARM, RISC-V, WebAssembly        │
│  └─────────────────┘                                            │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

6.1.2 LLVM 的 JIT 演进

2007    LLVM JIT (旧 JIT)
  │
2012    MCJIT 发布
  │     └─ 基于 MC 层的 JIT 引擎
  │
2015    ORC JIT v1
  │     └─ On-Request Compilation
  │
2019    ORC JIT v2
  │     └─ 重设计,更好的延迟编译
  │
2021    LLVM JITLink
        └─ 自定义链接器

6.2 LLVM IR 基础

6.2.1 LLVM IR 的特点

LLVM IR 是一种强类型、低级的、与目标无关的表示形式。

; LLVM IR 文本格式示例

; 定义一个简单的加法函数
define i32 @add(i32 %a, i32 %b) {
entry:
    %result = add i32 %a, %b
    ret i32 %result
}

; 循环示例:计算数组元素之和
define i64 @sum_array(i32* %arr, i64 %len) {
entry:
    %sum = alloca i64
    store i64 0, i64* %sum
    %i = alloca i64
    store i64 0, i64* %i
    br label %loop

loop:
    %i_val = load i64, i64* %i
    %cmp = icmp slt i64 %i_val, %len
    br i1 %cmp, %body, %exit

body:
    %ptr = getelementptr i32, i32* %arr, i64 %i_val
    %val = load i32, i32* %ptr
    %ext = sext i32 %val to i64
    %sum_val = load i64, i64* %sum
    %new_sum = add i64 %sum_val, %ext
    store i64 %new_sum, i64* %sum
    %new_i = add i64 %i_val, 1
    store i64 %new_i, i64* %i
    br label %loop

exit:
    %result = load i64, i64* %sum
    ret i64 %result
}

6.2.2 LLVM IR 类型系统

; 基本类型
; 整数: i1, i8, i16, i32, i64, i128
; 浮点: float, double, fp128

; 示例
define i32 @types_demo() {
    ; 整数常量
    %a = add i32 1, 2
    %b = add i64 1, 2

    ; 浮点常量
    %c = fadd float 1.0, 2.0
    %d = fadd double 1.0, 2.0

    ; 布尔
    %e = and i1 true, false

    ret i32 0
}

; 指针类型
%Point = type { double, double }

define double @distance(%Point* %p) {
    %x_ptr = getelementptr %Point, %Point* %p, i32 0, i32 0
    %y_ptr = getelementptr %Point, %Point* %p, i32 0, i32 1
    %x = load double, double* %x_ptr
    %y = load double, double* %y_ptr
    %x2 = fmul double %x, %x
    %y2 = fmul double %y, %y
    %sum = fadd double %x2, %y2
    %dist = call double @sqrt(double %sum)
    ret double %dist
}

declare double @sqrt(double)

6.2.3 生成 LLVM IR

// 使用 LLVM C++ API 生成 IR
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Verifier.h"

using namespace llvm;

int main() {
    LLVMContext context;
    Module module("my_module", context);
    IRBuilder<> builder(context);

    // 定义函数类型: i32 (i32, i32)
    Type* int32Type = Type::getInt32Ty(context);
    FunctionType* funcType = FunctionType::get(
        int32Type,
        {int32Type, int32Type},
        false
    );

    // 创建函数
    Function* addFunc = Function::Create(
        funcType,
        Function::ExternalLinkage,
        "add",
        module
    );

    // 创建基本块
    BasicBlock* entry = BasicBlock::Create(context, "entry", addFunc);
    builder.SetInsertPoint(entry);

    // 获取参数
    auto args = addFunc->arg_begin();
    Value* a = &*args++;
    Value* b = &*args;

    // 生成加法指令
    Value* sum = builder.CreateAdd(a, b, "sum");
    builder.CreateRet(sum);

    // 验证
    verifyFunction(*addFunc);

    // 输出 IR
    module.print(outs(), nullptr);

    return 0;
}
// 生成循环
Function* createSumLoop(Module& module, LLVMContext& context) {
    IRBuilder<> builder(context);
    Type* int64Type = Type::getInt64Ty(context);
    Type* int32PtrType = Type::getInt32PtrTy(context);

    FunctionType* funcType = FunctionType::get(
        int64Type,
        {int32PtrType, int64Type},
        false
    );

    Function* func = Function::Create(
        funcType,
        Function::ExternalLinkage,
        "sum_array",
        module
    );

    // 基本块
    BasicBlock* entry = BasicBlock::Create(context, "entry", func);
    BasicBlock* loop = BasicBlock::Create(context, "loop", func);
    BasicBlock* body = BasicBlock::Create(context, "body", func);
    BasicBlock* exit = BasicBlock::Create(context, "exit", func);

    // Entry
    builder.SetInsertPoint(entry);
    Value* arr = func->arg_begin();
    Value* len = func->arg_begin() + 1;
    Value* sumAlloca = builder.CreateAlloca(int64Type, nullptr, "sum");
    Value* iAlloca = builder.CreateAlloca(int64Type, nullptr, "i");
    builder.CreateStore(ConstantInt::get(int64Type, 0), sumAlloca);
    builder.CreateStore(ConstantInt::get(int64Type, 0), iAlloca);
    builder.CreateBr(loop);

    // Loop
    builder.SetInsertPoint(loop);
    Value* iVal = builder.CreateLoad(int64Type, iAlloca);
    Value* cmp = builder.CreateICmpSLT(iVal, len);
    builder.CreateCondBr(cmp, body, exit);

    // Body
    builder.SetInsertPoint(body);
    Value* ptr = builder.CreateGEP(Type::getInt32Ty(context), arr, iVal);
    Value* val = builder.CreateLoad(Type::getInt32Ty(context), ptr);
    Value* ext = builder.CreateSExt(val, int64Type);
    Value* sumVal = builder.CreateLoad(int64Type, sumAlloca);
    Value* newSum = builder.CreateAdd(sumVal, ext);
    builder.CreateStore(newSum, sumAlloca);
    Value* newI = builder.CreateAdd(iVal, ConstantInt::get(int64Type, 1));
    builder.CreateStore(newI, iAlloca);
    builder.CreateBr(loop);

    // Exit
    builder.SetInsertPoint(exit);
    Value* result = builder.CreateLoad(int64Type, sumAlloca);
    builder.CreateRet(result);

    return func;
}

6.3 MCJIT

6.3.1 MCJIT 概述

MCJIT 是 LLVM 的第一代正式 JIT 引擎,基于 MC(Machine Code)层实现。

// MCJIT 基本用法
#include "llvm/ExecutionEngine/MCJIT.h"
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
#include "llvm/Support/TargetSelect.h"

int main() {
    // 初始化目标
    InitializeNativeTarget();
    InitializeNativeTargetAsmPrinter();

    LLVMContext context;
    Module module("jit_demo", context);

    // ... 创建 IR ...

    // 创建 MCJIT 执行引擎
    std::string error;
    ExecutionEngine* engine = EngineBuilder(std::move(module))
        .setEngineKind(EngineKind::JIT)
        .setErrorStr(&error)
        .create();

    if (!engine) {
        errs() << "Failed to create engine: " << error << "\n";
        return 1;
    }

    // 获取函数指针
    auto func = (int(*)(int, int))engine->getFunctionAddress("add");
    if (func) {
        int result = func(3, 4);
        outs() << "Result: " << result << "\n";  // 7
    }

    delete engine;
    return 0;
}

6.3.2 MCJIT 的工作流程

┌─────────────────────────────────────────────────────────────────┐
│                    MCJIT 工作流程                                │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  1. LLVM IR                                                     │
│       │                                                         │
│       ▼                                                         │
│  2. 目标代码生成                                                │
│       └─ IR → 汇编代码 (MC 层)                                  │
│       │                                                         │
│       ▼                                                         │
│  3. 目标文件生成                                                │
│       └─ 汇编 → 目标文件 (Object File)                          │
│       │                                                         │
│       ▼                                                         │
│  4. 链接                                                       │
│       └─ 解析符号,重定位                                       │
│       │                                                         │
│       ▼                                                         │
│  5. 执行                                                       │
│       └─ 跳转到机器码执行                                       │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

6.3.3 MCJIT 的局限

局限说明
整模块编译必须编译整个模块
延迟编译有限不支持真正的按需编译
内存管理每个模块需要独立的内存管理器
重编译困难不支持高效的代码更新

6.4 ORC JIT

6.4.1 ORC JIT 概述

ORC(On-Request Compilation)JIT 是 LLVM 的下一代 JIT 框架,解决了 MCJIT 的诸多限制。

// ORC JIT 基本用法 (LLVM 17+)
#include "llvm/ExecutionEngine/Orc/LLJIT.h"
#include "llvm/Support/TargetSelect.h"

using namespace llvm;
using namespace llvm::orc;

int main() {
    InitializeNativeTarget();
    InitializeNativeTargetAsmPrinter();

    // 创建 LLJIT 实例
    auto jit = LLJITBuilder().create();

    if (!jit) {
        errs() << "Failed to create LLJIT: "
               << toString(jit.takeError()) << "\n";
        return 1;
    }

    // 从 IR 文件添加模块
    auto module = parseIRFile("module.ll", err, context);
    if (!module) {
        errs() << "Failed to parse IR\n";
        return 1;
    }

    // 添加到 JIT
    auto threadSafeModule = ThreadSafeModule(
        std::move(module), std::make_unique<LLVMContext>()
    );
    jit->addIRModule(std::move(threadSafeModule));

    // 查找并调用函数
    auto mainSym = jit->lookup("main");
    if (!mainSym) {
        errs() << "Failed to find main\n";
        return 1;
    }

    auto* mainFunc = mainSym->toPtr<int()>();
    int result = mainFunc();
    outs() << "Result: " << result << "\n";

    return 0;
}

6.4.2 ORC JIT v2 架构

┌─────────────────────────────────────────────────────────────────┐
│                     ORC JIT v2 架构                              │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐          │
│  │ Execution    │  │  IR Compile  │  │  Object      │          │
│  │ Session      │──│  Layer       │──│  Layer       │          │
│  └──────────────┘  └──────────────┘  └──────────────┘          │
│         │                                            │          │
│         │              ┌──────────────┐               │          │
│         └──────────────│   JITLink    │───────────────┘          │
│                        │  (Linker)    │                          │
│                        └──────────────┘                          │
│                                                                 │
│  主要组件:                                                       │
│  - ExecutionSession: 管理 JIT 执行上下文                         │
│  - IRCompileLayer: IR → Object 编译                              │
│  - ObjectLinkLayer: Object → 可执行代码                          │
│  - JITLink: 自定义链接器                                         │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

6.4.3 延迟编译

// ORC JIT 延迟编译
#include "llvm/ExecutionEngine/Orc/LLLazyJIT.h"

using namespace llvm::orc;

// 创建懒加载 JIT
auto jit = LLLazyJITBuilder().create();

// 添加模块(不立即编译)
jit->addLazyIRModule(std::move(module));

// 只有在实际调用时才编译
auto sym = jit->lookup("expensive_function");
// ← 此时才触发编译

6.4.4 模块重编译

// ORC JIT 支持代码更新
class JITRecompiler {
    std::unique_ptr<LLJIT> jit;
    ResourceTrackerSP tracker;

public:
    void compileAndRun(const std::string& code) {
        // 如果已有代码,移除旧模块
        if (tracker) {
            tracker->remove();
        }

        // 编译新代码
        auto module = compileCode(code);
        tracker = jit->getMainJITDylib().createResourceTracker();
        jit->addIRModule(
            ThreadSafeModule(std::move(module), makeContext()),
            tracker
        );

        // 执行
        auto mainSym = jit->lookup("main");
        auto* mainFunc = mainSym->toPtr<int()>();
        mainFunc();
    }
};

6.5 自定义编译器示例

6.5.1 构建简单语言 JIT

// 完整的表达式语言 JIT
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/ExecutionEngine/Orc/LLJIT.h"
#include <map>
#include <string>

class ExpressionJIT {
    LLVMContext context;
    std::unique_ptr<Module> module;
    IRBuilder<> builder;
    std::unique_ptr<orc::LLJIT> jit;
    std::map<std::string, Value*> namedValues;

public:
    ExpressionJIT() : builder(context) {
        module = std::make_unique<Module>("expr_jit", context);

        // 初始化 JIT
        auto jitOrErr = orc::LLJITBuilder().create();
        if (!jitOrErr) {
            errs() << "Failed to create JIT\n";
            exit(1);
        }
        jit = std::move(*jitOrErr);
    }

    // 编译表达式
    double evaluate(const std::string& expr) {
        // 解析表达式
        auto ast = parse(expr);

        // 生成 IR
        Function* func = codegen(ast);

        // 添加到 JIT
        module->setDataLayout(jit->getDataLayout());
        auto tsm = orc::ThreadSafeModule(
            std::move(module), std::make_unique<LLVMContext>()
        );
        jit->addIRModule(std::move(tsm));

        // 创建新模块用于后续编译
        module = std::make_unique<Module>("expr_jit", context);

        // 查找并执行
        auto sym = jit->lookup("__anon_expr");
        if (!sym) {
            errs() << "Failed to find function\n";
            return 0;
        }

        auto* funcPtr = sym->toPtr<double()>();
        return funcPtr();
    }

private:
    Function* codegen(ASTNode* node) {
        // 创建函数
        FunctionType* funcType = FunctionType::get(
            builder.getDoubleTy(), {}, false
        );
        Function* func = Function::Create(
            funcType, Function::ExternalLinkage,
            "__anon_expr", module.get()
        );

        BasicBlock* entry = BasicBlock::Create(context, "entry", func);
        builder.SetInsertPoint(entry);

        // 生成表达式代码
        Value* val = codegenExpr(node);
        builder.CreateRet(val);

        verifyFunction(*func);
        return func;
    }

    Value* codegenExpr(ASTNode* node) {
        switch (node->type) {
            case NodeType::Number:
                return ConstantFP::get(context, APFloat(node->value));

            case NodeType::BinaryOp:
                Value* L = codegenExpr(node->left);
                Value* R = codegenExpr(node->right);
                switch (node->op) {
                    case '+': return builder.CreateFAdd(L, R, "addtmp");
                    case '-': return builder.CreateFSub(L, R, "subtmp");
                    case '*': return builder.CreateFMul(L, R, "multmp");
                    case '/': return builder.CreateFDiv(L, R, "divtmp");
                }
        }
        return nullptr;
    }
};

// 使用
int main() {
    ExpressionJIT jit;

    std::cout << jit.evaluate("3 + 4 * 2") << std::endl;     // 11
    std::cout << jit.evaluate("(3 + 4) * 2") << std::endl;    // 14
    std::cout << jit.evaluate("sin(3.14)") << std::endl;      // ~0

    return 0;
}

6.5.2 LLVM JIT 优化管线配置

// 配置优化管线
#include "llvm/Passes/PassBuilder.h"

FunctionPassManager createOptPipeline() {
    FunctionPassManager FPM;

    // 添加优化 Pass
    FPM.addPass(InstCombinePass());        // 指令合并
    FPM.addPass(ReassociatePass());        // 重新关联
    FPM.addPass(GVNPass());                // 全局值编号
    FPM.addPass(SimplifyCFGPass());        // 简化 CFG
    FPM.addPass(LoopSimplifyPass());       // 循环简化
    FPM.addPass(LoopVectorizePass());      // 循环向量化
    FPM.addPass(LoopUnrollPass());         // 循环展开

    return FPM;
}

ModulePassManager createModulePipeline() {
    ModulePassManager MPM;

    // 函数 Pass
    FunctionPassManager FPM = createOptPipeline();
    MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));

    // 模块级 Pass
    MPM.addPass(GlobalDCEPass());          // 死全局消除
    MPM.addPass(ConstantMergePass());      // 常量合并

    return MPM;
}

6.6 DSL 编译

6.6.1 什么是 DSL

DSL(Domain Specific Language,领域特定语言)是为特定问题域设计的专用语言。LLVM JIT 非常适合为 DSL 构建编译器。

6.6.2 数学表达式 DSL

// 数学 DSL JIT 编译器
class MathDSLJIT {
    // AST 节点
    struct Expr {
        enum Type { Num, Var, BinOp, Call } type;
        double value;           // Num
        std::string name;       // Var, Call
        char op;                // BinOp
        std::vector<std::unique_ptr<Expr>> args;
    };

    LLVMContext ctx;
    IRBuilder<> builder;
    std::unique_ptr<Module> module;

public:
    // 编译数学函数
    // DSL 输入: "fn f(x) = x * x + 2 * x + 1"
    // 输出: 可调用的机器码函数
    void* compileFunction(const std::string& name,
                          const std::vector<std::string>& params,
                          Expr* body) {
        module = std::make_unique<Module>(name, ctx);
        IRBuilder<> builder(ctx);

        // 创建函数类型
        std::vector<Type*> paramTypes(params.size(),
                                       builder.getDoubleTy());
        FunctionType* funcType = FunctionType::get(
            builder.getDoubleTy(), paramTypes, false
        );

        Function* func = Function::Create(
            funcType, Function::ExternalLinkage, name, module.get()
        );

        // 设置参数名
        std::map<std::string, Value*> namedValues;
        size_t i = 0;
        for (auto& arg : func->args()) {
            arg.setName(params[i]);
            namedValues[params[i]] = &arg;
            i++;
        }

        // 生成函数体
        BasicBlock* entry = BasicBlock::Create(ctx, "entry", func);
        builder.SetInsertPoint(entry);
        Value* retVal = codegen(body, namedValues);
        builder.CreateRet(retVal);

        // 编译并返回函数指针
        return compileModule(func);
    }

private:
    Value* codegen(Expr* expr, std::map<std::string, Value*>& vars) {
        switch (expr->type) {
            case Expr::Num:
                return ConstantFP::get(ctx, APFloat(expr->value));

            case Expr::Var:
                if (vars.count(expr->name))
                    return vars[expr->name];
                return nullptr;

            case Expr::BinOp: {
                Value* L = codegen(expr->args[0].get(), vars);
                Value* R = codegen(expr->args[1].get(), vars);
                switch (expr->op) {
                    case '+': return builder.CreateFAdd(L, R);
                    case '-': return builder.CreateFSub(L, R);
                    case '*': return builder.CreateFMul(L, R);
                    case '/': return builder.CreateFDiv(L, R);
                    case '^':
                        // 内联 pow 的特殊情况
                        if (auto* c = dyn_cast<ConstantFP>(R)) {
                            if (c->getValue().convertToDouble() == 2.0)
                                return builder.CreateFMul(L, L);
                        }
                        return createPowCall(L, R);
                }
            }

            case Expr::Call:
                if (expr->name == "sin") {
                    Value* arg = codegen(expr->args[0].get(), vars);
                    return builder.CreateCall(getIntrinsic(Intrinsic::sin), {arg});
                }
                if (expr->name == "cos") {
                    Value* arg = codegen(expr->args[0].get(), vars);
                    return builder.CreateCall(getIntrinsic(Intrinsic::cos), {arg});
                }
        }
        return nullptr;
    }
};

6.6.3 SQL DSL 编译

// 简化的 SQL WHERE 子句编译
// DSL: "age > 18 AND city = 'Beijing'"

struct Row {
    int age;
    std::string city;
    double salary;
};

class SQLFilterJIT {
    LLVMContext ctx;
    IRBuilder<> builder;

    // 编译 SQL 表达式为过滤函数
    using FilterFunc = bool(*)(const Row*);

    FilterFunc compileFilter(const std::string& sqlWhere) {
        auto module = std::make_unique<Module>("sql_filter", ctx);

        // 解析 SQL WHERE 子句
        auto ast = parseSQLWhere(sqlWhere);

        // 创建 Row 结构体类型
        StructType* rowType = createRowType();

        // 创建过滤函数
        FunctionType* funcType = FunctionType::get(
            builder.getInt1Ty(),
            {PointerType::getUnqual(rowType)},
            false
        );

        Function* func = Function::Create(
            funcType, Function::ExternalLinkage,
            "filter", module.get()
        );

        // 生成过滤逻辑
        BasicBlock* entry = BasicBlock::Create(ctx, "entry", func);
        builder.SetInsertPoint(entry);

        Value* row = func->arg_begin();
        Value* result = codegenSQLExpr(ast, row);
        builder.CreateRet(result);

        // 编译
        return (FilterFunc)compileModule(func);
    }

    Value* codegenSQLExpr(SQLExpr* expr, Value* row) {
        switch (expr->type) {
            case SQLExpr::Compare: {
                Value* field = loadField(row, expr->field);
                Value* value = createConstant(expr->value);
                return builder.CreateICmpSGT(field, value);  // >
            }
            case SQLExpr::And: {
                Value* left = codegenSQLExpr(expr->left, row);
                Value* right = codegenSQLExpr(expr->right, row);
                return builder.CreateAnd(left, right);
            }
            case SQLExpr::Or: {
                Value* left = codegenSQLExpr(expr->left, row);
                Value* right = codegenSQLExpr(expr->right, row);
                return builder.CreateOr(left, right);
            }
        }
        return nullptr;
    }
};

6.7 性能优化技术

6.7.1 LLVM 优化 Pass

// 常用 LLVM 优化 Pass
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Vectorize.h"
#include "llvm/Transforms/IPO.h"

// 内联优化
FPM.addPass(InlinePass());

// 循环优化
FPM.addPass(LoopRotatePass());         // 循环旋转
FPM.addPass(LoopStrengthReducePass()); // 循环强度削减
FPM.addPass(IndVarSimplifyPass());     // 归纳变量简化

// 向量化
FPM.addPass(SLPVectorizerPass());      // SLP 向量化
FPM.addPass(LoopVectorizePass());      // 循环向量化

// 窥孔优化
FPM.addPass(PeepholePass());           // 窥孔优化
FPM.addPass(DivRemPairsPass());        // 除法/取余对优化

6.7.2 自定义优化 Pass

// 自定义优化 Pass 示例
struct MyCustomPass : public PassInfoMixin<MyCustomPass> {
    PreservedAnalyses run(Function& F, FunctionAnalysisManager& AM) {
        bool changed = false;

        for (auto& BB : F) {
            for (auto& I : BB) {
                // 检测特定模式并优化
                if (auto* mul = dyn_cast<BinaryOperator>(&I)) {
                    if (mul->getOpcode() == Instruction::Mul) {
                        // 优化乘以 2 为左移
                        if (isPowerOf2(getConstantValue(mul->getOperand(1)))) {
                            IRBuilder<> builder(mul);
                            int shift = log2(getConstantValue(mul->getOperand(1)));
                            Value* shifted = builder.CreateShl(
                                mul->getOperand(0),
                                ConstantInt::get(builder.getInt32Ty(), shift)
                            );
                            mul->replaceAllUsesWith(shifted);
                            changed = true;
                        }
                    }
                }
            }
        }

        return changed ? PreservedAnalyses::none() : PreservedAnalyses::all();
    }
};

// 注册到管线
FPM.addPass(MyCustomPass());

6.8 适用场景

6.8.1 LLVM JIT 的最佳场景

┌─────────────────────────────────────────────────────────────────┐
│                 LLVM JIT 最佳应用场景                            │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  1. 自定义编程语言                                              │
│     └─ 构建新的编程语言编译器                                   │
│                                                                 │
│  2. DSL 编译器                                                  │
│     └─ 数学 DSL、SQL DSL、配置 DSL                              │
│                                                                 │
│  3. 科学计算                                                    │
│     └─ 数值计算、矩阵运算、物理模拟                             │
│                                                                 │
│  4. 代码生成工具                                                │
│     └─ 模板引擎、ORM 查询生成                                   │
│                                                                 │
│  5. 硬件仿真                                                    │
│     └─ CPU 仿真、GPU 计算                                       │
│                                                                 │
│  6. 数据库查询                                                  │
│     └─ 查询计划编译、表达式求值                                 │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

6.8.2 数据库查询编译示例

// ClickHouse 风格的查询编译
// 将 SQL 查询编译为高效的机器码

// 原始 SQL:
// SELECT count(*), avg(price) FROM orders
// WHERE status = 'completed' AND date > '2024-01-01'
// GROUP BY category

// 编译为机器码函数
void* compileQuery(const Query& query) {
    // 1. 解析查询计划
    auto plan = analyzeQuery(query);

    // 2. 生成 LLVM IR
    auto func = generateIR(plan);

    // 3. 应用优化
    optimizeFunction(func);

    // 4. JIT 编译
    return jit.compile(func);
}

6.9 本章小结

关键要点

  1. LLVM 提供完整的编译基础设施:从前端到后端的完整工具链
  2. MCJIT 是稳定的 JIT 引擎:适合整模块编译
  3. ORC JIT 是下一代框架:支持延迟编译和代码更新
  4. 非常适合构建自定义编译器:DSL、领域特定语言
  5. 强大的优化能力:数十种优化 Pass 可组合使用

选择建议

  • 构建新语言编译器 → LLVM ORC JIT
  • 简单的表达式编译 → LLVM IR API
  • 数据库查询优化 → 查询编译
  • 科学计算 DSL → LLVM + 自定义前端

6.10 扩展阅读


上一章: 第5章 - GraalVM 下一章: 第7章 - Java HotSpot