Commit e06c2c85 authored by Bill Budge's avatar Bill Budge Committed by Commit Bot

[wasm] Fix wasm linkage to take advantage of all float registers on ARM

- Modifies LinkageAllocator to understand aliasing on ARM.
- Adds ability to allocate SIMD registers too. Before, these would
  default to stack allocated.
- Modifies WasmCompiler to be platform-independent.

Bug: v8:7754
Change-Id: I0c4355a44a4f409053b51ff675521a465e38aeb8
Reviewed-on: https://chromium-review.googlesource.com/1141114Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Commit-Queue: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#54533}
parent 0dd33901
......@@ -5269,32 +5269,20 @@ class LinkageLocationAllocator {
const DoubleRegister (&fp)[kNumFpRegs])
: allocator_(wasm::LinkageAllocator(gp, fp)) {}
LinkageLocation Next(MachineRepresentation type) {
MachineType mach_type = MachineType::TypeForRepresentation(type);
if (type == MachineRepresentation::kFloat32 ||
type == MachineRepresentation::kFloat64) {
if (allocator_.has_more_fp_regs()) {
DoubleRegister reg = allocator_.NextFpReg();
#if V8_TARGET_ARCH_ARM
// Allocate floats using a double register, but modify the code to
// reflect how ARM FP registers alias.
// TODO(bbudge) Modify wasm linkage to allow use of all float regs.
if (type == MachineRepresentation::kFloat32) {
int float_reg_code = reg.code() * 2;
DCHECK_GT(RegisterConfiguration::kMaxFPRegisters, float_reg_code);
return LinkageLocation::ForRegister(
DoubleRegister::from_code(float_reg_code).code(), mach_type);
}
#endif
return LinkageLocation::ForRegister(reg.code(), mach_type);
LinkageLocation Next(MachineRepresentation rep) {
MachineType type = MachineType::TypeForRepresentation(rep);
if (IsFloatingPoint(rep)) {
if (allocator_.CanAllocateFP(rep)) {
int reg_code = allocator_.NextFpReg(rep);
return LinkageLocation::ForRegister(reg_code, type);
}
} else if (allocator_.has_more_gp_regs()) {
return LinkageLocation::ForRegister(allocator_.NextGpReg().code(),
mach_type);
} else if (allocator_.CanAllocateGP()) {
int reg_code = allocator_.NextGpReg();
return LinkageLocation::ForRegister(reg_code, type);
}
// Cannot use register; use stack slot.
int index = -1 - allocator_.NextStackSlot(type);
return LinkageLocation::ForCallerFrameSlot(index, mach_type);
int index = -1 - allocator_.NextStackSlot(rep);
return LinkageLocation::ForCallerFrameSlot(index, type);
}
void SetStackOffset(int offset) { allocator_.SetStackOffset(offset); }
......
......@@ -124,17 +124,85 @@ class LinkageAllocator {
const DoubleRegister* fp, int fpc)
: gp_count_(gpc), gp_regs_(gp), fp_count_(fpc), fp_regs_(fp) {}
bool has_more_gp_regs() const { return gp_offset_ < gp_count_; }
bool has_more_fp_regs() const { return fp_offset_ < fp_count_; }
bool CanAllocateGP() const { return gp_offset_ < gp_count_; }
bool CanAllocateFP(MachineRepresentation rep) const {
#if V8_TARGET_ARCH_ARM
switch (rep) {
case MachineRepresentation::kFloat32:
return extra_float_reg >= 0 || fp_offset_ < fp_count_;
case MachineRepresentation::kFloat64:
return extra_double_reg >= 0 || fp_offset_ < fp_count_;
case MachineRepresentation::kSimd128:
return ((fp_offset_ + 1) & ~1) + 1 < fp_count_;
default:
UNREACHABLE();
return false;
}
#endif
return fp_offset_ < fp_count_;
}
Register NextGpReg() {
int NextGpReg() {
DCHECK_LT(gp_offset_, gp_count_);
return gp_regs_[gp_offset_++];
return gp_regs_[gp_offset_++].code();
}
DoubleRegister NextFpReg() {
int NextFpReg(MachineRepresentation rep) {
#if V8_TARGET_ARCH_ARM
switch (rep) {
case MachineRepresentation::kFloat32: {
// Use the extra S-register if we can.
if (extra_float_reg >= 0) {
int reg_code = extra_float_reg;
extra_float_reg = -1;
return reg_code;
}
// Allocate a D-register and split into 2 float registers.
int d_reg_code = NextFpReg(MachineRepresentation::kFloat64);
DCHECK_GT(16, d_reg_code); // D-registers 16 - 31 can't split.
int reg_code = d_reg_code * 2;
// Save the extra S-register.
DCHECK_EQ(-1, extra_float_reg);
extra_float_reg = reg_code + 1;
return reg_code;
}
case MachineRepresentation::kFloat64: {
// Use an extra D-register if we can.
if (extra_double_reg >= 0) {
int reg_code = extra_double_reg;
extra_double_reg = -1;
return reg_code;
}
DCHECK_LT(fp_offset_, fp_count_);
return fp_regs_[fp_offset_++].code();
}
case MachineRepresentation::kSimd128: {
// Q-register must be an even-odd pair, so we must try to allocate at
// the end, not using extra_double_reg. If we are at an odd D-register,
// skip past it (saving it to extra_double_reg).
DCHECK_LT(((fp_offset_ + 1) & ~1) + 1, fp_count_);
int d_reg1_code = fp_regs_[fp_offset_++].code();
if (d_reg1_code % 2 != 0) {
// If we're misaligned then extra_double_reg must have been consumed.
DCHECK_EQ(-1, extra_double_reg);
int odd_double_reg = d_reg1_code;
d_reg1_code = fp_regs_[fp_offset_++].code();
extra_double_reg = odd_double_reg;
}
// Combine the current D-register with the next to form a Q-register.
int d_reg2_code = fp_regs_[fp_offset_++].code();
DCHECK_EQ(0, d_reg1_code % 2);
DCHECK_EQ(d_reg1_code + 1, d_reg2_code);
USE(d_reg2_code);
return d_reg1_code / 2;
}
default:
UNREACHABLE();
}
#else
DCHECK_LT(fp_offset_, fp_count_);
return fp_regs_[fp_offset_++];
return fp_regs_[fp_offset_++].code();
#endif
}
// Stackslots are counted upwards starting from 0 (or the offset set by
......@@ -172,6 +240,14 @@ class LinkageAllocator {
int fp_offset_ = 0;
const DoubleRegister* const fp_regs_;
#if V8_TARGET_ARCH_ARM
// ARM FP register aliasing may require splitting or merging double registers.
// Track fragments of registers below fp_offset_ here. There can only be one
// extra float and double register.
int extra_float_reg = -1;
int extra_double_reg = -1;
#endif
int stack_offset_ = 0;
};
......
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