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 { ...@@ -5269,32 +5269,20 @@ class LinkageLocationAllocator {
const DoubleRegister (&fp)[kNumFpRegs]) const DoubleRegister (&fp)[kNumFpRegs])
: allocator_(wasm::LinkageAllocator(gp, fp)) {} : allocator_(wasm::LinkageAllocator(gp, fp)) {}
LinkageLocation Next(MachineRepresentation type) { LinkageLocation Next(MachineRepresentation rep) {
MachineType mach_type = MachineType::TypeForRepresentation(type); MachineType type = MachineType::TypeForRepresentation(rep);
if (type == MachineRepresentation::kFloat32 || if (IsFloatingPoint(rep)) {
type == MachineRepresentation::kFloat64) { if (allocator_.CanAllocateFP(rep)) {
if (allocator_.has_more_fp_regs()) { int reg_code = allocator_.NextFpReg(rep);
DoubleRegister reg = allocator_.NextFpReg(); return LinkageLocation::ForRegister(reg_code, type);
#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);
} }
} else if (allocator_.has_more_gp_regs()) { } else if (allocator_.CanAllocateGP()) {
return LinkageLocation::ForRegister(allocator_.NextGpReg().code(), int reg_code = allocator_.NextGpReg();
mach_type); return LinkageLocation::ForRegister(reg_code, type);
} }
// Cannot use register; use stack slot. // Cannot use register; use stack slot.
int index = -1 - allocator_.NextStackSlot(type); int index = -1 - allocator_.NextStackSlot(rep);
return LinkageLocation::ForCallerFrameSlot(index, mach_type); return LinkageLocation::ForCallerFrameSlot(index, type);
} }
void SetStackOffset(int offset) { allocator_.SetStackOffset(offset); } void SetStackOffset(int offset) { allocator_.SetStackOffset(offset); }
......
...@@ -124,17 +124,85 @@ class LinkageAllocator { ...@@ -124,17 +124,85 @@ class LinkageAllocator {
const DoubleRegister* fp, int fpc) const DoubleRegister* fp, int fpc)
: gp_count_(gpc), gp_regs_(gp), fp_count_(fpc), fp_regs_(fp) {} : gp_count_(gpc), gp_regs_(gp), fp_count_(fpc), fp_regs_(fp) {}
bool has_more_gp_regs() const { return gp_offset_ < gp_count_; } bool CanAllocateGP() const { return gp_offset_ < gp_count_; }
bool has_more_fp_regs() const { return fp_offset_ < fp_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_); 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_); 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 // Stackslots are counted upwards starting from 0 (or the offset set by
...@@ -172,6 +240,14 @@ class LinkageAllocator { ...@@ -172,6 +240,14 @@ class LinkageAllocator {
int fp_offset_ = 0; int fp_offset_ = 0;
const DoubleRegister* const fp_regs_; 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; 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