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 |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
204 return code()->instructions()[block->last_instruction_index()]; | 204 return code()->instructions()[block->last_instruction_index()]; |
205 } | 205 } |
206 | 206 |
207 | 207 |
208 void MoveOptimizer::OptimizeMerge(InstructionBlock* block) { | 208 void MoveOptimizer::OptimizeMerge(InstructionBlock* block) { |
209 DCHECK(block->PredecessorCount() > 1); | 209 DCHECK(block->PredecessorCount() > 1); |
210 // Ensure that the last instruction in all incoming blocks don't contain | 210 // Ensure that the last instruction in all incoming blocks don't contain |
211 // things that would prevent moving gap moves across them. | 211 // things that would prevent moving gap moves across them. |
212 for (RpoNumber& pred_index : block->predecessors()) { | 212 for (RpoNumber& pred_index : block->predecessors()) { |
213 const InstructionBlock* pred = code()->InstructionBlockAt(pred_index); | 213 const InstructionBlock* pred = code()->InstructionBlockAt(pred_index); |
| 214 |
| 215 // If the predecessor has more than one successor, we shouldn't attempt to |
| 216 // move down to this block (one of the successors) any of the gap moves, |
| 217 // because their effect may be necessary to the other successors. |
| 218 if (pred->SuccessorCount() > 1) return; |
| 219 |
214 const Instruction* last_instr = | 220 const Instruction* last_instr = |
215 code()->instructions()[pred->last_instruction_index()]; | 221 code()->instructions()[pred->last_instruction_index()]; |
216 if (last_instr->IsCall()) return; | 222 if (last_instr->IsCall()) return; |
217 if (last_instr->TempCount() != 0) return; | 223 if (last_instr->TempCount() != 0) return; |
218 if (last_instr->OutputCount() != 0) return; | 224 if (last_instr->OutputCount() != 0) return; |
219 for (size_t i = 0; i < last_instr->InputCount(); ++i) { | 225 for (size_t i = 0; i < last_instr->InputCount(); ++i) { |
220 const InstructionOperand* op = last_instr->InputAt(i); | 226 const InstructionOperand* op = last_instr->InputAt(i); |
221 if (!op->IsConstant() && !op->IsImmediate()) return; | 227 if (!op->IsConstant() && !op->IsImmediate()) return; |
222 } | 228 } |
223 } | 229 } |
(...skipping 15 matching lines...) Expand all Loading... |
239 MoveKey key = {src, dst}; | 245 MoveKey key = {src, dst}; |
240 auto res = move_map.insert(std::make_pair(key, 1)); | 246 auto res = move_map.insert(std::make_pair(key, 1)); |
241 if (!res.second) { | 247 if (!res.second) { |
242 res.first->second++; | 248 res.first->second++; |
243 if (res.first->second == block->PredecessorCount()) { | 249 if (res.first->second == block->PredecessorCount()) { |
244 correct_counts++; | 250 correct_counts++; |
245 } | 251 } |
246 } | 252 } |
247 } | 253 } |
248 } | 254 } |
249 if (move_map.empty() || correct_counts != move_map.size()) return; | 255 if (move_map.empty() || correct_counts == 0) return; |
| 256 |
250 // Find insertion point. | 257 // Find insertion point. |
251 Instruction* instr = nullptr; | 258 Instruction* instr = nullptr; |
252 for (int i = block->first_instruction_index(); | 259 for (int i = block->first_instruction_index(); |
253 i <= block->last_instruction_index(); ++i) { | 260 i <= block->last_instruction_index(); ++i) { |
254 instr = code()->instructions()[i]; | 261 instr = code()->instructions()[i]; |
255 if (!GapsCanMoveOver(instr, local_zone()) || !instr->AreMovesRedundant()) | 262 if (correct_counts != move_map.size() || |
| 263 !GapsCanMoveOver(instr, local_zone()) || !instr->AreMovesRedundant()) |
256 break; | 264 break; |
257 } | 265 } |
258 DCHECK_NOT_NULL(instr); | 266 DCHECK_NOT_NULL(instr); |
| 267 |
| 268 if (correct_counts != move_map.size()) { |
| 269 // Moves that are unique to each predecessor won't be pushed to the common |
| 270 // successor. |
| 271 OperandSet conflicting_srcs(local_zone()); |
| 272 for (auto iter = move_map.begin(), end = move_map.end(); iter != end;) { |
| 273 auto current = iter; |
| 274 ++iter; |
| 275 if (current->second != block->PredecessorCount()) { |
| 276 InstructionOperand dest = current->first.second; |
| 277 // Not all the moves in all the gaps are the same. Maybe some are. If |
| 278 // there are such moves, we could move them, but the destination of the |
| 279 // moves staying behind can't appear as a source of a common move, |
| 280 // because the move staying behind will clobber this destination. |
| 281 conflicting_srcs.insert(dest); |
| 282 move_map.erase(current); |
| 283 } |
| 284 } |
| 285 |
| 286 bool changed = false; |
| 287 do { |
| 288 // If a common move can't be pushed to the common successor, then its |
| 289 // destination also can't appear as source to any move being pushed. |
| 290 changed = false; |
| 291 for (auto iter = move_map.begin(), end = move_map.end(); iter != end;) { |
| 292 auto current = iter; |
| 293 ++iter; |
| 294 DCHECK_EQ(block->PredecessorCount(), current->second); |
| 295 if (conflicting_srcs.find(current->first.first) != |
| 296 conflicting_srcs.end()) { |
| 297 conflicting_srcs.insert(current->first.second); |
| 298 move_map.erase(current); |
| 299 changed = true; |
| 300 } |
| 301 } |
| 302 } while (changed); |
| 303 } |
| 304 |
| 305 if (move_map.empty()) return; |
| 306 |
| 307 DCHECK_NOT_NULL(instr); |
259 bool gap_initialized = true; | 308 bool gap_initialized = true; |
260 if (instr->parallel_moves()[0] == nullptr || | 309 if (instr->parallel_moves()[0] == nullptr || |
261 instr->parallel_moves()[0]->empty()) { | 310 instr->parallel_moves()[0]->empty()) { |
262 to_finalize_.push_back(instr); | 311 to_finalize_.push_back(instr); |
263 } else { | 312 } else { |
264 // Will compress after insertion. | 313 // Will compress after insertion. |
265 gap_initialized = false; | 314 gap_initialized = false; |
266 std::swap(instr->parallel_moves()[0], instr->parallel_moves()[1]); | 315 std::swap(instr->parallel_moves()[0], instr->parallel_moves()[1]); |
267 } | 316 } |
268 ParallelMove* moves = instr->GetOrCreateParallelMove( | 317 ParallelMove* moves = instr->GetOrCreateParallelMove( |
269 static_cast<Instruction::GapPosition>(0), code_zone()); | 318 static_cast<Instruction::GapPosition>(0), code_zone()); |
270 // Delete relevant entries in predecessors and move everything to block. | 319 // Delete relevant entries in predecessors and move everything to block. |
271 bool first_iteration = true; | 320 bool first_iteration = true; |
272 for (RpoNumber& pred_index : block->predecessors()) { | 321 for (RpoNumber& pred_index : block->predecessors()) { |
273 const InstructionBlock* pred = code()->InstructionBlockAt(pred_index); | 322 const InstructionBlock* pred = code()->InstructionBlockAt(pred_index); |
274 for (MoveOperands* move : *LastInstruction(pred)->parallel_moves()[0]) { | 323 for (MoveOperands* move : *LastInstruction(pred)->parallel_moves()[0]) { |
275 if (move->IsRedundant()) continue; | 324 if (move->IsRedundant()) continue; |
276 MoveKey key = {move->source(), move->destination()}; | 325 MoveKey key = {move->source(), move->destination()}; |
277 auto it = move_map.find(key); | 326 auto it = move_map.find(key); |
278 USE(it); | 327 if (it != move_map.end()) { |
279 DCHECK(it != move_map.end()); | 328 if (first_iteration) { |
280 if (first_iteration) { | 329 moves->AddMove(move->source(), move->destination()); |
281 moves->AddMove(move->source(), move->destination()); | 330 } |
| 331 move->Eliminate(); |
282 } | 332 } |
283 move->Eliminate(); | |
284 } | 333 } |
285 first_iteration = false; | 334 first_iteration = false; |
286 } | 335 } |
287 // Compress. | 336 // Compress. |
288 if (!gap_initialized) { | 337 if (!gap_initialized) { |
289 CompressMoves(instr->parallel_moves()[0], instr->parallel_moves()[1]); | 338 CompressMoves(instr->parallel_moves()[0], instr->parallel_moves()[1]); |
290 } | 339 } |
291 } | 340 } |
292 | 341 |
293 | 342 |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
342 static_cast<Instruction::GapPosition>(1), code_zone()); | 391 static_cast<Instruction::GapPosition>(1), code_zone()); |
343 slot_1->AddMove(group_begin->destination(), load->destination()); | 392 slot_1->AddMove(group_begin->destination(), load->destination()); |
344 load->Eliminate(); | 393 load->Eliminate(); |
345 } | 394 } |
346 loads.clear(); | 395 loads.clear(); |
347 } | 396 } |
348 | 397 |
349 } // namespace compiler | 398 } // namespace compiler |
350 } // namespace internal | 399 } // namespace internal |
351 } // namespace v8 | 400 } // namespace v8 |
OLD | NEW |