Verify absence of dead code after optimization info collection

Change-Id: I83d044211756ea6265ddbb442c630775665833c3
diff --git a/src/main/java/com/android/tools/r8/ir/code/BasicBlock.java b/src/main/java/com/android/tools/r8/ir/code/BasicBlock.java
index 4c3822a..f4bb790 100644
--- a/src/main/java/com/android/tools/r8/ir/code/BasicBlock.java
+++ b/src/main/java/com/android/tools/r8/ir/code/BasicBlock.java
@@ -527,6 +527,15 @@
     return !phis.isEmpty();
   }
 
+  public boolean hasDeadPhi(AppView<?> appView, IRCode code) {
+    for (Phi phi : phis) {
+      if (phi.isDead(appView, code)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
   public List<Phi> getPhis() {
     return phis;
   }
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java b/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java
index 5c88e60..a16d39d 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java
@@ -46,6 +46,7 @@
 import com.android.tools.r8.ir.code.Value;
 import com.android.tools.r8.ir.code.Xor;
 import com.android.tools.r8.ir.optimize.CodeRewriter;
+import com.android.tools.r8.ir.optimize.DeadCodeRemover;
 import com.android.tools.r8.ir.optimize.PeepholeOptimizer;
 import com.android.tools.r8.ir.optimize.PhiOptimizations;
 import com.android.tools.r8.ir.optimize.peepholes.BasicBlockMuncher;
@@ -127,10 +128,11 @@
     this.code = code;
   }
 
-  public CfCode build() {
+  public CfCode build(DeadCodeRemover deadCodeRemover) {
     computeInitializers();
     TypeVerificationHelper typeVerificationHelper = new TypeVerificationHelper(appView, code);
     typeVerificationHelper.computeVerificationTypes();
+    assert deadCodeRemover.verifyNoDeadCode(code);
     rewriteNots();
     LoadStoreHelper loadStoreHelper = new LoadStoreHelper(appView, code, typeVerificationHelper);
     loadStoreHelper.insertLoadsAndStores();
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
index 3b97428..f7b9ce0 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
@@ -1602,7 +1602,7 @@
   private void finalizeToCf(DexEncodedMethod method, IRCode code, OptimizationFeedback feedback) {
     assert !method.getCode().isDexCode();
     CfBuilder builder = new CfBuilder(appView, method, code);
-    CfCode result = builder.build();
+    CfCode result = builder.build(deadCodeRemover);
     method.setCode(result, appView);
     markProcessed(method, code, feedback);
   }
@@ -1654,6 +1654,7 @@
       IRCode code, DexEncodedMethod method, Timing timing) {
     // Always perform dead code elimination before register allocation. The register allocator
     // does not allow dead code (to make sure that we do not waste registers for unneeded values).
+    assert deadCodeRemover.verifyNoDeadCode(code);
     materializeInstructionBeforeLongOperationsWorkaround(code);
     workaroundForwardingInitializerBug(code);
     timing.begin("Allocate registers");
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
index 8a462f7..55db2fd 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
@@ -1177,12 +1177,13 @@
   }
 
   // Replace result uses for methods where something is known about what is returned.
-  public void rewriteMoveResult(IRCode code) {
+  public boolean rewriteMoveResult(IRCode code) {
     if (options.isGeneratingClassFiles() || !code.metadata().mayHaveInvokeMethod()) {
-      return;
+      return false;
     }
 
     AssumeDynamicTypeRemover assumeDynamicTypeRemover = new AssumeDynamicTypeRemover(appView, code);
+    boolean changed = false;
     boolean mayHaveRemovedTrivialPhi = false;
     Set<Value> affectedValues = Sets.newIdentityHashSet();
     Set<BasicBlock> blocksToBeRemoved = Sets.newIdentityHashSet();
@@ -1218,6 +1219,7 @@
               mayHaveRemovedTrivialPhi |= outValue.numberOfPhiUsers() > 0;
               outValue.replaceUsers(argument);
               invoke.setOutValue(null);
+              changed = true;
             }
           }
         }
@@ -1235,6 +1237,7 @@
       new TypeAnalysis(appView).narrowing(affectedValues);
     }
     assert code.isConsistentSSA();
+    return changed;
   }
 
   enum RemoveCheckCastInstructionIfTrivialResult {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/DeadCodeRemover.java b/src/main/java/com/android/tools/r8/ir/optimize/DeadCodeRemover.java
index f2056d3..ef9c66c 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/DeadCodeRemover.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/DeadCodeRemover.java
@@ -57,6 +57,24 @@
     timing.end();
   }
 
+  public boolean verifyNoDeadCode(IRCode code) {
+    assert !codeRewriter.rewriteMoveResult(code);
+    assert !removeUnneededCatchHandlers(code);
+    for (BasicBlock block : code.blocks) {
+      assert !block.hasDeadPhi(appView, code);
+      for (Instruction instruction : block.getInstructions()) {
+        // No unused move-result instructions.
+        assert !instruction.isInvoke()
+            || !instruction.hasOutValue()
+            || instruction.outValue().hasAnyUsers();
+        // No dead instructions.
+        assert !instruction.canBeDeadCode(appView, code)
+            || (instruction.hasOutValue() && !instruction.outValue().isDead(appView, code));
+      }
+    }
+    return true;
+  }
+
   // Add the block from where the value originates to the worklist.
   private static void updateWorklist(Queue<BasicBlock> worklist, Value value) {
     BasicBlock block = null;
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/staticizer/StaticizingProcessor.java b/src/main/java/com/android/tools/r8/ir/optimize/staticizer/StaticizingProcessor.java
index f68af70..e0ca9093 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/staticizer/StaticizingProcessor.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/staticizer/StaticizingProcessor.java
@@ -305,7 +305,7 @@
     IRCode code = method.buildIR(appView, origin);
     codeOptimizations.forEach(codeOptimization -> codeOptimization.accept(code, methodProcessor));
     CodeRewriter.removeAssumeInstructions(appView, code);
-    converter.finalizeIR(method, code, feedback, Timing.empty());
+    converter.removeDeadCodeAndFinalizeIR(method, code, feedback, Timing.empty());
   }
 
   private void insertAssumeInstructions(IRCode code, MethodProcessor methodProcessor) {