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