It is invalid to hoist stores or loads if they are not executed on all paths
from the hoisting point to the exit of the function. In the testcase, there are
paths in the loop that do not execute the stores or the loads, and so hoisting
them within the loop is unsafe.
The problem is that the current implementation of hoistingFromAllPaths is
incomplete: it walks all blocks dominated by the hoisting point, and does not
return false when the loop contains a path on which the hoisted ld/st is
not executed.
How is this different than just checking whether one of the successors is a loop backedge?
(and if so, why not just compute and store that set once :P)
If it's different, how is this not basically a dominance frontier check?
dominance frontier of BB = blocks where BB's dominance ends.
So this is a check if any of the blocks are in the dominance frontier of BB, no?