diff options
Diffstat (limited to 'compiler/optimizing/ssa_liveness_analysis.cc')
-rw-r--r-- | compiler/optimizing/ssa_liveness_analysis.cc | 52 |
1 files changed, 43 insertions, 9 deletions
diff --git a/compiler/optimizing/ssa_liveness_analysis.cc b/compiler/optimizing/ssa_liveness_analysis.cc index a5609fc466..7ed3c84f13 100644 --- a/compiler/optimizing/ssa_liveness_analysis.cc +++ b/compiler/optimizing/ssa_liveness_analysis.cc @@ -242,19 +242,53 @@ void SsaLivenessAnalysis::ComputeLiveRanges() { } if (instruction != nullptr) { instruction->GetLiveInterval()->AddUse( - current, environment, i, should_be_live); + current, environment, i, /* actual_user */ nullptr, should_be_live); } } } - // All inputs of an instruction must be live. - for (size_t i = 0, e = current->InputCount(); i < e; ++i) { - HInstruction* input = current->InputAt(i); - // Some instructions 'inline' their inputs, that is they do not need - // to be materialized. - if (input->HasSsaIndex() && current->GetLocations()->InAt(i).IsValid()) { - live_in->SetBit(input->GetSsaIndex()); - input->GetLiveInterval()->AddUse(current, /* environment */ nullptr, i); + // Process inputs of instructions. + if (current->IsEmittedAtUseSite()) { + if (kIsDebugBuild) { + DCHECK(!current->GetLocations()->Out().IsValid()); + for (HUseIterator<HInstruction*> use_it(current->GetUses()); + !use_it.Done(); + use_it.Advance()) { + HInstruction* user = use_it.Current()->GetUser(); + size_t index = use_it.Current()->GetIndex(); + DCHECK(!user->GetLocations()->InAt(index).IsValid()); + } + DCHECK(!current->HasEnvironmentUses()); + } + } else { + for (size_t i = 0, e = current->InputCount(); i < e; ++i) { + HInstruction* input = current->InputAt(i); + bool has_in_location = current->GetLocations()->InAt(i).IsValid(); + bool has_out_location = input->GetLocations()->Out().IsValid(); + + if (has_in_location) { + DCHECK(has_out_location); + DCHECK(input->HasSsaIndex()); + // `Input` generates a result used by `current`. Add use and update + // the live-in set. + input->GetLiveInterval()->AddUse(current, /* environment */ nullptr, i); + live_in->SetBit(input->GetSsaIndex()); + } else if (has_out_location) { + // `Input` generates a result but it is not used by `current`. + } else { + // `Input` is inlined into `current`. Walk over its inputs and record + // uses at `current`. + DCHECK(input->IsEmittedAtUseSite()); + for (size_t i2 = 0, e2 = input->InputCount(); i2 < e2; ++i2) { + HInstruction* inlined_input = input->InputAt(i2); + DCHECK(inlined_input->HasSsaIndex()) << "Recursive inlining not allowed."; + if (input->GetLocations()->InAt(i2).IsValid()) { + live_in->SetBit(inlined_input->GetSsaIndex()); + inlined_input->GetLiveInterval()->AddUse( + /* owner */ input, /* environment */ nullptr, i2, /* actual_user */ current); + } + } + } } } } |