llvmllvm-irssa

LLVM IR phi node with only one possible predecessor


What is the benefit of using a phi node when there is only one possible predecessor? For example, when I run opt -loop-<some specific pass> some-cool-file.ll -S, the output will frequently include a phi node with only one possible predecessor if I haven't already added one.

Example:

endcond.loopexit:                      ; preds = %loop <- note: one predecessor
  %res.lcssa = phi i64 [ %res, %loop ] ; I'm assuming this is from the
  br label %endcond                    ; loop-closed ssa form pass

endcond:
  %var = phi i64 [ %res.lcssa, %endcond.loopexit ], <other-pred>

If there is only one possible predecessor shouldn't the above be exactly the same as

endcond.loopexit:                      ; preds = %loop 
  br label %endcond                    ; res assigned a value in %loop

endcond:
  %var = phi i64 [ %res, %endcond.loopexit ], <other-pred> ; use %res directly

Don't get me wrong, I'm a huge fan of phi nodes, but I was just curious if there were any other benefits besides improving readability and warnings when adding a phi node when there is only one possible predecessor.


Solution

  • Absolutely, you're right that the two are equivalent. However, the former loop is in LCSSA (loop closed SSA) form. This form provides some very useful guarantees which simplify many loop optimisations.

    This isn't specific to LLVM, GCC does this as well. They have a nice summary of the concrete benefits of LCSSA form: https://gcc.gnu.org/onlinedocs/gccint/LCSSA.html

    During a typical compilation pass pipeline the LCSSA PHI nodes will be removed after loop optimisations by the InstCombine pass. (If you run opt with -instcombine after all your loop optimisations, you'll get the output you expected.)