Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(551)

Side by Side Diff: src/compiler/move-optimizer.cc

Issue 1527203002: [turbofan] fine grained move operand merge optimization (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | test/unittests/compiler/move-optimizer-unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | test/unittests/compiler/move-optimizer-unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698