blob: f1397faa06157161275b80fd51f02395e20978de [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// Copyright 2014 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Emily Bernierd0a1eb72015-03-24 16:35:39 -04005#ifndef V8_UNITTESTS_COMPILER_INSTRUCTION_SELECTOR_UNITTEST_H_
6#define V8_UNITTESTS_COMPILER_INSTRUCTION_SELECTOR_UNITTEST_H_
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007
8#include <deque>
9#include <set>
10
11#include "src/base/utils/random-number-generator.h"
12#include "src/compiler/instruction-selector.h"
13#include "src/compiler/raw-machine-assembler.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040014#include "src/macro-assembler.h"
15#include "test/unittests/test-utils.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016
17namespace v8 {
18namespace internal {
19namespace compiler {
20
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000021class InstructionSelectorTest : public TestWithContext,
22 public TestWithIsolateAndZone {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023 public:
24 InstructionSelectorTest();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000025 ~InstructionSelectorTest() override;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000026
27 base::RandomNumberGenerator* rng() { return &rng_; }
28
29 class Stream;
30
31 enum StreamBuilderMode {
32 kAllInstructions,
33 kTargetInstructions,
34 kAllExceptNopInstructions
35 };
36
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000037 class StreamBuilder final : public RawMachineAssembler {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000038 public:
39 StreamBuilder(InstructionSelectorTest* test, MachineType return_type)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000040 : RawMachineAssembler(test->isolate(),
41 new (test->zone()) Graph(test->zone()),
42 MakeCallDescriptor(test->zone(), return_type),
43 MachineType::PointerRepresentation(),
44 MachineOperatorBuilder::kAllOptionalOps),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000045 test_(test) {}
46 StreamBuilder(InstructionSelectorTest* test, MachineType return_type,
47 MachineType parameter0_type)
48 : RawMachineAssembler(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000049 test->isolate(), new (test->zone()) Graph(test->zone()),
50 MakeCallDescriptor(test->zone(), return_type, parameter0_type),
51 MachineType::PointerRepresentation(),
52 MachineOperatorBuilder::kAllOptionalOps),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000053 test_(test) {}
54 StreamBuilder(InstructionSelectorTest* test, MachineType return_type,
55 MachineType parameter0_type, MachineType parameter1_type)
56 : RawMachineAssembler(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000057 test->isolate(), new (test->zone()) Graph(test->zone()),
58 MakeCallDescriptor(test->zone(), return_type, parameter0_type,
59 parameter1_type),
60 MachineType::PointerRepresentation(),
61 MachineOperatorBuilder::kAllOptionalOps),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000062 test_(test) {}
63 StreamBuilder(InstructionSelectorTest* test, MachineType return_type,
64 MachineType parameter0_type, MachineType parameter1_type,
65 MachineType parameter2_type)
66 : RawMachineAssembler(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000067 test->isolate(), new (test->zone()) Graph(test->zone()),
68 MakeCallDescriptor(test->zone(), return_type, parameter0_type,
69 parameter1_type, parameter2_type),
70 MachineType::PointerRepresentation(),
71 MachineOperatorBuilder::kAllOptionalOps),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000072 test_(test) {}
73
74 Stream Build(CpuFeature feature) {
75 return Build(InstructionSelector::Features(feature));
76 }
77 Stream Build(CpuFeature feature1, CpuFeature feature2) {
78 return Build(InstructionSelector::Features(feature1, feature2));
79 }
80 Stream Build(StreamBuilderMode mode = kTargetInstructions) {
81 return Build(InstructionSelector::Features(), mode);
82 }
83 Stream Build(InstructionSelector::Features features,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000084 StreamBuilderMode mode = kTargetInstructions,
85 InstructionSelector::SourcePositionMode source_position_mode =
86 InstructionSelector::kAllSourcePositions);
87
88 const FrameStateFunctionInfo* GetFrameStateFunctionInfo(int parameter_count,
89 int local_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000090
91 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000092 CallDescriptor* MakeCallDescriptor(Zone* zone, MachineType return_type) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000093 MachineSignature::Builder builder(zone, 1, 0);
94 builder.AddReturn(return_type);
Ben Murdoch097c5b22016-05-18 11:27:45 +010095 return MakeSimpleCallDescriptor(zone, builder.Build());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000096 }
97
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000098 CallDescriptor* MakeCallDescriptor(Zone* zone, MachineType return_type,
99 MachineType parameter0_type) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000100 MachineSignature::Builder builder(zone, 1, 1);
101 builder.AddReturn(return_type);
102 builder.AddParam(parameter0_type);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100103 return MakeSimpleCallDescriptor(zone, builder.Build());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000104 }
105
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000106 CallDescriptor* MakeCallDescriptor(Zone* zone, MachineType return_type,
107 MachineType parameter0_type,
108 MachineType parameter1_type) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000109 MachineSignature::Builder builder(zone, 1, 2);
110 builder.AddReturn(return_type);
111 builder.AddParam(parameter0_type);
112 builder.AddParam(parameter1_type);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100113 return MakeSimpleCallDescriptor(zone, builder.Build());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000114 }
115
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000116 CallDescriptor* MakeCallDescriptor(Zone* zone, MachineType return_type,
117 MachineType parameter0_type,
118 MachineType parameter1_type,
119 MachineType parameter2_type) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000120 MachineSignature::Builder builder(zone, 1, 3);
121 builder.AddReturn(return_type);
122 builder.AddParam(parameter0_type);
123 builder.AddParam(parameter1_type);
124 builder.AddParam(parameter2_type);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100125 return MakeSimpleCallDescriptor(zone, builder.Build());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000126 }
127
128 private:
129 InstructionSelectorTest* test_;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100130
131 // Create a simple call descriptor for testing.
132 CallDescriptor* MakeSimpleCallDescriptor(Zone* zone,
133 MachineSignature* msig) {
134 LocationSignature::Builder locations(zone, msig->return_count(),
135 msig->parameter_count());
136
137 // Add return location(s).
138 const int return_count = static_cast<int>(msig->return_count());
139 for (int i = 0; i < return_count; i++) {
140 locations.AddReturn(LinkageLocation::ForCallerFrameSlot(-1 - i));
141 }
142
143 // Just put all parameters on the stack.
144 const int parameter_count = static_cast<int>(msig->parameter_count());
145 for (int i = 0; i < parameter_count; i++) {
146 locations.AddParam(LinkageLocation::ForCallerFrameSlot(-1 - i));
147 }
148
149 const RegList kCalleeSaveRegisters = 0;
150 const RegList kCalleeSaveFPRegisters = 0;
151
152 MachineType target_type = MachineType::Pointer();
153 LinkageLocation target_loc = LinkageLocation::ForAnyRegister();
154 return new (zone) CallDescriptor( // --
155 CallDescriptor::kCallAddress, // kind
156 target_type, // target MachineType
157 target_loc, // target location
158 msig, // machine_sig
159 locations.Build(), // location_sig
160 0, // stack_parameter_count
161 Operator::kNoProperties, // properties
162 kCalleeSaveRegisters, // callee-saved registers
163 kCalleeSaveFPRegisters, // callee-saved fp regs
164 CallDescriptor::kNoFlags, // flags
165 "iselect-test-call");
166 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000167 };
168
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000169 class Stream final {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000170 public:
171 size_t size() const { return instructions_.size(); }
172 const Instruction* operator[](size_t index) const {
173 EXPECT_LT(index, size());
174 return instructions_[index];
175 }
176
177 bool IsDouble(const InstructionOperand* operand) const {
178 return IsDouble(ToVreg(operand));
179 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400180
181 bool IsDouble(const Node* node) const { return IsDouble(ToVreg(node)); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000182
183 bool IsInteger(const InstructionOperand* operand) const {
184 return IsInteger(ToVreg(operand));
185 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400186
187 bool IsInteger(const Node* node) const { return IsInteger(ToVreg(node)); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000188
189 bool IsReference(const InstructionOperand* operand) const {
190 return IsReference(ToVreg(operand));
191 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400192
193 bool IsReference(const Node* node) const {
194 return IsReference(ToVreg(node));
195 }
196
197 float ToFloat32(const InstructionOperand* operand) const {
198 return ToConstant(operand).ToFloat32();
199 }
200
201 double ToFloat64(const InstructionOperand* operand) const {
202 return ToConstant(operand).ToFloat64();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000203 }
204
205 int32_t ToInt32(const InstructionOperand* operand) const {
206 return ToConstant(operand).ToInt32();
207 }
208
209 int64_t ToInt64(const InstructionOperand* operand) const {
210 return ToConstant(operand).ToInt64();
211 }
212
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400213 Handle<HeapObject> ToHeapObject(const InstructionOperand* operand) const {
214 return ToConstant(operand).ToHeapObject();
215 }
216
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000217 int ToVreg(const InstructionOperand* operand) const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000218 if (operand->IsConstant()) {
219 return ConstantOperand::cast(operand)->virtual_register();
220 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000221 EXPECT_EQ(InstructionOperand::UNALLOCATED, operand->kind());
222 return UnallocatedOperand::cast(operand)->virtual_register();
223 }
224
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400225 int ToVreg(const Node* node) const;
226
227 bool IsFixed(const InstructionOperand* operand, Register reg) const;
228 bool IsSameAsFirst(const InstructionOperand* operand) const;
229 bool IsUsedAtStart(const InstructionOperand* operand) const;
230
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000231 FrameStateDescriptor* GetFrameStateDescriptor(int deoptimization_id) {
232 EXPECT_LT(deoptimization_id, GetFrameStateDescriptorCount());
233 return deoptimization_entries_[deoptimization_id];
234 }
235
236 int GetFrameStateDescriptorCount() {
237 return static_cast<int>(deoptimization_entries_.size());
238 }
239
240 private:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400241 bool IsDouble(int virtual_register) const {
242 return doubles_.find(virtual_register) != doubles_.end();
243 }
244
245 bool IsInteger(int virtual_register) const {
246 return !IsDouble(virtual_register) && !IsReference(virtual_register);
247 }
248
249 bool IsReference(int virtual_register) const {
250 return references_.find(virtual_register) != references_.end();
251 }
252
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000253 Constant ToConstant(const InstructionOperand* operand) const {
254 ConstantMap::const_iterator i;
255 if (operand->IsConstant()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000256 i = constants_.find(ConstantOperand::cast(operand)->virtual_register());
257 EXPECT_EQ(ConstantOperand::cast(operand)->virtual_register(), i->first);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000258 EXPECT_FALSE(constants_.end() == i);
259 } else {
260 EXPECT_EQ(InstructionOperand::IMMEDIATE, operand->kind());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000261 auto imm = ImmediateOperand::cast(operand);
262 if (imm->type() == ImmediateOperand::INLINE) {
263 return Constant(imm->inline_value());
264 }
265 i = immediates_.find(imm->indexed_value());
266 EXPECT_EQ(imm->indexed_value(), i->first);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000267 EXPECT_FALSE(immediates_.end() == i);
268 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000269 return i->second;
270 }
271
272 friend class StreamBuilder;
273
274 typedef std::map<int, Constant> ConstantMap;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400275 typedef std::map<NodeId, int> VirtualRegisters;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000276
277 ConstantMap constants_;
278 ConstantMap immediates_;
279 std::deque<Instruction*> instructions_;
280 std::set<int> doubles_;
281 std::set<int> references_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400282 VirtualRegisters virtual_registers_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000283 std::deque<FrameStateDescriptor*> deoptimization_entries_;
284 };
285
286 base::RandomNumberGenerator rng_;
287};
288
289
290template <typename T>
291class InstructionSelectorTestWithParam
292 : public InstructionSelectorTest,
293 public ::testing::WithParamInterface<T> {};
294
295} // namespace compiler
296} // namespace internal
297} // namespace v8
298
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400299#endif // V8_UNITTESTS_COMPILER_INSTRUCTION_SELECTOR_UNITTEST_H_