Add tests for float32/float64 parameters/returns passed in float32/float64 registers.
R=mstarzinger@chromium.org BUG= Review URL: https://codereview.chromium.org/1291553005 Cr-Commit-Position: refs/heads/master@{#30143}
This commit is contained in:
parent
b2a8842dbb
commit
8525136bd3
@ -1,4 +1,4 @@
|
||||
// Copyright 2014 the V8 project authors. All rights reserved.
|
||||
// Copyright 2015 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
@ -19,65 +19,90 @@ using namespace v8::internal::compiler;
|
||||
|
||||
typedef RawMachineAssembler::Label MLabel;
|
||||
|
||||
#if !V8_TARGET_ARCH_ARM64
|
||||
#if V8_TARGET_ARCH_ARM64
|
||||
// TODO(titzer): fix native stack parameters on arm64
|
||||
#define NATIVE_STACK_PARAMS_OK
|
||||
#define DISABLE_NATIVE_STACK_PARAMS true
|
||||
#else
|
||||
#define DISABLE_NATIVE_STACK_PARAMS false
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
// Picks a representative set of registers from the allocatable set.
|
||||
// If there are less than 100 possible pairs, do them all, otherwise try
|
||||
typedef float float32;
|
||||
typedef double float64;
|
||||
|
||||
// Picks a representative pair of integers from the given range.
|
||||
// If there are less than {max_pairs} possible pairs, do them all, otherwise try
|
||||
// to select a representative set.
|
||||
class RegisterPairs {
|
||||
class Pairs {
|
||||
public:
|
||||
RegisterPairs()
|
||||
: max_(std::min(100, Register::kMaxNumAllocatableRegisters *
|
||||
Register::kMaxNumAllocatableRegisters)),
|
||||
Pairs(int max_pairs, int range)
|
||||
: range_(range),
|
||||
max_pairs_(std::min(max_pairs, range_ * range_)),
|
||||
counter_(0) {}
|
||||
|
||||
bool More() { return counter_ < max_; }
|
||||
bool More() { return counter_ < max_pairs_; }
|
||||
|
||||
void Next(int* r0, int* r1, bool same_is_ok) {
|
||||
do {
|
||||
// Find the next pair.
|
||||
if (exhaustive()) {
|
||||
*r0 = counter_ % Register::kMaxNumAllocatableRegisters;
|
||||
*r1 = counter_ / Register::kMaxNumAllocatableRegisters;
|
||||
*r0 = counter_ % range_;
|
||||
*r1 = counter_ / range_;
|
||||
} else {
|
||||
// Try each register at least once for both r0 and r1.
|
||||
// Try each integer at least once for both r0 and r1.
|
||||
int index = counter_ / 2;
|
||||
if (counter_ & 1) {
|
||||
*r0 = index % Register::kMaxNumAllocatableRegisters;
|
||||
*r1 = index / Register::kMaxNumAllocatableRegisters;
|
||||
*r0 = index % range_;
|
||||
*r1 = index / range_;
|
||||
} else {
|
||||
*r1 = index % Register::kMaxNumAllocatableRegisters;
|
||||
*r0 = index / Register::kMaxNumAllocatableRegisters;
|
||||
*r1 = index % range_;
|
||||
*r0 = index / range_;
|
||||
}
|
||||
}
|
||||
counter_++;
|
||||
if (same_is_ok) break;
|
||||
if (*r0 == *r1) {
|
||||
if (counter_ >= max_) {
|
||||
if (counter_ >= max_pairs_) {
|
||||
// For the last hurrah, reg#0 with reg#n-1
|
||||
*r0 = 0;
|
||||
*r1 = Register::kMaxNumAllocatableRegisters - 1;
|
||||
*r1 = range_ - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (true);
|
||||
|
||||
DCHECK(*r0 >= 0 && *r0 < Register::kMaxNumAllocatableRegisters);
|
||||
DCHECK(*r1 >= 0 && *r1 < Register::kMaxNumAllocatableRegisters);
|
||||
printf("pair = %d, %d\n", *r0, *r1);
|
||||
DCHECK(*r0 >= 0 && *r0 < range_);
|
||||
DCHECK(*r1 >= 0 && *r1 < range_);
|
||||
}
|
||||
|
||||
private:
|
||||
int max_;
|
||||
int range_;
|
||||
int max_pairs_;
|
||||
int counter_;
|
||||
bool exhaustive() {
|
||||
return max_ == (Register::kMaxNumAllocatableRegisters *
|
||||
Register::kMaxNumAllocatableRegisters);
|
||||
}
|
||||
bool exhaustive() { return max_pairs_ == (range_ * range_); }
|
||||
};
|
||||
|
||||
|
||||
// Pairs of general purpose registers.
|
||||
class RegisterPairs : public Pairs {
|
||||
public:
|
||||
RegisterPairs() : Pairs(100, Register::kMaxNumAllocatableRegisters) {}
|
||||
};
|
||||
|
||||
|
||||
// Pairs of double registers.
|
||||
class Float32RegisterPairs : public Pairs {
|
||||
public:
|
||||
Float32RegisterPairs()
|
||||
: Pairs(100, DoubleRegister::NumAllocatableAliasedRegisters()) {}
|
||||
};
|
||||
|
||||
|
||||
// Pairs of double registers.
|
||||
class Float64RegisterPairs : public Pairs {
|
||||
public:
|
||||
Float64RegisterPairs()
|
||||
: Pairs(100, DoubleRegister::NumAllocatableAliasedRegisters()) {}
|
||||
};
|
||||
|
||||
|
||||
@ -265,6 +290,220 @@ Handle<Code> WrapWithCFunction(Handle<Code> inner, CallDescriptor* desc) {
|
||||
}
|
||||
|
||||
|
||||
template <typename CType>
|
||||
class ArgsBuffer {
|
||||
public:
|
||||
static const int kMaxParamCount = 64;
|
||||
|
||||
explicit ArgsBuffer(int count, int seed = 1) : count_(count), seed_(seed) {
|
||||
// initialize the buffer with "seed 0"
|
||||
seed_ = 0;
|
||||
Mutate();
|
||||
seed_ = seed;
|
||||
}
|
||||
|
||||
class Sig : public MachineSignature {
|
||||
public:
|
||||
explicit Sig(int param_count)
|
||||
: MachineSignature(1, param_count, MachTypes()) {
|
||||
CHECK(param_count <= kMaxParamCount);
|
||||
}
|
||||
};
|
||||
|
||||
static MachineType* MachTypes() {
|
||||
MachineType t = MachineTypeForC<CType>();
|
||||
static MachineType kTypes[kMaxParamCount + 1] = {
|
||||
t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t,
|
||||
t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t,
|
||||
t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t, t};
|
||||
return kTypes;
|
||||
}
|
||||
|
||||
Node* MakeConstant(RawMachineAssembler& raw, int32_t value) {
|
||||
return raw.Int32Constant(value);
|
||||
}
|
||||
|
||||
Node* MakeConstant(RawMachineAssembler& raw, int64_t value) {
|
||||
return raw.Int64Constant(value);
|
||||
}
|
||||
|
||||
Node* MakeConstant(RawMachineAssembler& raw, float32 value) {
|
||||
return raw.Float32Constant(value);
|
||||
}
|
||||
|
||||
Node* MakeConstant(RawMachineAssembler& raw, float64 value) {
|
||||
return raw.Float64Constant(value);
|
||||
}
|
||||
|
||||
Node* LoadInput(RawMachineAssembler& raw, Node* base, int index) {
|
||||
Node* offset = raw.Int32Constant(index * sizeof(CType));
|
||||
return raw.Load(MachineTypeForC<CType>(), base, offset);
|
||||
}
|
||||
|
||||
Node* StoreOutput(RawMachineAssembler& raw, Node* value) {
|
||||
Node* base = raw.PointerConstant(&output);
|
||||
Node* offset = raw.Int32Constant(0);
|
||||
return raw.Store(MachineTypeForC<CType>(), base, offset, value);
|
||||
}
|
||||
|
||||
// Computes the next set of inputs by updating the {input} array.
|
||||
void Mutate();
|
||||
|
||||
void Reset() { memset(input, 0, sizeof(input)); }
|
||||
|
||||
int count_;
|
||||
int seed_;
|
||||
CType input[kMaxParamCount];
|
||||
CType output;
|
||||
};
|
||||
|
||||
|
||||
template <>
|
||||
void ArgsBuffer<int32_t>::Mutate() {
|
||||
uint32_t base = 1111111111u * seed_;
|
||||
for (int j = 0; j < count_; j++) {
|
||||
input[j] = static_cast<int32_t>(256 + base + j + seed_ * 13);
|
||||
}
|
||||
output = -1;
|
||||
seed_++;
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
void ArgsBuffer<int64_t>::Mutate() {
|
||||
uint64_t base = 11111111111111111ull * seed_;
|
||||
for (int j = 0; j < count_; j++) {
|
||||
input[j] = static_cast<int64_t>(256 + base + j + seed_ * 13);
|
||||
}
|
||||
output = -1;
|
||||
seed_++;
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
void ArgsBuffer<float32>::Mutate() {
|
||||
float64 base = -33.25 * seed_;
|
||||
for (int j = 0; j < count_; j++) {
|
||||
input[j] = 256 + base + j + seed_ * 13;
|
||||
}
|
||||
output = std::numeric_limits<float32>::quiet_NaN();
|
||||
seed_++;
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
void ArgsBuffer<float64>::Mutate() {
|
||||
float64 base = -111.25 * seed_;
|
||||
for (int j = 0; j < count_; j++) {
|
||||
input[j] = 256 + base + j + seed_ * 13;
|
||||
}
|
||||
output = std::numeric_limits<float64>::quiet_NaN();
|
||||
seed_++;
|
||||
}
|
||||
|
||||
|
||||
int ParamCount(CallDescriptor* desc) {
|
||||
return static_cast<int>(desc->GetMachineSignature()->parameter_count());
|
||||
}
|
||||
|
||||
|
||||
template <typename CType>
|
||||
class Computer {
|
||||
public:
|
||||
static void Run(CallDescriptor* desc,
|
||||
void (*build)(CallDescriptor*, RawMachineAssembler&),
|
||||
CType (*compute)(CallDescriptor*, CType* inputs),
|
||||
int seed = 1) {
|
||||
int num_params = ParamCount(desc);
|
||||
CHECK_LE(num_params, kMaxParamCount);
|
||||
Isolate* isolate = CcTest::InitIsolateOnce();
|
||||
HandleScope scope(isolate);
|
||||
Handle<Code> inner = Handle<Code>::null();
|
||||
{
|
||||
// Build the graph for the computation.
|
||||
Zone zone;
|
||||
Graph graph(&zone);
|
||||
RawMachineAssembler raw(isolate, &graph, desc);
|
||||
build(desc, raw);
|
||||
inner = CompileGraph("Compute", desc, &graph, raw.Export());
|
||||
}
|
||||
|
||||
CSignature0<int32_t> csig;
|
||||
ArgsBuffer<CType> io(num_params, seed);
|
||||
|
||||
{
|
||||
// constant mode.
|
||||
Handle<Code> wrapper = Handle<Code>::null();
|
||||
{
|
||||
// Wrap the above code with a callable function that passes constants.
|
||||
Zone zone;
|
||||
Graph graph(&zone);
|
||||
CallDescriptor* cdesc = Linkage::GetSimplifiedCDescriptor(&zone, &csig);
|
||||
RawMachineAssembler raw(isolate, &graph, cdesc);
|
||||
Unique<HeapObject> unique =
|
||||
Unique<HeapObject>::CreateUninitialized(inner);
|
||||
Node* target = raw.HeapConstant(unique);
|
||||
Node** args = zone.NewArray<Node*>(kMaxParamCount);
|
||||
for (int i = 0; i < num_params; i++) {
|
||||
args[i] = io.MakeConstant(raw, io.input[i]);
|
||||
}
|
||||
|
||||
Node* call = raw.CallN(desc, target, args);
|
||||
Node* store = io.StoreOutput(raw, call);
|
||||
USE(store);
|
||||
raw.Return(raw.Int32Constant(seed));
|
||||
wrapper =
|
||||
CompileGraph("Compute-wrapper-const", cdesc, &graph, raw.Export());
|
||||
}
|
||||
|
||||
CodeRunner<int32_t> runnable(isolate, wrapper, &csig);
|
||||
|
||||
// Run the code, checking it against the reference.
|
||||
CType expected = compute(desc, io.input);
|
||||
int32_t check_seed = runnable.Call();
|
||||
CHECK_EQ(seed, check_seed);
|
||||
CHECK_EQ(expected, io.output);
|
||||
}
|
||||
|
||||
{
|
||||
// buffer mode.
|
||||
Handle<Code> wrapper = Handle<Code>::null();
|
||||
{
|
||||
// Wrap the above code with a callable function that loads from {input}.
|
||||
Zone zone;
|
||||
Graph graph(&zone);
|
||||
CallDescriptor* cdesc = Linkage::GetSimplifiedCDescriptor(&zone, &csig);
|
||||
RawMachineAssembler raw(isolate, &graph, cdesc);
|
||||
Node* base = raw.PointerConstant(io.input);
|
||||
Unique<HeapObject> unique =
|
||||
Unique<HeapObject>::CreateUninitialized(inner);
|
||||
Node* target = raw.HeapConstant(unique);
|
||||
Node** args = zone.NewArray<Node*>(kMaxParamCount);
|
||||
for (int i = 0; i < num_params; i++) {
|
||||
args[i] = io.LoadInput(raw, base, i);
|
||||
}
|
||||
|
||||
Node* call = raw.CallN(desc, target, args);
|
||||
Node* store = io.StoreOutput(raw, call);
|
||||
USE(store);
|
||||
raw.Return(raw.Int32Constant(seed));
|
||||
wrapper = CompileGraph("Compute-wrapper", cdesc, &graph, raw.Export());
|
||||
}
|
||||
|
||||
CodeRunner<int32_t> runnable(isolate, wrapper, &csig);
|
||||
|
||||
// Run the code, checking it against the reference.
|
||||
for (int i = 0; i < 5; i++) {
|
||||
CType expected = compute(desc, io.input);
|
||||
int32_t check_seed = runnable.Call();
|
||||
CHECK_EQ(seed, check_seed);
|
||||
CHECK_EQ(expected, io.output);
|
||||
io.Mutate();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
@ -303,8 +542,9 @@ static void TestInt32Sub(CallDescriptor* desc) {
|
||||
}
|
||||
|
||||
|
||||
#ifdef NATIVE_STACK_PARAMS_OK
|
||||
static void CopyTwentyInt32(CallDescriptor* desc) {
|
||||
if (DISABLE_NATIVE_STACK_PARAMS) return;
|
||||
|
||||
const int kNumParams = 20;
|
||||
int32_t input[kNumParams];
|
||||
int32_t output[kNumParams];
|
||||
@ -365,7 +605,6 @@ static void CopyTwentyInt32(CallDescriptor* desc) {
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // NATIVE_STACK_PARAMS_OK
|
||||
|
||||
|
||||
static void Test_RunInt32SubWithRet(int retreg) {
|
||||
@ -415,7 +654,7 @@ TEST_INT32_SUB_WITH_RET(19)
|
||||
|
||||
|
||||
TEST(Run_Int32Sub_all_allocatable_single) {
|
||||
#ifdef NATIVE_STACK_PARAMS_OK
|
||||
if (DISABLE_NATIVE_STACK_PARAMS) return;
|
||||
Int32Signature sig(2);
|
||||
RegisterPairs pairs;
|
||||
while (pairs.More()) {
|
||||
@ -429,12 +668,11 @@ TEST(Run_Int32Sub_all_allocatable_single) {
|
||||
CallDescriptor* desc = config.Create(&zone, &sig);
|
||||
TestInt32Sub(desc);
|
||||
}
|
||||
#endif // NATIVE_STACK_PARAMS_OK
|
||||
}
|
||||
|
||||
|
||||
TEST(Run_CopyTwentyInt32_all_allocatable_pairs) {
|
||||
#ifdef NATIVE_STACK_PARAMS_OK
|
||||
if (DISABLE_NATIVE_STACK_PARAMS) return;
|
||||
Int32Signature sig(20);
|
||||
RegisterPairs pairs;
|
||||
while (pairs.More()) {
|
||||
@ -448,113 +686,14 @@ TEST(Run_CopyTwentyInt32_all_allocatable_pairs) {
|
||||
CallDescriptor* desc = config.Create(&zone, &sig);
|
||||
CopyTwentyInt32(desc);
|
||||
}
|
||||
#endif // NATIVE_STACK_PARAMS_OK
|
||||
}
|
||||
|
||||
|
||||
#ifdef NATIVE_STACK_PARAMS_OK
|
||||
int ParamCount(CallDescriptor* desc) {
|
||||
return static_cast<int>(desc->GetMachineSignature()->parameter_count());
|
||||
}
|
||||
|
||||
|
||||
// Super mega helper routine to generate a computation with a given
|
||||
// call descriptor, compile the code, wrap the code, and pass various inputs,
|
||||
// comparing against a reference implementation.
|
||||
static void Run_Int32_Computation(
|
||||
template <typename CType>
|
||||
static void Run_Computation(
|
||||
CallDescriptor* desc, void (*build)(CallDescriptor*, RawMachineAssembler&),
|
||||
int32_t (*compute)(CallDescriptor*, int32_t* inputs), int seed = 1) {
|
||||
int num_params = ParamCount(desc);
|
||||
CHECK_LE(num_params, kMaxParamCount);
|
||||
int32_t input[kMaxParamCount];
|
||||
Isolate* isolate = CcTest::InitIsolateOnce();
|
||||
HandleScope scope(isolate);
|
||||
Handle<Code> inner = Handle<Code>::null();
|
||||
{
|
||||
// Build the graph for the computation.
|
||||
Zone zone;
|
||||
Graph graph(&zone);
|
||||
RawMachineAssembler raw(isolate, &graph, desc);
|
||||
build(desc, raw);
|
||||
inner = CompileGraph("Compute", desc, &graph, raw.Export());
|
||||
}
|
||||
|
||||
CSignature0<int32_t> csig;
|
||||
|
||||
if (false) {
|
||||
// constant mode.
|
||||
Handle<Code> wrapper = Handle<Code>::null();
|
||||
{
|
||||
// Wrap the above code with a callable function that passes constants.
|
||||
Zone zone;
|
||||
Graph graph(&zone);
|
||||
CallDescriptor* cdesc = Linkage::GetSimplifiedCDescriptor(&zone, &csig);
|
||||
RawMachineAssembler raw(isolate, &graph, cdesc);
|
||||
Unique<HeapObject> unique =
|
||||
Unique<HeapObject>::CreateUninitialized(inner);
|
||||
Node* target = raw.HeapConstant(unique);
|
||||
Node** args = zone.NewArray<Node*>(kMaxParamCount);
|
||||
for (int i = 0; i < num_params; i++) {
|
||||
args[i] = raw.Int32Constant(0x100 + i);
|
||||
}
|
||||
|
||||
Node* call = raw.CallN(desc, target, args);
|
||||
raw.Return(call);
|
||||
wrapper = CompileGraph("Compute-wrapper", cdesc, &graph, raw.Export());
|
||||
}
|
||||
|
||||
CodeRunner<int32_t> runnable(isolate, wrapper, &csig);
|
||||
|
||||
// Run the code, checking it against the reference.
|
||||
for (int j = 0; j < kMaxParamCount; j++) {
|
||||
input[j] = 0x100 + j;
|
||||
}
|
||||
int32_t expected = compute(desc, input);
|
||||
int32_t result = runnable.Call();
|
||||
|
||||
CHECK_EQ(expected, result);
|
||||
}
|
||||
|
||||
{
|
||||
// buffer mode.
|
||||
Handle<Code> wrapper = Handle<Code>::null();
|
||||
{
|
||||
// Wrap the above code with a callable function that loads from {input}.
|
||||
Zone zone;
|
||||
Graph graph(&zone);
|
||||
CallDescriptor* cdesc = Linkage::GetSimplifiedCDescriptor(&zone, &csig);
|
||||
RawMachineAssembler raw(isolate, &graph, cdesc);
|
||||
Node* base = raw.PointerConstant(input);
|
||||
Unique<HeapObject> unique =
|
||||
Unique<HeapObject>::CreateUninitialized(inner);
|
||||
Node* target = raw.HeapConstant(unique);
|
||||
Node** args = zone.NewArray<Node*>(kMaxParamCount);
|
||||
for (int i = 0; i < num_params; i++) {
|
||||
Node* offset = raw.Int32Constant(i * sizeof(int32_t));
|
||||
args[i] = raw.Load(kMachInt32, base, offset);
|
||||
}
|
||||
|
||||
Node* call = raw.CallN(desc, target, args);
|
||||
raw.Return(call);
|
||||
wrapper = CompileGraph("Compute-wrapper", cdesc, &graph, raw.Export());
|
||||
}
|
||||
|
||||
CodeRunner<int32_t> runnable(isolate, wrapper, &csig);
|
||||
|
||||
// Run the code, checking it against the reference.
|
||||
for (int i = 0; i < 5; i++) {
|
||||
// Use pseudo-random values for each run, but the first run gets args
|
||||
// 100, 101, 102, 103... for easier diagnosis.
|
||||
uint32_t base = 1111111111u * i * seed;
|
||||
for (int j = 0; j < kMaxParamCount; j++) {
|
||||
input[j] = static_cast<int32_t>(100 + base + j);
|
||||
}
|
||||
int32_t expected = compute(desc, input);
|
||||
int32_t result = runnable.Call();
|
||||
|
||||
CHECK_EQ(expected, result);
|
||||
}
|
||||
}
|
||||
CType (*compute)(CallDescriptor*, CType* inputs), int seed = 1) {
|
||||
Computer<CType>::Run(desc, build, compute, seed);
|
||||
}
|
||||
|
||||
|
||||
@ -584,6 +723,7 @@ static int32_t Compute_Int32_WeightedSum(CallDescriptor* desc, int32_t* input) {
|
||||
|
||||
|
||||
static void Test_Int32_WeightedSum_of_size(int count) {
|
||||
if (DISABLE_NATIVE_STACK_PARAMS) return;
|
||||
Int32Signature sig(count);
|
||||
for (int p0 = 0; p0 < Register::kMaxNumAllocatableRegisters; p0++) {
|
||||
Zone zone;
|
||||
@ -594,8 +734,8 @@ static void Test_Int32_WeightedSum_of_size(int count) {
|
||||
Allocator rets(rarray, 1, nullptr, 0);
|
||||
RegisterConfig config(params, rets);
|
||||
CallDescriptor* desc = config.Create(&zone, &sig);
|
||||
Run_Int32_Computation(desc, Build_Int32_WeightedSum,
|
||||
Compute_Int32_WeightedSum, 257 + count);
|
||||
Run_Computation<int32_t>(desc, Build_Int32_WeightedSum,
|
||||
Compute_Int32_WeightedSum, 257 + count);
|
||||
}
|
||||
}
|
||||
|
||||
@ -618,19 +758,21 @@ TEST_INT32_WEIGHTEDSUM(19)
|
||||
|
||||
|
||||
template <int which>
|
||||
static void Build_Int32_Select(CallDescriptor* desc, RawMachineAssembler& raw) {
|
||||
static void Build_Select(CallDescriptor* desc, RawMachineAssembler& raw) {
|
||||
raw.Return(raw.Parameter(which));
|
||||
}
|
||||
|
||||
|
||||
template <int which>
|
||||
static int32_t Compute_Int32_Select(CallDescriptor* desc, int32_t* inputs) {
|
||||
template <typename CType, int which>
|
||||
static CType Compute_Select(CallDescriptor* desc, CType* inputs) {
|
||||
return inputs[which];
|
||||
}
|
||||
|
||||
|
||||
template <int which>
|
||||
void Test_Int32_Select() {
|
||||
if (DISABLE_NATIVE_STACK_PARAMS) return;
|
||||
|
||||
int parray[] = {0};
|
||||
int rarray[] = {0};
|
||||
Allocator params(parray, 1, nullptr, 0);
|
||||
@ -642,8 +784,8 @@ void Test_Int32_Select() {
|
||||
for (int i = which + 1; i <= 64; i++) {
|
||||
Int32Signature sig(i);
|
||||
CallDescriptor* desc = config.Create(&zone, &sig);
|
||||
Run_Int32_Computation(desc, Build_Int32_Select<which>,
|
||||
Compute_Int32_Select<which>, 1025 + which);
|
||||
Run_Computation<int32_t>(desc, Build_Select<which>,
|
||||
Compute_Select<int32_t, which>, 1025 + which);
|
||||
}
|
||||
}
|
||||
|
||||
@ -666,9 +808,79 @@ TEST_INT32_SELECT(19)
|
||||
TEST_INT32_SELECT(45)
|
||||
TEST_INT32_SELECT(62)
|
||||
TEST_INT32_SELECT(63)
|
||||
#endif // NATIVE_STACK_PARAMS_OK
|
||||
|
||||
|
||||
TEST(TheLastTestForLint) {
|
||||
// Yes, thank you.
|
||||
TEST(Int64Select_registers) {
|
||||
if (Register::kMaxNumAllocatableRegisters < 2) return;
|
||||
if (kPointerSize < 8) return; // TODO(titzer): int64 on 32-bit platforms
|
||||
|
||||
int rarray[] = {0};
|
||||
ArgsBuffer<int64_t>::Sig sig(2);
|
||||
|
||||
RegisterPairs pairs;
|
||||
Zone zone;
|
||||
while (pairs.More()) {
|
||||
int parray[2];
|
||||
pairs.Next(&parray[0], &parray[1], false);
|
||||
Allocator params(parray, 2, nullptr, 0);
|
||||
Allocator rets(rarray, 1, nullptr, 0);
|
||||
RegisterConfig config(params, rets);
|
||||
|
||||
CallDescriptor* desc = config.Create(&zone, &sig);
|
||||
Run_Computation<int64_t>(desc, Build_Select<0>, Compute_Select<int64_t, 0>,
|
||||
1021);
|
||||
|
||||
Run_Computation<int64_t>(desc, Build_Select<1>, Compute_Select<int64_t, 1>,
|
||||
1022);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST(Float32Select_registers) {
|
||||
if (DoubleRegister::kMaxNumAllocatableRegisters < 2) return;
|
||||
|
||||
int rarray[] = {0};
|
||||
ArgsBuffer<float32>::Sig sig(2);
|
||||
|
||||
Float32RegisterPairs pairs;
|
||||
Zone zone;
|
||||
while (pairs.More()) {
|
||||
int parray[2];
|
||||
pairs.Next(&parray[0], &parray[1], false);
|
||||
Allocator params(nullptr, 0, parray, 2);
|
||||
Allocator rets(nullptr, 0, rarray, 1);
|
||||
RegisterConfig config(params, rets);
|
||||
|
||||
CallDescriptor* desc = config.Create(&zone, &sig);
|
||||
Run_Computation<float32>(desc, Build_Select<0>, Compute_Select<float32, 0>,
|
||||
1019);
|
||||
|
||||
Run_Computation<float32>(desc, Build_Select<1>, Compute_Select<float32, 1>,
|
||||
1018);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST(Float64Select_registers) {
|
||||
if (DoubleRegister::kMaxNumAllocatableRegisters < 2) return;
|
||||
|
||||
int rarray[] = {0};
|
||||
ArgsBuffer<float64>::Sig sig(2);
|
||||
|
||||
Float64RegisterPairs pairs;
|
||||
Zone zone;
|
||||
while (pairs.More()) {
|
||||
int parray[2];
|
||||
pairs.Next(&parray[0], &parray[1], false);
|
||||
Allocator params(nullptr, 0, parray, 2);
|
||||
Allocator rets(nullptr, 0, rarray, 1);
|
||||
RegisterConfig config(params, rets);
|
||||
|
||||
CallDescriptor* desc = config.Create(&zone, &sig);
|
||||
Run_Computation<float64>(desc, Build_Select<0>, Compute_Select<float64, 0>,
|
||||
1033);
|
||||
|
||||
Run_Computation<float64>(desc, Build_Select<1>, Compute_Select<float64, 1>,
|
||||
1034);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user