diff --git a/runtime/vm/compiler/assembler/assembler_arm.cc b/runtime/vm/compiler/assembler/assembler_arm.cc index 771887ead8f..dac6e389fe5 100644 --- a/runtime/vm/compiler/assembler/assembler_arm.cc +++ b/runtime/vm/compiler/assembler/assembler_arm.cc @@ -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) { diff --git a/runtime/vm/compiler/assembler/assembler_arm.h b/runtime/vm/compiler/assembler/assembler_arm.h index 821426e0df2..ff2af91831c 100644 --- a/runtime/vm/compiler/assembler/assembler_arm.h +++ b/runtime/vm/compiler/assembler/assembler_arm.h @@ -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); diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc index 6bdd47615d2..e7379947468 100644 --- a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc +++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc @@ -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 __ diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc index b4f95bd3cf4..d7a6ff61f43 100644 --- a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc +++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc @@ -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 __ diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_riscv.cc b/runtime/vm/compiler/backend/flow_graph_compiler_riscv.cc index c129e1b7805..6e0172d2149 100644 --- a/runtime/vm/compiler/backend/flow_graph_compiler_riscv.cc +++ b/runtime/vm/compiler/backend/flow_graph_compiler_riscv.cc @@ -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(); diff --git a/runtime/vm/compiler/backend/flow_graph_test.cc b/runtime/vm/compiler/backend/flow_graph_test.cc index 8f82bb12c68..d97244f0d94 100644 --- a/runtime/vm/compiler/backend/flow_graph_test.cc +++ b/runtime/vm/compiler/backend/flow_graph_test.cc @@ -6,6 +6,7 @@ #include +#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 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