OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/base/utils/random-number-generator.h" | 5 #include "src/base/utils/random-number-generator.h" |
6 #include "src/compiler/pipeline.h" | 6 #include "src/compiler/pipeline.h" |
7 #include "test/unittests/compiler/instruction-sequence-unittest.h" | 7 #include "test/unittests/compiler/instruction-sequence-unittest.h" |
8 #include "test/unittests/test-utils.h" | 8 #include "test/unittests/test-utils.h" |
9 #include "testing/gmock/include/gmock/gmock.h" | 9 #include "testing/gmock/include/gmock/gmock.h" |
10 | 10 |
(...skipping 22 matching lines...) Expand all Loading... |
33 *loc++ = 0; | 33 *loc++ = 0; |
34 } | 34 } |
35 } | 35 } |
36 | 36 |
37 | 37 |
38 InstructionSequenceTest::InstructionSequenceTest() | 38 InstructionSequenceTest::InstructionSequenceTest() |
39 : sequence_(nullptr), | 39 : sequence_(nullptr), |
40 num_general_registers_(kDefaultNRegs), | 40 num_general_registers_(kDefaultNRegs), |
41 num_double_registers_(kDefaultNRegs), | 41 num_double_registers_(kDefaultNRegs), |
42 instruction_blocks_(zone()), | 42 instruction_blocks_(zone()), |
43 current_instruction_index_(-1), | |
44 current_block_(nullptr), | 43 current_block_(nullptr), |
45 block_returns_(false) { | 44 block_returns_(false) { |
46 InitializeRegisterNames(); | 45 InitializeRegisterNames(); |
47 } | 46 } |
48 | 47 |
49 | 48 |
50 void InstructionSequenceTest::SetNumRegs(int num_general_registers, | 49 void InstructionSequenceTest::SetNumRegs(int num_general_registers, |
51 int num_double_registers) { | 50 int num_double_registers) { |
52 CHECK(config_.is_empty()); | 51 CHECK(config_.is_empty()); |
53 CHECK(instructions_.empty()); | 52 CHECK(instructions_.empty()); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
93 loop_blocks_.pop_back(); | 92 loop_blocks_.pop_back(); |
94 } | 93 } |
95 | 94 |
96 | 95 |
97 void InstructionSequenceTest::StartBlock() { | 96 void InstructionSequenceTest::StartBlock() { |
98 block_returns_ = false; | 97 block_returns_ = false; |
99 NewBlock(); | 98 NewBlock(); |
100 } | 99 } |
101 | 100 |
102 | 101 |
103 int InstructionSequenceTest::EndBlock(BlockCompletion completion) { | 102 Instruction* InstructionSequenceTest::EndBlock(BlockCompletion completion) { |
104 int instruction_index = kMinInt; | 103 Instruction* result = nullptr; |
105 if (block_returns_) { | 104 if (block_returns_) { |
106 CHECK(completion.type_ == kBlockEnd || completion.type_ == kFallThrough); | 105 CHECK(completion.type_ == kBlockEnd || completion.type_ == kFallThrough); |
107 completion.type_ = kBlockEnd; | 106 completion.type_ = kBlockEnd; |
108 } | 107 } |
109 switch (completion.type_) { | 108 switch (completion.type_) { |
110 case kBlockEnd: | 109 case kBlockEnd: |
111 break; | 110 break; |
112 case kFallThrough: | 111 case kFallThrough: |
113 instruction_index = EmitFallThrough(); | 112 result = EmitFallThrough(); |
114 break; | 113 break; |
115 case kJump: | 114 case kJump: |
116 CHECK(!block_returns_); | 115 CHECK(!block_returns_); |
117 instruction_index = EmitJump(); | 116 result = EmitJump(); |
118 break; | 117 break; |
119 case kBranch: | 118 case kBranch: |
120 CHECK(!block_returns_); | 119 CHECK(!block_returns_); |
121 instruction_index = EmitBranch(completion.op_); | 120 result = EmitBranch(completion.op_); |
122 break; | 121 break; |
123 } | 122 } |
124 completions_.push_back(completion); | 123 completions_.push_back(completion); |
125 CHECK(current_block_ != nullptr); | 124 CHECK(current_block_ != nullptr); |
126 sequence()->EndBlock(current_block_->rpo_number()); | 125 sequence()->EndBlock(current_block_->rpo_number()); |
127 current_block_ = nullptr; | 126 current_block_ = nullptr; |
128 return instruction_index; | 127 return result; |
129 } | 128 } |
130 | 129 |
131 | 130 |
132 InstructionSequenceTest::TestOperand InstructionSequenceTest::Imm(int32_t imm) { | 131 InstructionSequenceTest::TestOperand InstructionSequenceTest::Imm(int32_t imm) { |
133 int index = sequence()->AddImmediate(Constant(imm)); | 132 int index = sequence()->AddImmediate(Constant(imm)); |
134 return TestOperand(kImmediate, index); | 133 return TestOperand(kImmediate, index); |
135 } | 134 } |
136 | 135 |
137 | 136 |
138 InstructionSequenceTest::VReg InstructionSequenceTest::Define( | 137 InstructionSequenceTest::VReg InstructionSequenceTest::Define( |
139 TestOperand output_op) { | 138 TestOperand output_op) { |
140 VReg vreg = NewReg(); | 139 VReg vreg = NewReg(); |
141 InstructionOperand outputs[1]{ConvertOutputOp(vreg, output_op)}; | 140 InstructionOperand outputs[1]{ConvertOutputOp(vreg, output_op)}; |
142 Emit(vreg.value_, kArchNop, 1, outputs); | 141 Emit(kArchNop, 1, outputs); |
143 return vreg; | 142 return vreg; |
144 } | 143 } |
145 | 144 |
146 | 145 |
147 int InstructionSequenceTest::Return(TestOperand input_op_0) { | 146 Instruction* InstructionSequenceTest::Return(TestOperand input_op_0) { |
148 block_returns_ = true; | 147 block_returns_ = true; |
149 InstructionOperand inputs[1]{ConvertInputOp(input_op_0)}; | 148 InstructionOperand inputs[1]{ConvertInputOp(input_op_0)}; |
150 return Emit(NewIndex(), kArchRet, 0, nullptr, 1, inputs); | 149 return Emit(kArchRet, 0, nullptr, 1, inputs); |
151 } | 150 } |
152 | 151 |
153 | 152 |
154 PhiInstruction* InstructionSequenceTest::Phi(VReg incoming_vreg_0, | 153 PhiInstruction* InstructionSequenceTest::Phi(VReg incoming_vreg_0, |
155 VReg incoming_vreg_1, | 154 VReg incoming_vreg_1, |
156 VReg incoming_vreg_2, | 155 VReg incoming_vreg_2, |
157 VReg incoming_vreg_3) { | 156 VReg incoming_vreg_3) { |
158 VReg inputs[] = {incoming_vreg_0, incoming_vreg_1, incoming_vreg_2, | 157 VReg inputs[] = {incoming_vreg_0, incoming_vreg_1, incoming_vreg_2, |
159 incoming_vreg_3}; | 158 incoming_vreg_3}; |
160 size_t input_count = 0; | 159 size_t input_count = 0; |
(...skipping 24 matching lines...) Expand all Loading... |
185 CHECK(vreg.value_ != kNoValue); | 184 CHECK(vreg.value_ != kNoValue); |
186 phi->SetInput(input, vreg.value_); | 185 phi->SetInput(input, vreg.value_); |
187 } | 186 } |
188 | 187 |
189 | 188 |
190 InstructionSequenceTest::VReg InstructionSequenceTest::DefineConstant( | 189 InstructionSequenceTest::VReg InstructionSequenceTest::DefineConstant( |
191 int32_t imm) { | 190 int32_t imm) { |
192 VReg vreg = NewReg(); | 191 VReg vreg = NewReg(); |
193 sequence()->AddConstant(vreg.value_, Constant(imm)); | 192 sequence()->AddConstant(vreg.value_, Constant(imm)); |
194 InstructionOperand outputs[1]{ConstantOperand(vreg.value_)}; | 193 InstructionOperand outputs[1]{ConstantOperand(vreg.value_)}; |
195 Emit(vreg.value_, kArchNop, 1, outputs); | 194 Emit(kArchNop, 1, outputs); |
196 return vreg; | 195 return vreg; |
197 } | 196 } |
198 | 197 |
199 | 198 |
200 int InstructionSequenceTest::EmitNop() { return Emit(NewIndex(), kArchNop); } | 199 Instruction* InstructionSequenceTest::EmitNop() { return Emit(kArchNop); } |
201 | 200 |
202 | 201 |
203 static size_t CountInputs(size_t size, | 202 static size_t CountInputs(size_t size, |
204 InstructionSequenceTest::TestOperand* inputs) { | 203 InstructionSequenceTest::TestOperand* inputs) { |
205 size_t i = 0; | 204 size_t i = 0; |
206 for (; i < size; ++i) { | 205 for (; i < size; ++i) { |
207 if (inputs[i].type_ == InstructionSequenceTest::kInvalid) break; | 206 if (inputs[i].type_ == InstructionSequenceTest::kInvalid) break; |
208 } | 207 } |
209 return i; | 208 return i; |
210 } | 209 } |
211 | 210 |
212 | 211 |
213 int InstructionSequenceTest::EmitI(size_t input_size, TestOperand* inputs) { | 212 Instruction* InstructionSequenceTest::EmitI(size_t input_size, |
| 213 TestOperand* inputs) { |
214 InstructionOperand* mapped_inputs = ConvertInputs(input_size, inputs); | 214 InstructionOperand* mapped_inputs = ConvertInputs(input_size, inputs); |
215 return Emit(NewIndex(), kArchNop, 0, nullptr, input_size, mapped_inputs); | 215 return Emit(kArchNop, 0, nullptr, input_size, mapped_inputs); |
216 } | 216 } |
217 | 217 |
218 | 218 |
219 int InstructionSequenceTest::EmitI(TestOperand input_op_0, | 219 Instruction* InstructionSequenceTest::EmitI(TestOperand input_op_0, |
220 TestOperand input_op_1, | 220 TestOperand input_op_1, |
221 TestOperand input_op_2, | 221 TestOperand input_op_2, |
222 TestOperand input_op_3) { | 222 TestOperand input_op_3) { |
223 TestOperand inputs[] = {input_op_0, input_op_1, input_op_2, input_op_3}; | 223 TestOperand inputs[] = {input_op_0, input_op_1, input_op_2, input_op_3}; |
224 return EmitI(CountInputs(arraysize(inputs), inputs), inputs); | 224 return EmitI(CountInputs(arraysize(inputs), inputs), inputs); |
225 } | 225 } |
226 | 226 |
227 | 227 |
228 InstructionSequenceTest::VReg InstructionSequenceTest::EmitOI( | 228 InstructionSequenceTest::VReg InstructionSequenceTest::EmitOI( |
229 TestOperand output_op, size_t input_size, TestOperand* inputs) { | 229 TestOperand output_op, size_t input_size, TestOperand* inputs) { |
230 VReg output_vreg = NewReg(); | 230 VReg output_vreg = NewReg(); |
231 InstructionOperand outputs[1]{ConvertOutputOp(output_vreg, output_op)}; | 231 InstructionOperand outputs[1]{ConvertOutputOp(output_vreg, output_op)}; |
232 InstructionOperand* mapped_inputs = ConvertInputs(input_size, inputs); | 232 InstructionOperand* mapped_inputs = ConvertInputs(input_size, inputs); |
233 Emit(output_vreg.value_, kArchNop, 1, outputs, input_size, mapped_inputs); | 233 Emit(kArchNop, 1, outputs, input_size, mapped_inputs); |
234 return output_vreg; | 234 return output_vreg; |
235 } | 235 } |
236 | 236 |
237 | 237 |
238 InstructionSequenceTest::VReg InstructionSequenceTest::EmitOI( | 238 InstructionSequenceTest::VReg InstructionSequenceTest::EmitOI( |
239 TestOperand output_op, TestOperand input_op_0, TestOperand input_op_1, | 239 TestOperand output_op, TestOperand input_op_0, TestOperand input_op_1, |
240 TestOperand input_op_2, TestOperand input_op_3) { | 240 TestOperand input_op_2, TestOperand input_op_3) { |
241 TestOperand inputs[] = {input_op_0, input_op_1, input_op_2, input_op_3}; | 241 TestOperand inputs[] = {input_op_0, input_op_1, input_op_2, input_op_3}; |
242 return EmitOI(output_op, CountInputs(arraysize(inputs), inputs), inputs); | 242 return EmitOI(output_op, CountInputs(arraysize(inputs), inputs), inputs); |
243 } | 243 } |
244 | 244 |
245 | 245 |
| 246 InstructionSequenceTest::VRegPair InstructionSequenceTest::EmitOOI( |
| 247 TestOperand output_op_0, TestOperand output_op_1, size_t input_size, |
| 248 TestOperand* inputs) { |
| 249 VRegPair output_vregs = std::make_pair(NewReg(), NewReg()); |
| 250 InstructionOperand outputs[2]{ |
| 251 ConvertOutputOp(output_vregs.first, output_op_0), |
| 252 ConvertOutputOp(output_vregs.second, output_op_1)}; |
| 253 InstructionOperand* mapped_inputs = ConvertInputs(input_size, inputs); |
| 254 Emit(kArchNop, 2, outputs, input_size, mapped_inputs); |
| 255 return output_vregs; |
| 256 } |
| 257 |
| 258 |
| 259 InstructionSequenceTest::VRegPair InstructionSequenceTest::EmitOOI( |
| 260 TestOperand output_op_0, TestOperand output_op_1, TestOperand input_op_0, |
| 261 TestOperand input_op_1, TestOperand input_op_2, TestOperand input_op_3) { |
| 262 TestOperand inputs[] = {input_op_0, input_op_1, input_op_2, input_op_3}; |
| 263 return EmitOOI(output_op_0, output_op_1, |
| 264 CountInputs(arraysize(inputs), inputs), inputs); |
| 265 } |
| 266 |
| 267 |
246 InstructionSequenceTest::VReg InstructionSequenceTest::EmitCall( | 268 InstructionSequenceTest::VReg InstructionSequenceTest::EmitCall( |
247 TestOperand output_op, size_t input_size, TestOperand* inputs) { | 269 TestOperand output_op, size_t input_size, TestOperand* inputs) { |
248 VReg output_vreg = NewReg(); | 270 VReg output_vreg = NewReg(); |
249 InstructionOperand outputs[1]{ConvertOutputOp(output_vreg, output_op)}; | 271 InstructionOperand outputs[1]{ConvertOutputOp(output_vreg, output_op)}; |
250 CHECK(UnallocatedOperand::cast(outputs[0]).HasFixedPolicy()); | 272 CHECK(UnallocatedOperand::cast(outputs[0]).HasFixedPolicy()); |
251 InstructionOperand* mapped_inputs = ConvertInputs(input_size, inputs); | 273 InstructionOperand* mapped_inputs = ConvertInputs(input_size, inputs); |
252 Emit(output_vreg.value_, kArchCallCodeObject, 1, outputs, input_size, | 274 Emit(kArchCallCodeObject, 1, outputs, input_size, mapped_inputs, 0, nullptr, |
253 mapped_inputs, 0, nullptr, true); | 275 true); |
254 return output_vreg; | 276 return output_vreg; |
255 } | 277 } |
256 | 278 |
257 | 279 |
258 InstructionSequenceTest::VReg InstructionSequenceTest::EmitCall( | 280 InstructionSequenceTest::VReg InstructionSequenceTest::EmitCall( |
259 TestOperand output_op, TestOperand input_op_0, TestOperand input_op_1, | 281 TestOperand output_op, TestOperand input_op_0, TestOperand input_op_1, |
260 TestOperand input_op_2, TestOperand input_op_3) { | 282 TestOperand input_op_2, TestOperand input_op_3) { |
261 TestOperand inputs[] = {input_op_0, input_op_1, input_op_2, input_op_3}; | 283 TestOperand inputs[] = {input_op_0, input_op_1, input_op_2, input_op_3}; |
262 return EmitCall(output_op, CountInputs(arraysize(inputs), inputs), inputs); | 284 return EmitCall(output_op, CountInputs(arraysize(inputs), inputs), inputs); |
263 } | 285 } |
264 | 286 |
265 | 287 |
266 const Instruction* InstructionSequenceTest::GetInstruction( | 288 Instruction* InstructionSequenceTest::EmitBranch(TestOperand input_op) { |
267 int instruction_index) { | |
268 auto it = instructions_.find(instruction_index); | |
269 CHECK(it != instructions_.end()); | |
270 return it->second; | |
271 } | |
272 | |
273 | |
274 int InstructionSequenceTest::EmitBranch(TestOperand input_op) { | |
275 InstructionOperand inputs[4]{ConvertInputOp(input_op), ConvertInputOp(Imm()), | 289 InstructionOperand inputs[4]{ConvertInputOp(input_op), ConvertInputOp(Imm()), |
276 ConvertInputOp(Imm()), ConvertInputOp(Imm())}; | 290 ConvertInputOp(Imm()), ConvertInputOp(Imm())}; |
277 InstructionCode opcode = kArchJmp | FlagsModeField::encode(kFlags_branch) | | 291 InstructionCode opcode = kArchJmp | FlagsModeField::encode(kFlags_branch) | |
278 FlagsConditionField::encode(kEqual); | 292 FlagsConditionField::encode(kEqual); |
279 auto instruction = | 293 auto instruction = |
280 NewInstruction(opcode, 0, nullptr, 4, inputs)->MarkAsControl(); | 294 NewInstruction(opcode, 0, nullptr, 4, inputs)->MarkAsControl(); |
281 return AddInstruction(NewIndex(), instruction); | 295 return AddInstruction(instruction); |
282 } | 296 } |
283 | 297 |
284 | 298 |
285 int InstructionSequenceTest::EmitFallThrough() { | 299 Instruction* InstructionSequenceTest::EmitFallThrough() { |
286 auto instruction = NewInstruction(kArchNop, 0, nullptr)->MarkAsControl(); | 300 auto instruction = NewInstruction(kArchNop, 0, nullptr)->MarkAsControl(); |
287 return AddInstruction(NewIndex(), instruction); | 301 return AddInstruction(instruction); |
288 } | 302 } |
289 | 303 |
290 | 304 |
291 int InstructionSequenceTest::EmitJump() { | 305 Instruction* InstructionSequenceTest::EmitJump() { |
292 InstructionOperand inputs[1]{ConvertInputOp(Imm())}; | 306 InstructionOperand inputs[1]{ConvertInputOp(Imm())}; |
293 auto instruction = | 307 auto instruction = |
294 NewInstruction(kArchJmp, 0, nullptr, 1, inputs)->MarkAsControl(); | 308 NewInstruction(kArchJmp, 0, nullptr, 1, inputs)->MarkAsControl(); |
295 return AddInstruction(NewIndex(), instruction); | 309 return AddInstruction(instruction); |
296 } | 310 } |
297 | 311 |
298 | 312 |
299 Instruction* InstructionSequenceTest::NewInstruction( | 313 Instruction* InstructionSequenceTest::NewInstruction( |
300 InstructionCode code, size_t outputs_size, InstructionOperand* outputs, | 314 InstructionCode code, size_t outputs_size, InstructionOperand* outputs, |
301 size_t inputs_size, InstructionOperand* inputs, size_t temps_size, | 315 size_t inputs_size, InstructionOperand* inputs, size_t temps_size, |
302 InstructionOperand* temps) { | 316 InstructionOperand* temps) { |
303 CHECK(current_block_); | 317 CHECK(current_block_); |
304 return Instruction::New(zone(), code, outputs_size, outputs, inputs_size, | 318 return Instruction::New(zone(), code, outputs_size, outputs, inputs_size, |
305 inputs, temps_size, temps); | 319 inputs, temps_size, temps); |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
451 size_t target_block_offset = block_offset + static_cast<size_t>(jump_offset); | 465 size_t target_block_offset = block_offset + static_cast<size_t>(jump_offset); |
452 CHECK(block_offset < instruction_blocks_.size()); | 466 CHECK(block_offset < instruction_blocks_.size()); |
453 CHECK(target_block_offset < instruction_blocks_.size()); | 467 CHECK(target_block_offset < instruction_blocks_.size()); |
454 auto block = instruction_blocks_[block_offset]; | 468 auto block = instruction_blocks_[block_offset]; |
455 auto target = instruction_blocks_[target_block_offset]; | 469 auto target = instruction_blocks_[target_block_offset]; |
456 block->successors().push_back(target->rpo_number()); | 470 block->successors().push_back(target->rpo_number()); |
457 target->predecessors().push_back(block->rpo_number()); | 471 target->predecessors().push_back(block->rpo_number()); |
458 } | 472 } |
459 | 473 |
460 | 474 |
461 int InstructionSequenceTest::Emit(int instruction_index, InstructionCode code, | 475 Instruction* InstructionSequenceTest::Emit( |
462 size_t outputs_size, | 476 InstructionCode code, size_t outputs_size, InstructionOperand* outputs, |
463 InstructionOperand* outputs, | 477 size_t inputs_size, InstructionOperand* inputs, size_t temps_size, |
464 size_t inputs_size, | 478 InstructionOperand* temps, bool is_call) { |
465 InstructionOperand* inputs, size_t temps_size, | |
466 InstructionOperand* temps, bool is_call) { | |
467 auto instruction = NewInstruction(code, outputs_size, outputs, inputs_size, | 479 auto instruction = NewInstruction(code, outputs_size, outputs, inputs_size, |
468 inputs, temps_size, temps); | 480 inputs, temps_size, temps); |
469 if (is_call) instruction->MarkAsCall(); | 481 if (is_call) instruction->MarkAsCall(); |
470 return AddInstruction(instruction_index, instruction); | 482 return AddInstruction(instruction); |
471 } | 483 } |
472 | 484 |
473 | 485 |
474 int InstructionSequenceTest::AddInstruction(int instruction_index, | 486 Instruction* InstructionSequenceTest::AddInstruction(Instruction* instruction) { |
475 Instruction* instruction) { | |
476 sequence()->AddInstruction(instruction); | 487 sequence()->AddInstruction(instruction); |
477 return instruction_index; | 488 return instruction; |
478 } | 489 } |
479 | 490 |
480 } // namespace compiler | 491 } // namespace compiler |
481 } // namespace internal | 492 } // namespace internal |
482 } // namespace v8 | 493 } // namespace v8 |
OLD | NEW |