Я думаю о компиляторах и у меня вопрос о том, как они поддерживают древовидный аспект инструкций. В основном инструкции , кажется, образуют дерево.
outer.for.body:
...
%val1 = load i32, i32* %arrayidx3, !llvm.access.group !4
...
br label %inner.for.body
inner.for.body:
...
%val0 = load i32, i32* %arrayidx1, !llvm.access.group !3
...
store i32 %val0, i32* %arrayidx2, !llvm.access.group !3
...
br i1 %exitcond, label %inner.for.end, label %inner.for.body, !llvm.loop !1
inner.for.end:
...
store i32 %val1, i32* %arrayidx4, !llvm.access.group !4
...
br i1 %exitcond, label %outer.for.end, label %outer.for.body, !llvm.loop !2
outer.for.end: ; preds = %for.body
Мне интересно, как это дерево поддерживается, когда у вас есть что-то вроде этого:
function hello() {
foo()
if (x == 0) {
a()
} else {
b()
}
bar()
}
Я бы подумал, что это примерно так (псевдокод):
call %foo
br %xcondition label %a, label %b
call %bar
Но это будет означать, что на самом деле больше нет бинарного дерева, потому что есть 3 ветви:
a()
b()
bar()
Но, тем не менее, вышеприведенное не имеет никакого смысла, потому что bar()
никогда не будет вызван, поскольку он либо a()
, либо b()
, и он прыгает без (я предполагаю) возврата , Вот где мой вопрос. Как выглядит сборка или LLVM IR (или псевдокод) для того, как он может справиться с этим делом.