Index: src/compiler/move-optimizer.cc |
diff --git a/src/compiler/move-optimizer.cc b/src/compiler/move-optimizer.cc |
index 6857b297d292e0ff482acb59322e37b69dba280c..ea514aaa1351f1577af95cc6d6753990451b66c4 100644 |
--- a/src/compiler/move-optimizer.cc |
+++ b/src/compiler/move-optimizer.cc |
@@ -21,16 +21,13 @@ bool GapsCanMoveOver(Instruction* instr) { return instr->IsNop(); } |
int FindFirstNonEmptySlot(Instruction* instr) { |
int i = Instruction::FIRST_GAP_POSITION; |
for (; i <= Instruction::LAST_GAP_POSITION; i++) { |
- auto move = instr->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(); |
+ auto moves = instr->parallel_moves()[i]; |
+ if (moves == nullptr) continue; |
+ for (auto move : *moves) { |
+ if (!move->IsRedundant()) return i; |
+ move->Eliminate(); |
} |
- if (op != move_ops->end()) break; // Found non-redundant move. |
- move_ops->Rewind(0); // Clear this redundant move. |
+ moves->clear(); // Clear this redundant move. |
} |
return i; |
} |
@@ -63,29 +60,27 @@ void MoveOptimizer::Run() { |
void MoveOptimizer::CompressMoves(MoveOpVector* eliminated, ParallelMove* left, |
ParallelMove* right) { |
DCHECK(eliminated->empty()); |
- auto move_ops = right->move_operands(); |
- if (!left->move_operands()->is_empty()) { |
+ if (!left->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; |
- auto to_eliminate = left->PrepareInsertAfter(op); |
+ for (auto move : *right) { |
+ if (move->IsRedundant()) continue; |
+ auto to_eliminate = left->PrepareInsertAfter(move); |
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. |
+ // Eliminate dead moves. |
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; |
- left->move_operands()->Add(*op, code_zone()); |
+ for (auto move : *right) { |
+ if (move->IsRedundant()) continue; |
+ left->push_back(move); |
} |
// Nuke right. |
- move_ops->Rewind(0); |
+ right->clear(); |
} |
@@ -159,14 +154,13 @@ void MoveOptimizer::OptimizeMerge(InstructionBlock* block) { |
auto pred = code()->InstructionBlockAt(pred_index); |
auto instr = LastInstruction(pred); |
if (instr->parallel_moves()[0] == nullptr || |
- instr->parallel_moves()[0]->move_operands()->is_empty()) { |
+ instr->parallel_moves()[0]->empty()) { |
return; |
} |
- auto move_ops = instr->parallel_moves()[0]->move_operands(); |
- for (auto op = move_ops->begin(); op != move_ops->end(); ++op) { |
- if (op->IsRedundant()) continue; |
- auto src = *op->source(); |
- auto dst = *op->destination(); |
+ for (auto move : *instr->parallel_moves()[0]) { |
+ if (move->IsRedundant()) continue; |
+ auto src = move->source(); |
+ auto dst = move->destination(); |
MoveKey key = {src, dst}; |
auto res = move_map.insert(std::make_pair(key, 1)); |
if (!res.second) { |
@@ -188,30 +182,29 @@ void MoveOptimizer::OptimizeMerge(InstructionBlock* block) { |
DCHECK(instr != nullptr); |
bool gap_initialized = true; |
if (instr->parallel_moves()[0] == nullptr || |
- instr->parallel_moves()[0]->move_operands()->is_empty()) { |
+ instr->parallel_moves()[0]->empty()) { |
to_finalize_.push_back(instr); |
} else { |
// Will compress after insertion. |
gap_initialized = false; |
std::swap(instr->parallel_moves()[0], instr->parallel_moves()[1]); |
} |
- auto move = instr->GetOrCreateParallelMove( |
+ auto moves = instr->GetOrCreateParallelMove( |
static_cast<Instruction::GapPosition>(0), code_zone()); |
// Delete relevant entries in predecessors and move everything to block. |
bool first_iteration = true; |
for (auto pred_index : block->predecessors()) { |
auto pred = code()->InstructionBlockAt(pred_index); |
- auto move_ops = LastInstruction(pred)->parallel_moves()[0]->move_operands(); |
- for (auto op = move_ops->begin(); op != move_ops->end(); ++op) { |
- if (op->IsRedundant()) continue; |
- MoveKey key = {*op->source(), *op->destination()}; |
+ for (auto move : *LastInstruction(pred)->parallel_moves()[0]) { |
+ if (move->IsRedundant()) continue; |
+ MoveKey key = {move->source(), move->destination()}; |
auto it = move_map.find(key); |
USE(it); |
DCHECK(it != move_map.end()); |
if (first_iteration) { |
- move->AddMove(op->source(), op->destination(), code_zone()); |
+ moves->AddMove(move->source(), move->destination()); |
} |
- op->Eliminate(); |
+ move->Eliminate(); |
} |
first_iteration = false; |
} |
@@ -223,70 +216,55 @@ void MoveOptimizer::OptimizeMerge(InstructionBlock* block) { |
} |
+namespace { |
+ |
+bool IsSlot(const InstructionOperand& op) { |
+ return op.IsStackSlot() || op.IsDoubleStackSlot(); |
+} |
+ |
+ |
+bool LoadCompare(const MoveOperands* a, const MoveOperands* b) { |
+ if (a->source() != b->source()) return a->source() < b->source(); |
+ if (IsSlot(a->destination()) && !IsSlot(b->destination())) return false; |
+ if (!IsSlot(a->destination()) && IsSlot(b->destination())) return true; |
+ return a->destination() < b->destination(); |
+} |
+ |
+} // namespace |
+ |
+ |
// 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(Instruction* instr) { |
auto loads = temp_vector_0(); |
DCHECK(loads.empty()); |
- auto new_moves = temp_vector_1(); |
- DCHECK(new_moves.empty()); |
- auto move_ops = instr->parallel_moves()[0]->move_operands(); |
- for (auto move = move_ops->begin(); move != move_ops->end(); ++move) { |
- if (move->IsRedundant()) { |
- move->Eliminate(); |
- continue; |
- } |
- if (!(move->source()->IsConstant() || move->source()->IsStackSlot() || |
- move->source()->IsDoubleStackSlot())) |
- continue; |
- // Search for existing move to this slot. |
- MoveOperands* found = nullptr; |
- for (auto load : loads) { |
- if (load->source()->Equals(move->source())) { |
- found = load; |
- break; |
- } |
- } |
- // Not found so insert. |
- if (found == nullptr) { |
+ // Find all the loads. |
+ for (auto move : *instr->parallel_moves()[0]) { |
+ if (move->IsRedundant()) continue; |
+ if (move->source().IsConstant() || IsSlot(move->source())) { |
loads.push_back(move); |
- // Replace source with copy for later use. |
- auto dest = move->destination(); |
- move->set_destination(InstructionOperand::New(code_zone(), *dest)); |
- continue; |
} |
- if ((found->destination()->IsStackSlot() || |
- found->destination()->IsDoubleStackSlot()) && |
- !(move->destination()->IsStackSlot() || |
- move->destination()->IsDoubleStackSlot())) { |
- // Found a better source for this load. Smash it in place to affect other |
- // loads that have already been split. |
- auto next_dest = |
- InstructionOperand::New(code_zone(), *found->destination()); |
- auto dest = move->destination(); |
- InstructionOperand::ReplaceWith(found->destination(), dest); |
- move->set_destination(next_dest); |
+ } |
+ if (loads.empty()) return; |
+ // Group the loads by source, moving the preferred destination to the |
+ // beginning of the group. |
+ std::sort(loads.begin(), loads.end(), LoadCompare); |
+ MoveOperands* group_begin = nullptr; |
+ for (auto load : loads) { |
+ // New group. |
+ if (group_begin == nullptr || load->source() != group_begin->source()) { |
+ group_begin = load; |
+ continue; |
} |
- // move from load destination. |
- move->set_source(found->destination()); |
- new_moves.push_back(move); |
+ // Nothing to be gained from splitting here. |
+ if (IsSlot(group_begin->destination())) continue; |
+ // Insert new move into slot 1. |
+ auto slot_1 = instr->GetOrCreateParallelMove( |
+ static_cast<Instruction::GapPosition>(1), code_zone()); |
+ slot_1->AddMove(group_begin->destination(), load->destination()); |
+ load->Eliminate(); |
} |
loads.clear(); |
- if (new_moves.empty()) return; |
- // Insert all new moves into slot 1. |
- auto slot_1 = instr->GetOrCreateParallelMove( |
- static_cast<Instruction::GapPosition>(1), code_zone()); |
- DCHECK(slot_1->move_operands()->is_empty()); |
- slot_1->move_operands()->AddBlock(MoveOperands(nullptr, nullptr), |
- static_cast<int>(new_moves.size()), |
- code_zone()); |
- auto it = slot_1->move_operands()->begin(); |
- for (auto new_move : new_moves) { |
- std::swap(*new_move, *it); |
- ++it; |
- } |
- DCHECK_EQ(it, slot_1->move_operands()->end()); |
- new_moves.clear(); |
} |
} // namespace compiler |