blob: 619e0aa4887aaad8e5df084b722452bc471c5079 [file] [log] [blame]
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001// 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
5#include "src/base/utils/random-number-generator.h"
6#include "src/compiler/pipeline.h"
7#include "test/unittests/compiler/instruction-sequence-unittest.h"
8#include "test/unittests/test-utils.h"
9#include "testing/gmock/include/gmock/gmock.h"
10
11namespace v8 {
12namespace internal {
13namespace compiler {
14
15static const char*
16 general_register_names_[RegisterConfiguration::kMaxGeneralRegisters];
17static const char*
Ben Murdochc5610432016-08-08 18:44:38 +010018 double_register_names_[RegisterConfiguration::kMaxFPRegisters];
Emily Bernierd0a1eb72015-03-24 16:35:39 -040019static char register_names_[10 * (RegisterConfiguration::kMaxGeneralRegisters +
Ben Murdochc5610432016-08-08 18:44:38 +010020 RegisterConfiguration::kMaxFPRegisters)];
Emily Bernierd0a1eb72015-03-24 16:35:39 -040021
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022namespace {
23static int allocatable_codes[InstructionSequenceTest::kDefaultNRegs] = {
24 0, 1, 2, 3, 4, 5, 6, 7};
25static int allocatable_double_codes[InstructionSequenceTest::kDefaultNRegs] = {
26 0, 1, 2, 3, 4, 5, 6, 7};
27}
28
29
Emily Bernierd0a1eb72015-03-24 16:35:39 -040030static void InitializeRegisterNames() {
31 char* loc = register_names_;
32 for (int i = 0; i < RegisterConfiguration::kMaxGeneralRegisters; ++i) {
33 general_register_names_[i] = loc;
34 loc += base::OS::SNPrintF(loc, 100, "gp_%d", i);
35 *loc++ = 0;
36 }
Ben Murdochc5610432016-08-08 18:44:38 +010037 for (int i = 0; i < RegisterConfiguration::kMaxFPRegisters; ++i) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040038 double_register_names_[i] = loc;
39 loc += base::OS::SNPrintF(loc, 100, "fp_%d", i) + 1;
40 *loc++ = 0;
41 }
42}
43
44
45InstructionSequenceTest::InstructionSequenceTest()
46 : sequence_(nullptr),
47 num_general_registers_(kDefaultNRegs),
48 num_double_registers_(kDefaultNRegs),
49 instruction_blocks_(zone()),
Emily Bernierd0a1eb72015-03-24 16:35:39 -040050 current_block_(nullptr),
51 block_returns_(false) {
52 InitializeRegisterNames();
53}
54
55
56void InstructionSequenceTest::SetNumRegs(int num_general_registers,
57 int num_double_registers) {
58 CHECK(config_.is_empty());
59 CHECK(instructions_.empty());
60 CHECK(instruction_blocks_.empty());
61 num_general_registers_ = num_general_registers;
62 num_double_registers_ = num_double_registers;
63}
64
65
66RegisterConfiguration* InstructionSequenceTest::config() {
67 if (config_.is_empty()) {
68 config_.Reset(new RegisterConfiguration(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000069 num_general_registers_, num_double_registers_, num_general_registers_,
Ben Murdoch61f157c2016-09-16 13:49:30 +010070 num_double_registers_, allocatable_codes, allocatable_double_codes,
71 kSimpleFPAliasing ? RegisterConfiguration::OVERLAP
72 : RegisterConfiguration::COMBINE,
73 general_register_names_,
74 double_register_names_, // float register names
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000075 double_register_names_));
Emily Bernierd0a1eb72015-03-24 16:35:39 -040076 }
77 return config_.get();
78}
79
80
81InstructionSequence* InstructionSequenceTest::sequence() {
82 if (sequence_ == nullptr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000083 sequence_ = new (zone())
84 InstructionSequence(isolate(), zone(), &instruction_blocks_);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040085 }
86 return sequence_;
87}
88
89
90void InstructionSequenceTest::StartLoop(int loop_blocks) {
91 CHECK(current_block_ == nullptr);
92 if (!loop_blocks_.empty()) {
93 CHECK(!loop_blocks_.back().loop_header_.IsValid());
94 }
95 LoopData loop_data = {Rpo::Invalid(), loop_blocks};
96 loop_blocks_.push_back(loop_data);
97}
98
99
100void InstructionSequenceTest::EndLoop() {
101 CHECK(current_block_ == nullptr);
102 CHECK(!loop_blocks_.empty());
103 CHECK_EQ(0, loop_blocks_.back().expected_blocks_);
104 loop_blocks_.pop_back();
105}
106
107
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000108void InstructionSequenceTest::StartBlock(bool deferred) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400109 block_returns_ = false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000110 NewBlock(deferred);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400111}
112
113
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000114Instruction* InstructionSequenceTest::EndBlock(BlockCompletion completion) {
115 Instruction* result = nullptr;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400116 if (block_returns_) {
117 CHECK(completion.type_ == kBlockEnd || completion.type_ == kFallThrough);
118 completion.type_ = kBlockEnd;
119 }
120 switch (completion.type_) {
121 case kBlockEnd:
122 break;
123 case kFallThrough:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000124 result = EmitJump();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400125 break;
126 case kJump:
127 CHECK(!block_returns_);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000128 result = EmitJump();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400129 break;
130 case kBranch:
131 CHECK(!block_returns_);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000132 result = EmitBranch(completion.op_);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400133 break;
134 }
135 completions_.push_back(completion);
136 CHECK(current_block_ != nullptr);
137 sequence()->EndBlock(current_block_->rpo_number());
138 current_block_ = nullptr;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000139 return result;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400140}
141
142
143InstructionSequenceTest::TestOperand InstructionSequenceTest::Imm(int32_t imm) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000144 return TestOperand(kImmediate, imm);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400145}
146
147
148InstructionSequenceTest::VReg InstructionSequenceTest::Define(
149 TestOperand output_op) {
150 VReg vreg = NewReg();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000151 InstructionOperand outputs[1]{ConvertOutputOp(vreg, output_op)};
152 Emit(kArchNop, 1, outputs);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400153 return vreg;
154}
155
156
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000157Instruction* InstructionSequenceTest::Return(TestOperand input_op_0) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400158 block_returns_ = true;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000159 InstructionOperand inputs[1]{ConvertInputOp(input_op_0)};
160 return Emit(kArchRet, 0, nullptr, 1, inputs);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400161}
162
163
164PhiInstruction* InstructionSequenceTest::Phi(VReg incoming_vreg_0,
165 VReg incoming_vreg_1,
166 VReg incoming_vreg_2,
167 VReg incoming_vreg_3) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400168 VReg inputs[] = {incoming_vreg_0, incoming_vreg_1, incoming_vreg_2,
169 incoming_vreg_3};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000170 size_t input_count = 0;
171 for (; input_count < arraysize(inputs); ++input_count) {
172 if (inputs[input_count].value_ == kNoValue) break;
173 }
174 CHECK(input_count > 0);
175 auto phi = new (zone()) PhiInstruction(zone(), NewReg().value_, input_count);
176 for (size_t i = 0; i < input_count; ++i) {
177 SetInput(phi, i, inputs[i]);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400178 }
179 current_block_->AddPhi(phi);
180 return phi;
181}
182
183
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000184PhiInstruction* InstructionSequenceTest::Phi(VReg incoming_vreg_0,
185 size_t input_count) {
186 auto phi = new (zone()) PhiInstruction(zone(), NewReg().value_, input_count);
187 SetInput(phi, 0, incoming_vreg_0);
188 current_block_->AddPhi(phi);
189 return phi;
190}
191
192
193void InstructionSequenceTest::SetInput(PhiInstruction* phi, size_t input,
194 VReg vreg) {
195 CHECK(vreg.value_ != kNoValue);
196 phi->SetInput(input, vreg.value_);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400197}
198
199
200InstructionSequenceTest::VReg InstructionSequenceTest::DefineConstant(
201 int32_t imm) {
202 VReg vreg = NewReg();
203 sequence()->AddConstant(vreg.value_, Constant(imm));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000204 InstructionOperand outputs[1]{ConstantOperand(vreg.value_)};
205 Emit(kArchNop, 1, outputs);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400206 return vreg;
207}
208
209
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000210Instruction* InstructionSequenceTest::EmitNop() { return Emit(kArchNop); }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400211
212
213static size_t CountInputs(size_t size,
214 InstructionSequenceTest::TestOperand* inputs) {
215 size_t i = 0;
216 for (; i < size; ++i) {
217 if (inputs[i].type_ == InstructionSequenceTest::kInvalid) break;
218 }
219 return i;
220}
221
222
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000223Instruction* InstructionSequenceTest::EmitI(size_t input_size,
224 TestOperand* inputs) {
225 InstructionOperand* mapped_inputs = ConvertInputs(input_size, inputs);
226 return Emit(kArchNop, 0, nullptr, input_size, mapped_inputs);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400227}
228
229
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000230Instruction* InstructionSequenceTest::EmitI(TestOperand input_op_0,
231 TestOperand input_op_1,
232 TestOperand input_op_2,
233 TestOperand input_op_3) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400234 TestOperand inputs[] = {input_op_0, input_op_1, input_op_2, input_op_3};
235 return EmitI(CountInputs(arraysize(inputs), inputs), inputs);
236}
237
238
239InstructionSequenceTest::VReg InstructionSequenceTest::EmitOI(
240 TestOperand output_op, size_t input_size, TestOperand* inputs) {
241 VReg output_vreg = NewReg();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000242 InstructionOperand outputs[1]{ConvertOutputOp(output_vreg, output_op)};
243 InstructionOperand* mapped_inputs = ConvertInputs(input_size, inputs);
244 Emit(kArchNop, 1, outputs, input_size, mapped_inputs);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400245 return output_vreg;
246}
247
248
249InstructionSequenceTest::VReg InstructionSequenceTest::EmitOI(
250 TestOperand output_op, TestOperand input_op_0, TestOperand input_op_1,
251 TestOperand input_op_2, TestOperand input_op_3) {
252 TestOperand inputs[] = {input_op_0, input_op_1, input_op_2, input_op_3};
253 return EmitOI(output_op, CountInputs(arraysize(inputs), inputs), inputs);
254}
255
256
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000257InstructionSequenceTest::VRegPair InstructionSequenceTest::EmitOOI(
258 TestOperand output_op_0, TestOperand output_op_1, size_t input_size,
259 TestOperand* inputs) {
260 VRegPair output_vregs = std::make_pair(NewReg(), NewReg());
261 InstructionOperand outputs[2]{
262 ConvertOutputOp(output_vregs.first, output_op_0),
263 ConvertOutputOp(output_vregs.second, output_op_1)};
264 InstructionOperand* mapped_inputs = ConvertInputs(input_size, inputs);
265 Emit(kArchNop, 2, outputs, input_size, mapped_inputs);
266 return output_vregs;
267}
268
269
270InstructionSequenceTest::VRegPair InstructionSequenceTest::EmitOOI(
271 TestOperand output_op_0, TestOperand output_op_1, TestOperand input_op_0,
272 TestOperand input_op_1, TestOperand input_op_2, TestOperand input_op_3) {
273 TestOperand inputs[] = {input_op_0, input_op_1, input_op_2, input_op_3};
274 return EmitOOI(output_op_0, output_op_1,
275 CountInputs(arraysize(inputs), inputs), inputs);
276}
277
278
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400279InstructionSequenceTest::VReg InstructionSequenceTest::EmitCall(
280 TestOperand output_op, size_t input_size, TestOperand* inputs) {
281 VReg output_vreg = NewReg();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000282 InstructionOperand outputs[1]{ConvertOutputOp(output_vreg, output_op)};
283 CHECK(UnallocatedOperand::cast(outputs[0]).HasFixedPolicy());
284 InstructionOperand* mapped_inputs = ConvertInputs(input_size, inputs);
285 Emit(kArchCallCodeObject, 1, outputs, input_size, mapped_inputs, 0, nullptr,
286 true);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400287 return output_vreg;
288}
289
290
291InstructionSequenceTest::VReg InstructionSequenceTest::EmitCall(
292 TestOperand output_op, TestOperand input_op_0, TestOperand input_op_1,
293 TestOperand input_op_2, TestOperand input_op_3) {
294 TestOperand inputs[] = {input_op_0, input_op_1, input_op_2, input_op_3};
295 return EmitCall(output_op, CountInputs(arraysize(inputs), inputs), inputs);
296}
297
298
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000299Instruction* InstructionSequenceTest::EmitBranch(TestOperand input_op) {
300 InstructionOperand inputs[4]{ConvertInputOp(input_op), ConvertInputOp(Imm()),
301 ConvertInputOp(Imm()), ConvertInputOp(Imm())};
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400302 InstructionCode opcode = kArchJmp | FlagsModeField::encode(kFlags_branch) |
303 FlagsConditionField::encode(kEqual);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000304 auto instruction = NewInstruction(opcode, 0, nullptr, 4, inputs);
305 return AddInstruction(instruction);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400306}
307
308
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000309Instruction* InstructionSequenceTest::EmitFallThrough() {
310 auto instruction = NewInstruction(kArchNop, 0, nullptr);
311 return AddInstruction(instruction);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400312}
313
314
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000315Instruction* InstructionSequenceTest::EmitJump() {
316 InstructionOperand inputs[1]{ConvertInputOp(Imm())};
317 auto instruction = NewInstruction(kArchJmp, 0, nullptr, 1, inputs);
318 return AddInstruction(instruction);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400319}
320
321
322Instruction* InstructionSequenceTest::NewInstruction(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000323 InstructionCode code, size_t outputs_size, InstructionOperand* outputs,
324 size_t inputs_size, InstructionOperand* inputs, size_t temps_size,
325 InstructionOperand* temps) {
326 CHECK(current_block_);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400327 return Instruction::New(zone(), code, outputs_size, outputs, inputs_size,
328 inputs, temps_size, temps);
329}
330
331
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000332InstructionOperand InstructionSequenceTest::Unallocated(
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400333 TestOperand op, UnallocatedOperand::ExtendedPolicy policy) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000334 return UnallocatedOperand(policy, op.vreg_.value_);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400335}
336
337
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000338InstructionOperand InstructionSequenceTest::Unallocated(
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400339 TestOperand op, UnallocatedOperand::ExtendedPolicy policy,
340 UnallocatedOperand::Lifetime lifetime) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000341 return UnallocatedOperand(policy, lifetime, op.vreg_.value_);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400342}
343
344
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000345InstructionOperand InstructionSequenceTest::Unallocated(
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400346 TestOperand op, UnallocatedOperand::ExtendedPolicy policy, int index) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000347 return UnallocatedOperand(policy, index, op.vreg_.value_);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400348}
349
350
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000351InstructionOperand InstructionSequenceTest::Unallocated(
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400352 TestOperand op, UnallocatedOperand::BasicPolicy policy, int index) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000353 return UnallocatedOperand(policy, index, op.vreg_.value_);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400354}
355
356
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000357InstructionOperand* InstructionSequenceTest::ConvertInputs(
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400358 size_t input_size, TestOperand* inputs) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000359 InstructionOperand* mapped_inputs =
360 zone()->NewArray<InstructionOperand>(static_cast<int>(input_size));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400361 for (size_t i = 0; i < input_size; ++i) {
362 mapped_inputs[i] = ConvertInputOp(inputs[i]);
363 }
364 return mapped_inputs;
365}
366
367
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000368InstructionOperand InstructionSequenceTest::ConvertInputOp(TestOperand op) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400369 if (op.type_ == kImmediate) {
370 CHECK_EQ(op.vreg_.value_, kNoValue);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000371 return ImmediateOperand(ImmediateOperand::INLINE, op.value_);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400372 }
373 CHECK_NE(op.vreg_.value_, kNoValue);
374 switch (op.type_) {
375 case kNone:
376 return Unallocated(op, UnallocatedOperand::NONE,
377 UnallocatedOperand::USED_AT_START);
378 case kUnique:
379 return Unallocated(op, UnallocatedOperand::NONE);
380 case kUniqueRegister:
381 return Unallocated(op, UnallocatedOperand::MUST_HAVE_REGISTER);
382 case kRegister:
383 return Unallocated(op, UnallocatedOperand::MUST_HAVE_REGISTER,
384 UnallocatedOperand::USED_AT_START);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000385 case kSlot:
386 return Unallocated(op, UnallocatedOperand::MUST_HAVE_SLOT,
387 UnallocatedOperand::USED_AT_START);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400388 case kFixedRegister:
389 CHECK(0 <= op.value_ && op.value_ < num_general_registers_);
390 return Unallocated(op, UnallocatedOperand::FIXED_REGISTER, op.value_);
391 case kFixedSlot:
392 return Unallocated(op, UnallocatedOperand::FIXED_SLOT, op.value_);
393 default:
394 break;
395 }
396 CHECK(false);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000397 return InstructionOperand();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400398}
399
400
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000401InstructionOperand InstructionSequenceTest::ConvertOutputOp(VReg vreg,
402 TestOperand op) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400403 CHECK_EQ(op.vreg_.value_, kNoValue);
404 op.vreg_ = vreg;
405 switch (op.type_) {
406 case kSameAsFirst:
407 return Unallocated(op, UnallocatedOperand::SAME_AS_FIRST_INPUT);
408 case kRegister:
409 return Unallocated(op, UnallocatedOperand::MUST_HAVE_REGISTER);
410 case kFixedSlot:
411 return Unallocated(op, UnallocatedOperand::FIXED_SLOT, op.value_);
412 case kFixedRegister:
413 CHECK(0 <= op.value_ && op.value_ < num_general_registers_);
414 return Unallocated(op, UnallocatedOperand::FIXED_REGISTER, op.value_);
415 default:
416 break;
417 }
418 CHECK(false);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000419 return InstructionOperand();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400420}
421
422
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000423InstructionBlock* InstructionSequenceTest::NewBlock(bool deferred) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400424 CHECK(current_block_ == nullptr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000425 Rpo rpo = Rpo::FromInt(static_cast<int>(instruction_blocks_.size()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400426 Rpo loop_header = Rpo::Invalid();
427 Rpo loop_end = Rpo::Invalid();
428 if (!loop_blocks_.empty()) {
429 auto& loop_data = loop_blocks_.back();
430 // This is a loop header.
431 if (!loop_data.loop_header_.IsValid()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000432 loop_end = Rpo::FromInt(rpo.ToInt() + loop_data.expected_blocks_);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400433 loop_data.expected_blocks_--;
434 loop_data.loop_header_ = rpo;
435 } else {
436 // This is a loop body.
437 CHECK_NE(0, loop_data.expected_blocks_);
438 // TODO(dcarney): handle nested loops.
439 loop_data.expected_blocks_--;
440 loop_header = loop_data.loop_header_;
441 }
442 }
443 // Construct instruction block.
444 auto instruction_block = new (zone())
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000445 InstructionBlock(zone(), rpo, loop_header, loop_end, deferred, false);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400446 instruction_blocks_.push_back(instruction_block);
447 current_block_ = instruction_block;
448 sequence()->StartBlock(rpo);
449 return instruction_block;
450}
451
452
453void InstructionSequenceTest::WireBlocks() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000454 CHECK(!current_block());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400455 CHECK(instruction_blocks_.size() == completions_.size());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000456 CHECK(loop_blocks_.empty());
457 // Wire in end block to look like a scheduler produced cfg.
458 auto end_block = NewBlock();
459 current_block_ = nullptr;
460 sequence()->EndBlock(end_block->rpo_number());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400461 size_t offset = 0;
462 for (const auto& completion : completions_) {
463 switch (completion.type_) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000464 case kBlockEnd: {
465 auto block = instruction_blocks_[offset];
466 block->successors().push_back(end_block->rpo_number());
467 end_block->predecessors().push_back(block->rpo_number());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400468 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000469 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400470 case kFallThrough: // Fallthrough.
471 case kJump:
472 WireBlock(offset, completion.offset_0_);
473 break;
474 case kBranch:
475 WireBlock(offset, completion.offset_0_);
476 WireBlock(offset, completion.offset_1_);
477 break;
478 }
479 ++offset;
480 }
481}
482
483
484void InstructionSequenceTest::WireBlock(size_t block_offset, int jump_offset) {
485 size_t target_block_offset = block_offset + static_cast<size_t>(jump_offset);
486 CHECK(block_offset < instruction_blocks_.size());
487 CHECK(target_block_offset < instruction_blocks_.size());
488 auto block = instruction_blocks_[block_offset];
489 auto target = instruction_blocks_[target_block_offset];
490 block->successors().push_back(target->rpo_number());
491 target->predecessors().push_back(block->rpo_number());
492}
493
494
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000495Instruction* InstructionSequenceTest::Emit(
496 InstructionCode code, size_t outputs_size, InstructionOperand* outputs,
497 size_t inputs_size, InstructionOperand* inputs, size_t temps_size,
498 InstructionOperand* temps, bool is_call) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400499 auto instruction = NewInstruction(code, outputs_size, outputs, inputs_size,
500 inputs, temps_size, temps);
501 if (is_call) instruction->MarkAsCall();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000502 return AddInstruction(instruction);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400503}
504
505
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000506Instruction* InstructionSequenceTest::AddInstruction(Instruction* instruction) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400507 sequence()->AddInstruction(instruction);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000508 return instruction;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400509}
510
511} // namespace compiler
512} // namespace internal
513} // namespace v8