Commit aca3716a authored by bbudge's avatar bbudge Committed by Commit bot

[Turbofan] Add Simd128 registers to RegisterConfiguration.

-Defines SIMD128_REGISTERS for all platforms.
-Adds Simd128 register information to RegisterConfiguration, and implements
aliasing calculations.

LOG=N
BUG=v8:4124

Review-Url: https://codereview.chromium.org/2092103004
Cr-Commit-Position: refs/heads/master@{#37437}
parent e8d2238d
......@@ -69,6 +69,10 @@ namespace internal {
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 SIMD128_REGISTERS(V) \
V(q0) V(q1) V(q2) V(q3) V(q4) V(q5) V(q6) V(q7) \
V(q8) V(q9) V(q10) V(q11) V(q12) V(q13) V(q14) V(q15)
#define ALLOCATABLE_DOUBLE_REGISTERS(V) \
V(d0) 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(d13) \
......
......@@ -40,7 +40,7 @@ namespace internal {
R(x8) R(x9) R(x10) R(x11) R(x12) R(x13) R(x14) R(x15) \
R(x18) R(x19) R(x20) R(x21) R(x22) R(x23) R(x24) R(x27)
#define FLOAT_REGISTERS(V) \
#define FLOAT_REGISTERS(V) \
V(s0) V(s1) V(s2) V(s3) V(s4) V(s5) V(s6) V(s7) \
V(s8) V(s9) V(s10) V(s11) V(s12) V(s13) V(s14) V(s15) \
V(s16) V(s17) V(s18) V(s19) V(s20) V(s21) V(s22) V(s23) \
......@@ -52,6 +52,10 @@ namespace internal {
R(d16) R(d17) R(d18) R(d19) R(d20) R(d21) R(d22) R(d23) \
R(d24) R(d25) R(d26) R(d27) R(d28) R(d29) R(d30) R(d31)
#define SIMD128_REGISTERS(V) \
V(q0) V(q1) V(q2) V(q3) V(q4) V(q5) V(q6) V(q7) \
V(q8) V(q9) V(q10) V(q11) V(q12) V(q13) V(q14) V(q15)
#define ALLOCATABLE_DOUBLE_REGISTERS(R) \
R(d0) R(d1) R(d2) R(d3) R(d4) R(d5) R(d6) R(d7) \
R(d8) R(d9) R(d10) R(d11) R(d12) R(d13) R(d14) R(d16) \
......
......@@ -32,26 +32,41 @@ bool Blocks(const OperandSet& set, const InstructionOperand& operand) {
// Only FP registers on archs with non-simple aliasing need extra checks.
if (!operand.IsFPRegister() || kSimpleFPAliasing) return false;
// Check operand against operands of other FP types for interference.
const LocationOperand& loc = LocationOperand::cast(operand);
MachineRepresentation rep = loc.representation();
MachineRepresentation other_fp_rep = rep == MachineRepresentation::kFloat64
? MachineRepresentation::kFloat32
: MachineRepresentation::kFloat64;
MachineRepresentation other_rep1, other_rep2;
switch (rep) {
case MachineRepresentation::kFloat32:
other_rep1 = MachineRepresentation::kFloat64;
other_rep2 = MachineRepresentation::kSimd128;
break;
case MachineRepresentation::kFloat64:
other_rep1 = MachineRepresentation::kFloat32;
other_rep2 = MachineRepresentation::kSimd128;
break;
case MachineRepresentation::kSimd128:
other_rep1 = MachineRepresentation::kFloat32;
other_rep2 = MachineRepresentation::kFloat64;
break;
default:
UNREACHABLE();
break;
}
const RegisterConfiguration* config = RegisterConfiguration::Turbofan();
if (config->fp_aliasing_kind() != RegisterConfiguration::COMBINE) {
// Overlap aliasing case.
return set.find(LocationOperand(loc.kind(), loc.location_kind(),
other_fp_rep, loc.register_code())) !=
set.end();
}
// Combine aliasing case.
int alias_base_index = -1;
int aliases = config->GetAliases(rep, loc.register_code(), other_fp_rep,
&alias_base_index);
int base = -1;
int aliases = config->GetAliases(rep, loc.register_code(), other_rep1, &base);
DCHECK(aliases > 0 || (aliases == 0 && base == -1));
while (aliases--) {
if (set.find(LocationOperand(loc.kind(), loc.location_kind(), other_rep1,
base + aliases)) != set.end())
return true;
}
aliases = config->GetAliases(rep, loc.register_code(), other_rep2, &base);
DCHECK(aliases > 0 || (aliases == 0 && base == -1));
while (aliases--) {
int aliased_reg = alias_base_index + aliases;
if (set.find(LocationOperand(loc.kind(), loc.location_kind(), other_fp_rep,
aliased_reg)) != set.end())
if (set.find(LocationOperand(loc.kind(), loc.location_kind(), other_rep2,
base + aliases)) != set.end())
return true;
}
return false;
......
This diff is collapsed.
......@@ -779,6 +779,12 @@ class RegisterAllocationData final : public ZoneObject {
const ZoneVector<TopLevelLiveRange*>& fixed_double_live_ranges() const {
return fixed_double_live_ranges_;
}
ZoneVector<TopLevelLiveRange*>& fixed_simd128_live_ranges() {
return fixed_simd128_live_ranges_;
}
const ZoneVector<TopLevelLiveRange*>& fixed_simd128_live_ranges() const {
return fixed_simd128_live_ranges_;
}
ZoneVector<BitVector*>& live_in_sets() { return live_in_sets_; }
ZoneVector<BitVector*>& live_out_sets() { return live_out_sets_; }
ZoneVector<SpillRange*>& spill_ranges() { return spill_ranges_; }
......@@ -842,6 +848,7 @@ class RegisterAllocationData final : public ZoneObject {
ZoneVector<TopLevelLiveRange*> fixed_live_ranges_;
ZoneVector<TopLevelLiveRange*> fixed_float_live_ranges_;
ZoneVector<TopLevelLiveRange*> fixed_double_live_ranges_;
ZoneVector<TopLevelLiveRange*> fixed_simd128_live_ranges_;
ZoneVector<SpillRange*> spill_ranges_;
DelayedReferences delayed_references_;
BitVector* assigned_registers_;
......
......@@ -75,7 +75,7 @@ namespace internal {
V(xmm7)
#define FLOAT_REGISTERS DOUBLE_REGISTERS
#define SIMD_REGISTERS DOUBLE_REGISTERS
#define SIMD128_REGISTERS DOUBLE_REGISTERS
#define ALLOCATABLE_DOUBLE_REGISTERS(V) \
V(xmm1) \
......
......@@ -23,8 +23,8 @@ enum class MachineRepresentation : uint8_t {
kWord32,
kWord64,
kFloat32,
kFloat64,
kSimd128,
kFloat64, // must follow kFloat32
kSimd128, // must follow kFloat64
kTagged
};
......
......@@ -64,6 +64,7 @@ namespace internal {
V(f24) V(f25) V(f26) V(f27) V(f28) V(f29) V(f30) V(f31)
#define FLOAT_REGISTERS DOUBLE_REGISTERS
#define SIMD128_REGISTERS DOUBLE_REGISTERS
#define ALLOCATABLE_DOUBLE_REGISTERS(V) \
V(f0) V(f2) V(f4) V(f6) V(f8) V(f10) V(f12) V(f14) \
......
......@@ -64,6 +64,7 @@ namespace internal {
V(f24) V(f25) V(f26) V(f27) V(f28) V(f29) V(f30) V(f31)
#define FLOAT_REGISTERS DOUBLE_REGISTERS
#define SIMD128_REGISTERS DOUBLE_REGISTERS
#define ALLOCATABLE_DOUBLE_REGISTERS(V) \
V(f0) V(f2) V(f4) V(f6) V(f8) V(f10) V(f12) V(f14) \
......
......@@ -110,6 +110,7 @@ namespace internal {
V(d24) V(d25) V(d26) V(d27) V(d28) V(d29) V(d30) V(d31)
#define FLOAT_REGISTERS DOUBLE_REGISTERS
#define SIMD128_REGISTERS DOUBLE_REGISTERS
#define ALLOCATABLE_DOUBLE_REGISTERS(V) \
V(d1) V(d2) V(d3) V(d4) V(d5) V(d6) V(d7) \
......
......@@ -45,10 +45,20 @@ static const char* const kDoubleRegisterNames[] = {
#undef REGISTER_NAME
};
static const char* const kSimd128RegisterNames[] = {
#define REGISTER_NAME(R) #R,
SIMD128_REGISTERS(REGISTER_NAME)
#undef REGISTER_NAME
};
STATIC_ASSERT(RegisterConfiguration::kMaxGeneralRegisters >=
Register::kNumRegisters);
STATIC_ASSERT(RegisterConfiguration::kMaxFPRegisters >=
FloatRegister::kMaxNumRegisters);
STATIC_ASSERT(RegisterConfiguration::kMaxFPRegisters >=
DoubleRegister::kMaxNumRegisters);
STATIC_ASSERT(RegisterConfiguration::kMaxFPRegisters >=
Simd128Register::kMaxNumRegisters);
enum CompilerSelector { CRANKSHAFT, TURBOFAN };
......@@ -93,7 +103,8 @@ class ArchDefaultRegisterConfiguration : public RegisterConfiguration {
#endif
kAllocatableGeneralCodes, kAllocatableDoubleCodes,
kSimpleFPAliasing ? AliasingKind::OVERLAP : AliasingKind::COMBINE,
kGeneralRegisterNames, kFloatRegisterNames, kDoubleRegisterNames) {
kGeneralRegisterNames, kFloatRegisterNames, kDoubleRegisterNames,
kSimd128RegisterNames) {
}
};
......@@ -128,22 +139,27 @@ RegisterConfiguration::RegisterConfiguration(
const int* allocatable_general_codes, const int* allocatable_double_codes,
AliasingKind fp_aliasing_kind, const char* const* general_register_names,
const char* const* float_register_names,
const char* const* double_register_names)
const char* const* double_register_names,
const char* const* simd128_register_names)
: num_general_registers_(num_general_registers),
num_float_registers_(0),
num_double_registers_(num_double_registers),
num_simd128_registers_(0),
num_allocatable_general_registers_(num_allocatable_general_registers),
num_allocatable_double_registers_(num_allocatable_double_registers),
num_allocatable_float_registers_(0),
num_allocatable_double_registers_(num_allocatable_double_registers),
num_allocatable_simd128_registers_(0),
allocatable_general_codes_mask_(0),
allocatable_double_codes_mask_(0),
allocatable_float_codes_mask_(0),
allocatable_double_codes_mask_(0),
allocatable_simd128_codes_mask_(0),
allocatable_general_codes_(allocatable_general_codes),
allocatable_double_codes_(allocatable_double_codes),
fp_aliasing_kind_(fp_aliasing_kind),
general_register_names_(general_register_names),
float_register_names_(float_register_names),
double_register_names_(double_register_names) {
double_register_names_(double_register_names),
simd128_register_names_(simd128_register_names) {
DCHECK(num_general_registers_ <= RegisterConfiguration::kMaxGeneralRegisters);
DCHECK(num_double_registers_ <= RegisterConfiguration::kMaxFPRegisters);
for (int i = 0; i < num_allocatable_general_registers_; ++i) {
......@@ -166,67 +182,82 @@ RegisterConfiguration::RegisterConfiguration(
base_code + 1;
allocatable_float_codes_mask_ |= (0x3 << base_code);
}
num_simd128_registers_ = num_double_registers_ / 2;
num_allocatable_simd128_registers_ = 0;
int last_simd128_code = allocatable_double_codes_[0] / 2;
for (int i = 1; i < num_allocatable_double_registers_; i++) {
int next_simd128_code = allocatable_double_codes_[i] / 2;
// This scheme assumes allocatable_double_codes_ are strictly increasing.
DCHECK_GE(next_simd128_code, last_simd128_code);
if (last_simd128_code == next_simd128_code) {
allocatable_simd128_codes_[num_allocatable_simd128_registers_++] =
next_simd128_code;
allocatable_simd128_codes_mask_ |= (0x1 << next_simd128_code);
}
last_simd128_code = next_simd128_code;
}
} else {
DCHECK(fp_aliasing_kind_ == OVERLAP);
num_float_registers_ = num_double_registers_;
num_allocatable_float_registers_ = num_allocatable_double_registers_;
num_float_registers_ = num_simd128_registers_ = num_double_registers_;
num_allocatable_float_registers_ = num_allocatable_simd128_registers_ =
num_allocatable_double_registers_;
for (int i = 0; i < num_allocatable_float_registers_; ++i) {
allocatable_float_codes_[i] = allocatable_double_codes_[i];
allocatable_float_codes_[i] = allocatable_simd128_codes_[i] =
allocatable_double_codes_[i];
}
allocatable_float_codes_mask_ = allocatable_double_codes_mask_;
allocatable_float_codes_mask_ = allocatable_simd128_codes_mask_ =
allocatable_double_codes_mask_;
}
}
// Assert that kFloat32, kFloat64, and kSimd128 are consecutive values.
STATIC_ASSERT(static_cast<int>(MachineRepresentation::kSimd128) ==
static_cast<int>(MachineRepresentation::kFloat64) + 1);
STATIC_ASSERT(static_cast<int>(MachineRepresentation::kFloat64) ==
static_cast<int>(MachineRepresentation::kFloat32) + 1);
int RegisterConfiguration::GetAliases(MachineRepresentation rep, int index,
MachineRepresentation other_rep,
int* alias_base_index) const {
DCHECK(fp_aliasing_kind_ == COMBINE);
DCHECK(rep == MachineRepresentation::kFloat32 ||
rep == MachineRepresentation::kFloat64);
DCHECK(other_rep == MachineRepresentation::kFloat32 ||
other_rep == MachineRepresentation::kFloat64);
DCHECK(IsFloatingPoint(rep) && IsFloatingPoint(other_rep));
if (rep == other_rep) {
*alias_base_index = index;
return 1;
}
if (rep == MachineRepresentation::kFloat32) {
DCHECK(other_rep == MachineRepresentation::kFloat64);
DCHECK(index < num_allocatable_float_registers_);
*alias_base_index = index / 2;
return 1;
}
DCHECK(rep == MachineRepresentation::kFloat64);
DCHECK(other_rep == MachineRepresentation::kFloat32);
if (index * 2 >= kMaxFPRegisters) {
// Alias indices are out of float register range.
return 0;
int rep_int = static_cast<int>(rep);
int other_rep_int = static_cast<int>(other_rep);
if (rep_int > other_rep_int) {
int shift = rep_int - other_rep_int;
int base_index = index << shift;
if (base_index >= kMaxFPRegisters) {
// Alias indices would be out of FP register range.
return 0;
}
*alias_base_index = base_index;
return 1 << shift;
}
*alias_base_index = index * 2;
return 2;
int shift = other_rep_int - rep_int;
*alias_base_index = index >> shift;
return 1;
}
bool RegisterConfiguration::AreAliases(MachineRepresentation rep, int index,
MachineRepresentation other_rep,
int other_index) const {
DCHECK(fp_aliasing_kind_ == COMBINE);
DCHECK(rep == MachineRepresentation::kFloat32 ||
rep == MachineRepresentation::kFloat64);
DCHECK(other_rep == MachineRepresentation::kFloat32 ||
other_rep == MachineRepresentation::kFloat64);
DCHECK(IsFloatingPoint(rep) && IsFloatingPoint(other_rep));
if (rep == other_rep) {
return index == other_index;
}
if (rep == MachineRepresentation::kFloat32) {
DCHECK(other_rep == MachineRepresentation::kFloat64);
return index / 2 == other_index;
}
DCHECK(rep == MachineRepresentation::kFloat64);
DCHECK(other_rep == MachineRepresentation::kFloat32);
if (index * 2 >= kMaxFPRegisters) {
// Alias indices are out of float register range.
return false;
int rep_int = static_cast<int>(rep);
int other_rep_int = static_cast<int>(other_rep);
if (rep_int > other_rep_int) {
int shift = rep_int - other_rep_int;
return index == other_index >> shift;
}
return index == other_index / 2;
int shift = other_rep_int - rep_int;
return index >> shift == other_index;
}
#undef REGISTER_COUNT
......
......@@ -40,19 +40,24 @@ class RegisterConfiguration {
AliasingKind fp_aliasing_kind,
char const* const* general_names,
char const* const* float_names,
char const* const* double_names);
char const* const* double_names,
char const* const* simd128_names);
int num_general_registers() const { return num_general_registers_; }
int num_float_registers() const { return num_float_registers_; }
int num_double_registers() const { return num_double_registers_; }
int num_simd128_registers() const { return num_simd128_registers_; }
int num_allocatable_general_registers() const {
return num_allocatable_general_registers_;
}
int num_allocatable_float_registers() const {
return num_allocatable_float_registers_;
}
int num_allocatable_double_registers() const {
return num_allocatable_double_registers_;
}
int num_allocatable_float_registers() const {
return num_allocatable_float_registers_;
int num_allocatable_simd128_registers() const {
return num_allocatable_simd128_registers_;
}
AliasingKind fp_aliasing_kind() const { return fp_aliasing_kind_; }
int32_t allocatable_general_codes_mask() const {
......@@ -67,17 +72,23 @@ class RegisterConfiguration {
bool IsAllocatableGeneralCode(int index) const {
return ((1 << index) & allocatable_general_codes_mask_) != 0;
}
int GetAllocatableFloatCode(int index) const {
return allocatable_float_codes_[index];
}
bool IsAllocatableFloatCode(int index) const {
return ((1 << index) & allocatable_float_codes_mask_) != 0;
}
int GetAllocatableDoubleCode(int index) const {
return allocatable_double_codes_[index];
}
bool IsAllocatableDoubleCode(int index) const {
return ((1 << index) & allocatable_double_codes_mask_) != 0;
}
int GetAllocatableFloatCode(int index) const {
return allocatable_float_codes_[index];
int GetAllocatableSimd128Code(int index) const {
return allocatable_simd128_codes_[index];
}
bool IsAllocatableFloatCode(int index) const {
return ((1 << index) & allocatable_float_codes_mask_) != 0;
bool IsAllocatableSimd128Code(int index) const {
return ((1 << index) & allocatable_simd128_codes_mask_) != 0;
}
const char* GetGeneralRegisterName(int code) const {
return general_register_names_[code];
......@@ -88,25 +99,31 @@ class RegisterConfiguration {
const char* GetDoubleRegisterName(int code) const {
return double_register_names_[code];
}
const char* GetSimd128RegisterName(int code) const {
return simd128_register_names_[code];
}
const int* allocatable_general_codes() const {
return allocatable_general_codes_;
}
const int* allocatable_float_codes() const {
return allocatable_float_codes_;
}
const int* allocatable_double_codes() const {
return allocatable_double_codes_;
}
const int* allocatable_float_codes() const {
return allocatable_float_codes_;
const int* allocatable_simd128_codes() const {
return allocatable_simd128_codes_;
}
// Aliasing calculations for floating point registers, when fp_aliasing_kind()
// is COMBINE. Currently only implemented for kFloat32, or kFloat64 reps.
// Returns the number of aliases, and if > 0, alias_base_index is set to the
// index of the first alias.
// is COMBINE. Currently only implemented for kFloat32, kFloat64, or kSimd128
// reps. Returns the number of aliases, and if > 0, alias_base_index is set to
// the index of the first alias.
int GetAliases(MachineRepresentation rep, int index,
MachineRepresentation other_rep, int* alias_base_index) const;
// Returns a value indicating whether two registers alias each other, when
// fp_aliasing_kind() is COMBINE. Currently only implemented for kFloat32, or
// kFloat64 reps.
// fp_aliasing_kind() is COMBINE. Currently implemented for kFloat32,
// kFloat64, or kSimd128 reps.
bool AreAliases(MachineRepresentation rep, int index,
MachineRepresentation other_rep, int other_index) const;
......@@ -114,19 +131,24 @@ class RegisterConfiguration {
const int num_general_registers_;
int num_float_registers_;
const int num_double_registers_;
int num_simd128_registers_;
int num_allocatable_general_registers_;
int num_allocatable_double_registers_;
int num_allocatable_float_registers_;
int num_allocatable_double_registers_;
int num_allocatable_simd128_registers_;
int32_t allocatable_general_codes_mask_;
int32_t allocatable_double_codes_mask_;
int32_t allocatable_float_codes_mask_;
int32_t allocatable_double_codes_mask_;
int32_t allocatable_simd128_codes_mask_;
const int* allocatable_general_codes_;
const int* allocatable_double_codes_;
int allocatable_float_codes_[kMaxFPRegisters];
const int* allocatable_double_codes_;
int allocatable_simd128_codes_[kMaxFPRegisters];
AliasingKind fp_aliasing_kind_;
char const* const* general_register_names_;
char const* const* float_register_names_;
char const* const* double_register_names_;
char const* const* simd128_register_names_;
};
} // namespace internal
......
......@@ -91,6 +91,7 @@ namespace internal {
V(d8) V(d9) V(d10) V(d11) V(d12) V(d13) V(d14) V(d15)
#define FLOAT_REGISTERS DOUBLE_REGISTERS
#define SIMD128_REGISTERS DOUBLE_REGISTERS
#define ALLOCATABLE_DOUBLE_REGISTERS(V) \
V(d1) V(d2) V(d3) V(d4) V(d5) V(d6) V(d7) \
......
......@@ -182,6 +182,7 @@ const Register arg_reg_4 = {Register::kCode_rcx};
V(xmm15)
#define FLOAT_REGISTERS DOUBLE_REGISTERS
#define SIMD128_REGISTERS DOUBLE_REGISTERS
#define ALLOCATABLE_DOUBLE_REGISTERS(V) \
V(xmm0) \
......
......@@ -75,6 +75,7 @@ namespace internal {
V(stX_7)
#define FLOAT_REGISTERS DOUBLE_REGISTERS
#define SIMD128_REGISTERS DOUBLE_REGISTERS
#define ALLOCATABLE_DOUBLE_REGISTERS(V) \
V(stX_0) \
......
......@@ -22,8 +22,8 @@ group("gn_all") {
if (v8_test_isolation_mode != "noop") {
deps += [
":bot_default_run",
":benchmarks_run",
":bot_default_run",
":default_run",
":mozilla_run",
":simdjs_run",
......@@ -54,7 +54,7 @@ group("default_tests") {
v8_isolate_run("bot_default") {
deps = [
":default_tests",
":default_tests",
":webkit_run",
]
......@@ -131,8 +131,8 @@ v8_isolate_run("fuzzer") {
"..:v8_simple_json_fuzzer",
"..:v8_simple_parser_fuzzer",
"..:v8_simple_regexp_fuzzer",
"..:v8_simple_wasm_fuzzer",
"..:v8_simple_wasm_asmjs_fuzzer",
"..:v8_simple_wasm_fuzzer",
]
isolate = "fuzzer/fuzzer.isolate"
......
......@@ -72,7 +72,8 @@ RegisterConfiguration* InstructionSequenceTest::config() {
: RegisterConfiguration::COMBINE,
general_register_names_,
double_register_names_, // float register names
double_register_names_));
double_register_names_,
double_register_names_)); // SIMD 128 register names
}
return config_.get();
}
......
......@@ -10,6 +10,7 @@ namespace internal {
const MachineRepresentation kFloat32 = MachineRepresentation::kFloat32;
const MachineRepresentation kFloat64 = MachineRepresentation::kFloat64;
const MachineRepresentation kSimd128 = MachineRepresentation::kSimd128;
class RegisterConfigurationUnitTest : public ::testing::Test {
public:
......@@ -30,7 +31,7 @@ TEST_F(RegisterConfigurationUnitTest, BasicProperties) {
RegisterConfiguration test(
kNumGeneralRegs, kNumDoubleRegs, kNumAllocatableGeneralRegs,
kNumAllocatableDoubleRegs, general_codes, double_codes,
RegisterConfiguration::OVERLAP, nullptr, nullptr, nullptr);
RegisterConfiguration::OVERLAP, nullptr, nullptr, nullptr, nullptr);
EXPECT_EQ(test.num_general_registers(), kNumGeneralRegs);
EXPECT_EQ(test.num_double_registers(), kNumDoubleRegs);
......@@ -38,6 +39,8 @@ TEST_F(RegisterConfigurationUnitTest, BasicProperties) {
kNumAllocatableGeneralRegs);
EXPECT_EQ(test.num_allocatable_double_registers(), kNumAllocatableDoubleRegs);
EXPECT_EQ(test.num_allocatable_float_registers(), kNumAllocatableDoubleRegs);
EXPECT_EQ(test.num_allocatable_simd128_registers(),
kNumAllocatableDoubleRegs);
EXPECT_EQ(test.allocatable_general_codes_mask(),
(1 << general_codes[0]) | (1 << general_codes[1]));
......@@ -45,11 +48,15 @@ TEST_F(RegisterConfigurationUnitTest, BasicProperties) {
EXPECT_EQ(test.GetAllocatableGeneralCode(1), general_codes[1]);
EXPECT_EQ(test.allocatable_double_codes_mask(),
(1 << double_codes[0]) | (1 << double_codes[1]));
EXPECT_EQ(test.GetAllocatableFloatCode(0), double_codes[0]);
EXPECT_EQ(test.GetAllocatableDoubleCode(0), double_codes[0]);
EXPECT_EQ(test.GetAllocatableSimd128Code(0), double_codes[0]);
EXPECT_EQ(test.GetAllocatableFloatCode(1), double_codes[1]);
EXPECT_EQ(test.GetAllocatableDoubleCode(1), double_codes[1]);
EXPECT_EQ(test.GetAllocatableSimd128Code(1), double_codes[1]);
}
TEST_F(RegisterConfigurationUnitTest, Aliasing) {
TEST_F(RegisterConfigurationUnitTest, CombineAliasing) {
const int kNumGeneralRegs = 3;
const int kNumDoubleRegs = 4;
const int kNumAllocatableGeneralRegs = 2;
......@@ -60,7 +67,7 @@ TEST_F(RegisterConfigurationUnitTest, Aliasing) {
RegisterConfiguration test(
kNumGeneralRegs, kNumDoubleRegs, kNumAllocatableGeneralRegs,
kNumAllocatableDoubleRegs, general_codes, double_codes,
RegisterConfiguration::COMBINE, nullptr, nullptr, nullptr);
RegisterConfiguration::COMBINE, nullptr, nullptr, nullptr, nullptr);
// There are 3 allocatable double regs, but only 2 can alias float regs.
EXPECT_EQ(test.num_allocatable_float_registers(), 4);
......@@ -71,20 +78,41 @@ TEST_F(RegisterConfigurationUnitTest, Aliasing) {
EXPECT_EQ(test.GetAllocatableFloatCode(2), double_codes[1] * 2);
EXPECT_EQ(test.GetAllocatableFloatCode(3), double_codes[1] * 2 + 1);
// There are 3 allocatable double regs, but only 2 pair to form 1 SIMD reg.
EXPECT_EQ(test.num_allocatable_simd128_registers(), 1);
// Test that even-odd pairs of double regs combine to form a SIMD reg.
EXPECT_EQ(test.GetAllocatableSimd128Code(0), double_codes[0] / 2);
// Registers alias themselves.
EXPECT_TRUE(test.AreAliases(kFloat32, 0, kFloat32, 0));
EXPECT_TRUE(test.AreAliases(kFloat64, 0, kFloat64, 0));
EXPECT_TRUE(test.AreAliases(kSimd128, 0, kSimd128, 0));
// Registers don't alias other registers of the same size.
EXPECT_FALSE(test.AreAliases(kFloat32, 1, kFloat32, 0));
EXPECT_FALSE(test.AreAliases(kFloat64, 1, kFloat64, 0));
// Float registers combine in pairs and alias double registers.
EXPECT_FALSE(test.AreAliases(kSimd128, 1, kSimd128, 0));
// Float registers combine in pairs to alias a double with index / 2, and
// in 4's to alias a simd128 with index / 4.
EXPECT_TRUE(test.AreAliases(kFloat32, 0, kFloat64, 0));
EXPECT_TRUE(test.AreAliases(kFloat32, 1, kFloat64, 0));
EXPECT_TRUE(test.AreAliases(kFloat32, 0, kSimd128, 0));
EXPECT_TRUE(test.AreAliases(kFloat32, 1, kSimd128, 0));
EXPECT_TRUE(test.AreAliases(kFloat32, 2, kSimd128, 0));
EXPECT_TRUE(test.AreAliases(kFloat32, 3, kSimd128, 0));
EXPECT_TRUE(test.AreAliases(kFloat64, 0, kFloat32, 0));
EXPECT_TRUE(test.AreAliases(kFloat64, 0, kFloat32, 1));
EXPECT_TRUE(test.AreAliases(kSimd128, 0, kFloat32, 0));
EXPECT_TRUE(test.AreAliases(kSimd128, 0, kFloat32, 1));
EXPECT_TRUE(test.AreAliases(kSimd128, 0, kFloat32, 2));
EXPECT_TRUE(test.AreAliases(kSimd128, 0, kFloat32, 3));
EXPECT_FALSE(test.AreAliases(kFloat32, 0, kFloat64, 1));
EXPECT_FALSE(test.AreAliases(kFloat32, 1, kFloat64, 1));
EXPECT_FALSE(test.AreAliases(kFloat32, 0, kSimd128, 1));
EXPECT_FALSE(test.AreAliases(kFloat32, 1, kSimd128, 1));
EXPECT_FALSE(test.AreAliases(kFloat64, 0, kSimd128, 1));
EXPECT_FALSE(test.AreAliases(kFloat64, 1, kSimd128, 1));
EXPECT_TRUE(test.AreAliases(kFloat64, 0, kFloat32, 1));
EXPECT_TRUE(test.AreAliases(kFloat64, 1, kFloat32, 2));
......@@ -92,6 +120,12 @@ TEST_F(RegisterConfigurationUnitTest, Aliasing) {
EXPECT_TRUE(test.AreAliases(kFloat64, 2, kFloat32, 4));
EXPECT_TRUE(test.AreAliases(kFloat64, 2, kFloat32, 5));
EXPECT_TRUE(test.AreAliases(kSimd128, 0, kFloat64, 1));
EXPECT_TRUE(test.AreAliases(kSimd128, 1, kFloat64, 2));
EXPECT_TRUE(test.AreAliases(kSimd128, 1, kFloat64, 3));
EXPECT_TRUE(test.AreAliases(kSimd128, 2, kFloat64, 4));
EXPECT_TRUE(test.AreAliases(kSimd128, 2, kFloat64, 5));
int alias_base_index = -1;
EXPECT_EQ(test.GetAliases(kFloat32, 0, kFloat32, &alias_base_index), 1);
EXPECT_EQ(alias_base_index, 0);
......@@ -112,7 +146,7 @@ TEST_F(RegisterConfigurationUnitTest, Aliasing) {
// Non-allocatable codes still alias.
EXPECT_EQ(test.GetAliases(kFloat64, 2, kFloat32, &alias_base_index), 2);
EXPECT_EQ(alias_base_index, 4);
// High numbered double registers don't alias nonexistent single registers.
// High numbered double and simd regs don't alias nonexistent float registers.
EXPECT_EQ(
test.GetAliases(kFloat64, RegisterConfiguration::kMaxFPRegisters / 2,
kFloat32, &alias_base_index),
......
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