Subzero: Prune unreachable nodes after constructing the Cfg.
The gcc torture test suite has examples where there is a function call (to a routine that throws an exception or aborts or something), followed by an "unreachable" instruction, followed by more code that may e.g. return a value to the caller. In these examples, the code following the unreachable is itself unreachable.
Problems arise when the unreachable code references a variable defined in the reachable code. This triggers a liveness consistency error because the use of the variable has no reaching definition.
It's a bit surprising that LLVM actually allows this, but it does so we need to deal with it.
The solution is, after initial CFG construction, do a traversal starting from the entry node and then delete any undiscovered nodes.
There is code in Subzero that assumes Cfg::Nodes[i]->Number == i, so the nodes need to be renumbered after pruning. The alternative was to set Nodes[i]=nullptr and not change the node number, but that would mean peppering the code base with CfgNode null checks.
BUG= none
R=jvoung@chromium.org
Review URL: https://codereview.chromium.org/1027933002
diff --git a/src/IceCfgNode.cpp b/src/IceCfgNode.cpp
index 02b9aac..b5e9d86 100644
--- a/src/IceCfgNode.cpp
+++ b/src/IceCfgNode.cpp
@@ -69,11 +69,14 @@
// constructed, the computePredecessors() pass finalizes it by
// creating the InEdges list.
void CfgNode::computePredecessors() {
- OutEdges = Insts.rbegin()->getTerminatorEdges();
for (CfgNode *Succ : OutEdges)
Succ->InEdges.push_back(this);
}
+void CfgNode::computeSuccessors() {
+ OutEdges = Insts.rbegin()->getTerminatorEdges();
+}
+
// This does part 1 of Phi lowering, by creating a new dest variable
// for each Phi instruction, replacing the Phi instruction's dest with
// that variable, and adding an explicit assignment of the old dest to
@@ -605,19 +608,21 @@
// entry.
bool IsEntry = (Func->getEntryNode() == this);
if (!(IsEntry || Live == LiveOrig)) {
- // This is a fatal liveness consistency error. Print some
- // diagnostics and abort.
- Ostream &Str = Func->getContext()->getStrDump();
- Func->resetCurrentNode();
- Str << "LiveOrig-Live =";
- for (SizeT i = Live.size(); i < LiveOrig.size(); ++i) {
- if (LiveOrig.test(i)) {
- Str << " ";
- Liveness->getVariable(i, this)->dump(Func);
+ if (ALLOW_DUMP) {
+ // This is a fatal liveness consistency error. Print some
+ // diagnostics and abort.
+ Ostream &Str = Func->getContext()->getStrDump();
+ Func->resetCurrentNode();
+ Str << "LiveOrig-Live =";
+ for (SizeT i = Live.size(); i < LiveOrig.size(); ++i) {
+ if (LiveOrig.test(i)) {
+ Str << " ";
+ Liveness->getVariable(i, this)->dump(Func);
+ }
}
+ Str << "\n";
}
- Str << "\n";
- llvm_unreachable("Fatal inconsistency in liveness analysis");
+ llvm::report_fatal_error("Fatal inconsistency in liveness analysis");
}
bool Changed = false;