Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(135)

Unified Diff: test/cctest/compiler/test-run-native-calls.cc

Issue 1291553005: Add tests for float32/float64 parameters/returns passed in float32/float64 registers. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: test/cctest/compiler/test-run-native-calls.cc
diff --git a/test/cctest/compiler/test-run-native-calls.cc b/test/cctest/compiler/test-run-native-calls.cc
index 942d699ae89167b13bce3bac8637ed377e9c96d9..fe30b3c97f1eb18e291817a0ca7ed7442a0fed8e 100644
--- a/test/cctest/compiler/test-run-native-calls.cc
+++ b/test/cctest/compiler/test-run-native-calls.cc
@@ -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);
+ }
}
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698