семантика фи-инструкции в llvm-IR - PullRequest
1 голос
/ 13 марта 2019

Попытка понять семантику фи-команд в llvm-IR

(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 = phi ...» на «% y = add i32 2, 1», тест был успешно скомпилирован.

Вопрос здесь об ошибке: почему не все предшественники перечислены в Фи в тесте? Из описания фи-инструкции в LangRef.html # phi-инструкция я не могу понять это.

1 Ответ

0 голосов
/ 13 марта 2019

Если имеется множество ребер из блока A в блок B, узлы PHI в B должны перечислять A столько раз, сколько существует ребер, каждый раз с одним и тем же значением. В вашем случае есть два ребра от entry до L1 (один для случая коммутатора по умолчанию и один для случая 1), поэтому entry должен быть указан дважды в узле PHI.

Но, возможно, более чистым решением в этом случае было бы просто снять корпус [i32 1, label %L1] с коммутатора, поскольку в любом случае это избыточно. Тогда будет только один край, и вам понадобится только одна запись для entry.

...