| 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 |