blob: 383e27dac62da0e7ecfb4db8fb0d2b27c4838df1 [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
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005#include "src/compiler/common-operator.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -04006#include "src/compiler/graph.h"
7#include "src/compiler/instruction.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008#include "src/compiler/schedule.h"
9#include "src/compiler/state-values-utils.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010
11namespace v8 {
12namespace internal {
13namespace compiler {
14
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015
16FlagsCondition CommuteFlagsCondition(FlagsCondition condition) {
17 switch (condition) {
18 case kSignedLessThan:
19 return kSignedGreaterThan;
20 case kSignedGreaterThanOrEqual:
21 return kSignedLessThanOrEqual;
22 case kSignedLessThanOrEqual:
23 return kSignedGreaterThanOrEqual;
24 case kSignedGreaterThan:
25 return kSignedLessThan;
26 case kUnsignedLessThan:
27 return kUnsignedGreaterThan;
28 case kUnsignedGreaterThanOrEqual:
29 return kUnsignedLessThanOrEqual;
30 case kUnsignedLessThanOrEqual:
31 return kUnsignedGreaterThanOrEqual;
32 case kUnsignedGreaterThan:
33 return kUnsignedLessThan;
34 case kFloatLessThanOrUnordered:
35 return kFloatGreaterThanOrUnordered;
36 case kFloatGreaterThanOrEqual:
37 return kFloatLessThanOrEqual;
38 case kFloatLessThanOrEqual:
39 return kFloatGreaterThanOrEqual;
40 case kFloatGreaterThanOrUnordered:
41 return kFloatLessThanOrUnordered;
42 case kFloatLessThan:
43 return kFloatGreaterThan;
44 case kFloatGreaterThanOrEqualOrUnordered:
45 return kFloatLessThanOrEqualOrUnordered;
46 case kFloatLessThanOrEqualOrUnordered:
47 return kFloatGreaterThanOrEqualOrUnordered;
48 case kFloatGreaterThan:
49 return kFloatLessThan;
50 case kEqual:
51 case kNotEqual:
52 case kOverflow:
53 case kNotOverflow:
54 case kUnorderedEqual:
55 case kUnorderedNotEqual:
56 return condition;
57 }
58 UNREACHABLE();
59 return condition;
60}
61
62
63void InstructionOperand::Print(const RegisterConfiguration* config) const {
64 OFStream os(stdout);
65 PrintableInstructionOperand wrapper;
66 wrapper.register_configuration_ = config;
67 wrapper.op_ = *this;
68 os << wrapper << std::endl;
69}
70
71
72void InstructionOperand::Print() const {
73 const RegisterConfiguration* config =
74 RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN);
75 Print(config);
76}
77
78
Emily Bernierd0a1eb72015-03-24 16:35:39 -040079std::ostream& operator<<(std::ostream& os,
80 const PrintableInstructionOperand& printable) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000081 const InstructionOperand& op = printable.op_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040082 const RegisterConfiguration* conf = printable.register_configuration_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000083 switch (op.kind()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000084 case InstructionOperand::UNALLOCATED: {
85 const UnallocatedOperand* unalloc = UnallocatedOperand::cast(&op);
86 os << "v" << unalloc->virtual_register();
87 if (unalloc->basic_policy() == UnallocatedOperand::FIXED_SLOT) {
88 return os << "(=" << unalloc->fixed_slot_index() << "S)";
89 }
90 switch (unalloc->extended_policy()) {
91 case UnallocatedOperand::NONE:
92 return os;
93 case UnallocatedOperand::FIXED_REGISTER:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000094 return os << "(="
95 << conf->GetGeneralRegisterName(
96 unalloc->fixed_register_index())
97 << ")";
Ben Murdochb8a8cc12014-11-26 15:28:44 +000098 case UnallocatedOperand::FIXED_DOUBLE_REGISTER:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000099 return os << "(="
100 << conf->GetDoubleRegisterName(
101 unalloc->fixed_register_index())
102 << ")";
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000103 case UnallocatedOperand::MUST_HAVE_REGISTER:
104 return os << "(R)";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000105 case UnallocatedOperand::MUST_HAVE_SLOT:
106 return os << "(S)";
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000107 case UnallocatedOperand::SAME_AS_FIRST_INPUT:
108 return os << "(1)";
109 case UnallocatedOperand::ANY:
110 return os << "(-)";
111 }
112 }
113 case InstructionOperand::CONSTANT:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000114 return os << "[constant:" << ConstantOperand::cast(op).virtual_register()
115 << "]";
116 case InstructionOperand::IMMEDIATE: {
117 auto imm = ImmediateOperand::cast(op);
118 switch (imm.type()) {
119 case ImmediateOperand::INLINE:
120 return os << "#" << imm.inline_value();
121 case ImmediateOperand::INDEXED:
122 return os << "[immediate:" << imm.indexed_value() << "]";
123 }
124 }
125 case InstructionOperand::EXPLICIT:
126 case InstructionOperand::ALLOCATED: {
127 auto allocated = LocationOperand::cast(op);
128 if (op.IsStackSlot()) {
129 os << "[stack:" << LocationOperand::cast(op).index();
130 } else if (op.IsDoubleStackSlot()) {
131 os << "[double_stack:" << LocationOperand::cast(op).index();
132 } else if (op.IsRegister()) {
133 os << "[" << LocationOperand::cast(op).GetRegister().ToString() << "|R";
134 } else {
135 DCHECK(op.IsDoubleRegister());
136 os << "[" << LocationOperand::cast(op).GetDoubleRegister().ToString()
137 << "|R";
138 }
139 if (allocated.IsExplicit()) {
140 os << "|E";
141 }
142 switch (allocated.representation()) {
143 case MachineRepresentation::kNone:
144 os << "|-";
145 break;
146 case MachineRepresentation::kBit:
147 os << "|b";
148 break;
149 case MachineRepresentation::kWord8:
150 os << "|w8";
151 break;
152 case MachineRepresentation::kWord16:
153 os << "|w16";
154 break;
155 case MachineRepresentation::kWord32:
156 os << "|w32";
157 break;
158 case MachineRepresentation::kWord64:
159 os << "|w64";
160 break;
161 case MachineRepresentation::kFloat32:
162 os << "|f32";
163 break;
164 case MachineRepresentation::kFloat64:
165 os << "|f64";
166 break;
167 case MachineRepresentation::kTagged:
168 os << "|t";
169 break;
170 }
171 return os << "]";
172 }
173 case InstructionOperand::INVALID:
174 return os << "(x)";
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000175 }
176 UNREACHABLE();
177 return os;
178}
179
180
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000181void MoveOperands::Print(const RegisterConfiguration* config) const {
182 OFStream os(stdout);
183 PrintableInstructionOperand wrapper;
184 wrapper.register_configuration_ = config;
185 wrapper.op_ = destination();
186 os << wrapper << " = ";
187 wrapper.op_ = source();
188 os << wrapper << std::endl;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000189}
190
191
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000192void MoveOperands::Print() const {
193 const RegisterConfiguration* config =
194 RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN);
195 Print(config);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000196}
197
198
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400199std::ostream& operator<<(std::ostream& os,
200 const PrintableMoveOperands& printable) {
201 const MoveOperands& mo = *printable.move_operands_;
202 PrintableInstructionOperand printable_op = {printable.register_configuration_,
203 mo.destination()};
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400204 os << printable_op;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000205 if (!mo.source().Equals(mo.destination())) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400206 printable_op.op_ = mo.source();
207 os << " = " << printable_op;
208 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000209 return os << ";";
210}
211
212
213bool ParallelMove::IsRedundant() const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000214 for (auto move : *this) {
215 if (!move->IsRedundant()) return false;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000216 }
217 return true;
218}
219
220
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000221MoveOperands* ParallelMove::PrepareInsertAfter(MoveOperands* move) const {
222 MoveOperands* replacement = nullptr;
223 MoveOperands* to_eliminate = nullptr;
224 for (auto curr : *this) {
225 if (curr->IsEliminated()) continue;
226 if (curr->destination().EqualsCanonicalized(move->source())) {
227 DCHECK(!replacement);
228 replacement = curr;
229 if (to_eliminate != nullptr) break;
230 } else if (curr->destination().EqualsCanonicalized(move->destination())) {
231 DCHECK(!to_eliminate);
232 to_eliminate = curr;
233 if (replacement != nullptr) break;
234 }
235 }
236 DCHECK_IMPLIES(replacement == to_eliminate, replacement == nullptr);
237 if (replacement != nullptr) move->set_source(replacement->source());
238 return to_eliminate;
239}
240
241
242ExplicitOperand::ExplicitOperand(LocationKind kind, MachineRepresentation rep,
243 int index)
244 : LocationOperand(EXPLICIT, kind, rep, index) {
245 DCHECK_IMPLIES(kind == REGISTER && !IsFloatingPoint(rep),
246 Register::from_code(index).IsAllocatable());
247 DCHECK_IMPLIES(kind == REGISTER && IsFloatingPoint(rep),
248 DoubleRegister::from_code(index).IsAllocatable());
249}
250
251
252Instruction::Instruction(InstructionCode opcode)
253 : opcode_(opcode),
254 bit_field_(OutputCountField::encode(0) | InputCountField::encode(0) |
255 TempCountField::encode(0) | IsCallField::encode(false)),
256 reference_map_(nullptr) {
257 parallel_moves_[0] = nullptr;
258 parallel_moves_[1] = nullptr;
259}
260
261
262Instruction::Instruction(InstructionCode opcode, size_t output_count,
263 InstructionOperand* outputs, size_t input_count,
264 InstructionOperand* inputs, size_t temp_count,
265 InstructionOperand* temps)
266 : opcode_(opcode),
267 bit_field_(OutputCountField::encode(output_count) |
268 InputCountField::encode(input_count) |
269 TempCountField::encode(temp_count) |
270 IsCallField::encode(false)),
271 reference_map_(nullptr) {
272 parallel_moves_[0] = nullptr;
273 parallel_moves_[1] = nullptr;
274 size_t offset = 0;
275 for (size_t i = 0; i < output_count; ++i) {
276 DCHECK(!outputs[i].IsInvalid());
277 operands_[offset++] = outputs[i];
278 }
279 for (size_t i = 0; i < input_count; ++i) {
280 DCHECK(!inputs[i].IsInvalid());
281 operands_[offset++] = inputs[i];
282 }
283 for (size_t i = 0; i < temp_count; ++i) {
284 DCHECK(!temps[i].IsInvalid());
285 operands_[offset++] = temps[i];
286 }
287}
288
289
290bool Instruction::AreMovesRedundant() const {
291 for (int i = Instruction::FIRST_GAP_POSITION;
292 i <= Instruction::LAST_GAP_POSITION; i++) {
293 if (parallel_moves_[i] != nullptr && !parallel_moves_[i]->IsRedundant()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400294 return false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000295 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400296 }
297 return true;
298}
299
300
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000301void Instruction::Print(const RegisterConfiguration* config) const {
302 OFStream os(stdout);
303 PrintableInstruction wrapper;
304 wrapper.instr_ = this;
305 wrapper.register_configuration_ = config;
306 os << wrapper << std::endl;
307}
308
309
310void Instruction::Print() const {
311 const RegisterConfiguration* config =
312 RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN);
313 Print(config);
314}
315
316
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400317std::ostream& operator<<(std::ostream& os,
318 const PrintableParallelMove& printable) {
319 const ParallelMove& pm = *printable.parallel_move_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000320 bool first = true;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000321 for (auto move : pm) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000322 if (move->IsEliminated()) continue;
323 if (!first) os << " ";
324 first = false;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400325 PrintableMoveOperands pmo = {printable.register_configuration_, move};
326 os << pmo;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000327 }
328 return os;
329}
330
331
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000332void ReferenceMap::RecordReference(const AllocatedOperand& op) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000333 // Do not record arguments as pointers.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000334 if (op.IsStackSlot() && LocationOperand::cast(op).index() < 0) return;
335 DCHECK(!op.IsDoubleRegister() && !op.IsDoubleStackSlot());
336 reference_operands_.push_back(op);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000337}
338
339
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000340std::ostream& operator<<(std::ostream& os, const ReferenceMap& pm) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000341 os << "{";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000342 bool first = true;
343 PrintableInstructionOperand poi = {
344 RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN),
345 InstructionOperand()};
346 for (auto& op : pm.reference_operands_) {
347 if (!first) {
348 os << ";";
349 } else {
350 first = false;
351 }
352 poi.op_ = op;
353 os << poi;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000354 }
355 return os << "}";
356}
357
358
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400359std::ostream& operator<<(std::ostream& os, const ArchOpcode& ao) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000360 switch (ao) {
361#define CASE(Name) \
362 case k##Name: \
363 return os << #Name;
364 ARCH_OPCODE_LIST(CASE)
365#undef CASE
366 }
367 UNREACHABLE();
368 return os;
369}
370
371
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400372std::ostream& operator<<(std::ostream& os, const AddressingMode& am) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000373 switch (am) {
374 case kMode_None:
375 return os;
376#define CASE(Name) \
377 case kMode_##Name: \
378 return os << #Name;
379 TARGET_ADDRESSING_MODE_LIST(CASE)
380#undef CASE
381 }
382 UNREACHABLE();
383 return os;
384}
385
386
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400387std::ostream& operator<<(std::ostream& os, const FlagsMode& fm) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000388 switch (fm) {
389 case kFlags_none:
390 return os;
391 case kFlags_branch:
392 return os << "branch";
393 case kFlags_set:
394 return os << "set";
395 }
396 UNREACHABLE();
397 return os;
398}
399
400
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400401std::ostream& operator<<(std::ostream& os, const FlagsCondition& fc) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000402 switch (fc) {
403 case kEqual:
404 return os << "equal";
405 case kNotEqual:
406 return os << "not equal";
407 case kSignedLessThan:
408 return os << "signed less than";
409 case kSignedGreaterThanOrEqual:
410 return os << "signed greater than or equal";
411 case kSignedLessThanOrEqual:
412 return os << "signed less than or equal";
413 case kSignedGreaterThan:
414 return os << "signed greater than";
415 case kUnsignedLessThan:
416 return os << "unsigned less than";
417 case kUnsignedGreaterThanOrEqual:
418 return os << "unsigned greater than or equal";
419 case kUnsignedLessThanOrEqual:
420 return os << "unsigned less than or equal";
421 case kUnsignedGreaterThan:
422 return os << "unsigned greater than";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000423 case kFloatLessThanOrUnordered:
424 return os << "less than or unordered (FP)";
425 case kFloatGreaterThanOrEqual:
426 return os << "greater than or equal (FP)";
427 case kFloatLessThanOrEqual:
428 return os << "less than or equal (FP)";
429 case kFloatGreaterThanOrUnordered:
430 return os << "greater than or unordered (FP)";
431 case kFloatLessThan:
432 return os << "less than (FP)";
433 case kFloatGreaterThanOrEqualOrUnordered:
434 return os << "greater than, equal or unordered (FP)";
435 case kFloatLessThanOrEqualOrUnordered:
436 return os << "less than, equal or unordered (FP)";
437 case kFloatGreaterThan:
438 return os << "greater than (FP)";
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000439 case kUnorderedEqual:
440 return os << "unordered equal";
441 case kUnorderedNotEqual:
442 return os << "unordered not equal";
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000443 case kOverflow:
444 return os << "overflow";
445 case kNotOverflow:
446 return os << "not overflow";
447 }
448 UNREACHABLE();
449 return os;
450}
451
452
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400453std::ostream& operator<<(std::ostream& os,
454 const PrintableInstruction& printable) {
455 const Instruction& instr = *printable.instr_;
456 PrintableInstructionOperand printable_op = {printable.register_configuration_,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000457 InstructionOperand()};
458 os << "gap ";
459 for (int i = Instruction::FIRST_GAP_POSITION;
460 i <= Instruction::LAST_GAP_POSITION; i++) {
461 os << "(";
462 if (instr.parallel_moves()[i] != nullptr) {
463 PrintableParallelMove ppm = {printable.register_configuration_,
464 instr.parallel_moves()[i]};
465 os << ppm;
466 }
467 os << ") ";
468 }
469 os << "\n ";
470
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000471 if (instr.OutputCount() > 1) os << "(";
472 for (size_t i = 0; i < instr.OutputCount(); i++) {
473 if (i > 0) os << ", ";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000474 printable_op.op_ = *instr.OutputAt(i);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400475 os << printable_op;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000476 }
477
478 if (instr.OutputCount() > 1) os << ") = ";
479 if (instr.OutputCount() == 1) os << " = ";
480
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000481 os << ArchOpcodeField::decode(instr.opcode());
482 AddressingMode am = AddressingModeField::decode(instr.opcode());
483 if (am != kMode_None) {
484 os << " : " << AddressingModeField::decode(instr.opcode());
485 }
486 FlagsMode fm = FlagsModeField::decode(instr.opcode());
487 if (fm != kFlags_none) {
488 os << " && " << fm << " if " << FlagsConditionField::decode(instr.opcode());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000489 }
490 if (instr.InputCount() > 0) {
491 for (size_t i = 0; i < instr.InputCount(); i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000492 printable_op.op_ = *instr.InputAt(i);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400493 os << " " << printable_op;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000494 }
495 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400496 return os;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000497}
498
499
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000500Constant::Constant(int32_t v) : type_(kInt32), value_(v) {}
501
502
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400503std::ostream& operator<<(std::ostream& os, const Constant& constant) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000504 switch (constant.type()) {
505 case Constant::kInt32:
506 return os << constant.ToInt32();
507 case Constant::kInt64:
508 return os << constant.ToInt64() << "l";
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400509 case Constant::kFloat32:
510 return os << constant.ToFloat32() << "f";
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000511 case Constant::kFloat64:
512 return os << constant.ToFloat64();
513 case Constant::kExternalReference:
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400514 return os << static_cast<const void*>(
515 constant.ToExternalReference().address());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000516 case Constant::kHeapObject:
517 return os << Brief(*constant.ToHeapObject());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400518 case Constant::kRpoNumber:
519 return os << "RPO" << constant.ToRpoNumber().ToInt();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000520 }
521 UNREACHABLE();
522 return os;
523}
524
525
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000526PhiInstruction::PhiInstruction(Zone* zone, int virtual_register,
527 size_t input_count)
528 : virtual_register_(virtual_register),
529 output_(UnallocatedOperand(UnallocatedOperand::NONE, virtual_register)),
530 operands_(input_count, InstructionOperand::kInvalidVirtualRegister,
531 zone) {}
532
533
534void PhiInstruction::SetInput(size_t offset, int virtual_register) {
535 DCHECK_EQ(InstructionOperand::kInvalidVirtualRegister, operands_[offset]);
536 operands_[offset] = virtual_register;
537}
538
539
540InstructionBlock::InstructionBlock(Zone* zone, RpoNumber rpo_number,
541 RpoNumber loop_header, RpoNumber loop_end,
542 bool deferred, bool handler)
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400543 : successors_(zone),
544 predecessors_(zone),
545 phis_(zone),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400546 ao_number_(rpo_number),
547 rpo_number_(rpo_number),
548 loop_header_(loop_header),
549 loop_end_(loop_end),
550 code_start_(-1),
551 code_end_(-1),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000552 deferred_(deferred),
553 handler_(handler),
554 needs_frame_(false),
555 must_construct_frame_(false),
556 must_deconstruct_frame_(false),
557 last_deferred_(RpoNumber::Invalid()) {}
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400558
559
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000560size_t InstructionBlock::PredecessorIndexOf(RpoNumber rpo_number) const {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400561 size_t j = 0;
562 for (InstructionBlock::Predecessors::const_iterator i = predecessors_.begin();
563 i != predecessors_.end(); ++i, ++j) {
564 if (*i == rpo_number) break;
565 }
566 return j;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000567}
568
569
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000570static RpoNumber GetRpo(const BasicBlock* block) {
571 if (block == nullptr) return RpoNumber::Invalid();
572 return RpoNumber::FromInt(block->rpo_number());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000573}
574
575
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000576static RpoNumber GetLoopEndRpo(const BasicBlock* block) {
577 if (!block->IsLoopHeader()) return RpoNumber::Invalid();
578 return RpoNumber::FromInt(block->loop_end()->rpo_number());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000579}
580
581
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400582static InstructionBlock* InstructionBlockFor(Zone* zone,
583 const BasicBlock* block) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000584 bool is_handler =
585 !block->empty() && block->front()->opcode() == IrOpcode::kIfException;
586 InstructionBlock* instr_block = new (zone)
587 InstructionBlock(zone, GetRpo(block), GetRpo(block->loop_header()),
588 GetLoopEndRpo(block), block->deferred(), is_handler);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400589 // Map successors and precessors
590 instr_block->successors().reserve(block->SuccessorCount());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000591 for (BasicBlock* successor : block->successors()) {
592 instr_block->successors().push_back(GetRpo(successor));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400593 }
594 instr_block->predecessors().reserve(block->PredecessorCount());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000595 for (BasicBlock* predecessor : block->predecessors()) {
596 instr_block->predecessors().push_back(GetRpo(predecessor));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400597 }
598 return instr_block;
599}
600
601
602InstructionBlocks* InstructionSequence::InstructionBlocksFor(
603 Zone* zone, const Schedule* schedule) {
604 InstructionBlocks* blocks = zone->NewArray<InstructionBlocks>(1);
605 new (blocks) InstructionBlocks(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000606 static_cast<int>(schedule->rpo_order()->size()), nullptr, zone);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400607 size_t rpo_number = 0;
608 for (BasicBlockVector::const_iterator it = schedule->rpo_order()->begin();
609 it != schedule->rpo_order()->end(); ++it, ++rpo_number) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000610 DCHECK(!(*blocks)[rpo_number]);
611 DCHECK(GetRpo(*it).ToSize() == rpo_number);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400612 (*blocks)[rpo_number] = InstructionBlockFor(zone, *it);
613 }
614 ComputeAssemblyOrder(blocks);
615 return blocks;
616}
617
618
619void InstructionSequence::ComputeAssemblyOrder(InstructionBlocks* blocks) {
620 int ao = 0;
621 for (auto const block : *blocks) {
622 if (!block->IsDeferred()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000623 block->set_ao_number(RpoNumber::FromInt(ao++));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400624 }
625 }
626 for (auto const block : *blocks) {
627 if (block->IsDeferred()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000628 block->set_ao_number(RpoNumber::FromInt(ao++));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400629 }
630 }
631}
632
633
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000634InstructionSequence::InstructionSequence(Isolate* isolate,
635 Zone* instruction_zone,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400636 InstructionBlocks* instruction_blocks)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000637 : isolate_(isolate),
638 zone_(instruction_zone),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400639 instruction_blocks_(instruction_blocks),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000640 source_positions_(zone()),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400641 block_starts_(zone()),
642 constants_(ConstantMap::key_compare(),
643 ConstantMap::allocator_type(zone())),
644 immediates_(zone()),
645 instructions_(zone()),
646 next_virtual_register_(0),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000647 reference_maps_(zone()),
648 representations_(zone()),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400649 deoptimization_entries_(zone()) {
650 block_starts_.reserve(instruction_blocks_->size());
651}
652
653
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000654int InstructionSequence::NextVirtualRegister() {
655 int virtual_register = next_virtual_register_++;
656 CHECK_NE(virtual_register, InstructionOperand::kInvalidVirtualRegister);
657 return virtual_register;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400658}
659
660
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000661Instruction* InstructionSequence::GetBlockStart(RpoNumber rpo) const {
662 const InstructionBlock* block = InstructionBlockAt(rpo);
663 return InstructionAt(block->code_start());
664}
665
666
667void InstructionSequence::StartBlock(RpoNumber rpo) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400668 DCHECK(block_starts_.size() == rpo.ToSize());
669 InstructionBlock* block = InstructionBlockAt(rpo);
670 int code_start = static_cast<int>(instructions_.size());
671 block->set_code_start(code_start);
672 block_starts_.push_back(code_start);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400673}
674
675
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000676void InstructionSequence::EndBlock(RpoNumber rpo) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000677 int end = static_cast<int>(instructions_.size());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400678 InstructionBlock* block = InstructionBlockAt(rpo);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000679 if (block->code_start() == end) { // Empty block. Insert a nop.
680 AddInstruction(Instruction::New(zone(), kArchNop));
681 end = static_cast<int>(instructions_.size());
682 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400683 DCHECK(block->code_start() >= 0 && block->code_start() < end);
684 block->set_code_end(end);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000685}
686
687
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400688int InstructionSequence::AddInstruction(Instruction* instr) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000689 int index = static_cast<int>(instructions_.size());
690 instructions_.push_back(instr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000691 if (instr->NeedsReferenceMap()) {
692 DCHECK(instr->reference_map() == nullptr);
693 ReferenceMap* reference_map = new (zone()) ReferenceMap(zone());
694 reference_map->set_instruction_position(index);
695 instr->set_reference_map(reference_map);
696 reference_maps_.push_back(reference_map);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000697 }
698 return index;
699}
700
701
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000702InstructionBlock* InstructionSequence::GetInstructionBlock(
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400703 int instruction_index) const {
704 DCHECK(instruction_blocks_->size() == block_starts_.size());
705 auto begin = block_starts_.begin();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000706 auto end = std::lower_bound(begin, block_starts_.end(), instruction_index);
707 // Post condition of std::lower_bound:
708 DCHECK(end == block_starts_.end() || *end >= instruction_index);
709 if (end == block_starts_.end() || *end > instruction_index) --end;
710 DCHECK(*end <= instruction_index);
711 size_t index = std::distance(begin, end);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400712 auto block = instruction_blocks_->at(index);
713 DCHECK(block->code_start() <= instruction_index &&
714 instruction_index < block->code_end());
715 return block;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000716}
717
718
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000719static MachineRepresentation FilterRepresentation(MachineRepresentation rep) {
720 switch (rep) {
721 case MachineRepresentation::kBit:
722 case MachineRepresentation::kWord8:
723 case MachineRepresentation::kWord16:
724 return InstructionSequence::DefaultRepresentation();
725 case MachineRepresentation::kWord32:
726 case MachineRepresentation::kWord64:
727 case MachineRepresentation::kFloat32:
728 case MachineRepresentation::kFloat64:
729 case MachineRepresentation::kTagged:
730 return rep;
731 case MachineRepresentation::kNone:
732 break;
733 }
734 UNREACHABLE();
735 return MachineRepresentation::kNone;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000736}
737
738
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000739MachineRepresentation InstructionSequence::GetRepresentation(
740 int virtual_register) const {
741 DCHECK_LE(0, virtual_register);
742 DCHECK_LT(virtual_register, VirtualRegisterCount());
743 if (virtual_register >= static_cast<int>(representations_.size())) {
744 return DefaultRepresentation();
745 }
746 return representations_[virtual_register];
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000747}
748
749
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000750void InstructionSequence::MarkAsRepresentation(MachineRepresentation rep,
751 int virtual_register) {
752 DCHECK_LE(0, virtual_register);
753 DCHECK_LT(virtual_register, VirtualRegisterCount());
754 if (virtual_register >= static_cast<int>(representations_.size())) {
755 representations_.resize(VirtualRegisterCount(), DefaultRepresentation());
756 }
757 rep = FilterRepresentation(rep);
758 DCHECK_IMPLIES(representations_[virtual_register] != rep,
759 representations_[virtual_register] == DefaultRepresentation());
760 representations_[virtual_register] = rep;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000761}
762
763
764InstructionSequence::StateId InstructionSequence::AddFrameStateDescriptor(
765 FrameStateDescriptor* descriptor) {
766 int deoptimization_id = static_cast<int>(deoptimization_entries_.size());
767 deoptimization_entries_.push_back(descriptor);
768 return StateId::FromInt(deoptimization_id);
769}
770
771FrameStateDescriptor* InstructionSequence::GetFrameStateDescriptor(
772 InstructionSequence::StateId state_id) {
773 return deoptimization_entries_[state_id.ToInt()];
774}
775
776
777int InstructionSequence::GetFrameStateDescriptorCount() {
778 return static_cast<int>(deoptimization_entries_.size());
779}
780
781
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000782RpoNumber InstructionSequence::InputRpo(Instruction* instr, size_t index) {
783 InstructionOperand* operand = instr->InputAt(index);
784 Constant constant =
785 operand->IsImmediate()
786 ? GetImmediate(ImmediateOperand::cast(operand))
787 : GetConstant(ConstantOperand::cast(operand)->virtual_register());
788 return constant.ToRpoNumber();
789}
790
791
792bool InstructionSequence::GetSourcePosition(const Instruction* instr,
793 SourcePosition* result) const {
794 auto it = source_positions_.find(instr);
795 if (it == source_positions_.end()) return false;
796 *result = it->second;
797 return true;
798}
799
800
801void InstructionSequence::SetSourcePosition(const Instruction* instr,
802 SourcePosition value) {
803 source_positions_.insert(std::make_pair(instr, value));
804}
805
806
807void InstructionSequence::Print(const RegisterConfiguration* config) const {
808 OFStream os(stdout);
809 PrintableInstructionSequence wrapper;
810 wrapper.register_configuration_ = config;
811 wrapper.sequence_ = this;
812 os << wrapper << std::endl;
813}
814
815
816void InstructionSequence::Print() const {
817 const RegisterConfiguration* config =
818 RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN);
819 Print(config);
820}
821
822
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400823FrameStateDescriptor::FrameStateDescriptor(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000824 Zone* zone, FrameStateType type, BailoutId bailout_id,
825 OutputFrameStateCombine state_combine, size_t parameters_count,
826 size_t locals_count, size_t stack_count,
827 MaybeHandle<SharedFunctionInfo> shared_info,
828 FrameStateDescriptor* outer_state)
829 : type_(type),
830 bailout_id_(bailout_id),
831 frame_state_combine_(state_combine),
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400832 parameters_count_(parameters_count),
833 locals_count_(locals_count),
834 stack_count_(stack_count),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000835 values_(zone),
836 shared_info_(shared_info),
837 outer_state_(outer_state) {}
838
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400839
840size_t FrameStateDescriptor::GetSize(OutputFrameStateCombine combine) const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000841 size_t size = 1 + parameters_count() + locals_count() + stack_count() +
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400842 (HasContext() ? 1 : 0);
843 switch (combine.kind()) {
844 case OutputFrameStateCombine::kPushOutput:
845 size += combine.GetPushCount();
846 break;
847 case OutputFrameStateCombine::kPokeAt:
848 break;
849 }
850 return size;
851}
852
853
854size_t FrameStateDescriptor::GetTotalSize() const {
855 size_t total_size = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000856 for (const FrameStateDescriptor* iter = this; iter != nullptr;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400857 iter = iter->outer_state_) {
858 total_size += iter->GetSize();
859 }
860 return total_size;
861}
862
863
864size_t FrameStateDescriptor::GetFrameCount() const {
865 size_t count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000866 for (const FrameStateDescriptor* iter = this; iter != nullptr;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400867 iter = iter->outer_state_) {
868 ++count;
869 }
870 return count;
871}
872
873
874size_t FrameStateDescriptor::GetJSFrameCount() const {
875 size_t count = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000876 for (const FrameStateDescriptor* iter = this; iter != nullptr;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400877 iter = iter->outer_state_) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000878 if (FrameStateFunctionInfo::IsJSFunctionType(iter->type_)) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400879 ++count;
880 }
881 }
882 return count;
883}
884
885
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000886std::ostream& operator<<(std::ostream& os, const RpoNumber& rpo) {
887 return os << rpo.ToSize();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400888}
889
890
891std::ostream& operator<<(std::ostream& os,
892 const PrintableInstructionSequence& printable) {
893 const InstructionSequence& code = *printable.sequence_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000894 for (size_t i = 0; i < code.immediates_.size(); ++i) {
895 Constant constant = code.immediates_[i];
896 os << "IMM#" << i << ": " << constant << "\n";
897 }
898 int i = 0;
899 for (ConstantMap::const_iterator it = code.constants_.begin();
900 it != code.constants_.end(); ++i, ++it) {
901 os << "CST#" << i << ": v" << it->first << " = " << it->second << "\n";
902 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400903 for (int i = 0; i < code.InstructionBlockCount(); i++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000904 RpoNumber rpo = RpoNumber::FromInt(i);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400905 const InstructionBlock* block = code.InstructionBlockAt(rpo);
906 CHECK(block->rpo_number() == rpo);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000907
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000908 os << "B" << block->rpo_number();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400909 os << ": AO#" << block->ao_number();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400910 if (block->IsDeferred()) os << " (deferred)";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000911 if (!block->needs_frame()) os << " (no frame)";
912 if (block->must_construct_frame()) os << " (construct frame)";
913 if (block->must_deconstruct_frame()) os << " (deconstruct frame)";
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000914 if (block->IsLoopHeader()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400915 os << " loop blocks: [" << block->rpo_number() << ", "
916 << block->loop_end() << ")";
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000917 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400918 os << " instructions: [" << block->code_start() << ", "
919 << block->code_end() << ")\n predecessors:";
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000920
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400921 for (auto pred : block->predecessors()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000922 os << " B" << pred.ToInt();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000923 }
924 os << "\n";
925
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400926 for (auto phi : block->phis()) {
927 PrintableInstructionOperand printable_op = {
928 printable.register_configuration_, phi->output()};
929 os << " phi: " << printable_op << " =";
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000930 for (auto input : phi->operands()) {
931 os << " v" << input;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000932 }
933 os << "\n";
934 }
935
936 ScopedVector<char> buf(32);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400937 PrintableInstruction printable_instr;
938 printable_instr.register_configuration_ = printable.register_configuration_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000939 for (int j = block->first_instruction_index();
940 j <= block->last_instruction_index(); j++) {
941 // TODO(svenpanne) Add some basic formatting to our streams.
942 SNPrintF(buf, "%5d", j);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400943 printable_instr.instr_ = code.InstructionAt(j);
944 os << " " << buf.start() << ": " << printable_instr << "\n";
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000945 }
946
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400947 for (auto succ : block->successors()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000948 os << " B" << succ.ToInt();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000949 }
950 os << "\n";
951 }
952 return os;
953}
954
955} // namespace compiler
956} // namespace internal
957} // namespace v8