Correctly delete all uses when building up the domination graph

We now consider the edge case where the dead instruction we wanted to
remove was used in a phi which is not directly following the block
we are processing right now. To fix this, we process all blocks
before trying to remove the instructions.

As a note, we remove catch phi uses right before removing the
instruction as they are related to the instruction itself and not
the block hierarchy.

Test: art/test/testrunner/testrunner.py --host --64 --optimizing -b
Test: dex2oat compiling locally the apps mentioned in the bug
Bug: 239519319
Change-Id: I70d47891203ae118851a1f20a7cee21de305cd61
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc
index cb07d2e..19731ae 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -150,17 +150,22 @@
   RemoveEnvironmentUses(instruction);
 }
 
-void HGraph::RemoveInstructionsAsUsersFromDeadBlocks(const ArenaBitVector& visited) const {
+void HGraph::RemoveDeadBlocksInstructionsAsUsersAndDisconnect(const ArenaBitVector& visited) const {
   for (size_t i = 0; i < blocks_.size(); ++i) {
     if (!visited.IsBitSet(i)) {
       HBasicBlock* block = blocks_[i];
       if (block == nullptr) continue;
+
+      // Remove as user.
       for (HInstructionIterator it(block->GetPhis()); !it.Done(); it.Advance()) {
         RemoveAsUser(it.Current());
       }
       for (HInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) {
         RemoveAsUser(it.Current());
       }
+
+      // Remove non-catch phi uses, and disconnect the block.
+      block->DisconnectFromSuccessors(&visited);
     }
   }
 }
@@ -175,7 +180,8 @@
     const HUseListNode<HInstruction*>& use = insn->GetUses().front();
     size_t use_index = use.GetIndex();
     HBasicBlock* user_block = use.GetUser()->GetBlock();
-    DCHECK(use.GetUser()->IsPhi() && user_block->IsCatchBlock());
+    DCHECK(use.GetUser()->IsPhi());
+    DCHECK(user_block->IsCatchBlock());
     for (HInstructionIterator phi_it(user_block->GetPhis()); !phi_it.Done(); phi_it.Advance()) {
       phi_it.Current()->AsPhi()->RemoveInputAt(use_index);
     }
@@ -189,8 +195,7 @@
       HBasicBlock* block = blocks_[i];
       if (block == nullptr) continue;
 
-      // Disconnect from its sucessors, and remove all remaining uses.
-      block->DisconnectFromSuccessors(&visited);
+      // Remove all remaining uses (which should be only catch phi uses), and the instructions.
       block->RemoveCatchPhiUsesAndInstruction(/* building_dominator_tree = */ true);
 
       // Remove the block from the list of blocks, so that further analyses
@@ -219,7 +224,8 @@
   // (2) Remove instructions and phis from blocks not visited during
   //     the initial DFS as users from other instructions, so that
   //     users can be safely removed before uses later.
-  RemoveInstructionsAsUsersFromDeadBlocks(visited);
+  //     Also disconnect the block from its successors, updating the successor's phis if needed.
+  RemoveDeadBlocksInstructionsAsUsersAndDisconnect(visited);
 
   // (3) Remove blocks not visited during the initial DFS.
   //     Step (5) requires dead blocks to be removed from the