diff options
Diffstat (limited to 'deps/v8/src/compiler/move-optimizer.cc')
-rw-r--r-- | deps/v8/src/compiler/move-optimizer.cc | 232 |
1 files changed, 129 insertions, 103 deletions
diff --git a/deps/v8/src/compiler/move-optimizer.cc b/deps/v8/src/compiler/move-optimizer.cc index 330f32f65d..f4e0513775 100644 --- a/deps/v8/src/compiler/move-optimizer.cc +++ b/deps/v8/src/compiler/move-optimizer.cc @@ -8,119 +8,98 @@ namespace v8 { namespace internal { namespace compiler { -MoveOptimizer::MoveOptimizer(Zone* local_zone, InstructionSequence* code) - : local_zone_(local_zone), - code_(code), - temp_vector_0_(local_zone), - temp_vector_1_(local_zone) {} - - -void MoveOptimizer::Run() { - // First smash all consecutive moves into the left most move slot. - for (auto* block : code()->instruction_blocks()) { - GapInstruction* prev_gap = nullptr; - for (int index = block->code_start(); index < block->code_end(); ++index) { - auto instr = code()->instructions()[index]; - if (!instr->IsGapMoves()) { - if (instr->IsSourcePosition() || instr->IsNop()) continue; - FinalizeMoves(&temp_vector_0_, &temp_vector_1_, prev_gap); - prev_gap = nullptr; - continue; - } - auto gap = GapInstruction::cast(instr); - // Find first non-empty slot. - int i = GapInstruction::FIRST_INNER_POSITION; - for (; i <= GapInstruction::LAST_INNER_POSITION; i++) { - auto move = gap->parallel_moves()[i]; - if (move == nullptr) continue; - auto move_ops = move->move_operands(); - auto op = move_ops->begin(); - for (; op != move_ops->end(); ++op) { - if (!op->IsRedundant()) break; - } - if (op == move_ops->end()) { - move_ops->Rewind(0); // Clear this redundant move. - } else { - break; // Found index of first non-redundant move. - } - } - // Nothing to do here. - if (i == GapInstruction::LAST_INNER_POSITION + 1) { - if (prev_gap != nullptr) { - // Slide prev_gap down so we always know where to look for it. - std::swap(prev_gap->parallel_moves()[0], gap->parallel_moves()[0]); - prev_gap = gap; - } - continue; - } - // Move the first non-empty gap to position 0. - std::swap(gap->parallel_moves()[0], gap->parallel_moves()[i]); - auto left = gap->parallel_moves()[0]; - // Compress everything into position 0. - for (++i; i <= GapInstruction::LAST_INNER_POSITION; ++i) { - auto move = gap->parallel_moves()[i]; - if (move == nullptr) continue; - CompressMoves(&temp_vector_0_, left, move); - } - if (prev_gap != nullptr) { - // Smash left into prev_gap, killing left. - auto pred_moves = prev_gap->parallel_moves()[0]; - CompressMoves(&temp_vector_0_, pred_moves, left); - std::swap(prev_gap->parallel_moves()[0], gap->parallel_moves()[0]); - } - prev_gap = gap; - } - FinalizeMoves(&temp_vector_0_, &temp_vector_1_, prev_gap); - } -} +namespace { - -static MoveOperands* PrepareInsertAfter(ParallelMove* left, MoveOperands* move, - Zone* zone) { +MoveOperands* PrepareInsertAfter(ParallelMove* left, MoveOperands* move, + Zone* zone) { auto move_ops = left->move_operands(); MoveOperands* replacement = nullptr; MoveOperands* to_eliminate = nullptr; for (auto curr = move_ops->begin(); curr != move_ops->end(); ++curr) { if (curr->IsEliminated()) continue; if (curr->destination()->Equals(move->source())) { - DCHECK_EQ(nullptr, replacement); + DCHECK(!replacement); replacement = curr; if (to_eliminate != nullptr) break; } else if (curr->destination()->Equals(move->destination())) { - DCHECK_EQ(nullptr, to_eliminate); + DCHECK(!to_eliminate); to_eliminate = curr; if (replacement != nullptr) break; } } DCHECK(!(replacement == to_eliminate && replacement != nullptr)); if (replacement != nullptr) { - auto new_source = new (zone) InstructionOperand( - replacement->source()->kind(), replacement->source()->index()); + auto new_source = InstructionOperand::New( + zone, replacement->source()->kind(), replacement->source()->index()); move->set_source(new_source); } return to_eliminate; } +bool GapsCanMoveOver(Instruction* instr) { + DCHECK(!instr->IsGapMoves()); + return instr->IsSourcePosition() || instr->IsNop(); +} + + +int FindFirstNonEmptySlot(GapInstruction* gap) { + int i = GapInstruction::FIRST_INNER_POSITION; + for (; i <= GapInstruction::LAST_INNER_POSITION; i++) { + auto move = gap->parallel_moves()[i]; + if (move == nullptr) continue; + auto move_ops = move->move_operands(); + auto op = move_ops->begin(); + for (; op != move_ops->end(); ++op) { + if (!op->IsRedundant()) break; + op->Eliminate(); + } + if (op != move_ops->end()) break; // Found non-redundant move. + move_ops->Rewind(0); // Clear this redundant move. + } + return i; +} + +} // namepace + + +MoveOptimizer::MoveOptimizer(Zone* local_zone, InstructionSequence* code) + : local_zone_(local_zone), + code_(code), + to_finalize_(local_zone), + temp_vector_0_(local_zone), + temp_vector_1_(local_zone) {} + + +void MoveOptimizer::Run() { + for (auto* block : code()->instruction_blocks()) { + CompressBlock(block); + } + for (auto gap : to_finalize_) { + FinalizeMoves(gap); + } +} + + void MoveOptimizer::CompressMoves(MoveOpVector* eliminated, ParallelMove* left, ParallelMove* right) { DCHECK(eliminated->empty()); auto move_ops = right->move_operands(); - // Modify the right moves in place and collect moves that will be killed by - // merging the two gaps. - for (auto op = move_ops->begin(); op != move_ops->end(); ++op) { - if (op->IsRedundant()) continue; - MoveOperands* to_eliminate = PrepareInsertAfter(left, op, code_zone()); - if (to_eliminate != nullptr) { - eliminated->push_back(to_eliminate); + if (!left->move_operands()->is_empty()) { + // Modify the right moves in place and collect moves that will be killed by + // merging the two gaps. + for (auto op = move_ops->begin(); op != move_ops->end(); ++op) { + if (op->IsRedundant()) continue; + MoveOperands* to_eliminate = PrepareInsertAfter(left, op, code_zone()); + if (to_eliminate != nullptr) eliminated->push_back(to_eliminate); } + // Eliminate dead moves. Must happen before insertion of new moves as the + // contents of eliminated are pointers into a list. + for (auto to_eliminate : *eliminated) { + to_eliminate->Eliminate(); + } + eliminated->clear(); } - // Eliminate dead moves. Must happen before insertion of new moves as the - // contents of eliminated are pointers into a list. - for (auto to_eliminate : *eliminated) { - to_eliminate->Eliminate(); - } - eliminated->clear(); // Add all possibly modified moves from right side. for (auto op = move_ops->begin(); op != move_ops->end(); ++op) { if (op->IsRedundant()) continue; @@ -131,13 +110,60 @@ void MoveOptimizer::CompressMoves(MoveOpVector* eliminated, ParallelMove* left, } -void MoveOptimizer::FinalizeMoves(MoveOpVector* loads, MoveOpVector* new_moves, - GapInstruction* gap) { - DCHECK(loads->empty()); - DCHECK(new_moves->empty()); - if (gap == nullptr) return; - // Split multiple loads of the same constant or stack slot off into the second - // slot and keep remaining moves in the first slot. +// Smash all consecutive moves into the left most move slot and accumulate them +// as much as possible across instructions. +void MoveOptimizer::CompressBlock(InstructionBlock* block) { + auto temp_vector = temp_vector_0(); + DCHECK(temp_vector.empty()); + GapInstruction* prev_gap = nullptr; + for (int index = block->code_start(); index < block->code_end(); ++index) { + auto instr = code()->instructions()[index]; + if (!instr->IsGapMoves()) { + if (GapsCanMoveOver(instr)) continue; + if (prev_gap != nullptr) to_finalize_.push_back(prev_gap); + prev_gap = nullptr; + continue; + } + auto gap = GapInstruction::cast(instr); + int i = FindFirstNonEmptySlot(gap); + // Nothing to do here. + if (i == GapInstruction::LAST_INNER_POSITION + 1) { + if (prev_gap != nullptr) { + // Slide prev_gap down so we always know where to look for it. + std::swap(prev_gap->parallel_moves()[0], gap->parallel_moves()[0]); + prev_gap = gap; + } + continue; + } + // Move the first non-empty gap to position 0. + std::swap(gap->parallel_moves()[0], gap->parallel_moves()[i]); + auto left = gap->parallel_moves()[0]; + // Compress everything into position 0. + for (++i; i <= GapInstruction::LAST_INNER_POSITION; ++i) { + auto move = gap->parallel_moves()[i]; + if (move == nullptr) continue; + CompressMoves(&temp_vector, left, move); + } + if (prev_gap != nullptr) { + // Smash left into prev_gap, killing left. + auto pred_moves = prev_gap->parallel_moves()[0]; + CompressMoves(&temp_vector, pred_moves, left); + // Slide prev_gap down so we always know where to look for it. + std::swap(prev_gap->parallel_moves()[0], gap->parallel_moves()[0]); + } + prev_gap = gap; + } + if (prev_gap != nullptr) to_finalize_.push_back(prev_gap); +} + + +// Split multiple loads of the same constant or stack slot off into the second +// slot and keep remaining moves in the first slot. +void MoveOptimizer::FinalizeMoves(GapInstruction* gap) { + auto loads = temp_vector_0(); + DCHECK(loads.empty()); + auto new_moves = temp_vector_1(); + DCHECK(new_moves.empty()); auto move_ops = gap->parallel_moves()[0]->move_operands(); for (auto move = move_ops->begin(); move != move_ops->end(); ++move) { if (move->IsRedundant()) { @@ -149,7 +175,7 @@ void MoveOptimizer::FinalizeMoves(MoveOpVector* loads, MoveOpVector* new_moves, continue; // Search for existing move to this slot. MoveOperands* found = nullptr; - for (auto load : *loads) { + for (auto load : loads) { if (load->source()->Equals(move->source())) { found = load; break; @@ -157,11 +183,11 @@ void MoveOptimizer::FinalizeMoves(MoveOpVector* loads, MoveOpVector* new_moves, } // Not found so insert. if (found == nullptr) { - loads->push_back(move); + loads.push_back(move); // Replace source with copy for later use. auto dest = move->destination(); - move->set_destination(new (code_zone()) - InstructionOperand(dest->kind(), dest->index())); + move->set_destination( + InstructionOperand::New(code_zone(), dest->kind(), dest->index())); continue; } if ((found->destination()->IsStackSlot() || @@ -173,31 +199,31 @@ void MoveOptimizer::FinalizeMoves(MoveOpVector* loads, MoveOpVector* new_moves, InstructionOperand::Kind found_kind = found->destination()->kind(); int found_index = found->destination()->index(); auto next_dest = - new (code_zone()) InstructionOperand(found_kind, found_index); + InstructionOperand::New(code_zone(), found_kind, found_index); auto dest = move->destination(); found->destination()->ConvertTo(dest->kind(), dest->index()); move->set_destination(next_dest); } // move from load destination. move->set_source(found->destination()); - new_moves->push_back(move); + new_moves.push_back(move); } - loads->clear(); - if (new_moves->empty()) return; + loads.clear(); + if (new_moves.empty()) return; // Insert all new moves into slot 1. auto slot_1 = gap->GetOrCreateParallelMove( static_cast<GapInstruction::InnerPosition>(1), code_zone()); DCHECK(slot_1->move_operands()->is_empty()); slot_1->move_operands()->AddBlock(MoveOperands(nullptr, nullptr), - static_cast<int>(new_moves->size()), + static_cast<int>(new_moves.size()), code_zone()); auto it = slot_1->move_operands()->begin(); - for (auto new_move : *new_moves) { + for (auto new_move : new_moves) { std::swap(*new_move, *it); ++it; } DCHECK_EQ(it, slot_1->move_operands()->end()); - new_moves->clear(); + new_moves.clear(); } } // namespace compiler |