The static single assignment (SSA) representation of code is almost but not quite canonical; there are two flavors, vanilla and edge-split in which extra nodes are inserted as necessary to cause every loop to have only one back edge. Rationale: adding the edge-split constraint makes certain optimizations slightly easier.
What I really want to know is whether the edge-split constraint is overall worth having, but that's a judgment call, so for a concrete factual question:
Do the following well-known compilers, which use SSA, use the edge-split constraint?
From investigation thus far:
This suggests LLVM uses edge-split: http://llvm.org/doxygen/LoopSimplify_8cpp.html#a209bb6a782608a71aa8ec5075970caa3
Go likewise: https://golang.org/src/cmd/compile/internal/ssa/critical.go