Skip to content

Commit 1f0ec8e

Browse files
modulovaluedart-scoped@luci-project-accounts.iam.gserviceaccount.com
authored andcommitted
[vm] arm64: add tbl
Needed to improve the performance of Int32x4.shuffle and Float32x4.shuffle. Also print the offset of 128-bit SIMD&FP loads and stores scaled by 16, as the disassembler printed it 16 times too small. Issue: #64170 Issue: #64345 TEST=vm/cc/Assembler_Tbl1 Change-Id: Icd4a3fb04600aaa28e038d04ef12164e292aa117 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/559001 Commit-Queue: Alexander Aprelev <aam@google.com> Reviewed-by: Slava Egorov <vegorov@google.com> Auto-Submit: Modestas Valauskas <valauskasmodestas@gmail.com> Reviewed-by: Alexander Aprelev <aam@google.com>
1 parent 693320c commit 1f0ec8e

4 files changed

Lines changed: 81 additions & 1 deletion

File tree

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1568,6 +1568,15 @@ class Assembler : public AssemblerBase {
15681568
(static_cast<int32_t>(vd) << kVdShift);
15691569
Emit(encoding);
15701570
}
1571+
// TBL Vd.16B, {Vn.16B}, Vm.16B: byte i of Vd is byte Vm[i] of Vn, or zero
1572+
// when Vm[i] is 16 or more.
1573+
void vtbl1(VRegister vd, VRegister vn, VRegister vm) {
1574+
const int32_t encoding = 0x4E000000 |
1575+
(static_cast<int32_t>(vm) << kVmShift) |
1576+
(static_cast<int32_t>(vn) << kVnShift) |
1577+
(static_cast<int32_t>(vd) << kVdShift);
1578+
Emit(encoding);
1579+
}
15711580
// UMINV Sd, Vn.4S: unsigned minimum across the four word lanes of Vn into the
15721581
// 32-bit scalar in the low bits of Vd.
15731582
void vuminv_4s(VRegister vd, VRegister vn) {

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

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2407,6 +2407,51 @@ ASSEMBLER_TEST_RUN(Uminv4S, test) {
24072407
"ret\n");
24082408
}
24092409

