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;