Subzero: Make optimizations more resilient for early Target development.
A good trick for implementing lowering for a new target is, for not-yet-implemented instructions, to insert a FakeUse of each instruction variable followed by a FakeDef of the dest variable. Otherwise one risks running afoul of liveness analysis integrity checks.
However, if all the high-level instructions in a basic block lack variables (e.g. unconditional branches, or void calls with only constant arguments), the resulting block may be completely empty. In O2 mode, this triggers a couple of assertions/errors that wouldn't normally occur:
1. CfgNode::contractIfEmpty() finds a block with a single out-edge that does *not* end with an unconditional branch.
2. CfgNode::livenessAddIntervals() tries to add a bogus liveness interval to a variable because the empty block contains no actual instruction numbers to form a valid interval from.
This adds some fixes/workarounds for those problems.
Another workaround for the empty basic block problem may be to just to add a FakeUse of the stack pointer when lowering an unconditional branch, which combined with the trick above, should prevent empty blocks. However, these fixes seem reasonable apart from that.
BUG= none
R=sehr@chromium.org
Review URL: https://codereview.chromium.org/1590303002 .
diff --git a/src/IceCfgNode.cpp b/src/IceCfgNode.cpp
index 9e3f23a..f06e631 100644
--- a/src/IceCfgNode.cpp
+++ b/src/IceCfgNode.cpp
@@ -852,10 +852,16 @@
else if (!I.isRedundantAssign())
return;
}
+ // Make sure there is actually a successor to repoint in-edges to.
+ if (OutEdges.empty())
+ return;
assert(OutEdges.size() == 1);
// Don't try to delete a self-loop.
if (OutEdges[0] == this)
return;
+ // Make sure the node actually contains (ends with) an unconditional branch.
+ if (Branch == nullptr)
+ return;
Branch->setDeleted();
CfgNode *Successor = OutEdges.front();