From 360fd45435e257473aec48e41bd702499846d5ff Mon Sep 17 00:00:00 2001 From: Daco Harkes Date: Fri, 3 Feb 2023 12:55:31 +0000 Subject: [PATCH] [vm] `MemoryCopyInstr` increase element size if possible A larger element size results in larger mov instructions. This reduces code size and increase performance. The element size can only be increased if * src_offset, dest_offset, and length parameters are const, * and if they contain a common denominator (powers of two). TEST=runtime/vm/compiler/backend/memory_copy_test.cc Bug: https://github.com/dart-lang/sdk/issues/51031 Change-Id: If35fb419aa118c497b15c122bdf6279266e2294a Cq-Include-Trybots: luci.dart.try:vm-precomp-ffi-qemu-linux-release-riscv64-try,vm-precomp-ffi-qemu-linux-release-arm-try,vm-ffi-android-debug-arm64c-try,vm-ffi-android-debug-arm-try,vm-kernel-nnbd-mac-debug-arm64-try,vm-kernel-nnbd-win-debug-x64-try,vm-kernel-win-debug-x64c-try,vm-kernel-win-debug-ia32-try,vm-kernel-nnbd-linux-debug-ia32-try,vm-reload-rollback-linux-debug-x64-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/279506 Commit-Queue: Daco Harkes Reviewed-by: Aske Simon Christensen Reviewed-by: Alexander Markov --- runtime/vm/compiler/backend/il.cc | 39 +++++++++++++++++++ runtime/vm/compiler/backend/il.h | 6 +++ .../vm/compiler/backend/memory_copy_test.cc | 5 +++ 3 files changed, 50 insertions(+) diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc index 7123f422974d..75a7ee973359 100644 --- a/runtime/vm/compiler/backend/il.cc +++ b/runtime/vm/compiler/backend/il.cc @@ -26,6 +26,7 @@ #include "vm/compiler/frontend/kernel_translation_helper.h" #include "vm/compiler/jit/compiler.h" #include "vm/compiler/method_recognizer.h" +#include "vm/compiler/runtime_api.h" #include "vm/cpu.h" #include "vm/dart_entry.h" #include "vm/object.h" @@ -6585,6 +6586,44 @@ Representation StoreIndexedInstr::RequiredInputRepresentation( return RepresentationOfArrayElement(class_id()); } +Instruction* MemoryCopyInstr::Canonicalize(FlowGraph* flow_graph) { + if (!length()->BindsToSmiConstant() || !src_start()->BindsToSmiConstant() || + !dest_start()->BindsToSmiConstant()) { + // TODO(https://dartbug.com/51031): Consider adding support for src/dest + // starts to be in bytes rather than element size. + return this; + } + + intptr_t new_length = length()->BoundSmiConstant(); + intptr_t new_src_start = src_start()->BoundSmiConstant(); + intptr_t new_dest_start = dest_start()->BoundSmiConstant(); + intptr_t new_element_size = element_size_; + while (((new_length | new_src_start | new_dest_start) & 1) == 0 && + new_element_size < compiler::target::kWordSize) { + new_length >>= 1; + new_src_start >>= 1; + new_dest_start >>= 1; + new_element_size <<= 1; + } + if (new_element_size == element_size_) { + return this; + } + + Zone* const zone = flow_graph->zone(); + auto* const length_instr = flow_graph->GetConstant( + Integer::ZoneHandle(zone, Integer::New(new_length, Heap::kOld)), + unboxed_length_ ? kUnboxedIntPtr : kTagged); + auto* const src_start_instr = flow_graph->GetConstant( + Integer::ZoneHandle(zone, Integer::New(new_src_start, Heap::kOld))); + auto* const dest_start_instr = flow_graph->GetConstant( + Integer::ZoneHandle(zone, Integer::New(new_dest_start, Heap::kOld))); + length()->BindTo(length_instr); + src_start()->BindTo(src_start_instr); + dest_start()->BindTo(dest_start_instr); + element_size_ = new_element_size; + return this; +} + bool Utf8ScanInstr::IsScanFlagsUnboxed() const { return scan_flags_field_.is_unboxed(); } diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h index 4a17295f20b3..ca29d52edf5a 100644 --- a/runtime/vm/compiler/backend/il.h +++ b/runtime/vm/compiler/backend/il.h @@ -3078,6 +3078,12 @@ class MemoryCopyInstr : public TemplateInstruction<5, NoThrow> { Value* dest_start() const { return inputs_[kDestStartPos]; } Value* length() const { return inputs_[kLengthPos]; } + intptr_t element_size() const { return element_size_; } + bool unboxed_length() const { return unboxed_length_; } + + // Optimizes MemoryCopyInstr with constant parameters to use larger moves. + virtual Instruction* Canonicalize(FlowGraph* flow_graph); + #define FIELD_LIST(F) \ F(classid_t, src_cid_) \ F(classid_t, dest_cid_) \ diff --git a/runtime/vm/compiler/backend/memory_copy_test.cc b/runtime/vm/compiler/backend/memory_copy_test.cc index d44e4ea9c533..f57c0a2e7bd4 100644 --- a/runtime/vm/compiler/backend/memory_copy_test.cc +++ b/runtime/vm/compiler/backend/memory_copy_test.cc @@ -234,4 +234,9 @@ MEMORY_COPY_TEST(5, 72, 1, 8) MEMORY_COPY_TEST(13, 14, 15, 16) #endif +// Size promotions with offsets. +MEMORY_COPY_TEST(2, 2, 8, 1) // promoted to 2. +MEMORY_COPY_TEST(4, 4, 8, 1) // promoted to 4. +MEMORY_COPY_TEST(8, 8, 8, 1) // promoted to 8. + } // namespace dart