2410+
ASSEMBLER_TEST_GENERATE(Tbl1, assembler) {
2411+
__ fldrq(V1, Address(R0, 0));
2412+
__ fldrq(V2, Address(R0, 16));
2413+
__ vtbl1(V0, V1, V2);
2414+
__ fstrq(V0, Address(R0, 32));
2415+
__ ret();
2416+
}
2417+
2418+
ASSEMBLER_TEST_RUN(Tbl1, test) {
2419+
struct {
2420+
uint8_t table[16];
2421+
uint8_t indices[16];
2422+
uint8_t result[16];
2423+
} buffer = {{0x85, 0x98, 0xAB, 0xBE, 0xD1, 0xE4, 0xF7, 0x8A, 0x9D, 0xB0, 0xC3,
2424+
0xD6, 0xE9, 0xFC, 0x8F, 0xA2},
2425+
{0x0F, 0x00, 0x07, 0x08, 0x10, 0x03, 0xFF, 0x0C, 0x01, 0x0E, 0x80,
2426+
0x05, 0x0A, 0x1F, 0x06, 0x0B},
2427+
{0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
2428+
0x5A, 0x5A, 0x5A, 0x5A, 0x5A}};
2429+
typedef void (*Tbl1Code)(void* buffer) DART_UNUSED;
2430+
reinterpret_cast<Tbl1Code>(test->entry())(&buffer);
2431+
EXPECT_EQ(0xA2, buffer.result[0]);
2432+
EXPECT_EQ(0x85, buffer.result[1]);
2433+
EXPECT_EQ(0x8A, buffer.result[2]);
2434+
EXPECT_EQ(0x9D, buffer.result[3]);
2435+
EXPECT_EQ(0x00, buffer.result[4]);
2436+
EXPECT_EQ(0xBE, buffer.result[5]);
2437+
EXPECT_EQ(0x00, buffer.result[6]);
2438+
EXPECT_EQ(0xE9, buffer.result[7]);
2439+
EXPECT_EQ(0x98, buffer.result[8]);
2440+
EXPECT_EQ(0x8F, buffer.result[9]);
2441+
EXPECT_EQ(0x00, buffer.result[10]);
2442+
EXPECT_EQ(0xE4, buffer.result[11]);
2443+
EXPECT_EQ(0xC3, buffer.result[12]);
2444+
EXPECT_EQ(0x00, buffer.result[13]);
2445+
EXPECT_EQ(0xF7, buffer.result[14]);
2446+
EXPECT_EQ(0xD6, buffer.result[15]);
2447+
EXPECT_DISASSEMBLY(
2448+
"fldrq v1, [r0]\n"
2449+
"fldrq v2, [r0, #16]\n"
2450+
"vtbl1 v0, v1, v2\n"
2451+
"fstrq v0, [r0, #32]\n"
2452+
"ret\n");
2453+
}
2454+
24102455
// Comparisons, branching.
24112456
ASSEMBLER_TEST_GENERATE(BranchALForward, assembler) {
24122457
Label l;

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

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,9 @@ void ARM64Decoder::PrintMemOperand(Instr* instr) {
185185
const Register rn = instr->RnField();
186186
if (instr->Bit(24) == 1) {
187187
// rn + scaled unsigned 12-bit immediate offset.
188-
const uint32_t scale = instr->SzField();
188+
const bool is_simd128 = (instr->Bit(26) == 1) && (instr->SzField() == 0) &&
189+
(instr->Bit(23) == 1);
190+
const uint32_t scale = is_simd128 ? 4 : instr->SzField();
189191
const uint32_t imm12 = instr->Imm12Field();
190192
const uint32_t off = imm12 << scale;
191193
Print("[");
@@ -1596,6 +1598,11 @@ void ARM64Decoder::DecodeDPSimd1(Instr* instr) {
15961598
Format(instr, "vuminv 'vd, 'vn");
15971599
return;
15981600
}
1601+
// TBL Vd.16B, {Vn.16B}, Vm.16B (Q=1, len=0, op=0 table lookup form).
1602+
if ((instr->InstructionBits() & 0xFFE0FC00) == 0x4E000000) {
1603+
Format(instr, "vtbl1 'vd, 'vn, 'vm");
1604+
return;
1605+
}
15991606
if (instr->IsSIMDCopyOp()) {
16001607
DecodeSIMDCopy(instr);
16011608
} else if (instr->IsSIMDThreeSameOp()) {

‎runtime/vm/simulator_arm64.cc‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3762,6 +3762,25 @@ void Simulator::DecodeDPSimd1(Instr* instr) {
37623762
return;
37633763
}
37643764

3765+
// TBL Vd.16B, {Vn.16B}, Vm.16B: byte-wise table lookup.
3766+
if ((instr->InstructionBits() & 0xFFE0FC00) == 0x4E000000) {
3767+
const VRegister vd = instr->VdField();
3768+
const VRegister vn = instr->VnField();
3769+
const VRegister vm = instr->VmField();
3770+
int64_t table_bits[2] = {get_vregisterd(vn, 0), get_vregisterd(vn, 1)};
3771+
int64_t index_bits[2] = {get_vregisterd(vm, 0), get_vregisterd(vm, 1)};
3772+
const uint8_t* table = reinterpret_cast<const uint8_t*>(&table_bits[0]);
3773+
const uint8_t* index = reinterpret_cast<const uint8_t*>(&index_bits[0]);
3774+
int64_t result_bits[2];
3775+
uint8_t* result = reinterpret_cast<uint8_t*>(&result_bits[0]);
3776+
for (int i = 0; i < 16; i++) {
3777+
result[i] = index[i] < 16 ? table[index[i]] : 0;
3778+
}
3779+
set_vregisterd(vd, 0, result_bits[0]);
3780+
set_vregisterd(vd, 1, result_bits[1]);
3781+
return;
3782+
}
3783+
37653784
// UMINV Sd, Vn.4S — unsigned minimum across the four word lanes.
37663785
if ((instr->InstructionBits() & 0xFFFFFC00) == 0x6EB1A800) {
37673786
const VRegister vd = instr->VdField();

0 commit comments

Comments
 (0)