Support hints for register pairs.
Change-Id: Ia49dc5bf3e9a2bd481425bfe7fbeea9feb66c8e6
diff --git a/compiler/optimizing/locations.h b/compiler/optimizing/locations.h
index 9ce8d35..ebca1cc 100644
--- a/compiler/optimizing/locations.h
+++ b/compiler/optimizing/locations.h
@@ -151,6 +151,10 @@
return GetKind() == kFpuRegisterPair;
}
+ bool IsRegisterKind() const {
+ return IsRegister() || IsFpuRegister() || IsRegisterPair() || IsFpuRegisterPair();
+ }
+
int reg() const {
DCHECK(IsRegister() || IsFpuRegister());
return GetPayload();
diff --git a/compiler/optimizing/ssa_liveness_analysis.cc b/compiler/optimizing/ssa_liveness_analysis.cc
index 2a84735..bebb73b 100644
--- a/compiler/optimizing/ssa_liveness_analysis.cc
+++ b/compiler/optimizing/ssa_liveness_analysis.cc
@@ -311,7 +311,12 @@
return live_in->UnionIfNotIn(live_out, kill);
}
+static int RegisterOrLowRegister(Location location) {
+ return location.IsPair() ? location.low() : location.reg();
+}
+
int LiveInterval::FindFirstRegisterHint(size_t* free_until) const {
+ DCHECK(!IsHighInterval());
if (GetParent() == this && defined_by_ != nullptr) {
// This is the first interval for the instruction. Try to find
// a register based on its definition.
@@ -333,8 +338,12 @@
if (user->IsPhi()) {
// If the phi has a register, try to use the same.
Location phi_location = user->GetLiveInterval()->ToLocation();
- if (SameRegisterKind(phi_location) && free_until[phi_location.reg()] >= use_position) {
- return phi_location.reg();
+ if (phi_location.IsRegisterKind()) {
+ DCHECK(SameRegisterKind(phi_location));
+ int reg = RegisterOrLowRegister(phi_location);
+ if (free_until[reg] >= use_position) {
+ return reg;
+ }
}
const GrowableArray<HBasicBlock*>& predecessors = user->GetBlock()->GetPredecessors();
// If the instruction dies at the phi assignment, we can try having the
@@ -347,8 +356,11 @@
HInstruction* input = user->InputAt(i);
Location location = input->GetLiveInterval()->GetLocationAt(
predecessors.Get(i)->GetLifetimeEnd() - 1);
- if (location.IsRegister() && free_until[location.reg()] >= use_position) {
- return location.reg();
+ if (location.IsRegisterKind()) {
+ int reg = RegisterOrLowRegister(location);
+ if (free_until[reg] >= use_position) {
+ return reg;
+ }
}
}
}
@@ -359,8 +371,12 @@
// We use the user's lifetime position - 1 (and not `use_position`) because the
// register is blocked at the beginning of the user.
size_t position = user->GetLifetimePosition() - 1;
- if (SameRegisterKind(expected) && free_until[expected.reg()] >= position) {
- return expected.reg();
+ if (expected.IsRegisterKind()) {
+ DCHECK(SameRegisterKind(expected));
+ int reg = RegisterOrLowRegister(expected);
+ if (free_until[reg] >= position) {
+ return reg;
+ }
}
}
}
@@ -382,8 +398,9 @@
// If the input dies at the end of the predecessor, we know its register can
// be reused.
Location input_location = input_interval.ToLocation();
- if (SameRegisterKind(input_location)) {
- return input_location.reg();
+ if (input_location.IsRegisterKind()) {
+ DCHECK(SameRegisterKind(input_location));
+ return RegisterOrLowRegister(input_location);
}
}
}
@@ -398,8 +415,9 @@
// If the input dies at the start of this instruction, we know its register can
// be reused.
Location location = input_interval.ToLocation();
- if (SameRegisterKind(location)) {
- return location.reg();
+ if (location.IsRegisterKind()) {
+ DCHECK(SameRegisterKind(location));
+ return RegisterOrLowRegister(location);
}
}
}
@@ -408,9 +426,19 @@
}
bool LiveInterval::SameRegisterKind(Location other) const {
- return IsFloatingPoint()
- ? other.IsFpuRegister()
- : other.IsRegister();
+ if (IsFloatingPoint()) {
+ if (IsLowInterval() || IsHighInterval()) {
+ return other.IsFpuRegisterPair();
+ } else {
+ return other.IsFpuRegister();
+ }
+ } else {
+ if (IsLowInterval() || IsHighInterval()) {
+ return other.IsRegisterPair();
+ } else {
+ return other.IsRegister();
+ }
+ }
}
bool LiveInterval::NeedsTwoSpillSlots() const {