blob: 51112a6470ee24e9d21ff18936a9d9554f782aa2 [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*
18 double_register_names_[RegisterConfiguration::kMaxDoubleRegisters];
19static char register_names_[10 * (RegisterConfiguration::kMaxGeneralRegisters +
20 RegisterConfiguration::kMaxDoubleRegisters)];
21
22
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023namespace {
24static int allocatable_codes[InstructionSequenceTest::kDefaultNRegs] = {
25 0, 1, 2, 3, 4, 5, 6, 7};
26static int allocatable_double_codes[InstructionSequenceTest::kDefaultNRegs] = {
27 0, 1, 2, 3, 4, 5, 6, 7};
28}
29
30
Emily Bernierd0a1eb72015-03-24 16:35:39 -040031static void InitializeRegisterNames() {
32 char* loc = register_names_;
33 for (int i = 0; i < RegisterConfiguration::kMaxGeneralRegisters; ++i) {
34 general_register_names_[i] = loc;
35 loc += base::OS::SNPrintF(loc, 100, "gp_%d", i);
36 *loc++ = 0;
37 }
38 for (int i = 0; i < RegisterConfiguration::kMaxDoubleRegisters; ++i) {
39 double_register_names_[i] = loc;
40 loc += base::OS::SNPrintF(loc, 100, "fp_%d", i) + 1;
41 *loc++ = 0;
42 }
43}
44
45
46InstructionSequenceTest::InstructionSequenceTest()
47 : sequence_(nullptr),
48 num_general_registers_(kDefaultNRegs),
49 num_double_registers_(kDefaultNRegs),
50 instruction_blocks_(zone()),
Emily Bernierd0a1eb72015-03-24 16:35:39 -040051 current_block_(nullptr),
52 block_returns_(false) {
53 InitializeRegisterNames();
54}
55
56
57void InstructionSequenceTest::SetNumRegs(int num_general_registers,
58 int num_double_registers) {
59 CHECK(config_.is_empty());
60 CHECK(instructions_.empty());
61 CHECK(instruction_blocks_.empty());
62 num_general_registers_ = num_general_registers;
63 num_double_registers_ = num_double_registers;
64}
65
66
67RegisterConfiguration* InstructionSequenceTest::config() {
68 if (config_.is_empty()) {
69 config_.Reset(new RegisterConfiguration(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000070 num_general_registers_, num_double_registers_, num_general_registers_,
71 num_double_registers_, num_double_registers_, allocatable_codes,
72 allocatable_double_codes, general_register_names_,
73 double_register_names_));
Emily Bernierd0a1eb72015-03-24 16:35:39 -040074 }
75 return config_.get();
76}
77
78
79InstructionSequence* InstructionSequenceTest::sequence() {
80 if (sequence_ == nullptr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000081 sequence_ = new (zone())
82 InstructionSequence(isolate(), zone(), &instruction_blocks_);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040083 }
84 return sequence_;
85}
86
87
88void InstructionSequenceTest::StartLoop(int loop_blocks) {
89 CHECK(current_block_ == nullptr);
90 if (!loop_blocks_.empty()) {
91 CHECK(!loop_blocks_.back().loop_header_.IsValid());
92 }
93 LoopData loop_data = {Rpo::Invalid(), loop_blocks};
94 loop_blocks_.push_back(loop_data);
95}
96
97
98void InstructionSequenceTest::EndLoop() {
99 CHECK(current_block_ == nullptr);
100 CHECK(!loop_blocks_.empty());
101 CHECK_EQ(0, loop_blocks_.back().expected_blocks_);
102 loop_blocks_.pop_back();
103}
104
105
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000106void InstructionSequenceTest::StartBlock(bool deferred) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400107 block_returns_ = false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000108 NewBlock(deferred);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400109}
110
111
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000112Instruction* InstructionSequenceTest::EndBlock(BlockCompletion completion) {
113 Instruction* result = nullptr;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400114 if (block_returns_) {
115 CHECK(completion.type_ == kBlockEnd || completion.type_ == kFallThrough);
116 completion.type_ = kBlockEnd;
117 }
118 switch (completion.type_) {
119 case kBlockEnd:
120 break;
121 case kFallThrough:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000122 result = EmitJump();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400123 break;
124 case kJump:
125 CHECK(!block_returns_);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000126 result = EmitJump();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400127 break;
128 case kBranch:
129 CHECK(!block_returns_);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000130 result = EmitBranch(completion.op_);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400131 break;
132 }
133 completions_.push_back(completion);
134 CHECK(current_block_ != nullptr);
135 sequence()->EndBlock(current_block_->rpo_number());
136 current_block_ = nullptr;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000137 return result;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400138}
139
140
141InstructionSequenceTest::TestOperand InstructionSequenceTest::Imm(int32_t imm) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000142 return TestOperand(kImmediate, imm);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400143}
144
145
146InstructionSequenceTest::VReg InstructionSequenceTest::Define(
147 TestOperand output_op) {
148 VReg vreg = NewReg();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000149 InstructionOperand outputs[1]{ConvertOutputOp(vreg, output_op)};
150 Emit(kArchNop, 1, outputs);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400151 return vreg;
152}
153
154
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000155Instruction* InstructionSequenceTest::Return(TestOperand input_op_0) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400156 block_returns_ = true;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000157 InstructionOperand inputs[1]{ConvertInputOp(input_op_0)};
158 return Emit(kArchRet, 0, nullptr, 1, inputs);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400159}
160
161
162PhiInstruction* InstructionSequenceTest::Phi(VReg incoming_vreg_0,
163 VReg incoming_vreg_1,
164 VReg incoming_vreg_2,
165 VReg incoming_vreg_3) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400166 VReg inputs[] = {incoming_vreg_0, incoming_vreg_1, incoming_vreg_2,
167 incoming_vreg_3};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000168 size_t input_count = 0;
169 for (; input_count < arraysize(inputs); ++input_count) {
170 if (inputs[input_count].value_ == kNoValue) break;
171 }
172 CHECK(input_count > 0);
173 auto phi = new (zone()) PhiInstruction(zone(), NewReg().value_, input_count);
174 for (size_t i = 0; i < input_count; ++i) {
175 SetInput(phi, i, inputs[i]);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400176 }
177 current_block_->AddPhi(phi);
178 return phi;
179}
180
181
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000182PhiInstruction* InstructionSequenceTest::Phi(VReg incoming_vreg_0,
183 size_t input_count) {
184 auto phi = new (zone()) PhiInstruction(zone(), NewReg().value_, input_count);
185 SetInput(phi, 0, incoming_vreg_0);
186 current_block_->AddPhi(phi);
187 return phi;
188}
189
190
191void InstructionSequenceTest::SetInput(PhiInstruction* phi, size_t input,
192 VReg vreg) {
193 CHECK(vreg.value_ != kNoValue);
194 phi->SetInput(input, vreg.value_);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400195}
196
197
198InstructionSequenceTest::VReg InstructionSequenceTest::DefineConstant(
199 int32_t imm) {
200 VReg vreg = NewReg();
201 sequence()->AddConstant(vreg.value_, Constant(imm));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000202 InstructionOperand outputs[1]{ConstantOperand(vreg.value_)};
203 Emit(kArchNop, 1, outputs);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400204 return vreg;
205}
206
207
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000208Instruction* InstructionSequenceTest::EmitNop() { return Emit(kArchNop); }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400209
210
211static size_t CountInputs(size_t size,
212 InstructionSequenceTest::TestOperand* inputs) {
213 size_t i = 0;
214 for (; i < size; ++i) {
215 if (inputs[i].type_ == InstructionSequenceTest::kInvalid) break;
216 }
217 return i;
218}
219
220
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000221Instruction* InstructionSequenceTest::EmitI(size_t input_size,
222 TestOperand* inputs) {
223 InstructionOperand* mapped_inputs = ConvertInputs(input_size, inputs);
224 return Emit(kArchNop, 0, nullptr, input_size, mapped_inputs);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400225}
226
227
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000228Instruction* InstructionSequenceTest::EmitI(TestOperand input_op_0,
229 TestOperand input_op_1,
230 TestOperand input_op_2,
231 TestOperand input_op_3) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400232 TestOperand inputs[] = {input_op_0, input_op_1, input_op_2, input_op_3};
233 return EmitI(CountInputs(arraysize(inputs), inputs), inputs);
234}
235
236
237InstructionSequenceTest::VReg InstructionSequenceTest::EmitOI(
238 TestOperand output_op, size_t input_size, TestOperand* inputs) {
239 VReg output_vreg = NewReg();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000240 InstructionOperand outputs[1]{ConvertOutputOp(output_vreg, output_op)};
241 InstructionOperand* mapped_inputs = ConvertInputs(input_size, inputs);
242 Emit(kArchNop, 1, outputs, input_size, mapped_inputs);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400243 return output_vreg;
244}
245
246
247InstructionSequenceTest::VReg InstructionSequenceTest::EmitOI(
248 TestOperand output_op, TestOperand input_op_0, TestOperand input_op_1,
249 TestOperand input_op_2, TestOperand input_op_3) {
250 TestOperand inputs[] = {input_op_0, input_op_1, input_op_2, input_op_3};
251 return EmitOI(output_op, CountInputs(arraysize(inputs), inputs), inputs);
252}
253
254
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000255InstructionSequenceTest::VRegPair InstructionSequenceTest::EmitOOI(
256 TestOperand output_op_0, TestOperand output_op_1, size_t input_size,
257 TestOperand* inputs) {
258 VRegPair output_vregs = std::make_pair(NewReg(), NewReg());
259 InstructionOperand outputs[2]{
260 ConvertOutputOp(output_vregs.first, output_op_0),
261 ConvertOutputOp(output_vregs.second, output_op_1)};
262 InstructionOperand* mapped_inputs = ConvertInputs(input_size, inputs);
263 Emit(kArchNop, 2, outputs, input_size, mapped_inputs);
264 return output_vregs;
265}
266
267
268InstructionSequenceTest::VRegPair InstructionSequenceTest::EmitOOI(
269 TestOperand output_op_0, TestOperand output_op_1, TestOperand input_op_0,
270 TestOperand input_op_1, TestOperand input_op_2, TestOperand input_op_3) {
271 TestOperand inputs[] = {input_op_0, input_op_1, input_op_2, input_op_3};
272 return EmitOOI(output_op_0, output_op_1,
273 CountInputs(arraysize(inputs), inputs), inputs);
274}
275
276
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400277InstructionSequenceTest::VReg InstructionSequenceTest::EmitCall(
278 TestOperand output_op, size_t input_size, TestOperand* inputs) {
279 VReg output_vreg = NewReg();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000280 InstructionOperand outputs[1]{ConvertOutputOp(output_vreg, output_op)};
281 CHECK(UnallocatedOperand::cast(outputs[0]).HasFixedPolicy());
282 InstructionOperand* mapped_inputs = ConvertInputs(input_size, inputs);
283 Emit(kArchCallCodeObject, 1, outputs, input_size, mapped_inputs, 0, nullptr,
284 true);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400285 return output_vreg;
286}
287
288
289InstructionSequenceTest::VReg InstructionSequenceTest::EmitCall(
290 TestOperand output_op, TestOperand input_op_0, TestOperand input_op_1,
291 TestOperand input_op_2, TestOperand input_op_3) {
292 TestOperand inputs[] = {input_op_0, input_op_1, input_op_2, input_op_3};
293 return EmitCall(output_op, CountInputs(arraysize(inputs), inputs), inputs);
294}
295
296
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000297Instruction* InstructionSequenceTest::EmitBranch(TestOperand input_op) {
298 InstructionOperand inputs[4]{ConvertInputOp(input_op), ConvertInputOp(Imm()),
299 ConvertInputOp(Imm()), ConvertInputOp(Imm())};
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400300 InstructionCode opcode = kArchJmp | FlagsModeField::encode(kFlags_branch) |
301 FlagsConditionField::encode(kEqual);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000302 auto instruction = NewInstruction(opcode, 0, nullptr, 4, inputs);
303 return AddInstruction(instruction);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400304}
305
306
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000307Instruction* InstructionSequenceTest::EmitFallThrough() {
308 auto instruction = NewInstruction(kArchNop, 0, nullptr);
309 return AddInstruction(instruction);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400310}
311
312
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000313Instruction* InstructionSequenceTest::EmitJump() {
314 InstructionOperand inputs[1]{ConvertInputOp(Imm())};
315 auto instruction = NewInstruction(kArchJmp, 0, nullptr, 1, inputs);
316 return AddInstruction(instruction);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400317}
318
319
320Instruction* InstructionSequenceTest::NewInstruction(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000321 InstructionCode code, size_t outputs_size, InstructionOperand* outputs,
322 size_t inputs_size, InstructionOperand* inputs, size_t temps_size,
323 InstructionOperand* temps) {
324 CHECK(current_block_);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400325 return Instruction::New(zone(), code, outputs_size, outputs, inputs_size,
326 inputs, temps_size, temps);
327}
328
329
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000330InstructionOperand InstructionSequenceTest::Unallocated(
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400331 TestOperand op, UnallocatedOperand::ExtendedPolicy policy) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000332 return UnallocatedOperand(policy, op.vreg_.value_);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400333}
334
335
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000336InstructionOperand InstructionSequenceTest::Unallocated(
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400337 TestOperand op, UnallocatedOperand::ExtendedPolicy policy,
338 UnallocatedOperand::Lifetime lifetime) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000339 return UnallocatedOperand(policy, lifetime, op.vreg_.value_);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400340}
341
342
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000343InstructionOperand InstructionSequenceTest::Unallocated(
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400344 TestOperand op, UnallocatedOperand::ExtendedPolicy policy, int index) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000345 return UnallocatedOperand(policy, index, op.vreg_.value_);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400346}
347
348
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000349InstructionOperand InstructionSequenceTest::Unallocated(
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400350 TestOperand op, UnallocatedOperand::BasicPolicy policy, int index) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000351 return UnallocatedOperand(policy, index, op.vreg_.value_);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400352}
353
354
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000355InstructionOperand* InstructionSequenceTest::ConvertInputs(
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400356 size_t input_size, TestOperand* inputs) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000357 InstructionOperand* mapped_inputs =
358 zone()->NewArray<InstructionOperand>(static_cast<int>(input_size));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400359 for (size_t i = 0; i < input_size; ++i) {
360 mapped_inputs[i] = ConvertInputOp(inputs[i]);
361 }
362 return mapped_inputs;
363}
364
365
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000366InstructionOperand InstructionSequenceTest::ConvertInputOp(TestOperand op) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400367 if (op.type_ == kImmediate) {
368 CHECK_EQ(op.vreg_.value_, kNoValue);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000369 return ImmediateOperand(ImmediateOperand::INLINE, op.value_);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400370 }
371 CHECK_NE(op.vreg_.value_, kNoValue);
372 switch (op.type_) {
373 case kNone:
374 return Unallocated(op, UnallocatedOperand::NONE,
375 UnallocatedOperand::USED_AT_START);
376 case kUnique:
377 return Unallocated(op, UnallocatedOperand::NONE);
378 case kUniqueRegister:
379 return Unallocated(op, UnallocatedOperand::MUST_HAVE_REGISTER);
380 case kRegister:
381 return Unallocated(op, UnallocatedOperand::MUST_HAVE_REGISTER,
382 UnallocatedOperand::USED_AT_START);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000383 case kSlot:
384 return Unallocated(op, UnallocatedOperand::MUST_HAVE_SLOT,
385 UnallocatedOperand::USED_AT_START);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400386 case kFixedRegister:
387 CHECK(0 <= op.value_ && op.value_ < num_general_registers_);
388 return Unallocated(op, UnallocatedOperand::FIXED_REGISTER, op.value_);
389 case kFixedSlot:
390 return Unallocated(op, UnallocatedOperand::FIXED_SLOT, op.value_);
391 default:
392 break;
393 }
394 CHECK(false);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000395 return InstructionOperand();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400396}
397
398
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000399InstructionOperand InstructionSequenceTest::ConvertOutputOp(VReg vreg,
400 TestOperand op) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400401 CHECK_EQ(op.vreg_.value_, kNoValue);
402 op.vreg_ = vreg;
403 switch (op.type_) {
404 case kSameAsFirst:
405 return Unallocated(op, UnallocatedOperand::SAME_AS_FIRST_INPUT);
406 case kRegister:
407 return Unallocated(op, UnallocatedOperand::MUST_HAVE_REGISTER);
408 case kFixedSlot:
409 return Unallocated(op, UnallocatedOperand::FIXED_SLOT, op.value_);
410 case kFixedRegister:
411 CHECK(0 <= op.value_ && op.value_ < num_general_registers_);
412 return Unallocated(op, UnallocatedOperand::FIXED_REGISTER, op.value_);
413 default:
414 break;
415 }
416 CHECK(false);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000417 return InstructionOperand();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400418}
419
420
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000421InstructionBlock* InstructionSequenceTest::NewBlock(bool deferred) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400422 CHECK(current_block_ == nullptr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000423 Rpo rpo = Rpo::FromInt(static_cast<int>(instruction_blocks_.size()));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400424 Rpo loop_header = Rpo::Invalid();
425 Rpo loop_end = Rpo::Invalid();
426 if (!loop_blocks_.empty()) {
427 auto& loop_data = loop_blocks_.back();
428 // This is a loop header.
429 if (!loop_data.loop_header_.IsValid()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000430 loop_end = Rpo::FromInt(rpo.ToInt() + loop_data.expected_blocks_);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400431 loop_data.expected_blocks_--;
432 loop_data.loop_header_ = rpo;
433 } else {
434 // This is a loop body.
435 CHECK_NE(0, loop_data.expected_blocks_);
436 // TODO(dcarney): handle nested loops.
437 loop_data.expected_blocks_--;
438 loop_header = loop_data.loop_header_;
439 }
440 }
441 // Construct instruction block.
442 auto instruction_block = new (zone())
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000443 InstructionBlock(zone(), rpo, loop_header, loop_end, deferred, false);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400444 instruction_blocks_.push_back(instruction_block);
445 current_block_ = instruction_block;
446 sequence()->StartBlock(rpo);
447 return instruction_block;
448}
449
450
451void InstructionSequenceTest::WireBlocks() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000452 CHECK(!current_block());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400453 CHECK(instruction_blocks_.size() == completions_.size());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000454 CHECK(loop_blocks_.empty());
455 // Wire in end block to look like a scheduler produced cfg.
456 auto end_block = NewBlock();
457 current_block_ = nullptr;
458 sequence()->EndBlock(end_block->rpo_number());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400459 size_t offset = 0;
460 for (const auto& completion : completions_) {
461 switch (completion.type_) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000462 case kBlockEnd: {
463 auto block = instruction_blocks_[offset];
464 block->successors().push_back(end_block->rpo_number());
465 end_block->predecessors().push_back(block->rpo_number());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400466 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000467 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400468 case kFallThrough: // Fallthrough.
469 case kJump:
470 WireBlock(offset, completion.offset_0_);
471 break;
472 case kBranch:
473 WireBlock(offset, completion.offset_0_);
474 WireBlock(offset, completion.offset_1_);
475 break;
476 }
477 ++offset;
478 }
479}
480
481
482void InstructionSequenceTest::WireBlock(size_t block_offset, int jump_offset) {
483 size_t target_block_offset = block_offset + static_cast<size_t>(jump_offset);
484 CHECK(block_offset < instruction_blocks_.size());
485 CHECK(target_block_offset < instruction_blocks_.size());
486 auto block = instruction_blocks_[block_offset];
487 auto target = instruction_blocks_[target_block_offset];
488 block->successors().push_back(target->rpo_number());
489 target->predecessors().push_back(block->rpo_number());
490}
491
492
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000493Instruction* InstructionSequenceTest::Emit(
494 InstructionCode code, size_t outputs_size, InstructionOperand* outputs,
495 size_t inputs_size, InstructionOperand* inputs, size_t temps_size,
496 InstructionOperand* temps, bool is_call) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400497 auto instruction = NewInstruction(code, outputs_size, outputs, inputs_size,
498 inputs, temps_size, temps);
499 if (is_call) instruction->MarkAsCall();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000500 return AddInstruction(instruction);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400501}
502
503
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000504Instruction* InstructionSequenceTest::AddInstruction(Instruction* instruction) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400505 sequence()->AddInstruction(instruction);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000506 return instruction;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400507}
508
509} // namespace compiler
510} // namespace internal
511} // namespace v8