There is a piece of logic in GuardWidening which is very limited, and it happens
to ignore implicit control flow, therefore it "works fine" with guards expressed as
intrinsic calls. However, when the guards are represented as branches, its limitations
create a lot of trouble.
The intent here is to make sure that we do not widen code across complex CFG,
so that it can end up being in hotter code than it used to be. The old logic was limited
to unique immediate successor and that's it.
This patch changes the logic there to work the following way: when we need to check
if we can widen from DominatedBlock into DominatingBlock, we first try to find the
lowest (by CFG) transitive successor of DominatingBlock which is guaranteed to not
be significantly colder than the DominatingBlock. It means that every time we move
to either:
- Unique successor of the current block, if it only has one successor;
- The only taken successor, if the current block ends with br(const);
- If one of successors ends with deopt, another one is taken;
If the lowest block we can find this way is the DominatedBlock, then it is safe to assume
that this widening won't move the code into a hotter location.
I did not touch the existing check with PDT. It looks fishy to me (post-dominance doesn't
really guarantee anything about hotness), but let's keep it as is and maybe fix later.
With this patch, Guard Widening can widen explicitly expressed branches across more than one
dominating guard if it's profitable.
Crazy compile time heuristic. I guess that IfFalse terminates with deopt is more likely. So just re-order them.