summaryrefslogtreecommitdiffstats
path: root/compiler/optimizing/code_generator_arm.cc
diff options
context:
space:
mode:
authorNicolas Geoffray <ngeoffray@google.com>2015-02-10 19:33:22 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2015-02-10 19:33:23 +0000
commit1d6957f0b9d560c75a1901a83a45b4f3510a1015 (patch)
tree36a174d4b12ef46744c5f3e80f8afeb46809a2e6 /compiler/optimizing/code_generator_arm.cc
parent0525d6aa15cb9db70e26c01f7e7a695bae377268 (diff)
parentf7a0c4e421b5edaad5b7a15bfff687da28d0b287 (diff)
downloadart-1d6957f0b9d560c75a1901a83a45b4f3510a1015.zip
art-1d6957f0b9d560c75a1901a83a45b4f3510a1015.tar.gz
art-1d6957f0b9d560c75a1901a83a45b4f3510a1015.tar.bz2
Merge "Improve ParallelMoveResolver to work with pairs."
Diffstat (limited to 'compiler/optimizing/code_generator_arm.cc')
-rw-r--r--compiler/optimizing/code_generator_arm.cc128
1 files changed, 99 insertions, 29 deletions
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index c6c1fd7..e5de2ab 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -3360,11 +3360,41 @@ void ParallelMoveResolverARM::EmitMove(size_t index) {
__ StoreSToOffset(source.AsFpuRegister<SRegister>(), SP, destination.GetStackIndex());
}
} else if (source.IsDoubleStackSlot()) {
- DCHECK(destination.IsDoubleStackSlot()) << destination;
- __ LoadFromOffset(kLoadWord, IP, SP, source.GetStackIndex());
- __ StoreToOffset(kStoreWord, IP, SP, destination.GetStackIndex());
- __ LoadFromOffset(kLoadWord, IP, SP, source.GetHighStackIndex(kArmWordSize));
- __ StoreToOffset(kStoreWord, IP, SP, destination.GetHighStackIndex(kArmWordSize));
+ if (destination.IsDoubleStackSlot()) {
+ __ LoadFromOffset(kLoadWord, IP, SP, source.GetStackIndex());
+ __ StoreToOffset(kStoreWord, IP, SP, destination.GetStackIndex());
+ __ LoadFromOffset(kLoadWord, IP, SP, source.GetHighStackIndex(kArmWordSize));
+ __ StoreToOffset(kStoreWord, IP, SP, destination.GetHighStackIndex(kArmWordSize));
+ } else if (destination.IsRegisterPair()) {
+ DCHECK(ExpectedPairLayout(destination));
+ __ LoadFromOffset(
+ kLoadWordPair, destination.AsRegisterPairLow<Register>(), SP, source.GetStackIndex());
+ } else {
+ DCHECK(destination.IsFpuRegisterPair()) << destination;
+ __ LoadDFromOffset(FromLowSToD(destination.AsFpuRegisterPairLow<SRegister>()),
+ SP,
+ source.GetStackIndex());
+ }
+ } else if (source.IsRegisterPair()) {
+ if (destination.IsRegisterPair()) {
+ __ Mov(destination.AsRegisterPairLow<Register>(), source.AsRegisterPairLow<Register>());
+ __ Mov(destination.AsRegisterPairHigh<Register>(), source.AsRegisterPairHigh<Register>());
+ } else {
+ DCHECK(destination.IsDoubleStackSlot()) << destination;
+ DCHECK(ExpectedPairLayout(source));
+ __ StoreToOffset(
+ kStoreWordPair, source.AsRegisterPairLow<Register>(), SP, destination.GetStackIndex());
+ }
+ } else if (source.IsFpuRegisterPair()) {
+ if (destination.IsFpuRegisterPair()) {
+ __ vmovd(FromLowSToD(destination.AsFpuRegisterPairLow<SRegister>()),
+ FromLowSToD(source.AsFpuRegisterPairLow<SRegister>()));
+ } else {
+ DCHECK(destination.IsDoubleStackSlot()) << destination;
+ __ StoreDToOffset(FromLowSToD(source.AsFpuRegisterPairLow<SRegister>()),
+ SP,
+ destination.GetStackIndex());
+ }
} else {
DCHECK(source.IsConstant()) << source;
HInstruction* constant = source.GetConstant();
@@ -3379,17 +3409,11 @@ void ParallelMoveResolverARM::EmitMove(size_t index) {
}
} else if (constant->IsLongConstant()) {
int64_t value = constant->AsLongConstant()->GetValue();
- if (destination.IsRegister()) {
- // In the presence of long or double constants, the parallel move resolver will
- // split the move into two, but keeps the same constant for both moves. Here,
- // we use the low or high part depending on which register this move goes to.
- if (destination.reg() % 2 == 0) {
- __ LoadImmediate(destination.AsRegister<Register>(), Low32Bits(value));
- } else {
- __ LoadImmediate(destination.AsRegister<Register>(), High32Bits(value));
- }
+ if (destination.IsRegisterPair()) {
+ __ LoadImmediate(destination.AsRegisterPairLow<Register>(), Low32Bits(value));
+ __ LoadImmediate(destination.AsRegisterPairHigh<Register>(), High32Bits(value));
} else {
- DCHECK(destination.IsDoubleStackSlot());
+ DCHECK(destination.IsDoubleStackSlot()) << destination;
__ LoadImmediate(IP, Low32Bits(value));
__ StoreToOffset(kStoreWord, IP, SP, destination.GetStackIndex());
__ LoadImmediate(IP, High32Bits(value));
@@ -3397,20 +3421,11 @@ void ParallelMoveResolverARM::EmitMove(size_t index) {
}
} else if (constant->IsDoubleConstant()) {
double value = constant->AsDoubleConstant()->GetValue();
- uint64_t int_value = bit_cast<uint64_t, double>(value);
- if (destination.IsFpuRegister()) {
- // In the presence of long or double constants, the parallel move resolver will
- // split the move into two, but keeps the same constant for both moves. Here,
- // we use the low or high part depending on which register this move goes to.
- if (destination.reg() % 2 == 0) {
- __ LoadSImmediate(destination.AsFpuRegister<SRegister>(),
- bit_cast<float, uint32_t>(Low32Bits(int_value)));
- } else {
- __ LoadSImmediate(destination.AsFpuRegister<SRegister>(),
- bit_cast<float, uint32_t>(High32Bits(int_value)));
- }
+ if (destination.IsFpuRegisterPair()) {
+ __ LoadDImmediate(FromLowSToD(destination.AsFpuRegisterPairLow<SRegister>()), value);
} else {
- DCHECK(destination.IsDoubleStackSlot());
+ DCHECK(destination.IsDoubleStackSlot()) << destination;
+ uint64_t int_value = bit_cast<uint64_t, double>(value);
__ LoadImmediate(IP, Low32Bits(int_value));
__ StoreToOffset(kStoreWord, IP, SP, destination.GetStackIndex());
__ LoadImmediate(IP, High32Bits(int_value));
@@ -3468,6 +3483,61 @@ void ParallelMoveResolverARM::EmitSwap(size_t index) {
__ vmovrs(IP, source.AsFpuRegister<SRegister>());
__ vmovs(source.AsFpuRegister<SRegister>(), destination.AsFpuRegister<SRegister>());
__ vmovsr(destination.AsFpuRegister<SRegister>(), IP);
+ } else if (source.IsRegisterPair() && destination.IsRegisterPair()) {
+ __ Mov(IP, source.AsRegisterPairLow<Register>());
+ __ Mov(source.AsRegisterPairLow<Register>(), destination.AsRegisterPairLow<Register>());
+ __ Mov(destination.AsRegisterPairLow<Register>(), IP);
+ __ Mov(IP, source.AsRegisterPairHigh<Register>());
+ __ Mov(source.AsRegisterPairHigh<Register>(), destination.AsRegisterPairHigh<Register>());
+ __ Mov(destination.AsRegisterPairHigh<Register>(), IP);
+ } else if (source.IsRegisterPair() || destination.IsRegisterPair()) {
+ // TODO: Find a D register available in the parallel moves,
+ // or reserve globally a D register.
+ DRegister tmp = D0;
+ Register low_reg = source.IsRegisterPair()
+ ? source.AsRegisterPairLow<Register>()
+ : destination.AsRegisterPairLow<Register>();
+ int mem = source.IsRegisterPair()
+ ? destination.GetStackIndex()
+ : source.GetStackIndex();
+ DCHECK(ExpectedPairLayout(source.IsRegisterPair() ? source : destination));
+ // Make room for the pushed DRegister.
+ mem += 8;
+ __ vpushd(tmp, 1);
+ __ vmovdrr(tmp, low_reg, static_cast<Register>(low_reg + 1));
+ __ LoadFromOffset(kLoadWordPair, low_reg, SP, mem);
+ __ StoreDToOffset(tmp, SP, mem);
+ __ vpopd(tmp, 1);
+ } else if (source.IsFpuRegisterPair() && destination.IsFpuRegisterPair()) {
+ // TODO: Find a D register available in the parallel moves,
+ // or reserve globally a D register.
+ DRegister tmp = D0;
+ DRegister first = FromLowSToD(source.AsFpuRegisterPairLow<SRegister>());
+ DRegister second = FromLowSToD(destination.AsFpuRegisterPairLow<SRegister>());
+ while (tmp == first || tmp == second) {
+ tmp = static_cast<DRegister>(tmp + 1);
+ }
+ __ vpushd(tmp, 1);
+ __ vmovd(tmp, first);
+ __ vmovd(first, second);
+ __ vmovd(second, tmp);
+ __ vpopd(tmp, 1);
+ } else if (source.IsFpuRegisterPair() || destination.IsFpuRegisterPair()) {
+ DRegister reg = source.IsFpuRegisterPair()
+ ? FromLowSToD(source.AsFpuRegisterPairLow<SRegister>())
+ : FromLowSToD(destination.AsFpuRegisterPairLow<SRegister>());
+ int mem = source.IsFpuRegisterPair()
+ ? destination.GetStackIndex()
+ : source.GetStackIndex();
+ // TODO: Find or reserve a D register.
+ DRegister tmp = reg == D0 ? D1 : D0;
+ // Make room for the pushed DRegister.
+ mem += 8;
+ __ vpushd(tmp, 1);
+ __ vmovd(tmp, reg);
+ __ LoadDFromOffset(reg, SP, mem);
+ __ StoreDToOffset(tmp, SP, mem);
+ __ vpopd(tmp, 1);
} else if (source.IsFpuRegister() || destination.IsFpuRegister()) {
SRegister reg = source.IsFpuRegister() ? source.AsFpuRegister<SRegister>()
: destination.AsFpuRegister<SRegister>();
@@ -3476,7 +3546,7 @@ void ParallelMoveResolverARM::EmitSwap(size_t index) {
: source.GetStackIndex();
__ vmovrs(IP, reg);
- __ LoadFromOffset(kLoadWord, IP, SP, mem);
+ __ LoadSFromOffset(reg, SP, mem);
__ StoreToOffset(kStoreWord, IP, SP, mem);
} else if (source.IsDoubleStackSlot() && destination.IsDoubleStackSlot()) {
Exchange(source.GetStackIndex(), destination.GetStackIndex());