| 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 |