OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/compiler/move-optimizer.h" | 5 #include "src/compiler/move-optimizer.h" |
6 | 6 |
7 namespace v8 { | 7 namespace v8 { |
8 namespace internal { | 8 namespace internal { |
9 namespace compiler { | 9 namespace compiler { |
10 | 10 |
11 namespace { | 11 namespace { |
12 | 12 |
13 typedef std::pair<InstructionOperand, InstructionOperand> MoveKey; | 13 typedef std::pair<InstructionOperand, InstructionOperand> MoveKey; |
14 | 14 |
15 struct MoveKeyCompare { | 15 struct MoveKeyCompare { |
16 bool operator()(const MoveKey& a, const MoveKey& b) const { | 16 bool operator()(const MoveKey& a, const MoveKey& b) const { |
17 if (a.first.EqualsCanonicalized(b.first)) { | 17 if (a.first.EqualsCanonicalized(b.first)) { |
18 return a.second.CompareCanonicalized(b.second); | 18 return a.second.CompareCanonicalized(b.second); |
19 } | 19 } |
20 return a.first.CompareCanonicalized(b.first); | 20 return a.first.CompareCanonicalized(b.first); |
21 } | 21 } |
22 }; | 22 }; |
23 | 23 |
| 24 struct OperandCompare { |
| 25 bool operator()(const InstructionOperand& a, |
| 26 const InstructionOperand& b) const { |
| 27 return a.CompareCanonicalized(b); |
| 28 } |
| 29 }; |
| 30 |
24 typedef ZoneMap<MoveKey, unsigned, MoveKeyCompare> MoveMap; | 31 typedef ZoneMap<MoveKey, unsigned, MoveKeyCompare> MoveMap; |
25 typedef ZoneSet<InstructionOperand, CompareOperandModuloType> OperandSet; | 32 typedef ZoneSet<InstructionOperand, CompareOperandModuloType> OperandSet; |
26 | 33 |
27 | 34 |
28 bool GapsCanMoveOver(Instruction* instr) { return instr->IsNop(); } | 35 bool GapsCanMoveOver(Instruction* instr, Zone* zone) { |
| 36 if (instr->IsNop()) return true; |
| 37 if (instr->ClobbersTemps() || instr->ClobbersRegisters() || |
| 38 instr->ClobbersDoubleRegisters()) { |
| 39 return false; |
| 40 } |
| 41 if (instr->arch_opcode() != ArchOpcode::kArchNop) return false; |
| 42 |
| 43 ZoneSet<InstructionOperand, OperandCompare> operands(zone); |
| 44 for (size_t i = 0; i < instr->InputCount(); ++i) { |
| 45 operands.insert(*instr->InputAt(i)); |
| 46 } |
| 47 for (size_t i = 0; i < instr->OutputCount(); ++i) { |
| 48 operands.insert(*instr->OutputAt(i)); |
| 49 } |
| 50 for (size_t i = 0; i < instr->TempCount(); ++i) { |
| 51 operands.insert(*instr->TempAt(i)); |
| 52 } |
| 53 for (int i = Instruction::GapPosition::FIRST_GAP_POSITION; |
| 54 i <= Instruction::GapPosition::LAST_GAP_POSITION; ++i) { |
| 55 ParallelMove* moves = instr->parallel_moves()[i]; |
| 56 if (moves == nullptr) continue; |
| 57 for (MoveOperands* move : *moves) { |
| 58 if (operands.count(move->source()) > 0 || |
| 59 operands.count(move->destination()) > 0) { |
| 60 return false; |
| 61 } |
| 62 } |
| 63 } |
| 64 return true; |
| 65 } |
29 | 66 |
30 | 67 |
31 int FindFirstNonEmptySlot(Instruction* instr) { | 68 int FindFirstNonEmptySlot(Instruction* instr) { |
32 int i = Instruction::FIRST_GAP_POSITION; | 69 int i = Instruction::FIRST_GAP_POSITION; |
33 for (; i <= Instruction::LAST_GAP_POSITION; i++) { | 70 for (; i <= Instruction::LAST_GAP_POSITION; i++) { |
34 auto moves = instr->parallel_moves()[i]; | 71 auto moves = instr->parallel_moves()[i]; |
35 if (moves == nullptr) continue; | 72 if (moves == nullptr) continue; |
36 for (auto move : *moves) { | 73 for (auto move : *moves) { |
37 if (!move->IsRedundant()) return i; | 74 if (!move->IsRedundant()) return i; |
38 move->Eliminate(); | 75 move->Eliminate(); |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
128 // Smash left into prev_instr, killing left. | 165 // Smash left into prev_instr, killing left. |
129 auto pred_moves = prev_instr->parallel_moves()[0]; | 166 auto pred_moves = prev_instr->parallel_moves()[0]; |
130 CompressMoves(&temp_vector, pred_moves, left); | 167 CompressMoves(&temp_vector, pred_moves, left); |
131 } | 168 } |
132 } | 169 } |
133 if (prev_instr != nullptr) { | 170 if (prev_instr != nullptr) { |
134 // Slide prev_instr down so we always know where to look for it. | 171 // Slide prev_instr down so we always know where to look for it. |
135 std::swap(prev_instr->parallel_moves()[0], instr->parallel_moves()[0]); | 172 std::swap(prev_instr->parallel_moves()[0], instr->parallel_moves()[0]); |
136 } | 173 } |
137 prev_instr = instr->parallel_moves()[0] == nullptr ? nullptr : instr; | 174 prev_instr = instr->parallel_moves()[0] == nullptr ? nullptr : instr; |
138 if (GapsCanMoveOver(instr)) continue; | 175 if (GapsCanMoveOver(instr, local_zone())) continue; |
139 if (prev_instr != nullptr) { | 176 if (prev_instr != nullptr) { |
140 to_finalize_.push_back(prev_instr); | 177 to_finalize_.push_back(prev_instr); |
141 prev_instr = nullptr; | 178 prev_instr = nullptr; |
142 } | 179 } |
143 } | 180 } |
144 if (prev_instr != nullptr) { | 181 if (prev_instr != nullptr) { |
145 to_finalize_.push_back(prev_instr); | 182 to_finalize_.push_back(prev_instr); |
146 } | 183 } |
147 } | 184 } |
148 | 185 |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
191 } | 228 } |
192 } | 229 } |
193 } | 230 } |
194 } | 231 } |
195 if (move_map.empty() || correct_counts != move_map.size()) return; | 232 if (move_map.empty() || correct_counts != move_map.size()) return; |
196 // Find insertion point. | 233 // Find insertion point. |
197 Instruction* instr = nullptr; | 234 Instruction* instr = nullptr; |
198 for (int i = block->first_instruction_index(); | 235 for (int i = block->first_instruction_index(); |
199 i <= block->last_instruction_index(); ++i) { | 236 i <= block->last_instruction_index(); ++i) { |
200 instr = code()->instructions()[i]; | 237 instr = code()->instructions()[i]; |
201 if (!GapsCanMoveOver(instr) || !instr->AreMovesRedundant()) break; | 238 if (!GapsCanMoveOver(instr, local_zone()) || !instr->AreMovesRedundant()) |
| 239 break; |
202 } | 240 } |
203 DCHECK(instr != nullptr); | 241 DCHECK(instr != nullptr); |
204 bool gap_initialized = true; | 242 bool gap_initialized = true; |
205 if (instr->parallel_moves()[0] == nullptr || | 243 if (instr->parallel_moves()[0] == nullptr || |
206 instr->parallel_moves()[0]->empty()) { | 244 instr->parallel_moves()[0]->empty()) { |
207 to_finalize_.push_back(instr); | 245 to_finalize_.push_back(instr); |
208 } else { | 246 } else { |
209 // Will compress after insertion. | 247 // Will compress after insertion. |
210 gap_initialized = false; | 248 gap_initialized = false; |
211 std::swap(instr->parallel_moves()[0], instr->parallel_moves()[1]); | 249 std::swap(instr->parallel_moves()[0], instr->parallel_moves()[1]); |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
287 static_cast<Instruction::GapPosition>(1), code_zone()); | 325 static_cast<Instruction::GapPosition>(1), code_zone()); |
288 slot_1->AddMove(group_begin->destination(), load->destination()); | 326 slot_1->AddMove(group_begin->destination(), load->destination()); |
289 load->Eliminate(); | 327 load->Eliminate(); |
290 } | 328 } |
291 loads.clear(); | 329 loads.clear(); |
292 } | 330 } |
293 | 331 |
294 } // namespace compiler | 332 } // namespace compiler |
295 } // namespace internal | 333 } // namespace internal |
296 } // namespace v8 | 334 } // namespace v8 |
OLD | NEW |