ART: Implement DeadPhiHandling in PrimitiveTypePropagation
DeadPhiHandling revives non-conflicting phis with environment uses
but does not properly merge types. To not duplicate code, this patch
modifies PrimitiveTypePropagation to deal with conflicts and thus
replaces DeadPhiHandling altogether.
Bug: 24252151
Bug: 24252100
Change-Id: I198c71d1b8167fc05783a5a24aa9f1e3804acafe
diff --git a/compiler/optimizing/ssa_phi_elimination.cc b/compiler/optimizing/ssa_phi_elimination.cc
index 72f9ddd..c6993f3 100644
--- a/compiler/optimizing/ssa_phi_elimination.cc
+++ b/compiler/optimizing/ssa_phi_elimination.cc
@@ -29,17 +29,28 @@
HBasicBlock* block = it.Current();
for (HInstructionIterator inst_it(block->GetPhis()); !inst_it.Done(); inst_it.Advance()) {
HPhi* phi = inst_it.Current()->AsPhi();
- // Set dead ahead of running through uses. The phi may have no use.
- phi->SetDead();
- for (HUseIterator<HInstruction*> use_it(phi->GetUses()); !use_it.Done(); use_it.Advance()) {
- HUseListNode<HInstruction*>* current = use_it.Current();
- HInstruction* user = current->GetUser();
- if (!user->IsPhi()) {
- worklist_.push_back(phi);
- phi->SetLive();
- break;
+ if (phi->IsDead()) {
+ // Phis are constructed live so this one was proven conflicting.
+ continue;
+ }
+
+ bool is_live = false;
+ if (graph_->IsDebuggable() && phi->HasEnvironmentUses()) {
+ is_live = true;
+ } else {
+ for (HUseIterator<HInstruction*> use_it(phi->GetUses()); !use_it.Done(); use_it.Advance()) {
+ if (!use_it.Current()->GetUser()->IsPhi()) {
+ is_live = true;
+ break;
+ }
}
}
+
+ if (is_live) {
+ worklist_.push_back(phi);
+ } else {
+ phi->SetDead();
+ }
}
}
@@ -50,8 +61,10 @@
for (HInputIterator it(phi); !it.Done(); it.Advance()) {
HInstruction* input = it.Current();
if (input->IsPhi() && input->AsPhi()->IsDead()) {
- worklist_.push_back(input->AsPhi());
+ // If we revive a phi it must have been live at the beginning of
+ // the pass but had no non-phi uses of its own.
input->AsPhi()->SetLive();
+ worklist_.push_back(input->AsPhi());
}
}
}
@@ -75,8 +88,8 @@
for (HUseIterator<HInstruction*> use_it(phi->GetUses()); !use_it.Done();
use_it.Advance()) {
HInstruction* user = use_it.Current()->GetUser();
- DCHECK(user->IsLoopHeaderPhi()) << user->GetId();
- DCHECK(user->AsPhi()->IsDead()) << user->GetId();
+ DCHECK(user->IsPhi());
+ DCHECK(user->AsPhi()->IsDead());
}
}
// Remove the phi from use lists of its inputs.