Index: src/compiler/move-optimizer.cc |
diff --git a/src/compiler/move-optimizer.cc b/src/compiler/move-optimizer.cc |
index 7ec98abd7c8df3208661c56ba5fd6c3b8bf0a2ac..e99b5e9ebe4024bb85ac2bf34b220d6e8fdab6fc 100644 |
--- a/src/compiler/move-optimizer.cc |
+++ b/src/compiler/move-optimizer.cc |
@@ -21,11 +21,48 @@ struct MoveKeyCompare { |
} |
}; |
+struct OperandCompare { |
+ bool operator()(const InstructionOperand& a, |
+ const InstructionOperand& b) const { |
+ return a.CompareCanonicalized(b); |
+ } |
+}; |
+ |
typedef ZoneMap<MoveKey, unsigned, MoveKeyCompare> MoveMap; |
typedef ZoneSet<InstructionOperand, CompareOperandModuloType> OperandSet; |
-bool GapsCanMoveOver(Instruction* instr) { return instr->IsNop(); } |
+bool GapsCanMoveOver(Instruction* instr, Zone* zone) { |
+ if (instr->IsNop()) return true; |
+ if (instr->ClobbersTemps() || instr->ClobbersRegisters() || |
+ instr->ClobbersDoubleRegisters()) { |
+ return false; |
+ } |
+ if (instr->arch_opcode() != ArchOpcode::kArchNop) return false; |
+ |
+ ZoneSet<InstructionOperand, OperandCompare> operands(zone); |
+ for (size_t i = 0; i < instr->InputCount(); ++i) { |
+ operands.insert(*instr->InputAt(i)); |
+ } |
+ for (size_t i = 0; i < instr->OutputCount(); ++i) { |
+ operands.insert(*instr->OutputAt(i)); |
+ } |
+ for (size_t i = 0; i < instr->TempCount(); ++i) { |
+ operands.insert(*instr->TempAt(i)); |
+ } |
+ for (int i = Instruction::GapPosition::FIRST_GAP_POSITION; |
+ i <= Instruction::GapPosition::LAST_GAP_POSITION; ++i) { |
+ ParallelMove* moves = instr->parallel_moves()[i]; |
+ if (moves == nullptr) continue; |
+ for (MoveOperands* move : *moves) { |
+ if (operands.count(move->source()) > 0 || |
+ operands.count(move->destination()) > 0) { |
+ return false; |
+ } |
+ } |
+ } |
+ return true; |
+} |
int FindFirstNonEmptySlot(Instruction* instr) { |
@@ -135,7 +172,7 @@ void MoveOptimizer::CompressBlock(InstructionBlock* block) { |
std::swap(prev_instr->parallel_moves()[0], instr->parallel_moves()[0]); |
} |
prev_instr = instr->parallel_moves()[0] == nullptr ? nullptr : instr; |
- if (GapsCanMoveOver(instr)) continue; |
+ if (GapsCanMoveOver(instr, local_zone())) continue; |
if (prev_instr != nullptr) { |
to_finalize_.push_back(prev_instr); |
prev_instr = nullptr; |
@@ -198,7 +235,8 @@ void MoveOptimizer::OptimizeMerge(InstructionBlock* block) { |
for (int i = block->first_instruction_index(); |
i <= block->last_instruction_index(); ++i) { |
instr = code()->instructions()[i]; |
- if (!GapsCanMoveOver(instr) || !instr->AreMovesRedundant()) break; |
+ if (!GapsCanMoveOver(instr, local_zone()) || !instr->AreMovesRedundant()) |
+ break; |
} |
DCHECK(instr != nullptr); |
bool gap_initialized = true; |