diff options
author | 2015-09-28 13:49:59 +0100 | |
---|---|---|
committer | 2015-11-04 18:13:45 +0000 | |
commit | 1749e2cfb5c5ed4d6970a09aecf898ca9cdfcb75 (patch) | |
tree | 57ab54c48a7404abf0c9f2c919e8a6c805d98587 /compiler/optimizing/ssa_phi_elimination.cc | |
parent | c8894ab5021aecd0fa5eba94af47f732914af33b (diff) |
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
Diffstat (limited to 'compiler/optimizing/ssa_phi_elimination.cc')
-rw-r--r-- | compiler/optimizing/ssa_phi_elimination.cc | 37 |
1 files changed, 25 insertions, 12 deletions
diff --git a/compiler/optimizing/ssa_phi_elimination.cc b/compiler/optimizing/ssa_phi_elimination.cc index 72f9ddd506..c6993f3aca 100644 --- a/compiler/optimizing/ssa_phi_elimination.cc +++ b/compiler/optimizing/ssa_phi_elimination.cc @@ -29,17 +29,28 @@ void SsaDeadPhiElimination::MarkDeadPhis() { 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 @@ void SsaDeadPhiElimination::MarkDeadPhis() { 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 @@ void SsaDeadPhiElimination::EliminateDeadPhis() { 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. |