summaryrefslogtreecommitdiff
path: root/compiler/optimizing/ssa_liveness_analysis.cc
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/optimizing/ssa_liveness_analysis.cc')
-rw-r--r--compiler/optimizing/ssa_liveness_analysis.cc52
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);
+ }
+ }
+ }
}
}
}