Commit 2332ebd8 authored by Thibaud Michaud's avatar Thibaud Michaud Committed by Commit Bot

[liftoff][mv] Remove multi-value overhead

- Add a separate function to load return slots, instead of encoding this
in the offset,
- Add fast path for single return.

Drive-by: Reuse helper function for stack slot loads on ia32 and x64.

R=clemensb@chromium.org

Bug: v8:10576
Change-Id: Iea5ad2f0982c443cf2297227e9a2367cbb14581f
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2264099Reviewed-by: 's avatarClemens Backes <clemensb@chromium.org>
Commit-Queue: Thibaud Michaud <thibaudm@chromium.org>
Cr-Commit-Position: refs/heads/master@{#68535}
parent 6e856b5e
......@@ -45,9 +45,7 @@ constexpr int kInstanceOffset = 2 * kSystemPointerSize;
constexpr int32_t kPatchInstructionsRequired = 3;
constexpr int kHalfStackSlotSize = LiftoffAssembler::kStackSlotSize >> 1;
inline MemOperand GetStackSlot(int offset) {
return MemOperand(offset > 0 ? fp : sp, -offset);
}
inline MemOperand GetStackSlot(int offset) { return MemOperand(fp, -offset); }
inline MemOperand GetHalfStackSlot(int offset, RegPairHalf half) {
int32_t half_offset =
......@@ -1228,6 +1226,12 @@ void LiftoffAssembler::StoreCallerFrameSlot(LiftoffRegister src,
liftoff::Store(this, src, dst, type);
}
void LiftoffAssembler::LoadReturnStackSlot(LiftoffRegister dst, int offset,
ValueType type) {
MemOperand src(sp, offset);
liftoff::Load(this, dst, src, type);
}
void LiftoffAssembler::MoveStackValue(uint32_t dst_offset, uint32_t src_offset,
ValueType type) {
DCHECK_NE(dst_offset, src_offset);
......
......@@ -41,9 +41,7 @@ namespace liftoff {
constexpr int kInstanceOffset = 2 * kSystemPointerSize;
inline MemOperand GetStackSlot(int offset) {
return MemOperand(offset > 0 ? fp : sp, -offset);
}
inline MemOperand GetStackSlot(int offset) { return MemOperand(fp, -offset); }
inline MemOperand GetInstanceOperand() { return GetStackSlot(kInstanceOffset); }
......@@ -697,6 +695,11 @@ void LiftoffAssembler::StoreCallerFrameSlot(LiftoffRegister src,
Str(liftoff::GetRegFromType(src, type), MemOperand(fp, offset));
}
void LiftoffAssembler::LoadReturnStackSlot(LiftoffRegister dst, int offset,
ValueType type) {
Ldr(liftoff::GetRegFromType(dst, type), MemOperand(sp, offset));
}
void LiftoffAssembler::MoveStackValue(uint32_t dst_offset, uint32_t src_offset,
ValueType type) {
UseScratchRegisterScope temps(this);
......
......@@ -23,9 +23,7 @@ namespace liftoff {
// ebp-4 holds the stack marker, ebp-8 is the instance parameter.
constexpr int kInstanceOffset = 8;
inline Operand GetStackSlot(int offset) {
return Operand(offset > 0 ? ebp : esp, -offset);
}
inline Operand GetStackSlot(int offset) { return Operand(ebp, -offset); }
inline MemOperand GetHalfStackSlot(int offset, RegPairHalf half) {
int32_t half_offset =
......@@ -632,6 +630,11 @@ void LiftoffAssembler::LoadCallerFrameSlot(LiftoffRegister dst,
type);
}
void LiftoffAssembler::LoadReturnStackSlot(LiftoffRegister reg, int offset,
ValueType type) {
liftoff::Load(this, reg, esp, offset, type);
}
void LiftoffAssembler::StoreCallerFrameSlot(LiftoffRegister src,
uint32_t caller_slot_idx,
ValueType type) {
......@@ -719,27 +722,7 @@ void LiftoffAssembler::Spill(int offset, WasmValue value) {
}
void LiftoffAssembler::Fill(LiftoffRegister reg, int offset, ValueType type) {
Operand src = liftoff::GetStackSlot(offset);
switch (type.kind()) {
case ValueType::kI32:
mov(reg.gp(), src);
break;
case ValueType::kI64:
mov(reg.low_gp(), liftoff::GetHalfStackSlot(offset, kLowWord));
mov(reg.high_gp(), liftoff::GetHalfStackSlot(offset, kHighWord));
break;
case ValueType::kF32:
movss(reg.fp(), src);
break;
case ValueType::kF64:
movsd(reg.fp(), src);
break;
case ValueType::kS128:
movdqu(reg.fp(), src);
break;
default:
UNREACHABLE();
}
liftoff::Load(this, reg, ebp, -offset, type);
}
void LiftoffAssembler::FillI64Half(Register reg, int offset, RegPairHalf half) {
......
......@@ -828,7 +828,7 @@ void LiftoffAssembler::FinishCall(const FunctionSig* sig,
} else {
DCHECK(loc.IsCallerFrameSlot());
reg_pair[pair_idx] = GetUnusedRegister(rc, pinned);
Fill(reg_pair[pair_idx], -return_offset, lowered_type);
LoadReturnStackSlot(reg_pair[pair_idx], return_offset, lowered_type);
const int type_size = lowered_type.element_size_bytes();
const int slot_size = RoundUp<kSystemPointerSize>(type_size);
return_offset += slot_size;
......@@ -877,6 +877,29 @@ void LiftoffAssembler::ParallelRegisterMove(
void LiftoffAssembler::MoveToReturnLocations(
const FunctionSig* sig, compiler::CallDescriptor* descriptor) {
StackTransferRecipe stack_transfers(this);
if (sig->return_count() == 1) {
ValueType return_type = sig->GetReturn(0);
// Defaults to a gp reg, will be set below if return type is not gp.
LiftoffRegister return_reg = LiftoffRegister(kGpReturnRegisters[0]);
if (needs_gp_reg_pair(return_type)) {
return_reg = LiftoffRegister::ForPair(kGpReturnRegisters[0],
kGpReturnRegisters[1]);
} else if (needs_fp_reg_pair(return_type)) {
return_reg = LiftoffRegister::ForFpPair(kFpReturnRegisters[0]);
} else if (reg_class_for(return_type) == kFpReg) {
return_reg = LiftoffRegister(kFpReturnRegisters[0]);
} else {
DCHECK_EQ(kGpReg, reg_class_for(return_type));
}
stack_transfers.LoadIntoRegister(return_reg,
cache_state_.stack_state.back(),
cache_state_.stack_state.back().offset());
return;
}
// Slow path for multi-return.
int call_desc_return_idx = 0;
DCHECK_LE(sig->return_count(), cache_state_.stack_height());
VarState* slots = cache_state_.stack_state.end() - sig->return_count();
......@@ -902,7 +925,6 @@ void LiftoffAssembler::MoveToReturnLocations(
}
// Prepare and execute stack transfers.
call_desc_return_idx = 0;
StackTransferRecipe stack_transfers(this);
for (size_t i = 0; i < sig->return_count(); ++i) {
ValueType return_type = sig->GetReturn(i);
bool needs_gp_pair = needs_gp_reg_pair(return_type);
......
......@@ -541,6 +541,7 @@ class LiftoffAssembler : public TurboAssembler {
ValueType);
inline void StoreCallerFrameSlot(LiftoffRegister, uint32_t caller_slot_idx,
ValueType);
inline void LoadReturnStackSlot(LiftoffRegister, int offset, ValueType);
inline void MoveStackValue(uint32_t dst_offset, uint32_t src_offset,
ValueType);
......
......@@ -35,9 +35,7 @@ static_assert((kLiftoffAssemblerFpCacheRegs &
// rbp-8 holds the stack marker, rbp-16 is the instance parameter.
constexpr int kInstanceOffset = 16;
inline Operand GetStackSlot(int offset) {
return Operand(offset > 0 ? rbp : rsp, -offset);
}
inline Operand GetStackSlot(int offset) { return Operand(rbp, -offset); }
// TODO(clemensb): Make this a constexpr variable once Operand is constexpr.
inline Operand GetInstanceOperand() { return GetStackSlot(kInstanceOffset); }
......@@ -699,6 +697,12 @@ void LiftoffAssembler::StoreCallerFrameSlot(LiftoffRegister src,
liftoff::Store(this, dst, src, type);
}
void LiftoffAssembler::LoadReturnStackSlot(LiftoffRegister reg, int offset,
ValueType type) {
Operand src(rsp, offset);
liftoff::Load(this, reg, src, type);
}
void LiftoffAssembler::MoveStackValue(uint32_t dst_offset, uint32_t src_offset,
ValueType type) {
DCHECK_NE(dst_offset, src_offset);
......@@ -789,26 +793,7 @@ void LiftoffAssembler::Spill(int offset, WasmValue value) {
}
void LiftoffAssembler::Fill(LiftoffRegister reg, int offset, ValueType type) {
Operand src = liftoff::GetStackSlot(offset);
switch (type.kind()) {
case ValueType::kI32:
movl(reg.gp(), src);
break;
case ValueType::kI64:
movq(reg.gp(), src);
break;
case ValueType::kF32:
Movss(reg.fp(), src);
break;
case ValueType::kF64:
Movsd(reg.fp(), src);
break;
case ValueType::kS128:
Movdqu(reg.fp(), src);
break;
default:
UNREACHABLE();
}
liftoff::Load(this, reg, liftoff::GetStackSlot(offset), type);
}
void LiftoffAssembler::FillI64Half(Register, int offset, RegPairHalf) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment