[vm, compiler] Handle large offsets with double spill slots on RISC-V.

Fix non-existent addressing mode in ARM fpu spilling.

TEST=ci
Change-Id: I0ecb973059a6cab11dce5b87137b54e0d1ac5ac5
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/243703
Commit-Queue: Ryan Macnak <rmacnak@google.com>
Reviewed-by: Alexander Markov <alexmarkov@google.com>
This commit is contained in:
Ryan Macnak 2022-05-05 22:11:17 +00:00 committed by Commit Bot
parent f964af3bf3
commit 2cf4bf72a8
6 changed files with 120 additions and 13 deletions

View file

@ -2455,6 +2455,16 @@ void Assembler::PopList(RegList regs, Condition cond) {
ldm(IA_W, SP, regs, cond);
}
void Assembler::PushQuad(FpuRegister reg, Condition cond) {
DRegister dreg = EvenDRegisterOf(reg);
vstmd(DB_W, SP, dreg, 2, cond); // 2 D registers per Q register.
}
void Assembler::PopQuad(FpuRegister reg, Condition cond) {
DRegister dreg = EvenDRegisterOf(reg);
vldmd(IA_W, SP, dreg, 2, cond); // 2 D registers per Q register.
}
void Assembler::PushRegisters(const RegisterSet& regs) {
const intptr_t fpu_regs_count = regs.FpuRegisterCount();
if (fpu_regs_count > 0) {

View file

@ -1134,6 +1134,9 @@ class Assembler : public AssemblerBase {
void PushList(RegList regs, Condition cond = AL);
void PopList(RegList regs, Condition cond = AL);
void PushQuad(FpuRegister rd, Condition cond = AL);
void PopQuad(FpuRegister rd, Condition cond = AL);
void PushRegisters(const RegisterSet& regs);
void PopRegisters(const RegisterSet& regs);

View file

@ -1271,15 +1271,11 @@ void ParallelMoveResolver::RestoreScratch(Register reg) {
}
void ParallelMoveResolver::SpillFpuScratch(FpuRegister reg) {
DRegister dreg = EvenDRegisterOf(reg);
__ vstrd(dreg,
compiler::Address(SP, -kDoubleSize, compiler::Address::PreIndex));
__ PushQuad(reg);
}
void ParallelMoveResolver::RestoreFpuScratch(FpuRegister reg) {
DRegister dreg = EvenDRegisterOf(reg);
__ vldrd(dreg,
compiler::Address(SP, kDoubleSize, compiler::Address::PostIndex));
__ PopQuad(reg);
}
#undef __

View file

@ -1234,11 +1234,11 @@ void ParallelMoveResolver::RestoreScratch(Register reg) {
}
void ParallelMoveResolver::SpillFpuScratch(FpuRegister reg) {
__ PushDouble(reg);
__ PushQuad(reg);
}
void ParallelMoveResolver::RestoreFpuScratch(FpuRegister reg) {
__ PopDouble(reg);
__ PopQuad(reg);
}
#undef __

View file

@ -819,7 +819,7 @@ void FlowGraphCompiler::EmitMove(Location destination,
} else if (destination.IsFpuRegister()) {
const intptr_t src_offset = source.ToStackSlotOffset();
FRegister dst = destination.fpu_reg();
__ fld(dst, compiler::Address(source.base_reg(), src_offset));
__ LoadDFromOffset(dst, source.base_reg(), src_offset);
} else {
ASSERT(destination.IsStackSlot());
const intptr_t source_offset = source.ToStackSlotOffset();
@ -837,7 +837,7 @@ void FlowGraphCompiler::EmitMove(Location destination,
destination.IsDoubleStackSlot()) {
const intptr_t dest_offset = destination.ToStackSlotOffset();
FRegister src = source.fpu_reg();
__ fsd(src, compiler::Address(destination.base_reg(), dest_offset));
__ StoreDToOffset(src, destination.base_reg(), dest_offset);
} else {
ASSERT(destination.IsQuadStackSlot());
UNIMPLEMENTED();
@ -847,14 +847,14 @@ void FlowGraphCompiler::EmitMove(Location destination,
if (destination.IsFpuRegister()) {
const intptr_t source_offset = source.ToStackSlotOffset();
const FRegister dst = destination.fpu_reg();
__ fld(dst, compiler::Address(source.base_reg(), source_offset));
__ LoadDFromOffset(dst, source.base_reg(), source_offset);
} else {
ASSERT(destination.IsDoubleStackSlot() ||
destination.IsStackSlot() /*32-bit float*/);
const intptr_t source_offset = source.ToStackSlotOffset();
const intptr_t dest_offset = destination.ToStackSlotOffset();
__ fld(FTMP, compiler::Address(source.base_reg(), source_offset));
__ fsd(FTMP, compiler::Address(destination.base_reg(), dest_offset));
__ LoadDFromOffset(FTMP, source.base_reg(), source_offset);
__ StoreDToOffset(FTMP, destination.base_reg(), dest_offset);
}
} else if (source.IsQuadStackSlot()) {
UNIMPLEMENTED();

View file

@ -6,6 +6,7 @@
#include <vector>
#include "platform/text_buffer.h"
#include "platform/utils.h"
#include "vm/compiler/backend/block_builder.h"
#include "vm/compiler/backend/il_printer.h"
@ -146,4 +147,101 @@ ISOLATE_UNIT_TEST_CASE(FlowGraph_LateVariablePhiUnboxing) {
EXPECT_PROPERTY(late_var, it.representation() == kTagged);
}
void TestLargeFrame(const char* type,
const char* zero,
const char* one,
const char* main) {
SetFlagScope<int> sfs(&FLAG_optimization_counter_threshold, 1000);
TextBuffer printer(256 * KB);
intptr_t num_locals = 2000;
printer.Printf("import 'dart:typed_data';\n");
printer.Printf("@pragma('vm:never-inline')\n");
printer.Printf("%s one() { return %s; }\n", type, one);
printer.Printf("@pragma('vm:never-inline')\n");
printer.Printf("%s largeFrame(int n) {\n", type);
for (intptr_t i = 0; i < num_locals; i++) {
printer.Printf(" %s local%" Pd " = %s;\n", type, i, zero);
}
printer.Printf(" for (int i = 0; i < n; i++) {\n");
for (intptr_t i = 0; i < num_locals; i++) {
printer.Printf(" local%" Pd " += one();\n", i);
}
printer.Printf(" }\n");
printer.Printf(" %s sum = %s;\n", type, zero);
for (intptr_t i = 0; i < num_locals; i++) {
printer.Printf(" sum += local%" Pd ";\n", i);
}
printer.Printf(" return sum;\n");
printer.Printf("}\n");
printer.AddString(main);
const auto& root_library = Library::Handle(LoadTestScript(printer.buffer()));
Invoke(root_library, "main");
}
ISOLATE_UNIT_TEST_CASE(FlowGraph_LargeFrame_Int) {
TestLargeFrame("int", "0", "1",
"main() {\n"
" for (var i = 0; i < 100; i++) {\n"
" var r = largeFrame(1);\n"
" if (r != 2000) throw r;\n"
" }\n"
" return 'Okay';\n"
"}\n");
}
ISOLATE_UNIT_TEST_CASE(FlowGraph_LargeFrame_Double) {
TestLargeFrame("double", "0.0", "1.0",
"main() {\n"
" for (var i = 0; i < 100; i++) {\n"
" var r = largeFrame(1);\n"
" if (r != 2000.0) throw r;\n"
" }\n"
" return 'Okay';\n"
"}\n");
}
ISOLATE_UNIT_TEST_CASE(FlowGraph_LargeFrame_Int32x4) {
TestLargeFrame("Int32x4", "Int32x4(0, 0, 0, 0)", "Int32x4(1, 2, 3, 4)",
"main() {\n"
" for (var i = 0; i < 100; i++) {\n"
" var r = largeFrame(1);\n"
" if (r.x != 2000) throw r;\n"
" if (r.y != 4000) throw r;\n"
" if (r.z != 6000) throw r;\n"
" if (r.w != 8000) throw r;\n"
" }\n"
" return 'Okay';\n"
"}\n");
}
ISOLATE_UNIT_TEST_CASE(FlowGraph_LargeFrame_Float32x4) {
TestLargeFrame("Float32x4", "Float32x4(0.0, 0.0, 0.0, 0.0)",
"Float32x4(1.0, 2.0, 3.0, 4.0)",
"main() {\n"
" for (var i = 0; i < 100; i++) {\n"
" var r = largeFrame(1);\n"
" if (r.x != 2000.0) throw r;\n"
" if (r.y != 4000.0) throw r;\n"
" if (r.z != 6000.0) throw r;\n"
" if (r.w != 8000.0) throw r;\n"
" }\n"
" return 'Okay';\n"
"}\n");
}
ISOLATE_UNIT_TEST_CASE(FlowGraph_LargeFrame_Float64x2) {
TestLargeFrame("Float64x2", "Float64x2(0.0, 0.0)", "Float64x2(1.0, 2.0)",
"main() {\n"
" for (var i = 0; i < 100; i++) {\n"
" var r = largeFrame(1);\n"
" if (r.x != 2000.0) throw r;\n"
" if (r.y != 4000.0) throw r;\n"
" }\n"
" return 'Okay';\n"
"}\n");
}
} // namespace dart