summaryrefslogtreecommitdiff
path: root/compiler/optimizing/ssa_builder.cc
diff options
context:
space:
mode:
author David Brazdil <dbrazdil@google.com> 2015-09-17 16:47:21 +0100
committer David Brazdil <dbrazdil@google.com> 2015-09-21 16:44:00 +0100
commitb701315cb7c4dfe907c27c24c819b7a14141fd2e (patch)
tree0bb83a5d10c6de112a3b105335d19b06987fc423 /compiler/optimizing/ssa_builder.cc
parent9e30c0e177adabaaf94a66c91130a19a7632fc7c (diff)
ART: Fix bug in DeadPhiHandling
When reviving dead phis for --debuggable, the DeadPhiHandling algorithm could produce two phis of the same type, which causes the SSAChecker graph verifier to fail. This patch fixes the bug. Note that the code is currently not exercised because compilation is delegated to Quick for --debuggable. Bug: 24129675 Change-Id: I26b6dcf3071b325cc7871b989a36c505279ae681
Diffstat (limited to 'compiler/optimizing/ssa_builder.cc')
-rw-r--r--compiler/optimizing/ssa_builder.cc30
1 files changed, 25 insertions, 5 deletions
diff --git a/compiler/optimizing/ssa_builder.cc b/compiler/optimizing/ssa_builder.cc
index 6f71ea3d6b..acc734a6b2 100644
--- a/compiler/optimizing/ssa_builder.cc
+++ b/compiler/optimizing/ssa_builder.cc
@@ -57,8 +57,13 @@ class DeadPhiHandling : public ValueObject {
};
bool DeadPhiHandling::UpdateType(HPhi* phi) {
+ if (phi->IsDead()) {
+ // Phi was rendered dead while waiting in the worklist because it was replaced
+ // with an equivalent.
+ return false;
+ }
+
Primitive::Type existing = phi->GetType();
- DCHECK(phi->IsLive());
bool conflict = false;
Primitive::Type new_type = existing;
@@ -112,11 +117,26 @@ bool DeadPhiHandling::UpdateType(HPhi* phi) {
phi->SetType(Primitive::kPrimVoid);
phi->SetDead();
return true;
- } else {
- DCHECK(phi->IsLive());
- phi->SetType(new_type);
- return existing != new_type;
+ } else if (existing == new_type) {
+ return false;
}
+
+ DCHECK(phi->IsLive());
+ phi->SetType(new_type);
+
+ // There might exist a `new_type` equivalent of `phi` already. In that case,
+ // we replace the equivalent with the, now live, `phi`.
+ HPhi* equivalent = phi->GetNextEquivalentPhiWithSameType();
+ if (equivalent != nullptr) {
+ // There cannot be more than two equivalents with the same type.
+ DCHECK(equivalent->GetNextEquivalentPhiWithSameType() == nullptr);
+ // If doing fix-point iteration, the equivalent might be in `worklist_`.
+ // Setting it dead will make UpdateType skip it.
+ equivalent->SetDead();
+ equivalent->ReplaceWith(phi);
+ }
+
+ return true;
}
void DeadPhiHandling::VisitBasicBlock(HBasicBlock* block) {