Index: runtime/vm/intermediate_language_arm.cc |
diff --git a/runtime/vm/intermediate_language_arm.cc b/runtime/vm/intermediate_language_arm.cc |
index 86d9c5a07095de27b6034f33ca34020e06921dbd..c097fef251a19765166ae035b5a3bfcce877c32c 100644 |
--- a/runtime/vm/intermediate_language_arm.cc |
+++ b/runtime/vm/intermediate_language_arm.cc |
@@ -1,4 +1,3 @@ |
- |
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
// for details. All rights reserved. Use of this source code is governed by a |
// BSD-style license that can be found in the LICENSE file. |
@@ -1239,7 +1238,13 @@ static bool CanBeImmediateIndex(Value* value, |
LocationSummary* LoadIndexedInstr::MakeLocationSummary(Zone* zone, |
bool opt) const { |
const intptr_t kNumInputs = 2; |
- const intptr_t kNumTemps = aligned() ? 0 : 1; |
+ intptr_t kNumTemps = 0; |
+ if (!aligned()) { |
+ kNumTemps += 1; |
+ if (representation() == kUnboxedDouble) { |
+ kNumTemps += 2; |
+ } |
+ } |
LocationSummary* locs = new (zone) |
LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
locs->set_in(0, Location::RequiresRegister()); |
@@ -1276,6 +1281,10 @@ LocationSummary* LoadIndexedInstr::MakeLocationSummary(Zone* zone, |
} |
if (!aligned()) { |
locs->set_temp(0, Location::RequiresRegister()); |
+ if (representation() == kUnboxedDouble) { |
+ locs->set_temp(1, Location::RequiresRegister()); |
+ locs->set_temp(2, Location::RequiresRegister()); |
+ } |
} |
return locs; |
} |
@@ -1325,16 +1334,32 @@ void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
case kTypedDataFloat32ArrayCid: |
// Load single precision float. |
// vldrs does not support indexed addressing. |
- __ vldrs(EvenSRegisterOf(dresult0), element_address); |
+ if (aligned()) { |
+ __ vldrs(EvenSRegisterOf(dresult0), element_address); |
+ } else { |
+ const Register value = locs()->temp(1).reg(); |
+ __ LoadWordUnaligned(value, address, TMP); |
+ __ vmovsr(EvenSRegisterOf(dresult0), value); |
+ } |
break; |
case kTypedDataFloat64ArrayCid: |
// vldrd does not support indexed addressing. |
- __ vldrd(dresult0, element_address); |
+ if (aligned()) { |
+ __ vldrd(dresult0, element_address); |
+ } else { |
+ const Register value1 = locs()->temp(1).reg(); |
zra
2017/06/19 15:02:48
You can save a temporary register here by using vm
rmacnak
2017/06/19 17:18:32
Done.
|
+ const Register value2 = locs()->temp(2).reg(); |
+ __ LoadWordUnaligned(value1, address, TMP); |
+ __ AddImmediate(address, address, 4); |
+ __ LoadWordUnaligned(value2, address, TMP); |
+ __ vmovdrr(dresult0, value1, value2); |
+ } |
break; |
case kTypedDataFloat64x2ArrayCid: |
case kTypedDataInt32x4ArrayCid: |
case kTypedDataFloat32x4ArrayCid: |
ASSERT(element_address.Equals(Address(IP))); |
+ ASSERT(aligned()); |
__ vldmd(IA, IP, dresult0, 2); |
break; |
default: |
@@ -1459,34 +1484,41 @@ LocationSummary* StoreIndexedInstr::MakeLocationSummary(Zone* zone, |
LocationSummary* locs; |
bool needs_base = false; |
+ intptr_t kNumTemps = 0; |
if (CanBeImmediateIndex(index(), class_id(), IsExternal(), |
false, // Store. |
&needs_base)) { |
- const intptr_t kNumTemps = aligned() ? (needs_base ? 1 : 0) : 2; |
+ if (!aligned()) { |
+ kNumTemps += 2; |
+ if (class_id() == kTypedDataFloat64ArrayCid) { |
+ kNumTemps += 1; |
+ } |
+ } else if (needs_base) { |
+ kNumTemps += 1; |
+ } |
+ |
locs = new (zone) |
LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
// CanBeImmediateIndex must return false for unsafe smis. |
locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); |
- if (needs_base) { |
- locs->set_temp(0, Location::RequiresRegister()); |
- } |
+ } else { |
if (!aligned()) { |
- locs->set_temp(0, Location::RequiresRegister()); |
- locs->set_temp(1, Location::RequiresRegister()); |
+ kNumTemps += 2; |
+ if (class_id() == kTypedDataFloat64ArrayCid) { |
+ kNumTemps += 1; |
+ } |
} |
- } else { |
- const intptr_t kNumTemps = aligned() ? 0 : 2; |
+ |
locs = new (zone) |
LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
locs->set_in(1, Location::WritableRegister()); |
- if (!aligned()) { |
- locs->set_temp(0, Location::RequiresRegister()); |
- locs->set_temp(1, Location::RequiresRegister()); |
- } |
} |
locs->set_in(0, Location::RequiresRegister()); |
+ for (intptr_t i = 0; i < kNumTemps; i++) { |
+ locs->set_temp(i, Location::RequiresRegister()); |
+ } |
switch (class_id()) { |
case kArrayCid: |
@@ -1532,6 +1564,8 @@ void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
(locs()->temp_count() > 0) ? locs()->temp(0).reg() : kNoRegister; |
const Register temp2 = |
(locs()->temp_count() > 1) ? locs()->temp(1).reg() : kNoRegister; |
+ const Register temp3 = |
+ (locs()->temp_count() > 2) ? locs()->temp(2).reg() : kNoRegister; |
Address element_address(kNoRegister); |
if (aligned()) { |
@@ -1636,18 +1670,36 @@ void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
case kTypedDataFloat32ArrayCid: { |
const SRegister value_reg = |
EvenSRegisterOf(EvenDRegisterOf(locs()->in(2).fpu_reg())); |
- __ vstrs(value_reg, element_address); |
+ if (aligned()) { |
+ __ vstrs(value_reg, element_address); |
+ } else { |
+ const Register& address = temp; |
zra
2017/06/19 15:02:48
Is & needed?
rmacnak
2017/06/19 17:18:32
No, removed.
|
+ const Register& value = temp2; |
+ __ vmovrs(value, value_reg); |
+ __ StoreWordUnaligned(value, address, TMP); |
+ } |
break; |
} |
case kTypedDataFloat64ArrayCid: { |
const DRegister value_reg = EvenDRegisterOf(locs()->in(2).fpu_reg()); |
- __ vstrd(value_reg, element_address); |
+ if (aligned()) { |
+ __ vstrd(value_reg, element_address); |
+ } else { |
+ const Register& address = temp; |
+ const Register& value1 = temp2; |
+ const Register& value2 = temp3; |
+ __ vmovrrd(value1, value2, value_reg); |
zra
2017/06/19 15:02:48
Same idea here for saving a temporary by using vmo
|
+ __ StoreWordUnaligned(value1, address, TMP); |
+ __ AddImmediate(address, address, 4); |
+ __ StoreWordUnaligned(value2, address, TMP); |
+ } |
break; |
} |
case kTypedDataFloat64x2ArrayCid: |
case kTypedDataInt32x4ArrayCid: |
case kTypedDataFloat32x4ArrayCid: { |
ASSERT(element_address.Equals(Address(index.reg()))); |
+ ASSERT(aligned()); |
const DRegister value_reg = EvenDRegisterOf(locs()->in(2).fpu_reg()); |
__ vstmd(IA, index.reg(), value_reg, 2); |
break; |