PPC: make simd registers independent of double/fp registers

PPC Simd regs are already using separate set of register banks
on ppc, more details can be found here:
https://crrev.com/c/2718472

Here we are making use of this CL https://crrev.com/c/3005768
(fcd3ef4) and fully separating Simd regs during register allocation.

Member function `toSimd()` is also introduced which will be used
to cast FP regs to Simd regs in liftoff.

Change-Id: Ic5551fb04f37de7fc9501a2f1aba8fb44f622d95
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3755213
Commit-Queue: Milad Farazmand <mfarazma@redhat.com>
Reviewed-by: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/main@{#81707}
This commit is contained in:
Milad Fa 2022-07-12 14:55:20 -04:00 committed by V8 LUCI CQ
parent 060f05787c
commit dda8d86087
3 changed files with 68 additions and 50 deletions

View File

@ -42,6 +42,12 @@ namespace internal {
#define DOUBLE_REGISTERS(V) \
LOW_DOUBLE_REGISTERS(V) NON_LOW_DOUBLE_REGISTERS(V)
#define ALLOCATABLE_DOUBLE_REGISTERS(V) \
V(d1) V(d2) V(d3) V(d4) V(d5) V(d6) V(d7) \
V(d8) V(d9) V(d10) V(d11) V(d12) V(d15) \
V(d16) V(d17) V(d18) V(d19) V(d20) V(d21) V(d22) V(d23) \
V(d24) V(d25) V(d26) V(d27) V(d28) V(d29) V(d30) V(d31)
#define FLOAT_REGISTERS DOUBLE_REGISTERS
#define SIMD128_REGISTERS(V) \
V(v0) V(v1) V(v2) V(v3) V(v4) V(v5) V(v6) V(v7) \
@ -49,11 +55,11 @@ namespace internal {
V(v16) V(v17) V(v18) V(v19) V(v20) V(v21) V(v22) V(v23) \
V(v24) V(v25) V(v26) V(v27) V(v28) V(v29) V(v30) V(v31)
#define ALLOCATABLE_DOUBLE_REGISTERS(V) \
V(d1) V(d2) V(d3) V(d4) V(d5) V(d6) V(d7) \
V(d8) V(d9) V(d10) V(d11) V(d12) V(d15) \
V(d16) V(d17) V(d18) V(d19) V(d20) V(d21) V(d22) V(d23) \
V(d24) V(d25) V(d26) V(d27) V(d28) V(d29) V(d30) V(d31)
#define ALLOCATABLE_SIMD128_REGISTERS(V) \
V(v0) V(v1) V(v2) V(v3) V(v4) V(v5) V(v6) V(v7) \
V(v8) V(v9) V(v10) V(v11) V(v12) V(v15) \
V(v16) V(v17) V(v18) V(v19) V(v20) V(v21) V(v22) V(v23) \
V(v24) V(v25) V(v26) V(v27) V(v28) V(v29) V(v30) V(v31)
#define C_REGISTERS(V) \
V(cr0) V(cr1) V(cr2) V(cr3) V(cr4) V(cr5) V(cr6) V(cr7) \
@ -138,41 +144,9 @@ constexpr int ArgumentPaddingSlots(int argument_count) {
return 0;
}
constexpr AliasingKind kFPAliasing = AliasingKind::kOverlap;
constexpr AliasingKind kFPAliasing = AliasingKind::kIndependent;
constexpr bool kSimdMaskRegisters = false;
enum DoubleRegisterCode {
#define REGISTER_CODE(R) kDoubleCode_##R,
DOUBLE_REGISTERS(REGISTER_CODE)
#undef REGISTER_CODE
kDoubleAfterLast
};
// Double word FP register.
class DoubleRegister : public RegisterBase<DoubleRegister, kDoubleAfterLast> {
public:
// A few double registers are reserved: one as a scratch register and one to
// hold 0.0, that does not fit in the immediate field of vmov instructions.
// d14: 0.0
// d15: scratch register.
static constexpr int kSizeInBytes = 8;
// This function differs from kNumRegisters by returning the number of double
// registers supported by the current CPU, while kNumRegisters always returns
// 32.
inline static int SupportedRegisterCount();
private:
friend class RegisterBase;
explicit constexpr DoubleRegister(int code) : RegisterBase(code) {}
};
ASSERT_TRIVIALLY_COPYABLE(DoubleRegister);
static_assert(sizeof(DoubleRegister) <= sizeof(int),
"DoubleRegister can efficiently be passed by value");
using FloatRegister = DoubleRegister;
// | | 0
// | | 1
// | | 2
@ -206,14 +180,55 @@ enum Simd128RegisterCode {
// Simd128 register.
class Simd128Register
: public RegisterBase<Simd128Register, kSimd128AfterLast> {
private:
friend class RegisterBase;
public:
explicit constexpr Simd128Register(int code) : RegisterBase(code) {}
};
ASSERT_TRIVIALLY_COPYABLE(Simd128Register);
static_assert(sizeof(Simd128Register) <= sizeof(int),
"Simd128Register can efficiently be passed by value");
enum DoubleRegisterCode {
#define REGISTER_CODE(R) kDoubleCode_##R,
DOUBLE_REGISTERS(REGISTER_CODE)
#undef REGISTER_CODE
kDoubleAfterLast
};
// Double word FP register.
class DoubleRegister : public RegisterBase<DoubleRegister, kDoubleAfterLast> {
public:
// A few double registers are reserved: one as a scratch register and one to
// hold 0.0, that does not fit in the immediate field of vmov instructions.
// d14: 0.0
// d15: scratch register.
static constexpr int kSizeInBytes = 8;
// This function differs from kNumRegisters by returning the number of double
// registers supported by the current CPU, while kNumRegisters always returns
// 32.
inline static int SupportedRegisterCount();
// On PPC Simdi128 registers are separate from Double registers.
// More details can be found here: https://crrev.com/c/2718472 . This is a
// helper function to cast a Double to a Simdi128 register.
Simd128Register toSimd() const {
DCHECK(base::IsInRange(static_cast<int>(code()), 0, kSimd128AfterLast - 1));
return Simd128Register(code());
}
private:
friend class RegisterBase;
explicit constexpr DoubleRegister(int code) : RegisterBase(code) {}
};
ASSERT_TRIVIALLY_COPYABLE(DoubleRegister);
static_assert(sizeof(DoubleRegister) <= sizeof(int),
"DoubleRegister can efficiently be passed by value");
using FloatRegister = DoubleRegister;
#define DECLARE_SIMD128_REGISTER(R) \
constexpr Simd128Register R = Simd128Register::from_code(kSimd128Code_##R);
SIMD128_REGISTERS(DECLARE_SIMD128_REGISTER)
@ -230,8 +245,6 @@ constexpr DoubleRegister kFirstCalleeSavedDoubleReg = d14;
constexpr DoubleRegister kLastCalleeSavedDoubleReg = d31;
constexpr DoubleRegister kDoubleRegZero = d14;
constexpr DoubleRegister kScratchDoubleReg = d13;
// Simd128 zero and scratch regs must have the same numbers as Double zero and
// scratch
constexpr Simd128Register kSimd128RegZero = v14;
constexpr Simd128Register kScratchSimd128Reg = v13;

View File

@ -46,8 +46,9 @@ const int kNumCalleeSaved = 18;
const DoubleRegList kCallerSavedDoubles = {d0, d1, d2, d3, d4, d5, d6,
d7, d8, d9, d10, d11, d12, d13};
const Simd128RegList kCallerSavedSimd128s = {v0, v1, v2, v3, v4, v5, v6,
v7, v8, v9, v10, v11, v12, v13};
const Simd128RegList kCallerSavedSimd128s = {v0, v1, v2, v3, v4, v5, v6,
v7, v8, v9, v10, v11, v12, v13,
v14, v15, v16, v17, v18, v19};
const int kNumCallerSavedDoubles = 14;

View File

@ -19,7 +19,7 @@ static const int kMaxAllocatableGeneralRegisterCount =
ALLOCATABLE_GENERAL_REGISTERS(REGISTER_COUNT) 0;
static const int kMaxAllocatableDoubleRegisterCount =
ALLOCATABLE_DOUBLE_REGISTERS(REGISTER_COUNT) 0;
#if V8_TARGET_ARCH_RISCV64
#if V8_TARGET_ARCH_RISCV64 || V8_TARGET_ARCH_PPC64
static const int kMaxAllocatableSIMD128RegisterCount =
ALLOCATABLE_SIMD128_REGISTERS(REGISTER_COUNT) 0;
#endif
@ -38,12 +38,16 @@ static const int kAllocatableNoVFP32DoubleCodes[] = {
#endif // V8_TARGET_ARCH_ARM
#undef REGISTER_CODE
#if V8_TARGET_ARCH_RISCV64
#if V8_TARGET_ARCH_RISCV64 || V8_TARGET_ARCH_PPC64
static const int kAllocatableSIMD128Codes[] = {
#if V8_TARGET_ARCH_RISCV64
#define REGISTER_CODE(R) kVRCode_##R,
#else
#define REGISTER_CODE(R) kSimd128Code_##R,
#endif
ALLOCATABLE_SIMD128_REGISTERS(REGISTER_CODE)};
#undef REGISTER_CODE
#endif // V8_TARGET_ARCH_RISCV64
#endif // V8_TARGET_ARCH_RISCV64 || V8_TARGET_ARCH_PPC64
static_assert(RegisterConfiguration::kMaxGeneralRegisters >=
Register::kNumRegisters);
@ -56,11 +60,11 @@ static_assert(RegisterConfiguration::kMaxFPRegisters >=
static int get_num_simd128_registers() {
return
#if V8_TARGET_ARCH_RISCV64
#if V8_TARGET_ARCH_RISCV64 || V8_TARGET_ARCH_PPC64
Simd128Register::kNumRegisters;
#else
0;
#endif // V8_TARGET_ARCH_RISCV64
#endif // V8_TARGET_ARCH_RISCV64 || V8_TARGET_ARCH_PPC64
}
// Callers on architectures other than Arm expect this to be be constant
@ -100,7 +104,7 @@ static int get_num_allocatable_double_registers() {
static int get_num_allocatable_simd128_registers() {
return
#if V8_TARGET_ARCH_RISCV64
#if V8_TARGET_ARCH_RISCV64 || V8_TARGET_ARCH_PPC64
kMaxAllocatableSIMD128RegisterCount;
#else
0;
@ -121,7 +125,7 @@ static const int* get_allocatable_double_codes() {
static const int* get_allocatable_simd128_codes() {
return
#if V8_TARGET_ARCH_RISCV64
#if V8_TARGET_ARCH_RISCV64 || V8_TARGET_ARCH_PPC64
kAllocatableSIMD128Codes;
#else
kAllocatableDoubleCodes;