llvm ir中if-else通过icmp+br实现:icmp生成i1条件值,br i1完成跳转;每个基本块须以ret或br结尾,分支汇聚需用phi节点合并值,漏写终结指令或phi前驱将导致验证失败。

LLVM IR 用 br 指令配合 icmp 实现 if-else 分支,不依赖语法糖,所有分支必须显式跳转到基本块(Basic Block),且每个基本块必须以终结指令(如 ret 或 br)结尾。
条件判断靠 icmp + br i1
icmp 不是“if”,它只做比较并返回 i1(布尔)值;真正的分支由 br i1 %cond, label %then, label %else 完成。漏掉这一步或误用 br label(无条件跳转)会导致控制流断裂。
-
icmp slt i32 %a, %b:有符号小于,C 中a 的等价表示 -
icmp eq i32 %x, 0:等于零,对应 C 中if (x)的真值判断逻辑(非零为真) - 必须用
i1类型变量接icmp结果,不能直接拿整数当条件用 - 若条件结果未被
br i1消费,IR 验证(verifyModule)会报错:"Branch condition must be of type i1"
then 和 else 必须是独立基本块
LLVM IR 不允许在同一个基本块里写“if 分支体 + else 分支体”。每个分支逻辑必须封装在单独的 BasicBlock 中,且这些块必须被函数包含、有明确前驱(preds)关系。
- 错误写法:
br i1 %cond, label %entry, label %entry(跳回同一块,无分支语义) - 正确结构:至少三个块 —— 入口块(含
icmp和br)、then块、else块 - 若某分支没有
ret或后续跳转,会导致“missing terminator”错误 - 使用
IRBuilder时,每次调用SetInsertPoint(BB)后,所有新指令都插入该块,别忘了切换回目标块再写逻辑
返回值处理:LLVM IR 本身不强制要求 if-else 表达式返回值
LLVM IR 是低层表示,if 不是表达式,而是控制流结构。但如果你在构建类 Kaleidoscope 或自定义语言的 codegen,需手动确保两个分支最终产生相同类型值并汇聚(通常用 PHI 节点)。
- 简单函数如
int f(int x) { return x>5 ? 1 : 2; }可分别在then/else块中ret i32 1和ret i32 2 - 若要将结果用于后续计算(比如赋给变量再参与加法),必须引入 PHI 节点:
%result = phi i32 [ 1, %then ], [ 2, %else ] - PHI 节点只能出现在基本块开头,且每个前驱块必须提供一个入边值,顺序和
br中 label 顺序无关,但必须完整覆盖所有前驱 - 忘记加 PHI 或漏掉某个前驱,会导致验证失败或运行时未定义行为
最容易被忽略的是基本块的终结性和 PHI 的完整性——LLVM 不会自动补全控制流出口或合并值,所有跳转路径、所有返回点、所有汇聚点都得手写清楚。哪怕只是调试输出一条 printf,也得确保它所在的基本块以 ret 或 br 结尾,否则 IR 构建直接失败。











