OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/compiler/common-operator.h" | 5 #include "src/compiler/common-operator.h" |
6 #include "src/compiler/graph.h" | 6 #include "src/compiler/graph.h" |
7 #include "src/compiler/instruction.h" | 7 #include "src/compiler/instruction.h" |
8 #include "src/compiler/schedule.h" | 8 #include "src/compiler/schedule.h" |
9 | 9 |
10 namespace v8 { | 10 namespace v8 { |
11 namespace internal { | 11 namespace internal { |
12 namespace compiler { | 12 namespace compiler { |
13 | 13 |
14 std::ostream& operator<<(std::ostream& os, | 14 std::ostream& operator<<(std::ostream& os, |
15 const PrintableInstructionOperand& printable) { | 15 const PrintableInstructionOperand& printable) { |
16 const InstructionOperand& op = *printable.op_; | 16 const InstructionOperand& op = printable.op_; |
17 const RegisterConfiguration* conf = printable.register_configuration_; | 17 const RegisterConfiguration* conf = printable.register_configuration_; |
18 switch (op.kind()) { | 18 switch (op.kind()) { |
19 case InstructionOperand::UNALLOCATED: { | 19 case InstructionOperand::UNALLOCATED: { |
20 const UnallocatedOperand* unalloc = UnallocatedOperand::cast(&op); | 20 const UnallocatedOperand* unalloc = UnallocatedOperand::cast(&op); |
21 os << "v" << unalloc->virtual_register(); | 21 os << "v" << unalloc->virtual_register(); |
22 if (unalloc->basic_policy() == UnallocatedOperand::FIXED_SLOT) { | 22 if (unalloc->basic_policy() == UnallocatedOperand::FIXED_SLOT) { |
23 return os << "(=" << unalloc->fixed_slot_index() << "S)"; | 23 return os << "(=" << unalloc->fixed_slot_index() << "S)"; |
24 } | 24 } |
25 switch (unalloc->extended_policy()) { | 25 switch (unalloc->extended_policy()) { |
26 case UnallocatedOperand::NONE: | 26 case UnallocatedOperand::NONE: |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
75 UNREACHABLE(); | 75 UNREACHABLE(); |
76 return os; | 76 return os; |
77 } | 77 } |
78 | 78 |
79 | 79 |
80 std::ostream& operator<<(std::ostream& os, | 80 std::ostream& operator<<(std::ostream& os, |
81 const PrintableMoveOperands& printable) { | 81 const PrintableMoveOperands& printable) { |
82 const MoveOperands& mo = *printable.move_operands_; | 82 const MoveOperands& mo = *printable.move_operands_; |
83 PrintableInstructionOperand printable_op = {printable.register_configuration_, | 83 PrintableInstructionOperand printable_op = {printable.register_configuration_, |
84 mo.destination()}; | 84 mo.destination()}; |
85 | |
86 os << printable_op; | 85 os << printable_op; |
87 if (!mo.source()->Equals(mo.destination())) { | 86 if (mo.source() != mo.destination()) { |
88 printable_op.op_ = mo.source(); | 87 printable_op.op_ = mo.source(); |
89 os << " = " << printable_op; | 88 os << " = " << printable_op; |
90 } | 89 } |
91 return os << ";"; | 90 return os << ";"; |
92 } | 91 } |
93 | 92 |
94 | 93 |
95 bool ParallelMove::IsRedundant() const { | 94 bool ParallelMove::IsRedundant() const { |
96 for (int i = 0; i < move_operands_.length(); ++i) { | 95 for (auto move : *this) { |
97 if (!move_operands_[i].IsRedundant()) return false; | 96 if (!move->IsRedundant()) return false; |
98 } | 97 } |
99 return true; | 98 return true; |
100 } | 99 } |
101 | 100 |
102 | 101 |
103 MoveOperands* ParallelMove::PrepareInsertAfter(MoveOperands* move) const { | 102 MoveOperands* ParallelMove::PrepareInsertAfter(MoveOperands* move) const { |
104 auto move_ops = move_operands(); | |
105 MoveOperands* replacement = nullptr; | 103 MoveOperands* replacement = nullptr; |
106 MoveOperands* to_eliminate = nullptr; | 104 MoveOperands* to_eliminate = nullptr; |
107 for (auto curr = move_ops->begin(); curr != move_ops->end(); ++curr) { | 105 for (auto curr : *this) { |
108 if (curr->IsEliminated()) continue; | 106 if (curr->IsEliminated()) continue; |
109 if (curr->destination()->Equals(move->source())) { | 107 if (curr->destination() == move->source()) { |
110 DCHECK(!replacement); | 108 DCHECK(!replacement); |
111 replacement = curr; | 109 replacement = curr; |
112 if (to_eliminate != nullptr) break; | 110 if (to_eliminate != nullptr) break; |
113 } else if (curr->destination()->Equals(move->destination())) { | 111 } else if (curr->destination() == move->destination()) { |
114 DCHECK(!to_eliminate); | 112 DCHECK(!to_eliminate); |
115 to_eliminate = curr; | 113 to_eliminate = curr; |
116 if (replacement != nullptr) break; | 114 if (replacement != nullptr) break; |
117 } | 115 } |
118 } | 116 } |
119 DCHECK_IMPLIES(replacement == to_eliminate, replacement == nullptr); | 117 DCHECK_IMPLIES(replacement == to_eliminate, replacement == nullptr); |
120 if (replacement != nullptr) move->set_source(replacement->source()); | 118 if (replacement != nullptr) move->set_source(replacement->source()); |
121 return to_eliminate; | 119 return to_eliminate; |
122 } | 120 } |
123 | 121 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
168 } | 166 } |
169 } | 167 } |
170 return true; | 168 return true; |
171 } | 169 } |
172 | 170 |
173 | 171 |
174 std::ostream& operator<<(std::ostream& os, | 172 std::ostream& operator<<(std::ostream& os, |
175 const PrintableParallelMove& printable) { | 173 const PrintableParallelMove& printable) { |
176 const ParallelMove& pm = *printable.parallel_move_; | 174 const ParallelMove& pm = *printable.parallel_move_; |
177 bool first = true; | 175 bool first = true; |
178 for (ZoneList<MoveOperands>::iterator move = pm.move_operands()->begin(); | 176 for (auto move : pm) { |
179 move != pm.move_operands()->end(); ++move) { | |
180 if (move->IsEliminated()) continue; | 177 if (move->IsEliminated()) continue; |
181 if (!first) os << " "; | 178 if (!first) os << " "; |
182 first = false; | 179 first = false; |
183 PrintableMoveOperands pmo = {printable.register_configuration_, move}; | 180 PrintableMoveOperands pmo = {printable.register_configuration_, move}; |
184 os << pmo; | 181 os << pmo; |
185 } | 182 } |
186 return os; | 183 return os; |
187 } | 184 } |
188 | 185 |
189 | 186 |
190 void ReferenceMap::RecordReference(const InstructionOperand& op) { | 187 void ReferenceMap::RecordReference(const InstructionOperand& op) { |
191 // Do not record arguments as pointers. | 188 // Do not record arguments as pointers. |
192 if (op.IsStackSlot() && StackSlotOperand::cast(op).index() < 0) return; | 189 if (op.IsStackSlot() && StackSlotOperand::cast(op).index() < 0) return; |
193 DCHECK(!op.IsDoubleRegister() && !op.IsDoubleStackSlot()); | 190 DCHECK(!op.IsDoubleRegister() && !op.IsDoubleStackSlot()); |
194 reference_operands_.push_back(op); | 191 reference_operands_.push_back(op); |
195 } | 192 } |
196 | 193 |
197 | 194 |
198 std::ostream& operator<<(std::ostream& os, const ReferenceMap& pm) { | 195 std::ostream& operator<<(std::ostream& os, const ReferenceMap& pm) { |
199 os << "{"; | 196 os << "{"; |
200 bool first = true; | 197 bool first = true; |
201 PrintableInstructionOperand poi = {RegisterConfiguration::ArchDefault(), | 198 PrintableInstructionOperand poi = {RegisterConfiguration::ArchDefault(), |
202 nullptr}; | 199 InstructionOperand()}; |
203 for (auto& op : pm.reference_operands_) { | 200 for (auto& op : pm.reference_operands_) { |
204 if (!first) { | 201 if (!first) { |
205 os << ";"; | 202 os << ";"; |
206 } else { | 203 } else { |
207 first = false; | 204 first = false; |
208 } | 205 } |
209 poi.op_ = &op; | 206 poi.op_ = op; |
210 os << poi; | 207 os << poi; |
211 } | 208 } |
212 return os << "}"; | 209 return os << "}"; |
213 } | 210 } |
214 | 211 |
215 | 212 |
216 std::ostream& operator<<(std::ostream& os, const ArchOpcode& ao) { | 213 std::ostream& operator<<(std::ostream& os, const ArchOpcode& ao) { |
217 switch (ao) { | 214 switch (ao) { |
218 #define CASE(Name) \ | 215 #define CASE(Name) \ |
219 case k##Name: \ | 216 case k##Name: \ |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
288 } | 285 } |
289 UNREACHABLE(); | 286 UNREACHABLE(); |
290 return os; | 287 return os; |
291 } | 288 } |
292 | 289 |
293 | 290 |
294 std::ostream& operator<<(std::ostream& os, | 291 std::ostream& operator<<(std::ostream& os, |
295 const PrintableInstruction& printable) { | 292 const PrintableInstruction& printable) { |
296 const Instruction& instr = *printable.instr_; | 293 const Instruction& instr = *printable.instr_; |
297 PrintableInstructionOperand printable_op = {printable.register_configuration_, | 294 PrintableInstructionOperand printable_op = {printable.register_configuration_, |
298 NULL}; | 295 InstructionOperand()}; |
299 os << "gap "; | 296 os << "gap "; |
300 for (int i = Instruction::FIRST_GAP_POSITION; | 297 for (int i = Instruction::FIRST_GAP_POSITION; |
301 i <= Instruction::LAST_GAP_POSITION; i++) { | 298 i <= Instruction::LAST_GAP_POSITION; i++) { |
302 os << "("; | 299 os << "("; |
303 if (instr.parallel_moves()[i] != NULL) { | 300 if (instr.parallel_moves()[i] != NULL) { |
304 PrintableParallelMove ppm = {printable.register_configuration_, | 301 PrintableParallelMove ppm = {printable.register_configuration_, |
305 instr.parallel_moves()[i]}; | 302 instr.parallel_moves()[i]}; |
306 os << ppm; | 303 os << ppm; |
307 } | 304 } |
308 os << ") "; | 305 os << ") "; |
309 } | 306 } |
310 os << "\n "; | 307 os << "\n "; |
311 | 308 |
312 if (instr.OutputCount() > 1) os << "("; | 309 if (instr.OutputCount() > 1) os << "("; |
313 for (size_t i = 0; i < instr.OutputCount(); i++) { | 310 for (size_t i = 0; i < instr.OutputCount(); i++) { |
314 if (i > 0) os << ", "; | 311 if (i > 0) os << ", "; |
315 printable_op.op_ = instr.OutputAt(i); | 312 printable_op.op_ = *instr.OutputAt(i); |
316 os << printable_op; | 313 os << printable_op; |
317 } | 314 } |
318 | 315 |
319 if (instr.OutputCount() > 1) os << ") = "; | 316 if (instr.OutputCount() > 1) os << ") = "; |
320 if (instr.OutputCount() == 1) os << " = "; | 317 if (instr.OutputCount() == 1) os << " = "; |
321 | 318 |
322 os << ArchOpcodeField::decode(instr.opcode()); | 319 os << ArchOpcodeField::decode(instr.opcode()); |
323 AddressingMode am = AddressingModeField::decode(instr.opcode()); | 320 AddressingMode am = AddressingModeField::decode(instr.opcode()); |
324 if (am != kMode_None) { | 321 if (am != kMode_None) { |
325 os << " : " << AddressingModeField::decode(instr.opcode()); | 322 os << " : " << AddressingModeField::decode(instr.opcode()); |
326 } | 323 } |
327 FlagsMode fm = FlagsModeField::decode(instr.opcode()); | 324 FlagsMode fm = FlagsModeField::decode(instr.opcode()); |
328 if (fm != kFlags_none) { | 325 if (fm != kFlags_none) { |
329 os << " && " << fm << " if " << FlagsConditionField::decode(instr.opcode()); | 326 os << " && " << fm << " if " << FlagsConditionField::decode(instr.opcode()); |
330 } | 327 } |
331 if (instr.InputCount() > 0) { | 328 if (instr.InputCount() > 0) { |
332 for (size_t i = 0; i < instr.InputCount(); i++) { | 329 for (size_t i = 0; i < instr.InputCount(); i++) { |
333 printable_op.op_ = instr.InputAt(i); | 330 printable_op.op_ = *instr.InputAt(i); |
334 os << " " << printable_op; | 331 os << " " << printable_op; |
335 } | 332 } |
336 } | 333 } |
337 return os; | 334 return os; |
338 } | 335 } |
339 | 336 |
340 | 337 |
341 Constant::Constant(int32_t v) : type_(kInt32), value_(v) {} | 338 Constant::Constant(int32_t v) : type_(kInt32), value_(v) {} |
342 | 339 |
343 | 340 |
(...skipping 17 matching lines...) Expand all Loading... |
361 } | 358 } |
362 UNREACHABLE(); | 359 UNREACHABLE(); |
363 return os; | 360 return os; |
364 } | 361 } |
365 | 362 |
366 | 363 |
367 PhiInstruction::PhiInstruction(Zone* zone, int virtual_register, | 364 PhiInstruction::PhiInstruction(Zone* zone, int virtual_register, |
368 size_t input_count) | 365 size_t input_count) |
369 : virtual_register_(virtual_register), | 366 : virtual_register_(virtual_register), |
370 output_(UnallocatedOperand(UnallocatedOperand::NONE, virtual_register)), | 367 output_(UnallocatedOperand(UnallocatedOperand::NONE, virtual_register)), |
371 operands_(input_count, zone), | 368 operands_(input_count, InstructionOperand::kInvalidVirtualRegister, |
372 inputs_(input_count, zone) {} | 369 zone) {} |
373 | 370 |
374 | 371 |
375 void PhiInstruction::SetInput(size_t offset, int virtual_register) { | 372 void PhiInstruction::SetInput(size_t offset, int virtual_register) { |
376 DCHECK(inputs_[offset].IsInvalid()); | 373 DCHECK_EQ(InstructionOperand::kInvalidVirtualRegister, operands_[offset]); |
377 auto input = UnallocatedOperand(UnallocatedOperand::ANY, virtual_register); | |
378 inputs_[offset] = input; | |
379 operands_[offset] = virtual_register; | 374 operands_[offset] = virtual_register; |
380 } | 375 } |
381 | 376 |
382 | 377 |
383 InstructionBlock::InstructionBlock(Zone* zone, RpoNumber rpo_number, | 378 InstructionBlock::InstructionBlock(Zone* zone, RpoNumber rpo_number, |
384 RpoNumber loop_header, RpoNumber loop_end, | 379 RpoNumber loop_header, RpoNumber loop_end, |
385 bool deferred) | 380 bool deferred) |
386 : successors_(zone), | 381 : successors_(zone), |
387 predecessors_(zone), | 382 predecessors_(zone), |
388 phis_(zone), | 383 phis_(zone), |
(...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
719 os << " instructions: [" << block->code_start() << ", " | 714 os << " instructions: [" << block->code_start() << ", " |
720 << block->code_end() << ")\n predecessors:"; | 715 << block->code_end() << ")\n predecessors:"; |
721 | 716 |
722 for (auto pred : block->predecessors()) { | 717 for (auto pred : block->predecessors()) { |
723 os << " B" << pred.ToInt(); | 718 os << " B" << pred.ToInt(); |
724 } | 719 } |
725 os << "\n"; | 720 os << "\n"; |
726 | 721 |
727 for (auto phi : block->phis()) { | 722 for (auto phi : block->phis()) { |
728 PrintableInstructionOperand printable_op = { | 723 PrintableInstructionOperand printable_op = { |
729 printable.register_configuration_, &phi->output()}; | 724 printable.register_configuration_, phi->output()}; |
730 os << " phi: " << printable_op << " ="; | 725 os << " phi: " << printable_op << " ="; |
731 for (auto input : phi->inputs()) { | 726 for (auto input : phi->operands()) { |
732 printable_op.op_ = &input; | 727 os << " v" << input; |
733 os << " " << printable_op; | |
734 } | 728 } |
735 os << "\n"; | 729 os << "\n"; |
736 } | 730 } |
737 | 731 |
738 ScopedVector<char> buf(32); | 732 ScopedVector<char> buf(32); |
739 PrintableInstruction printable_instr; | 733 PrintableInstruction printable_instr; |
740 printable_instr.register_configuration_ = printable.register_configuration_; | 734 printable_instr.register_configuration_ = printable.register_configuration_; |
741 for (int j = block->first_instruction_index(); | 735 for (int j = block->first_instruction_index(); |
742 j <= block->last_instruction_index(); j++) { | 736 j <= block->last_instruction_index(); j++) { |
743 // TODO(svenpanne) Add some basic formatting to our streams. | 737 // TODO(svenpanne) Add some basic formatting to our streams. |
744 SNPrintF(buf, "%5d", j); | 738 SNPrintF(buf, "%5d", j); |
745 printable_instr.instr_ = code.InstructionAt(j); | 739 printable_instr.instr_ = code.InstructionAt(j); |
746 os << " " << buf.start() << ": " << printable_instr << "\n"; | 740 os << " " << buf.start() << ": " << printable_instr << "\n"; |
747 } | 741 } |
748 | 742 |
749 for (auto succ : block->successors()) { | 743 for (auto succ : block->successors()) { |
750 os << " B" << succ.ToInt(); | 744 os << " B" << succ.ToInt(); |
751 } | 745 } |
752 os << "\n"; | 746 os << "\n"; |
753 } | 747 } |
754 return os; | 748 return os; |
755 } | 749 } |
756 | 750 |
757 } // namespace compiler | 751 } // namespace compiler |
758 } // namespace internal | 752 } // namespace internal |
759 } // namespace v8 | 753 } // namespace v8 |
OLD | NEW |