blob: fc7c144939292c251d6a3171552a6e6ca8333bcc [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 Bernier958fae72015-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 Bernier958fae72015-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 Murdoch014dc512016-03-22 12:00:34 +000021class InstructionSelectorTest : public TestWithContext,
22 public TestWithIsolateAndZone {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023 public:
24 InstructionSelectorTest();
Ben Murdoch014dc512016-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 Murdoch014dc512016-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 Murdoch014dc512016-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 Murdoch014dc512016-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 Murdoch014dc512016-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 Murdoch014dc512016-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 Murdoch014dc512016-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 Murdoch014dc512016-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 Murdoch014dc512016-03-22 12:00:34 +000095 return Linkage::GetSimplifiedCDescriptor(zone, builder.Build());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000096 }
97
Ben Murdoch014dc512016-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 Murdoch014dc512016-03-22 12:00:34 +0000103 return Linkage::GetSimplifiedCDescriptor(zone, builder.Build());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000104 }
105
Ben Murdoch014dc512016-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 Murdoch014dc512016-03-22 12:00:34 +0000113 return Linkage::GetSimplifiedCDescriptor(zone, builder.Build());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000114 }
115
Ben Murdoch014dc512016-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 Murdoch014dc512016-03-22 12:00:34 +0000125 return Linkage::GetSimplifiedCDescriptor(zone, builder.Build());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000126 }
127
128 private:
129 InstructionSelectorTest* test_;
130 };
131
Ben Murdoch014dc512016-03-22 12:00:34 +0000132 class Stream final {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000133 public:
134 size_t size() const { return instructions_.size(); }
135 const Instruction* operator[](size_t index) const {
136 EXPECT_LT(index, size());
137 return instructions_[index];
138 }
139
140 bool IsDouble(const InstructionOperand* operand) const {
141 return IsDouble(ToVreg(operand));
142 }
Emily Bernier958fae72015-03-24 16:35:39 -0400143
144 bool IsDouble(const Node* node) const { return IsDouble(ToVreg(node)); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000145
146 bool IsInteger(const InstructionOperand* operand) const {
147 return IsInteger(ToVreg(operand));
148 }
Emily Bernier958fae72015-03-24 16:35:39 -0400149
150 bool IsInteger(const Node* node) const { return IsInteger(ToVreg(node)); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000151
152 bool IsReference(const InstructionOperand* operand) const {
153 return IsReference(ToVreg(operand));
154 }
Emily Bernier958fae72015-03-24 16:35:39 -0400155
156 bool IsReference(const Node* node) const {
157 return IsReference(ToVreg(node));
158 }
159
160 float ToFloat32(const InstructionOperand* operand) const {
161 return ToConstant(operand).ToFloat32();
162 }
163
164 double ToFloat64(const InstructionOperand* operand) const {
165 return ToConstant(operand).ToFloat64();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000166 }
167
168 int32_t ToInt32(const InstructionOperand* operand) const {
169 return ToConstant(operand).ToInt32();
170 }
171
172 int64_t ToInt64(const InstructionOperand* operand) const {
173 return ToConstant(operand).ToInt64();
174 }
175
Emily Bernier958fae72015-03-24 16:35:39 -0400176 Handle<HeapObject> ToHeapObject(const InstructionOperand* operand) const {
177 return ToConstant(operand).ToHeapObject();
178 }
179
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000180 int ToVreg(const InstructionOperand* operand) const {
Ben Murdoch014dc512016-03-22 12:00:34 +0000181 if (operand->IsConstant()) {
182 return ConstantOperand::cast(operand)->virtual_register();
183 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000184 EXPECT_EQ(InstructionOperand::UNALLOCATED, operand->kind());
185 return UnallocatedOperand::cast(operand)->virtual_register();
186 }
187
Emily Bernier958fae72015-03-24 16:35:39 -0400188 int ToVreg(const Node* node) const;
189
190 bool IsFixed(const InstructionOperand* operand, Register reg) const;
191 bool IsSameAsFirst(const InstructionOperand* operand) const;
192 bool IsUsedAtStart(const InstructionOperand* operand) const;
193
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000194 FrameStateDescriptor* GetFrameStateDescriptor(int deoptimization_id) {
195 EXPECT_LT(deoptimization_id, GetFrameStateDescriptorCount());
196 return deoptimization_entries_[deoptimization_id];
197 }
198
199 int GetFrameStateDescriptorCount() {
200 return static_cast<int>(deoptimization_entries_.size());
201 }
202
203 private:
Emily Bernier958fae72015-03-24 16:35:39 -0400204 bool IsDouble(int virtual_register) const {
205 return doubles_.find(virtual_register) != doubles_.end();
206 }
207
208 bool IsInteger(int virtual_register) const {
209 return !IsDouble(virtual_register) && !IsReference(virtual_register);
210 }
211
212 bool IsReference(int virtual_register) const {
213 return references_.find(virtual_register) != references_.end();
214 }
215
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000216 Constant ToConstant(const InstructionOperand* operand) const {
217 ConstantMap::const_iterator i;
218 if (operand->IsConstant()) {
Ben Murdoch014dc512016-03-22 12:00:34 +0000219 i = constants_.find(ConstantOperand::cast(operand)->virtual_register());
220 EXPECT_EQ(ConstantOperand::cast(operand)->virtual_register(), i->first);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000221 EXPECT_FALSE(constants_.end() == i);
222 } else {
223 EXPECT_EQ(InstructionOperand::IMMEDIATE, operand->kind());
Ben Murdoch014dc512016-03-22 12:00:34 +0000224 auto imm = ImmediateOperand::cast(operand);
225 if (imm->type() == ImmediateOperand::INLINE) {
226 return Constant(imm->inline_value());
227 }
228 i = immediates_.find(imm->indexed_value());
229 EXPECT_EQ(imm->indexed_value(), i->first);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000230 EXPECT_FALSE(immediates_.end() == i);
231 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000232 return i->second;
233 }
234
235 friend class StreamBuilder;
236
237 typedef std::map<int, Constant> ConstantMap;
Emily Bernier958fae72015-03-24 16:35:39 -0400238 typedef std::map<NodeId, int> VirtualRegisters;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000239
240 ConstantMap constants_;
241 ConstantMap immediates_;
242 std::deque<Instruction*> instructions_;
243 std::set<int> doubles_;
244 std::set<int> references_;
Emily Bernier958fae72015-03-24 16:35:39 -0400245 VirtualRegisters virtual_registers_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000246 std::deque<FrameStateDescriptor*> deoptimization_entries_;
247 };
248
249 base::RandomNumberGenerator rng_;
250};
251
252
253template <typename T>
254class InstructionSelectorTestWithParam
255 : public InstructionSelectorTest,
256 public ::testing::WithParamInterface<T> {};
257
258} // namespace compiler
259} // namespace internal
260} // namespace v8
261
Emily Bernier958fae72015-03-24 16:35:39 -0400262#endif // V8_UNITTESTS_COMPILER_INSTRUCTION_SELECTOR_UNITTEST_H_