llvm-IR 中的 phi 指令语义

phi instruction semantics in llvm-IR

试图理解 llvm-IR 中的 phi 指令语义

(https://llvm.org/docs/LangRef.html#phi-instruction)

让我们考虑以下示例:

 ; Function Attrs: norecurse nounwind
 define i32 @main( i32 %argc, i8** %argv) {
 entry:
   switch  i32 %argc, label %L1 [ i32 0, label %L0
                                  i32 1, label %L1 ]
 L0:
   %x = add i32 %argc, 1
   br label %L1
 L1:
    %y = phi i32 [ %argc, %entry ], [ %x, %L0 ]
    %z = sub i32 %y, 1
   %w = udiv i32 100, %z
   ret i32 %w
 }

用 clang-7.0.1 编译

 $ clang-7.0.1 -O0 test.ll -o a.out
 PHINode should have one entry for each predecessor of its parent basic
 block!
 %y = phi i32 [ %argc, %entry ], [ %x, %L0 ]
 fatal error: error in backend: Broken function found, compilation

中止!

当我用“%y = add i32 2, 1”替换“%y = phi ...”时,测试编译成功。

这里的问题是关于错误信息的: 为什么不是所有的前辈都在测试中列出phi?根据 LangRef.html#phi-instruction 中 phi 指令的描述,我不能 明白了。

当从块A到块B有多个边时,则B中的PHI节点必须列出A的次数与边的数量一样多,每次都具有相同的值。在您的情况下,有从 entryL1 的两条边(一条用于开关的默认情况,一条用于第 1 种情况),因此 entry 需要在 PHI 中列出两次节点。

但在这种情况下,也许更简洁的解决方案是从您的交换机中删除 [i32 1, label %L1] 案例,因为无论如何这是多余的。那么只有一个边缘,你只需要一个条目 entry.