You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

LLVM Loop Vectorizer未矢量化自定义IR,求解决方法

如何让LoopVectorizer成功矢量化手动生成的LLVM IR循环?

我用IRBuilder生成了LLVM IR代码,尝试用LoopVectorizer对其中的循环进行矢量化,但没能成功。以下是ModulePassManager运行后的LLVM IR代码:

; Function Attrs: argmemonly nofree norecurse nosync nounwind
define void @batch_function_0(ptr nocapture readonly %parameters, ptr nocapture readnone %series, ptr nocapture %state_vars, ptr nocapture readnone %solver_workspace, ptr nocapture readnone %date_time, double %fractional_step) local_unnamed_addr #1 {
entry:
  br label %loop

loop:                                             ; preds = %loop, %entry
  %index = phi i64 [ 0, %entry ], [ %next_iter, %loop ]
  %subtemp = add nuw nsw i64 %index, -100
  %var_ptr = getelementptr double, ptr %state_vars, i64 %subtemp
  %var = load double, ptr %var_ptr, align 8
  %addtemp = add nuw nsw i64 %index, 2
  %par_ptr = getelementptr double, ptr %parameters, i64 %addtemp
  %par = load double, ptr %par_ptr, align 8
  %fmultemp = fmul fast double %par, %var
  %var_ptr1 = getelementptr double, ptr %state_vars, i64 %index
  store double %fmultemp, ptr %var_ptr1, align 8
  %next_iter = add nuw nsw i64 %index, 1
  %loopcond.not = icmp eq i64 %next_iter, 100
  br i1 %loopcond.not, label %afterloop, label %loop

afterloop:                                        ; preds = %loop
  ret void
}

我的优化Pass配置如下:

llvm::LoopAnalysisManager     lam;
llvm::FunctionAnalysisManager fam;
llvm::CGSCCAnalysisManager    cgam;
llvm::ModuleAnalysisManager   mam;

llvm::PassBuilder pb;

pb.registerModuleAnalyses(mam);
pb.registerCGSCCAnalyses(cgam);
pb.registerFunctionAnalyses(fam);
pb.registerLoopAnalyses(lam);
pb.crossRegisterProxies(lam, fam, cgam, mam);

llvm::ModulePassManager mpm = pb.buildPerModuleDefaultPipeline(llvm::OptimizationLevel::O2);

mpm.addPass(llvm::createModuleToFunctionPassAdaptor(llvm::LoopVectorizePass()));

mpm.run(*data->module, mam);

对应的等价C代码如下(该代码用Clang -O2编译时可被矢量化,我并非从C生成原始IR):

void
testfun(double *state_var, double *par) {
    for(int i = 0; i < 100; ++i) {
        state_var[i] = state_var[i-100]*par[i+2];
    }
}

解决方案

  • 调整Pass执行顺序:默认O2优化流水线已经包含LoopVectorizePass,你在其后重复添加可能导致Pass执行时机不对。可以尝试移除手动添加的LoopVectorizePass,直接依赖默认O2流水线;或者手动构建Pass序列,确保LoopVectorizer在循环简化、别名分析等前置优化之后运行。

  • 解决内存访问的别名与对齐问题:

    • 给state_vars和parameters指针添加noalias属性,明确告知编译器两个指针指向的内存区域无重叠,消除存储-加载的依赖顾虑。
    • 确保内存访问对齐,比如给state_vars和parameters添加align 64(适配多数平台的向量宽度)属性,矢量化要求内存访问符合向量对齐标准。
  • 优化循环终止条件的形式:将当前的终止条件icmp eq i64 %next_iter, 100改为更符合LoopVectorizer预期的icmp slt i64 %index, 100,调整后的循环结构更贴近常见的循环模式,便于矢量化分析。

  • 明确反向内存访问的安全性:循环中state_var[i-100]的反向访问可能让LoopVectorizer产生顾虑,可通过添加llvm::AssumeInst来告知编译器该访问是安全的,不存在越界或未定义行为;或者确保state_vars指针指向的内存区域包含i-100对应的偏移位置。

  • 强制启用矢量化(用于测试):创建LoopVectorizePass时启用强制矢量化选项,验证是否是启发式判断导致的不矢量化:

    mpm.addPass(llvm::createModuleToFunctionPassAdaptor(
        llvm::LoopVectorizePass(llvm::LoopVectorizeOptions().setForce(true))));
    

内容的提问来源于stack exchange,提问作者Magnus Dahler Norling

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 12:23:21