From 6149d5ec76625c8e773d8d7b47dd25e72ee7231d Mon Sep 17 00:00:00 2001 From: dcarney Date: Fri, 30 Jan 2015 02:58:22 -0800 Subject: [PATCH] [turbofan] cleanup MoveOptimizer a little BUG= Review URL: https://codereview.chromium.org/888813002 Cr-Commit-Position: refs/heads/master@{#26350} --- src/compiler/move-optimizer.cc | 218 ++++++++++++++++++--------------- src/compiler/move-optimizer.h | 8 +- 2 files changed, 128 insertions(+), 98 deletions(-) diff --git a/src/compiler/move-optimizer.cc b/src/compiler/move-optimizer.cc index 855256e92c..94846012e2 100644 --- a/src/compiler/move-optimizer.cc +++ b/src/compiler/move-optimizer.cc @@ -8,75 +8,10 @@ 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) {} +namespace { - -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); - } -} - - -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; @@ -102,25 +37,69 @@ static MoveOperands* PrepareInsertAfter(ParallelMove* left, MoveOperands* move, } +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,7 +183,7 @@ 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()) @@ -180,24 +206,24 @@ void MoveOptimizer::FinalizeMoves(MoveOpVector* loads, MoveOpVector* new_moves, } // 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(1), code_zone()); DCHECK(slot_1->move_operands()->is_empty()); slot_1->move_operands()->AddBlock(MoveOperands(nullptr, nullptr), - static_cast(new_moves->size()), + static_cast(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 diff --git a/src/compiler/move-optimizer.h b/src/compiler/move-optimizer.h index bbce6867d6..2bde09eae5 100644 --- a/src/compiler/move-optimizer.h +++ b/src/compiler/move-optimizer.h @@ -19,18 +19,22 @@ class MoveOptimizer FINAL { private: typedef ZoneVector MoveOpVector; + typedef ZoneVector GapInstructions; InstructionSequence* code() const { return code_; } Zone* local_zone() const { return local_zone_; } Zone* code_zone() const { return code()->zone(); } + MoveOpVector& temp_vector_0() { return temp_vector_0_; } + MoveOpVector& temp_vector_1() { return temp_vector_1_; } + void CompressBlock(InstructionBlock* blocke); void CompressMoves(MoveOpVector* eliminated, ParallelMove* left, ParallelMove* right); - void FinalizeMoves(MoveOpVector* loads, MoveOpVector* new_moves, - GapInstruction* gap); + void FinalizeMoves(GapInstruction* gap); Zone* const local_zone_; InstructionSequence* const code_; + GapInstructions to_finalize_; MoveOpVector temp_vector_0_; MoveOpVector temp_vector_1_;