Skip to content

Commit

Permalink
[arm, arm64] Implemented unaligned scalar float access.
Browse files Browse the repository at this point in the history
[arm64] Fix unaligned (u)int64 stores.

Fix unaligned access test to use host endianness.

Issue #22151

R=zra@google.com

Review-Url: https://codereview.chromium.org/2940883008 .
  • Loading branch information
rmacnak-google committed Jun 19, 2017
1 parent eafc070 commit 72e1775
Show file tree
Hide file tree
Showing 14 changed files with 299 additions and 161 deletions.
8 changes: 4 additions & 4 deletions runtime/vm/assembler_arm64.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1561,13 +1561,13 @@ void Assembler::StoreUnaligned(Register src,
if ((sz == kWord) || (sz == kUnsignedWord)) {
return;
}
LsrImmediate(tmp, src, 24);
str(tmp, Address(addr, 4), kUnsignedByte);
LsrImmediate(tmp, src, 32);
str(tmp, Address(addr, 5), kUnsignedByte);
str(tmp, Address(addr, 4), kUnsignedByte);
LsrImmediate(tmp, src, 40);
str(tmp, Address(addr, 6), kUnsignedByte);
str(tmp, Address(addr, 5), kUnsignedByte);
LsrImmediate(tmp, src, 48);
str(tmp, Address(addr, 6), kUnsignedByte);
LsrImmediate(tmp, src, 56);
str(tmp, Address(addr, 7), kUnsignedByte);
if (sz == kDoubleWord) {
return;
Expand Down
12 changes: 12 additions & 0 deletions runtime/vm/assembler_arm64.h
Original file line number Diff line number Diff line change
Expand Up @@ -843,6 +843,18 @@ class Assembler : public ValueObject {
EmitFPImm(FMOVDI, vd, imm8);
return true;
}
void fmovsr(VRegister vd, Register rn) {
ASSERT(rn != R31);
ASSERT(rn != CSP);
const Register crn = ConcreteRegister(rn);
EmitFPIntCvtOp(FMOVSR, static_cast<Register>(vd), crn, kWord);
}
void fmovrs(Register rd, VRegister vn) {
ASSERT(rd != R31);
ASSERT(rd != CSP);
const Register crd = ConcreteRegister(rd);
EmitFPIntCvtOp(FMOVRS, crd, static_cast<Register>(vn), kWord);
}
void fmovdr(VRegister vd, Register rn) {
ASSERT(rn != R31);
ASSERT(rn != CSP);
Expand Down
32 changes: 32 additions & 0 deletions runtime/vm/assembler_arm64_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2113,6 +2113,38 @@ ASSEMBLER_TEST_RUN(Fmovdr, test) {
}


ASSEMBLER_TEST_GENERATE(Fmovrs, assembler) {
__ LoadDImmediate(V2, 1.0);
__ fcvtsd(V1, V2);
__ fmovrs(R0, V1);
__ ret();
}


ASSEMBLER_TEST_RUN(Fmovrs, test) {
typedef int64_t (*Int64Return)() DART_UNUSED;
int64_t result = EXECUTE_TEST_CODE_INT64(Int64Return, test->entry());
const uint32_t one = bit_cast<uint32_t, float>(1.0f);
EXPECT_EQ(one, static_cast<uint32_t>(result));
}


ASSEMBLER_TEST_GENERATE(Fmovsr, assembler) {
__ LoadImmediate(R2, bit_cast<uint32_t, float>(1.0f));
__ fmovsr(V1, R2);
__ fmovrs(R0, V1);
__ ret();
}


ASSEMBLER_TEST_RUN(Fmovsr, test) {
typedef int64_t (*Int64Return)() DART_UNUSED;
int64_t result = EXECUTE_TEST_CODE_INT64(Int64Return, test->entry());
const uint32_t one = bit_cast<uint32_t, float>(1.0f);
EXPECT_EQ(one, static_cast<uint32_t>(result));
}


ASSEMBLER_TEST_GENERATE(FldrdFstrdPrePostIndex, assembler) {
__ SetupDartSP();
__ LoadDImmediate(V1, 42.0);
Expand Down
4 changes: 3 additions & 1 deletion runtime/vm/constants_arm64.h
Original file line number Diff line number Diff line change
Expand Up @@ -620,8 +620,10 @@ enum FPImmOp {

// C3.6.30
enum FPIntCvtOp {
FPIntCvtMask = 0x5f20fc00,
FPIntCvtMask = 0x5f00fc00,
FPIntCvtFixed = FPFixed | B21,
FMOVRS = FPIntCvtFixed | B18 | B17,
FMOVSR = FPIntCvtFixed | B18 | B17 | B16,
FMOVRD = FPIntCvtFixed | B22 | B18 | B17,
FMOVDR = FPIntCvtFixed | B22 | B18 | B17 | B16,
FCVTZDS = FPIntCvtFixed | B22 | B20 | B19,
Expand Down
31 changes: 22 additions & 9 deletions runtime/vm/disassembler_arm64.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1319,18 +1319,31 @@ void ARM64Decoder::DecodeFPImm(Instr* instr) {


void ARM64Decoder::DecodeFPIntCvt(Instr* instr) {
if ((instr->Bit(29) != 0) || (instr->Bits(22, 2) != 1)) {
if ((instr->Bit(29) != 0)) {
Unknown(instr);
return;
}
if (instr->Bits(16, 5) == 2) {
Format(instr, "scvtfd'sf 'vd, 'rn");
} else if (instr->Bits(16, 5) == 6) {
Format(instr, "fmovrd'sf 'rd, 'vn");
} else if (instr->Bits(16, 5) == 7) {
Format(instr, "fmovdr'sf 'vd, 'rn");
} else if (instr->Bits(16, 5) == 24) {
Format(instr, "fcvtzds'sf 'rd, 'vn");

if ((instr->SFField() == 0) && (instr->Bits(22, 2) == 0)) {
if (instr->Bits(16, 5) == 6) {
Format(instr, "fmovrs'sf 'rd, 'vn");
} else if (instr->Bits(16, 5) == 7) {
Format(instr, "fmovsr'sf 'vd, 'rn");
} else {
Unknown(instr);
}
} else if (instr->Bits(22, 2) == 1) {
if (instr->Bits(16, 5) == 2) {
Format(instr, "scvtfd'sf 'vd, 'rn");
} else if (instr->Bits(16, 5) == 6) {
Format(instr, "fmovrd'sf 'rd, 'vn");
} else if (instr->Bits(16, 5) == 7) {
Format(instr, "fmovdr'sf 'vd, 'rn");
} else if (instr->Bits(16, 5) == 24) {
Format(instr, "fcvtzds'sf 'rd, 'vn");
} else {
Unknown(instr);
}
} else {
Unknown(instr);
}
Expand Down
2 changes: 0 additions & 2 deletions runtime/vm/intermediate_language.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4080,8 +4080,6 @@ static AlignmentType StrengthenAlignment(intptr_t cid,
case kExternalOneByteStringCid:
// Don't need to worry about alignment for accessing bytes.
return kAlignedAccess;
case kTypedDataFloat32ArrayCid:
case kTypedDataFloat64ArrayCid:
case kTypedDataFloat64x2ArrayCid:
case kTypedDataInt32x4ArrayCid:
case kTypedDataFloat32x4ArrayCid:
Expand Down
79 changes: 61 additions & 18 deletions runtime/vm/intermediate_language_arm.cc
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -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 += 1;
}
}
LocationSummary* locs = new (zone)
LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
locs->set_in(0, Location::RequiresRegister());
Expand Down Expand Up @@ -1276,6 +1281,9 @@ LocationSummary* LoadIndexedInstr::MakeLocationSummary(Zone* zone,
}
if (!aligned()) {
locs->set_temp(0, Location::RequiresRegister());
if (representation() == kUnboxedDouble) {
locs->set_temp(1, Location::RequiresRegister());
}
}
return locs;
}
Expand Down Expand Up @@ -1325,16 +1333,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 value = locs()->temp(1).reg();
__ LoadWordUnaligned(value, address, TMP);
__ vmovsr(EvenSRegisterOf(dresult0), value);
__ AddImmediate(address, address, 4);
__ LoadWordUnaligned(value, address, TMP);
__ vmovsr(OddSRegisterOf(dresult0), value);
}
break;
case kTypedDataFloat64x2ArrayCid:
case kTypedDataInt32x4ArrayCid:
case kTypedDataFloat32x4ArrayCid:
ASSERT(element_address.Equals(Address(IP)));
ASSERT(aligned());
__ vldmd(IA, IP, dresult0, 2);
break;
default:
Expand Down Expand Up @@ -1459,34 +1483,35 @@ 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;
} 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;
}
} 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:
Expand Down Expand Up @@ -1636,18 +1661,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;
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 value = temp2;
__ vmovrs(value, EvenSRegisterOf(value_reg));
__ StoreWordUnaligned(value, address, TMP);
__ AddImmediate(address, address, 4);
__ vmovrs(value, OddSRegisterOf(value_reg));
__ StoreWordUnaligned(value, 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;
Expand Down
31 changes: 25 additions & 6 deletions runtime/vm/intermediate_language_arm64.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1127,15 +1127,26 @@ void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
ASSERT(aligned());
case kTypedDataFloat32ArrayCid:
// Load single precision float.
__ fldrs(result, element_address);
if (aligned()) {
__ fldrs(result, element_address);
} else {
__ LoadUnaligned(TMP, address, TMP2, kUnsignedWord);
__ fmovsr(result, TMP);
}
break;
case kTypedDataFloat64ArrayCid:
// Load double precision float.
__ fldrd(result, element_address);
if (aligned()) {
__ fldrd(result, element_address);
} else {
__ LoadUnaligned(TMP, address, TMP2, kDoubleWord);
__ fmovdr(result, TMP);
}
break;
case kTypedDataFloat64x2ArrayCid:
case kTypedDataInt32x4ArrayCid:
case kTypedDataFloat32x4ArrayCid:
ASSERT(aligned());
__ fldrq(result, element_address);
break;
default:
Expand Down Expand Up @@ -1472,15 +1483,23 @@ void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
break;
}
case kTypedDataFloat32ArrayCid: {
ASSERT(aligned());
const VRegister value_reg = locs()->in(2).fpu_reg();
__ fstrs(value_reg, element_address);
if (aligned()) {
__ fstrs(value_reg, element_address);
} else {
__ fmovrs(TMP, value_reg);
__ StoreUnaligned(TMP, address, scratch, kWord);
}
break;
}
case kTypedDataFloat64ArrayCid: {
ASSERT(aligned());
const VRegister value_reg = locs()->in(2).fpu_reg();
__ fstrd(value_reg, element_address);
if (aligned()) {
__ fstrd(value_reg, element_address);
} else {
__ fmovrd(TMP, value_reg);
__ StoreUnaligned(TMP, address, scratch, kDoubleWord);
}
break;
}
case kTypedDataFloat64x2ArrayCid:
Expand Down

0 comments on commit 72e1775

Please sign in to comment.