Recompute dominator tree after DCE.
bug:22031382
(cherry picked from commit 1f82ecc6a0c9f88d03d6d1a6d95eeb8707bd06c1)
Change-Id: I9a74edb185cb806045903dfe9695d9cc1a02e86b
diff --git a/compiler/optimizing/boolean_simplifier.cc b/compiler/optimizing/boolean_simplifier.cc
index 8100a29..daf7d67 100644
--- a/compiler/optimizing/boolean_simplifier.cc
+++ b/compiler/optimizing/boolean_simplifier.cc
@@ -141,6 +141,12 @@
block->MergeWith(false_block);
block->MergeWith(merge_block);
+ // No need to update any dominance information, as we are simplifying
+ // a simple diamond shape, where the join block is merged with the
+ // entry block. Any following blocks would have had the join block
+ // as a dominator, and `MergeWith` handles changing that to the
+ // entry block.
+
// Remove the original condition if it is now unused.
if (!if_condition->HasUses()) {
if_condition->GetBlock()->RemoveInstructionOrPhi(if_condition);
diff --git a/compiler/optimizing/dead_code_elimination.cc b/compiler/optimizing/dead_code_elimination.cc
index 6fbe75e..2362cc1 100644
--- a/compiler/optimizing/dead_code_elimination.cc
+++ b/compiler/optimizing/dead_code_elimination.cc
@@ -67,6 +67,7 @@
ArenaBitVector affected_loops(allocator, graph_->GetBlocks().Size(), false);
MarkReachableBlocks(graph_->GetEntryBlock(), &live_blocks);
+ bool removed_one_or_more_blocks = false;
// Remove all dead blocks. Iterate in post order because removal needs the
// block's chain of dominators and nested loops need to be updated from the
@@ -83,9 +84,17 @@
MaybeRecordDeadBlock(block);
MarkLoopHeadersContaining(*block, &affected_loops);
block->DisconnectAndDelete();
+ removed_one_or_more_blocks = true;
}
}
+ // If we removed at least one block, we need to recompute the full
+ // dominator tree.
+ if (removed_one_or_more_blocks) {
+ graph_->ClearDominanceInformation();
+ graph_->ComputeDominanceInformation();
+ }
+
// Connect successive blocks created by dead branches. Order does not matter.
for (HReversePostOrderIterator it(*graph_); !it.Done();) {
HBasicBlock* block = it.Current();
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc
index c01364a..88490d0 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -116,9 +116,24 @@
// dominators and the reverse post order.
SimplifyCFG();
- // (5) Compute the immediate dominator of each block. We visit
- // the successors of a block only when all its forward branches
- // have been processed.
+ // (5) Compute the dominance information and the reverse post order.
+ ComputeDominanceInformation();
+}
+
+void HGraph::ClearDominanceInformation() {
+ for (HReversePostOrderIterator it(*this); !it.Done(); it.Advance()) {
+ it.Current()->ClearDominanceInformation();
+ }
+ reverse_post_order_.Reset();
+}
+
+void HBasicBlock::ClearDominanceInformation() {
+ dominated_blocks_.Reset();
+ dominator_ = nullptr;
+}
+
+void HGraph::ComputeDominanceInformation() {
+ DCHECK(reverse_post_order_.IsEmpty());
GrowableArray<size_t> visits(arena_, blocks_.Size());
visits.SetSize(blocks_.Size());
reverse_post_order_.Add(entry_block_);
@@ -1037,8 +1052,7 @@
}
predecessors_.Reset();
- // Disconnect the block from its successors and update their dominators
- // and phis.
+ // Disconnect the block from its successors and update their phis.
for (size_t i = 0, e = successors_.Size(); i < e; ++i) {
HBasicBlock* successor = successors_.Get(i);
// Delete this block from the list of predecessors.
@@ -1049,19 +1063,6 @@
// dominator of `successor` which violates the order DCHECKed at the top.
DCHECK(!successor->predecessors_.IsEmpty());
- // Recompute the successor's dominator.
- HBasicBlock* old_dominator = successor->GetDominator();
- HBasicBlock* new_dominator = successor->predecessors_.Get(0);
- for (size_t j = 1, f = successor->predecessors_.Size(); j < f; ++j) {
- new_dominator = graph_->FindCommonDominator(
- new_dominator, successor->predecessors_.Get(j));
- }
- if (old_dominator != new_dominator) {
- successor->SetDominator(new_dominator);
- old_dominator->RemoveDominatedBlock(successor);
- new_dominator->AddDominatedBlock(successor);
- }
-
// Remove this block's entries in the successor's phis.
if (successor->predecessors_.Size() == 1u) {
// The successor has just one predecessor left. Replace phis with the only
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 394e3fc..b36d9b8 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -170,6 +170,9 @@
return true;
}
+ void ComputeDominanceInformation();
+ void ClearDominanceInformation();
+
void BuildDominatorTree();
void TransformToSsa();
void SimplifyCFG();
@@ -547,11 +550,10 @@
LOG(FATAL) << "Unreachable";
UNREACHABLE();
}
+ void ClearDominanceInformation();
int NumberOfBackEdges() const {
- return loop_information_ == nullptr
- ? 0
- : loop_information_->NumberOfBackEdges();
+ return IsLoopHeader() ? loop_information_->NumberOfBackEdges() : 0;
}
HInstruction* GetFirstInstruction() const { return instructions_.first_instruction_; }
diff --git a/test/515-dce-dominator/expected.txt b/test/515-dce-dominator/expected.txt
new file mode 100644
index 0000000..ccaf6f8
--- /dev/null
+++ b/test/515-dce-dominator/expected.txt
@@ -0,0 +1 @@
+Enter
diff --git a/test/515-dce-dominator/info.txt b/test/515-dce-dominator/info.txt
new file mode 100644
index 0000000..af706e0
--- /dev/null
+++ b/test/515-dce-dominator/info.txt
@@ -0,0 +1,3 @@
+Regression test for the DCE phase of optimizing, where
+we need to recompute the full dominance information of
+the graph when blocks get removed.
diff --git a/test/515-dce-dominator/smali/Dominator.smali b/test/515-dce-dominator/smali/Dominator.smali
new file mode 100644
index 0000000..a504aba
--- /dev/null
+++ b/test/515-dce-dominator/smali/Dominator.smali
@@ -0,0 +1,37 @@
+# Copyright (C) 2015 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+.class public LDominator;
+
+.super Ljava/lang/Object;
+
+.method public static method(I)I
+ .registers 2
+ const/4 v0, 0
+ :b1
+ if-ne v0, v0, :b3
+ :b2
+ if-eq v0, p0, :b4
+ :b5
+ if-eq v0, p0, :b2
+ goto :b6
+ :b4
+ goto :b7
+ :b3
+ goto :b6
+ :b6
+ goto :b7
+ :b7
+ return v1
+.end method
diff --git a/test/515-dce-dominator/src/Main.java b/test/515-dce-dominator/src/Main.java
new file mode 100644
index 0000000..bf9ee25
--- /dev/null
+++ b/test/515-dce-dominator/src/Main.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.lang.reflect.Method;
+
+public class Main {
+ public static void main(String[] args) throws Exception {
+ // Workaround for b/18051191.
+ System.out.println("Enter");
+ Class<?> c = Class.forName("Dominator");
+ Method m = c.getMethod("method", int.class);
+ Object[] arguments = { 5 };
+ m.invoke(null, arguments);
+ }
+}