如何从LLVM IR提取目标无关Selection DAG信息?llc命令报错求解
关于LLVM Selection DAG提取与llc调试报错的问题
背景信息
我通过clang -S -emit-llvm demo.c生成了LLVM IR,其中demo.c的代码为:
int demo(int a, int b){ int c = a+b; return c; }
对应的IR如下:
define dso_local i32 @demo(i32 %0, i32 %1) #0 { %3 = alloca i32, align 4 %4 = alloca i32, align 4 %5 = alloca i32, align 4 store i32 %0, i32* %3, align 4 store i32 %1, i32* %4, align 4 %6 = load i32, i32* %3, align 4 %7 = load i32, i32* %4, align 4 %8 = add nsw i32 %6, %7 store i32 %8, i32* %5, align 4 %9 = load i32, i32* %5, align 4 ret i32 %9 }
核心问题与解决方案
1. 提取目标无关Selection DAG信息的方法
LLVM中目标无关的Selection DAG是由SelectionDAGBuilder从LLVM IR转换而来的初始DAG,尚未进行目标相关的Lowering处理。获取该阶段信息的方式有两种:
- 使用llc调试选项:确保LLVM为Debug构建,执行
llc -debug-only=isel -fast-isel=false foo.ll,日志会输出初始DAG的构建过程与节点信息;若要可视化,需先安装Graphviz并在构建LLVM时启用LLVM_ENABLE_GRAPHVIZ=ON,再执行llc -view-dag-combine1-dags -fast-isel=false -mtriple=<目标架构> foo.ll,会弹出DAG图形窗口。 - 修改LLVM源码:在
SelectionDAGBuilder.cpp的关键节点(如visitInstruction方法)添加打印或导出逻辑,直接输出目标无关DAG的节点类型、操作数等信息。
2. 是否需要自行编写Selection DAG?实现方式
针对自定义流水线,不需要从头编写目标无关Selection DAG——LLVM的SelectionDAGBuilder已完成从IR到目标无关DAG的转换。若需扩展或定制:
- 若要添加自定义目标无关SDNode:定义新的SDNode子类,在
SelectionDAGBuilder中处理自定义IR指令,生成对应的SDNode并加入DAG。 - 若要适配自定义流水线的目标相关逻辑:需在目标后端的
TargetLowering子类中,添加目标相关的DAG Lowering规则,将通用SDNode转换为自定义流水线支持的节点或指令。
3. llc调试命令报错的解决建议
针对llc -fast-isel=false -view-dag-combine1-dags foo.ll与llc -debug foo.ll的报错,可按以下步骤排查:
- 确认使用自建llc:执行
./build/bin/llc --version,避免调用系统自带的不兼容版本。 - 补全依赖:
-view-dag系列选项需要Graphviz支持,需安装Graphviz(如apt install graphviz或brew install graphviz),并在cmake构建LLVM时添加-DLLVM_ENABLE_GRAPHVIZ=ON。 - 重新全量构建:确保执行
cmake -DCMAKE_BUILD_TYPE=Debug -DLLVM_ENABLE_GRAPHVIZ=ON ..后,用cmake --build . -j$(nproc)完成全编译,避免组件缺失。 - 指定目标架构:部分报错因默认目标架构不兼容,可添加
-mtriple=x86_64-pc-linux-gnu(或对应平台triple)明确目标架构。
内容的提问来源于stack exchange,提问作者pralay das
相关产品推荐
相关产品推荐

