From 9db3cb75ba993d333a41d0ad13c348d1b9126eee Mon Sep 17 00:00:00 2001 From: Zhi An Ng Date: Thu, 14 Jan 2021 07:01:33 +0000 Subject: [PATCH] [wasm-simd][liftoff][arm] Prototype load lane Prototype load lane instructions on ARM Liftoff. We had a helper function for load lane that was living in instruction-selector. Move it out to assembler-arm so we can reuse that in Liftoff. Bug: v8:10975 Change-Id: Ic6e15c23eb778fb94a882609be622d2ca1f61ddb Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2614225 Commit-Queue: Zhi An Ng Reviewed-by: Bill Budge Cr-Commit-Position: refs/heads/master@{#72106} --- src/codegen/arm/assembler-arm.cc | 16 ++++++++ src/codegen/arm/assembler-arm.h | 21 +++++++++++ .../backend/arm/instruction-selector-arm.cc | 37 +------------------ src/wasm/baseline/arm/liftoff-assembler-arm.h | 12 +++++- 4 files changed, 50 insertions(+), 36 deletions(-) diff --git a/src/codegen/arm/assembler-arm.cc b/src/codegen/arm/assembler-arm.cc index ef8a4669c5..56da962a91 100644 --- a/src/codegen/arm/assembler-arm.cc +++ b/src/codegen/arm/assembler-arm.cc @@ -43,6 +43,7 @@ #include "src/base/overflowing-math.h" #include "src/codegen/arm/assembler-arm-inl.h" #include "src/codegen/assembler-inl.h" +#include "src/codegen/machine-type.h" #include "src/codegen/macro-assembler.h" #include "src/codegen/string-constants.h" #include "src/deoptimizer/deoptimizer.h" @@ -5397,6 +5398,21 @@ Register UseScratchRegisterScope::Acquire() { return reg; } +LoadStoreLaneParams::LoadStoreLaneParams(MachineRepresentation rep, + uint8_t laneidx) { + if (rep == MachineRepresentation::kWord8) { + *this = LoadStoreLaneParams(laneidx, Neon8, 8); + } else if (rep == MachineRepresentation::kWord16) { + *this = LoadStoreLaneParams(laneidx, Neon16, 4); + } else if (rep == MachineRepresentation::kWord32) { + *this = LoadStoreLaneParams(laneidx, Neon32, 2); + } else if (rep == MachineRepresentation::kWord64) { + *this = LoadStoreLaneParams(laneidx, Neon64, 1); + } else { + UNREACHABLE(); + } +} + } // namespace internal } // namespace v8 diff --git a/src/codegen/arm/assembler-arm.h b/src/codegen/arm/assembler-arm.h index eecb40b027..bf5859f499 100644 --- a/src/codegen/arm/assembler-arm.h +++ b/src/codegen/arm/assembler-arm.h @@ -41,6 +41,7 @@ #define V8_CODEGEN_ARM_ASSEMBLER_ARM_H_ #include + #include #include @@ -48,6 +49,7 @@ #include "src/codegen/arm/register-arm.h" #include "src/codegen/assembler.h" #include "src/codegen/constant-pool.h" +#include "src/codegen/machine-type.h" #include "src/numbers/double.h" #include "src/utils/boxed-float.h" @@ -1394,6 +1396,25 @@ class V8_EXPORT_PRIVATE V8_NODISCARD UseScratchRegisterScope { VfpRegList old_available_vfp_; }; +// Helper struct for load lane and store lane to indicate which opcode to use +// and what memory size to be encoded in the opcode, and the new lane index. +class LoadStoreLaneParams { + public: + bool low_op; + NeonSize sz; + uint8_t laneidx; + // The register mapping on ARM (1 Q to 2 D), means that loading/storing high + // lanes of a Q register is equivalent to loading/storing the high D reg, + // modulo number of lanes in a D reg. This constructor decides, based on the + // laneidx and load/store size, whether the low or high D reg is accessed, and + // what the new lane index is. + LoadStoreLaneParams(MachineRepresentation rep, uint8_t laneidx); + + private: + LoadStoreLaneParams(uint8_t laneidx, NeonSize sz, int lanes) + : low_op(laneidx < lanes), sz(sz), laneidx(laneidx % lanes) {} +}; + } // namespace internal } // namespace v8 diff --git a/src/compiler/backend/arm/instruction-selector-arm.cc b/src/compiler/backend/arm/instruction-selector-arm.cc index 6b287f7725..c36e191402 100644 --- a/src/compiler/backend/arm/instruction-selector-arm.cc +++ b/src/compiler/backend/arm/instruction-selector-arm.cc @@ -511,41 +511,9 @@ void InstructionSelector::VisitAbortCSAAssert(Node* node) { Emit(kArchAbortCSAAssert, g.NoOutput(), g.UseFixed(node->InputAt(0), r1)); } -namespace { -// Helper struct for load lane and store lane to indicate which opcode to use -// and what memory size to be encoded in the opcode, and the new lane index. -struct LoadStoreLaneParams { - bool low_op; - NeonSize sz; - uint8_t laneidx; - LoadStoreLaneParams(uint8_t laneidx, NeonSize sz, int lanes) - : low_op(laneidx < lanes), sz(sz), laneidx(laneidx % lanes) {} -}; - -// The register mapping on ARM (1 Q to 2 D), means that loading/storing high -// lanes of a Q register is equivalent to loading/storing the high D reg, modulo -// number of lanes in a D reg. This function decides, based on the laneidx and -// load/store size, whether the low or high D reg is accessed, and what the new -// lane index is. -LoadStoreLaneParams GetLoadStoreLaneParams(MachineRepresentation rep, - uint8_t laneidx) { - if (rep == MachineRepresentation::kWord8) { - return LoadStoreLaneParams(laneidx, Neon8, 8); - } else if (rep == MachineRepresentation::kWord16) { - return LoadStoreLaneParams(laneidx, Neon16, 4); - } else if (rep == MachineRepresentation::kWord32) { - return LoadStoreLaneParams(laneidx, Neon32, 2); - } else if (rep == MachineRepresentation::kWord64) { - return LoadStoreLaneParams(laneidx, Neon64, 1); - } else { - UNREACHABLE(); - } -} -} // namespace - void InstructionSelector::VisitStoreLane(Node* node) { StoreLaneParameters params = StoreLaneParametersOf(node->op()); - LoadStoreLaneParams f = GetLoadStoreLaneParams(params.rep, params.laneidx); + LoadStoreLaneParams f(params.rep, params.laneidx); InstructionCode opcode = f.low_op ? kArmS128StoreLaneLow : kArmS128StoreLaneHigh; opcode |= MiscField::encode(f.sz); @@ -563,8 +531,7 @@ void InstructionSelector::VisitStoreLane(Node* node) { void InstructionSelector::VisitLoadLane(Node* node) { LoadLaneParameters params = LoadLaneParametersOf(node->op()); - LoadStoreLaneParams f = - GetLoadStoreLaneParams(params.rep.representation(), params.laneidx); + LoadStoreLaneParams f(params.rep.representation(), params.laneidx); InstructionCode opcode = f.low_op ? kArmS128LoadLaneLow : kArmS128LoadLaneHigh; opcode |= MiscField::encode(f.sz); diff --git a/src/wasm/baseline/arm/liftoff-assembler-arm.h b/src/wasm/baseline/arm/liftoff-assembler-arm.h index 662585e4d5..1098304363 100644 --- a/src/wasm/baseline/arm/liftoff-assembler-arm.h +++ b/src/wasm/baseline/arm/liftoff-assembler-arm.h @@ -2362,7 +2362,17 @@ void LiftoffAssembler::LoadLane(LiftoffRegister dst, LiftoffRegister src, Register addr, Register offset_reg, uintptr_t offset_imm, LoadType type, uint8_t laneidx, uint32_t* protected_load_pc) { - bailout(kSimd, "loadlane"); + UseScratchRegisterScope temps(this); + Register actual_src_addr = liftoff::CalculateActualAddress( + this, &temps, addr, offset_reg, offset_imm); + TurboAssembler::Move(liftoff::GetSimd128Register(dst), + liftoff::GetSimd128Register(src)); + *protected_load_pc = pc_offset(); + LoadStoreLaneParams load_params(type.mem_type().representation(), laneidx); + NeonListOperand dst_op = + NeonListOperand(load_params.low_op ? dst.low_fp() : dst.high_fp()); + TurboAssembler::LoadLane(load_params.sz, dst_op, load_params.laneidx, + NeonMemOperand(actual_src_addr)); } void LiftoffAssembler::emit_i8x16_swizzle(LiftoffRegister dst,