blob: 9360ca4c148f7a338edfc6320c68b4055aae18bb [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_,
70 num_double_registers_, num_double_registers_, allocatable_codes,
71 allocatable_double_codes, general_register_names_,
72 double_register_names_));
Emily Bernierd0a1eb72015-03-24 16:35:39 -040073 }
74 return config_.get();
75}
76
77
78InstructionSequence* InstructionSequenceTest::sequence() {
79 if (sequence_ == nullptr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000080 sequence_ = new (zone())
81 InstructionSequence(isolate(), zone(), &instruction_blocks_);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040082 }
83 return sequence_;
84}
85
86
87void InstructionSequenceTest::StartLoop(int loop_blocks) {
88 CHECK(current_block_ == nullptr);
89 if (!loop_blocks_.empty()) {
90 CHECK(!loop_blocks_.back().loop_header_.IsValid());
91 }
92 LoopData loop_data = {Rpo::Invalid(), loop_blocks};
93 loop_blocks_.push_back(loop_data);
94}
95
96
97void InstructionSequenceTest::EndLoop() {
98 CHECK(current_block_ == nullptr);
99 CHECK(!loop_blocks_.empty());
100 CHECK_EQ(0, loop_blocks_.back().expected_blocks_);
101 loop_blocks_.pop_back();
102}
103
104
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000105void InstructionSequenceTest::StartBlock(bool deferred) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400106 block_returns_ = false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000107 NewBlock(deferred);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400108}
109
110
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000111Instruction* InstructionSequenceTest::EndBlock(BlockCompletion completion) {
112 Instruction* result = nullptr;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400113 if (block_returns_) {
114 CHECK(completion.type_ == kBlockEnd || completion.type_ == kFallThrough);
115 completion.type_ = kBlockEnd;
116 }
117 switch (completion.type_) {
118 case kBlockEnd:
119 break;
120 case kFallThrough:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000121 result = EmitJump();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400122 break;
123 case kJump:
124 CHECK(!block_returns_);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000125 result = EmitJump();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400126 break;
127 case kBranch:
128 CHECK(!block_returns_);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000129 result = EmitBranch(completion.op_);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400130 break;
131 }
132 completions_.push_back(completion);
133 CHECK(current_block_ != nullptr);
134 sequence()->EndBlock(current_block_->rpo_number());
135 current_block_ = nullptr;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000136 return result;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400137}
138
139
140InstructionSequenceTest::TestOperand InstructionSequenceTest::Imm(int32_t imm) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000141 return TestOperand(kImmediate, imm);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400142}
143
144
145InstructionSequenceTest::VReg InstructionSequenceTest::Define(
146 TestOperand output_op) {
147 VReg vreg = NewReg();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000148 InstructionOperand outputs[1]{ConvertOutputOp(vreg, output_op)};
149 Emit(kArchNop, 1, outputs);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400150 return vreg;
151}
152
153
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000154Instruction* InstructionSequenceTest::Return(TestOperand input_op_0) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400155 block_returns_ = true;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000156 InstructionOperand inputs[1]{ConvertInputOp(input_op_0)};
157 return Emit(kArchRet, 0, nullptr, 1, inputs);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400158}
159
160
161PhiInstruction* InstructionSequenceTest::Phi(VReg incoming_vreg_0,
162 VReg incoming_vreg_1,
163 VReg incoming_vreg_2,
164 VReg incoming_vreg_3) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400165 VReg inputs[] = {incoming_vreg_0, incoming_vreg_1, incoming_vreg_2,
166 incoming_vreg_3};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000167 size_t input_count = 0;
168 for (; input_count < arraysize(inputs); ++input_count) {
169 if (inputs[input_count].value_ == kNoValue) break;
170 }
171 CHECK(input_count > 0);
172 auto phi = new (zone()) PhiInstruction(zone(), NewReg().value_, input_count);
173 for (size_t i = 0; i < input_count; ++i) {
174 SetInput(phi, i, inputs[i]);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400175 }
176 current_block_->AddPhi(phi);
177 return phi;
178}
179
180
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000181PhiInstruction* InstructionSequenceTest::Phi(VReg incoming_vreg_0,
182 size_t input_count) {
183 auto phi = new (zone()) PhiInstruction(zone(), NewReg().value_, input_count);
184 SetInput(phi, 0, incoming_vreg_0);
185 current_block_->AddPhi(phi);
186 return phi;
187}
188
189
190void InstructionSequenceTest::SetInput(PhiInstruction* phi, size_t input,
191 VReg vreg) {
192 CHECK(vreg.value_ != kNoValue);
193 phi->SetInput(input, vreg.value_);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400194}
195
196
197InstructionSequenceTest::VReg InstructionSequenceTest::DefineConstant(
198 int32_t imm) {
199 VReg vreg = NewReg();
200 sequence()->AddConstant(vreg.value_, Constant(imm));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000201 InstructionOperand outputs[1]{ConstantOperand(vreg.value_)};
202 Emit(kArchNop, 1, outputs);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400203 return vreg;
204}
205
206
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000207Instruction* InstructionSequenceTest::EmitNop() { return Emit(kArchNop); }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400208
209
210static size_t CountInputs(size_t size,
211 InstructionSequenceTest::TestOperand* inputs) {
212 size_t i = 0;
213 for (; i < size; ++i) {
214 if (inputs[i].type_ == InstructionSequenceTest::kInvalid) break;
215 }
216 return i;
217}
218
219
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000220Instruction* InstructionSequenceTest::EmitI(size_t input_size,
221 TestOperand* inputs) {
222 InstructionOperand* mapped_inputs = ConvertInputs(input_size, inputs);
223 return Emit(kArchNop, 0, nullptr, input_size, mapped_inputs);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400224}
225
226
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000227Instruction* InstructionSequenceTest::EmitI(TestOperand input_op_0,
228 TestOperand input_op_1,
229 TestOperand input_op_2,
230 TestOperand input_op_3) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400231 TestOperand inputs[] = {input_op_0, input_op_1, input_op_2, input_op_3};
232 return EmitI(CountInputs(arraysize(inputs), inputs), inputs);
233}
234
235
236InstructionSequenceTest::VReg InstructionSequenceTest::EmitOI(
237 TestOperand output_op, size_t input_size, TestOperand* inputs) {
238 VReg output_vreg = NewReg();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000239 InstructionOperand outputs[1]{ConvertOutputOp(output_vreg, output_op)};
240 InstructionOperand* mapped_inputs = ConvertInputs(input_size, inputs);
241 Emit(kArchNop, 1, outputs, input_size, mapped_inputs);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400242 return output_vreg;
243}
244
245
246InstructionSequenceTest::VReg InstructionSequenceTest::EmitOI(
247 TestOperand output_op, TestOperand input_op_0, TestOperand input_op_1,
248 TestOperand input_op_2, TestOperand input_op_3) {
249 TestOperand inputs[] = {input_op_0, input_op_1, input_op_2, input_op_3};
250 return EmitOI(output_op, CountInputs(arraysize(inputs), inputs), inputs);
251}
252
253
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000254InstructionSequenceTest::VRegPair InstructionSequenceTest::EmitOOI(
255 TestOperand output_op_0, TestOperand output_op_1, size_t input_size,
256 TestOperand* inputs) {
257 VRegPair output_vregs = std::make_pair(NewReg(), NewReg());
258 InstructionOperand outputs[2]{
259 ConvertOutputOp(output_vregs.first, output_op_0),
260 ConvertOutputOp(output_vregs.second, output_op_1)};
261 InstructionOperand* mapped_inputs = ConvertInputs(input_size, inputs);
262 Emit(kArchNop, 2, outputs, input_size, mapped_inputs);
263 return output_vregs;
264}
265
266
267InstructionSequenceTest::VRegPair InstructionSequenceTest::EmitOOI(
268 TestOperand output_op_0, TestOperand output_op_1, TestOperand input_op_0,
269 TestOperand input_op_1, TestOperand input_op_2, TestOperand input_op_3) {
270 TestOperand inputs[] = {input_op_0, input_op_1, input_op_2, input_op_3};
271 return EmitOOI(output_op_0, output_op_1,
272 CountInputs(arraysize(inputs), inputs), inputs);
273}
274
275
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400276InstructionSequenceTest::VReg InstructionSequenceTest::EmitCall(
277 TestOperand output_op, size_t input_size, TestOperand* inputs) {
278 VReg output_vreg = NewReg();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000279 InstructionOperand outputs[1]{ConvertOutputOp(output_vreg, output_op)};
280 CHECK(UnallocatedOperand::cast(outputs[0]).HasFixedPolicy());
281 InstructionOperand* mapped_inputs = ConvertInputs(input_size, inputs);
282 Emit(kArchCallCodeObject, 1, outputs, input_size, mapped_inputs, 0, nullptr,
283 true);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400284 return output_vreg;
285}
286
287
288InstructionSequenceTest::VReg InstructionSequenceTest::EmitCall(
289 TestOperand output_op, TestOperand input_op_0, TestOperand input_op_1,
290 TestOperand input_op_2, TestOperand input_op_3) {
291 TestOperand inputs[] = {input_op_0, input_op_1, input_op_2, input_op_3};
292 return EmitCall(output_op, CountInputs(arraysize(inputs), inputs), inputs);
293}
294
295
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000296Instruction* InstructionSequenceTest::EmitBranch(TestOperand input_op) {
297 InstructionOperand inputs[4]{ConvertInputOp(input_op), ConvertInputOp(Imm()),
298 ConvertInputOp(Imm()), ConvertInputOp(Imm())};
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400299 InstructionCode opcode = kArchJmp | FlagsModeField::encode(kFlags_branch) |
300 FlagsConditionField::encode(kEqual);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000301 auto instruction = NewInstruction(opcode, 0, nullptr, 4, inputs);
302 return AddInstruction(instruction);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400303}
304
305
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000306Instruction* InstructionSequenceTest::EmitFallThrough() {
307 auto instruction = NewInstruction(kArchNop, 0, nullptr);
308 return AddInstruction(instruction);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400309}
310
311
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000312Instruction* InstructionSequenceTest::EmitJump() {
313 InstructionOperand inputs[1]{ConvertInputOp(Imm())};
314 auto instruction = NewInstruction(kArchJmp, 0, nullptr, 1, inputs);
315 return AddInstruction(instruction);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400316}
317
318
319Instruction* InstructionSequenceTest::NewInstruction(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000320 InstructionCode code, size_t outputs_size, InstructionOperand* outputs,
321 size_t inputs_size, InstructionOperand* inputs, size_t temps_size,
322 InstructionOperand* temps) {
323 CHECK(current_block_);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400324 return Instruction::New(zone(), code, outputs_size, outputs, inputs_size,
325 inputs, temps_size, temps);
326}
327
328
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000329InstructionOperand InstructionSequenceTest::Unallocated(
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400330 TestOperand op, UnallocatedOperand::ExtendedPolicy policy) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000331 return UnallocatedOperand(policy, op.vreg_.value_);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400332}
333
334
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000335InstructionOperand InstructionSequenceTest::Unallocated(
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400336 TestOperand op, UnallocatedOperand::ExtendedPolicy policy,
337 UnallocatedOperand::Lifetime lifetime) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000338 return UnallocatedOperand(policy, lifetime, op.vreg_.value_);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400339}
340
341
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000342InstructionOperand InstructionSequenceTest::Unallocated(
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400343 TestOperand op, UnallocatedOperand::ExtendedPolicy policy, int index) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000344 return UnallocatedOperand(policy, index, op.vreg_.value_);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400345}
346
347
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000348InstructionOperand InstructionSequenceTest::Unallocated(
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400349 TestOperand op, UnallocatedOperand::BasicPolicy policy, int index) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000350 return UnallocatedOperand(policy, index, op.vreg_.value_);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400351}
352
353
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000354InstructionOperand* InstructionSequenceTest::ConvertInputs(
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400355 size_t input_size, TestOperand* inputs) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000356 InstructionOperand* mapped_inputs =
357 zone()->NewArray<InstructionOperand>(static_cast<int>(input_size));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400358 for (size_t i = 0; i < input_size; ++i) {
359 mapped_inputs[i] = ConvertInputOp(inputs[i]);
360 }
361 return mapped_inputs;
362}
363
364
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000365InstructionOperand InstructionSequenceTest::ConvertInputOp(TestOperand op) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400366 if (op.type_ == kImmediate) {
367 CHECK_EQ(op.vreg_.value_, kNoValue);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000368 return ImmediateOperand(ImmediateOperand::INLINE, op.value_);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400369 }
370 CHECK_NE(op.vreg_.value_, kNoValue);
371 switch (op.type_) {
372 case kNone:
373 return Unallocated(op, UnallocatedOperand::NONE,
374 UnallocatedOperand::USED_AT_START);
375 case kUnique:
376 return Unallocated(op, UnallocatedOperand::NONE);
377 case kUniqueRegister:
378 return Unallocated(op, UnallocatedOperand::MUST_HAVE_REGISTER);
379 case kRegister:
380 return Unallocated(op, UnallocatedOperand::MUST_HAVE_REGISTER,
381 UnallocatedOperand::USED_AT_START);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000382 case kSlot:
383 return Unallocated(op, UnallocatedOperand::MUST_HAVE_SLOT,
384 UnallocatedOperand::USED_AT_START);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400385 case kFixedRegister:
386 CHECK(0 <= op.value_ && op.value_ < num_general_registers_);
387 return Unallocated(op, UnallocatedOperand::FIXED_REGISTER, op.value_);
388 case kFixedSlot:
389 return Unallocated(op, UnallocatedOperand::FIXED_SLOT, op.value_);
390 default:
391 break;
392 }
393 CHECK(false);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000394 return InstructionOperand();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400395}
396
397
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000398InstructionOperand InstructionSequenceTest::ConvertOutputOp(VReg vreg,
399 TestOperand op) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400400 CHECK_EQ(op.vreg_.value_, kNoValue);
401 op.vreg_ = vreg;
402 switch (op.type_) {
403 case kSameAsFirst:
404 return Unallocated(op, UnallocatedOperand::SAME_AS_FIRST_INPUT);
405 case kRegister:
406 return Unallocated(op, UnallocatedOperand::MUST_HAVE_REGISTER);
407 case kFixedSlot:
408 return Unallocated(op, UnallocatedOperand::FIXED_SLOT, op.value_);
409 case kFixedRegister:
410 CHECK(0 <= op.value_ && op.value_ < num_general_registers_);
411 return Unallocated(op, UnallocatedOperand::FIXED_REGISTER, op.value_);
412 default:
413 break;
414 }
415 CHECK(false);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000416 return InstructionOperand();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400417}
418
419
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000420InstructionBlock* InstructionSequenceTest::NewBlock(bool deferred) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400421 CHECK(current_block_ == nullptr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000422 Rpo rpo = Rpo::FromInt(static_cast<int>(instruction_blocks_.size()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400423 Rpo loop_header = Rpo::Invalid();
424 Rpo loop_end = Rpo::Invalid();
425 if (!loop_blocks_.empty()) {
426 auto& loop_data = loop_blocks_.back();
427 // This is a loop header.
428 if (!loop_data.loop_header_.IsValid()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000429 loop_end = Rpo::FromInt(rpo.ToInt() + loop_data.expected_blocks_);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400430 loop_data.expected_blocks_--;
431 loop_data.loop_header_ = rpo;
432 } else {
433 // This is a loop body.
434 CHECK_NE(0, loop_data.expected_blocks_);
435 // TODO(dcarney): handle nested loops.
436 loop_data.expected_blocks_--;
437 loop_header = loop_data.loop_header_;
438 }
439 }
440 // Construct instruction block.
441 auto instruction_block = new (zone())
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000442 InstructionBlock(zone(), rpo, loop_header, loop_end, deferred, false);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400443 instruction_blocks_.push_back(instruction_block);
444 current_block_ = instruction_block;
445 sequence()->StartBlock(rpo);
446 return instruction_block;
447}
448
449
450void InstructionSequenceTest::WireBlocks() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000451 CHECK(!current_block());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400452 CHECK(instruction_blocks_.size() == completions_.size());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000453 CHECK(loop_blocks_.empty());
454 // Wire in end block to look like a scheduler produced cfg.
455 auto end_block = NewBlock();
456 current_block_ = nullptr;
457 sequence()->EndBlock(end_block->rpo_number());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400458 size_t offset = 0;
459 for (const auto& completion : completions_) {
460 switch (completion.type_) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000461 case kBlockEnd: {
462 auto block = instruction_blocks_[offset];
463 block->successors().push_back(end_block->rpo_number());
464 end_block->predecessors().push_back(block->rpo_number());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400465 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000466 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400467 case kFallThrough: // Fallthrough.
468 case kJump:
469 WireBlock(offset, completion.offset_0_);
470 break;
471 case kBranch:
472 WireBlock(offset, completion.offset_0_);
473 WireBlock(offset, completion.offset_1_);
474 break;
475 }
476 ++offset;
477 }
478}
479
480
481void InstructionSequenceTest::WireBlock(size_t block_offset, int jump_offset) {
482 size_t target_block_offset = block_offset + static_cast<size_t>(jump_offset);
483 CHECK(block_offset < instruction_blocks_.size());
484 CHECK(target_block_offset < instruction_blocks_.size());
485 auto block = instruction_blocks_[block_offset];
486 auto target = instruction_blocks_[target_block_offset];
487 block->successors().push_back(target->rpo_number());
488 target->predecessors().push_back(block->rpo_number());
489}
490
491
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000492Instruction* InstructionSequenceTest::Emit(
493 InstructionCode code, size_t outputs_size, InstructionOperand* outputs,
494 size_t inputs_size, InstructionOperand* inputs, size_t temps_size,
495 InstructionOperand* temps, bool is_call) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400496 auto instruction = NewInstruction(code, outputs_size, outputs, inputs_size,
497 inputs, temps_size, temps);
498 if (is_call) instruction->MarkAsCall();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000499 return AddInstruction(instruction);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400500}
501
502
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000503Instruction* InstructionSequenceTest::AddInstruction(Instruction* instruction) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400504 sequence()->AddInstruction(instruction);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000505 return instruction;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400506}
507
508} // namespace compiler
509} // namespace internal
510} // namespace v8