Commit 6f7ad6c2 by Jim Stichnoth

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 .
parent 57ec7dfe
......@@ -257,6 +257,14 @@ void Cfg::renumberInstructions() {
NextInstNumber = Inst::NumberInitial;
for (CfgNode *Node : Nodes)
Node->renumberInstructions();
// Make sure the entry node is the first node and therefore got the lowest
// instruction numbers, to facilitate live range computation of function
// arguments. We want to model function arguments as being live on entry to
// the function, otherwise an argument whose only use is in the first
// instruction will be assigned a trivial live range and the register
// allocator will not recognize its live range as overlapping another
// variable's live range.
assert(Nodes.empty() || (*Nodes.begin() == getEntryNode()));
}
// placePhiLoads() must be called before placePhiStores().
......@@ -839,14 +847,19 @@ void Cfg::liveness(LivenessMode Mode) {
// instruction of the method is "r=arg1+arg2", both args may be assigned
// the same register. This is accomplished by extending the entry block's
// instruction range from [2,n) to [1,n) which will transform the
// problematic [2,2) live ranges into [1,2).
// problematic [2,2) live ranges into [1,2). This extension works because
// the entry node is guaranteed to have the lowest instruction numbers.
if (Node == getEntryNode()) {
// TODO(stichnot): Make it a strict requirement that the entry node
// gets the lowest instruction numbers, so that extending the live
// range for in-args is guaranteed to work.
FirstInstNum = Inst::NumberExtended;
// Just in case the entry node somehow contains no instructions...
if (LastInstNum == Inst::NumberSentinel)
LastInstNum = FirstInstNum;
}
Node->livenessAddIntervals(getLiveness(), FirstInstNum, LastInstNum);
// If this node somehow contains no instructions, don't bother trying to
// add liveness intervals for it, because variables that are live-in and
// live-out will have a bogus interval added.
if (FirstInstNum != Inst::NumberSentinel)
Node->livenessAddIntervals(getLiveness(), FirstInstNum, LastInstNum);
}
}
}
......
......@@ -852,10 +852,16 @@ void CfgNode::contractIfEmpty() {
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();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment