[turbofan] cleanup MoveOptimizer a little
BUG= Review URL: https://codereview.chromium.org/888813002 Cr-Commit-Position: refs/heads/master@{#26350}
This commit is contained in:
parent
75c1c0df50
commit
6149d5ec76
@ -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<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
|
||||
|
@ -19,18 +19,22 @@ class MoveOptimizer FINAL {
|
||||
|
||||
private:
|
||||
typedef ZoneVector<MoveOperands*> MoveOpVector;
|
||||
typedef ZoneVector<GapInstruction*> 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_;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user