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
diff --git a/compiler/optimizing/ssa_builder.cc b/compiler/optimizing/ssa_builder.cc
index 6f71ea3..acc734a 100644
--- a/compiler/optimizing/ssa_builder.cc
+++ b/compiler/optimizing/ssa_builder.cc
@@ -57,8 +57,13 @@
};
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 @@
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) {