Skip to content

Commit 28ee0b0

Browse files
modulovaluedart-scoped@luci-project-accounts.iam.gserviceaccount.com
authored andcommitted
[vm] arm64: use rev64 for 32x4 shuffles
Adds REV64 on .4S lanes and lowers shuffle mask 0xB1 (yxwz) to it. Issue: #64170 Issue: #64345 Issue: #64511 TEST=vm/cc/Assembler_Rev64S TEST=lib/typed_data/simd_shuffle_all_masks_test Change-Id: Ideb7bfb87ebfb096b99ff9b424950f3bb61e46df Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/562681 Reviewed-by: Alexander Markov <alexmarkov@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com> Auto-Submit: Modestas Valauskas <valauskasmodestas@gmail.com> Commit-Queue: Martin Kustermann <kustermann@google.com>
1 parent b89d96f commit 28ee0b0

5 files changed

Lines changed: 51 additions & 0 deletions

File tree

‎runtime/vm/compiler/assembler/assembler_arm64.h‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1580,6 +1580,14 @@ class Assembler : public AssemblerBase {
15801580
(static_cast<int32_t>(vd) << kVdShift);
15811581
Emit(encoding);
15821582
}
1583+
// REV64 Vd.4S, Vn.4S: swaps the two 32-bit lanes in each 64-bit half, so
1584+
// the lanes n0, n1, n2, n3 of Vn become n1, n0, n3, n2.
1585+
void vrev64_4s(VRegister vd, VRegister vn) {
1586+
const int32_t encoding = 0x4EA00800 |
1587+
(static_cast<int32_t>(vn) << kVnShift) |
1588+
(static_cast<int32_t>(vd) << kVdShift);
1589+
Emit(encoding);
1590+
}
15831591
// UMINV Sd, Vn.4S: unsigned minimum across the four word lanes of Vn into the
15841592
// 32-bit scalar in the low bits of Vd.
15851593
void vuminv_4s(VRegister vd, VRegister vn) {

‎runtime/vm/compiler/assembler/assembler_arm64_test.cc‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2452,6 +2452,29 @@ ASSEMBLER_TEST_RUN(Tbl1, test) {
24522452
"ret\n");
24532453
}
24542454

2455+
ASSEMBLER_TEST_GENERATE(Rev64S, assembler) {
2456+
__ fldrq(V1, Address(R0, 0));
2457+
__ vrev64_4s(V0, V1);
2458+
__ fstrq(V0, Address(R0, 16));
2459+
__ ret();
2460+
}
2461+
2462+
ASSEMBLER_TEST_RUN(Rev64S, test) {
2463+
typedef void (*Rev64SCode)(uint32_t* buffer) DART_UNUSED;
2464+
uint32_t buffer[8] = {0x01234567, 0x89ABCDEF, 0x76543210, 0xFEDCBA98,
2465+
0x5A5A5A5A, 0x5A5A5A5A, 0x5A5A5A5A, 0x5A5A5A5A};
2466+
reinterpret_cast<Rev64SCode>(test->entry())(buffer);
2467+
EXPECT_EQ(0x89ABCDEFu, buffer[4]);
2468+
EXPECT_EQ(0x01234567u, buffer[5]);
2469+
EXPECT_EQ(0xFEDCBA98u, buffer[6]);
2470+
EXPECT_EQ(0x76543210u, buffer[7]);
2471+
EXPECT_DISASSEMBLY(
2472+
"fldrq v1, [r0]\n"
2473+
"vrev64s v0, v1\n"
2474+
"fstrq v0, [r0, #16]\n"
2475+
"ret\n");
2476+
}
2477+
24552478
// Comparisons, branching.
24562479
ASSEMBLER_TEST_GENERATE(BranchALForward, assembler) {
24572480
Label l;

‎runtime/vm/compiler/assembler/disassembler_arm64.cc‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1600,6 +1600,11 @@ void ARM64Decoder::DecodeDPSimd1(Instr* instr) {
16001600
Format(instr, "vuminv 'vd, 'vn");
16011601
return;
16021602
}
1603+
// REV64 Vd.4S, Vn.4S.
1604+
if ((instr->InstructionBits() & 0xFFFFFC00) == 0x4EA00800) {
1605+
Format(instr, "vrev64s 'vd, 'vn");
1606+
return;
1607+
}
16031608
// TBL Vd.16B, {Vn.16B}, Vm.16B (Q=1, len=0, op=0 table lookup form).
16041609
if ((instr->InstructionBits() & 0xFFE0FC00) == 0x4E000000) {
16051610
Format(instr, "vtbl1 'vd, 'vn, 'vm");

‎runtime/vm/compiler/backend/il_arm64.cc‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4001,6 +4001,9 @@ DEFINE_EMIT(Simd32x4Shuffle, (VRegister result, VRegister value)) {
40014001
case 0xFF: // wwww
40024002
__ vdups(result, value, 3);
40034003
break;
4004+
case 0xB1: // yxwz
4005+
__ vrev64_4s(result, value);
4006+
break;
40044007
default:
40054008
__ LoadQImmediate(VTMP, ShuffleTableIndices(mask));
40064009
__ vtbl1(result, value, VTMP);

‎runtime/vm/simulator_arm64.cc‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3773,6 +3773,18 @@ void Simulator::DecodeDPSimd1(Instr* instr) {
37733773
return;
37743774
}
37753775

3776+
// REV64 Vd.4S, Vn.4S: swaps the two 32-bit lanes in each 64-bit half.
3777+
if ((instr->InstructionBits() & 0xFFFFFC00) == 0x4EA00800) {
3778+
const VRegister vd = instr->VdField();
3779+
const VRegister vn = instr->VnField();
3780+
const int32_t res[4] = {get_vregisters(vn, 1), get_vregisters(vn, 0),
3781+
get_vregisters(vn, 3), get_vregisters(vn, 2)};
3782+
for (int i = 0; i < 4; i++) {
3783+
set_vregisters(vd, i, res[i]);
3784+
}
3785+
return;
3786+
}
3787+
37763788
// TBL Vd.16B, {Vn.16B}, Vm.16B: byte-wise table lookup.
37773789
if ((instr->InstructionBits() & 0xFFE0FC00) == 0x4E000000) {
37783790
const VRegister vd = instr->VdField();

0 commit comments

Comments
 (0)