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

Side by Side Diff: src/hydrogen.cc

Issue 9141016: Improve GVN handling of ElementTransitions. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Remove debugging code Created 8 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | src/hydrogen-instructions.h » ('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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 1359 matching lines...) Expand 10 before | Expand all | Expand 10 after
1370 1370
1371 private: 1371 private:
1372 GVNFlagSet CollectSideEffectsOnPathsToDominatedBlock( 1372 GVNFlagSet CollectSideEffectsOnPathsToDominatedBlock(
1373 HBasicBlock* dominator, 1373 HBasicBlock* dominator,
1374 HBasicBlock* dominated); 1374 HBasicBlock* dominated);
1375 void AnalyzeBlock(HBasicBlock* block, HValueMap* map); 1375 void AnalyzeBlock(HBasicBlock* block, HValueMap* map);
1376 void ComputeBlockSideEffects(); 1376 void ComputeBlockSideEffects();
1377 void LoopInvariantCodeMotion(); 1377 void LoopInvariantCodeMotion();
1378 void ProcessLoopBlock(HBasicBlock* block, 1378 void ProcessLoopBlock(HBasicBlock* block,
1379 HBasicBlock* before_loop, 1379 HBasicBlock* before_loop,
1380 GVNFlagSet loop_kills); 1380 GVNFlagSet loop_kills,
1381 GVNFlagSet* preceeding_loop_depends);
1381 bool AllowCodeMotion(); 1382 bool AllowCodeMotion();
1382 bool ShouldMove(HInstruction* instr, HBasicBlock* loop_header); 1383 bool ShouldMove(HInstruction* instr, HBasicBlock* loop_header);
1383 1384
1384 HGraph* graph() { return graph_; } 1385 HGraph* graph() { return graph_; }
1385 CompilationInfo* info() { return info_; } 1386 CompilationInfo* info() { return info_; }
1386 Zone* zone() { return graph_->zone(); } 1387 Zone* zone() { return graph_->zone(); }
1387 1388
1388 HGraph* graph_; 1389 HGraph* graph_;
1389 CompilationInfo* info_; 1390 CompilationInfo* info_;
1390 bool removed_side_effects_; 1391 bool removed_side_effects_;
1391 1392
1392 // A map of block IDs to their side effects. 1393 // A map of block IDs to their side effects.
1393 ZoneList<GVNFlagSet> block_side_effects_; 1394 ZoneList<GVNFlagSet> block_side_effects_;
1394 1395
1395 // A map of loop header block IDs to their loop's side effects. 1396 // A map of loop header block IDs to their loop's side effects.
1396 ZoneList<GVNFlagSet> loop_side_effects_; 1397 ZoneList<GVNFlagSet> loop_side_effects_;
1397 1398
1398 // Used when collecting side effects on paths from dominator to 1399 // Used when collecting side effects on paths from dominator to
1399 // dominated. 1400 // dominated.
1400 SparseSet visited_on_paths_; 1401 SparseSet visited_on_paths_;
1401 }; 1402 };
1402 1403
1403 1404
1404 bool HGlobalValueNumberer::Analyze() { 1405 bool HGlobalValueNumberer::Analyze() {
1406 removed_side_effects_ = false;
1405 ComputeBlockSideEffects(); 1407 ComputeBlockSideEffects();
1406 if (FLAG_loop_invariant_code_motion) { 1408 if (FLAG_loop_invariant_code_motion) {
1407 LoopInvariantCodeMotion(); 1409 LoopInvariantCodeMotion();
1408 } 1410 }
1409 HValueMap* map = new(zone()) HValueMap(); 1411 HValueMap* map = new(zone()) HValueMap();
1410 AnalyzeBlock(graph_->entry_block(), map); 1412 AnalyzeBlock(graph_->entry_block(), map);
1411 return removed_side_effects_; 1413 return removed_side_effects_;
1412 } 1414 }
1413 1415
1414 1416
1415 void HGlobalValueNumberer::ComputeBlockSideEffects() { 1417 void HGlobalValueNumberer::ComputeBlockSideEffects() {
1418 for (int i = 0; i < loop_side_effects_.length(); ++i) {
1419 loop_side_effects_[i].RemoveAll();
1420 }
1416 for (int i = graph_->blocks()->length() - 1; i >= 0; --i) { 1421 for (int i = graph_->blocks()->length() - 1; i >= 0; --i) {
1417 // Compute side effects for the block. 1422 // Compute side effects for the block.
1418 HBasicBlock* block = graph_->blocks()->at(i); 1423 HBasicBlock* block = graph_->blocks()->at(i);
1419 HInstruction* instr = block->first(); 1424 HInstruction* instr = block->first();
1420 int id = block->block_id(); 1425 int id = block->block_id();
1421 GVNFlagSet side_effects; 1426 GVNFlagSet side_effects;
1422 while (instr != NULL) { 1427 while (instr != NULL) {
1423 side_effects.Add(instr->ChangesFlags()); 1428 side_effects.Add(instr->ChangesFlags());
1424 instr = instr->next(); 1429 instr = instr->next();
1425 } 1430 }
(...skipping 17 matching lines...) Expand all
1443 1448
1444 void HGlobalValueNumberer::LoopInvariantCodeMotion() { 1449 void HGlobalValueNumberer::LoopInvariantCodeMotion() {
1445 for (int i = graph_->blocks()->length() - 1; i >= 0; --i) { 1450 for (int i = graph_->blocks()->length() - 1; i >= 0; --i) {
1446 HBasicBlock* block = graph_->blocks()->at(i); 1451 HBasicBlock* block = graph_->blocks()->at(i);
1447 if (block->IsLoopHeader()) { 1452 if (block->IsLoopHeader()) {
1448 GVNFlagSet side_effects = loop_side_effects_[block->block_id()]; 1453 GVNFlagSet side_effects = loop_side_effects_[block->block_id()];
1449 TraceGVN("Try loop invariant motion for block B%d effects=0x%x\n", 1454 TraceGVN("Try loop invariant motion for block B%d effects=0x%x\n",
1450 block->block_id(), 1455 block->block_id(),
1451 side_effects.ToIntegral()); 1456 side_effects.ToIntegral());
1452 1457
1458 GVNFlagSet preceeding_loop_depends;
1453 HBasicBlock* last = block->loop_information()->GetLastBackEdge(); 1459 HBasicBlock* last = block->loop_information()->GetLastBackEdge();
1454 for (int j = block->block_id(); j <= last->block_id(); ++j) { 1460 for (int j = block->block_id(); j <= last->block_id(); ++j) {
1455 ProcessLoopBlock(graph_->blocks()->at(j), block, side_effects); 1461 ProcessLoopBlock(graph_->blocks()->at(j), block, side_effects,
1462 &preceeding_loop_depends);
1456 } 1463 }
1457 } 1464 }
1458 } 1465 }
1459 } 1466 }
1460 1467
1461 1468
1462 void HGlobalValueNumberer::ProcessLoopBlock(HBasicBlock* block, 1469 void HGlobalValueNumberer::ProcessLoopBlock(HBasicBlock* block,
1463 HBasicBlock* loop_header, 1470 HBasicBlock* loop_header,
1464 GVNFlagSet loop_kills) { 1471 GVNFlagSet loop_kills,
1472 GVNFlagSet* preceeding_loop_depends) {
1465 HBasicBlock* pre_header = loop_header->predecessors()->at(0); 1473 HBasicBlock* pre_header = loop_header->predecessors()->at(0);
1466 GVNFlagSet depends_flags = HValue::ConvertChangesToDependsFlags(loop_kills); 1474 GVNFlagSet depends_flags = HValue::ConvertChangesToDependsFlags(loop_kills);
1467 TraceGVN("Loop invariant motion for B%d depends_flags=0x%x\n", 1475 TraceGVN("Loop invariant motion for B%d depends_flags=0x%x\n",
1468 block->block_id(), 1476 block->block_id(),
1469 depends_flags.ToIntegral()); 1477 depends_flags.ToIntegral());
1470 HInstruction* instr = block->first(); 1478 HInstruction* instr = block->first();
1471 while (instr != NULL) { 1479 while (instr != NULL) {
1472 HInstruction* next = instr->next(); 1480 HInstruction* next = instr->next();
1473 if (instr->CheckFlag(HValue::kUseGVN) && 1481 bool hoisted = false;
1474 !instr->gvn_flags().ContainsAnyOf(depends_flags)) { 1482 if (instr->CheckFlag(HValue::kUseGVN)) {
1475 TraceGVN("Checking instruction %d (%s)\n", 1483 TraceGVN("Checking instruction %d (%s) instr 0x%X, block 0x%X\n",
1476 instr->id(), 1484 instr->id(),
1477 instr->Mnemonic()); 1485 instr->Mnemonic(),
1478 bool inputs_loop_invariant = true; 1486 instr->gvn_flags().ToIntegral(),
1479 for (int i = 0; i < instr->OperandCount(); ++i) { 1487 depends_flags.ToIntegral() );
1480 if (instr->OperandAt(i)->IsDefinedAfter(pre_header)) { 1488 bool can_hoist = !instr->gvn_flags().ContainsAnyOf(depends_flags);
1481 inputs_loop_invariant = false; 1489 if (!can_hoist &&
1490 !instr->HasObservableSideEffects() &&
1491 instr->HasOneTimeSideEffects()) {
1492 // It's only possible to hoist one time side effects if there are no
1493 // dependencies on their changes from the loop header to the current
1494 // instruction.
fschneider 2012/01/25 00:04:57 In general a path from the header to the current i
danno 2012/01/31 15:38:26 I'm not sure that's true. We're careful to order t
1495 can_hoist =
fschneider 2012/01/25 00:04:57 Please add a unit test that covers the two cases t
danno 2012/01/31 15:38:26 Done.
1496 !preceeding_loop_depends->ContainsAnyOf(
1497 HValue::ConvertChangesToDependsFlags(instr->ChangesFlags()));
1498 }
1499
1500 if (can_hoist) {
1501 bool inputs_loop_invariant = true;
1502 for (int i = 0; i < instr->OperandCount(); ++i) {
1503 if (instr->OperandAt(i)->IsDefinedAfter(pre_header)) {
1504 inputs_loop_invariant = false;
1505 }
1506 }
1507
1508 if (inputs_loop_invariant && ShouldMove(instr, loop_header)) {
1509 TraceGVN("Found loop invariant instruction %d\n", instr->id());
1510 // Move the instruction out of the loop.
1511 instr->Unlink();
1512 instr->InsertBefore(pre_header->end());
1513 if (instr->HasSideEffects()) removed_side_effects_ = true;
1514 hoisted = true;
1482 } 1515 }
1483 } 1516 }
1484 1517 }
1485 if (inputs_loop_invariant && ShouldMove(instr, loop_header)) { 1518 if (!hoisted) {
1486 TraceGVN("Found loop invariant instruction %d\n", instr->id()); 1519 // Hoisting an instruction to the preheader causes its DependsOn flags to
1487 // Move the instruction out of the loop. 1520 // not prevent hosting OneTimeSideEffecct instructions.
1488 instr->Unlink(); 1521 preceeding_loop_depends->Add(instr->DependsOnFlags());
1489 instr->InsertBefore(pre_header->end());
1490 }
1491 } 1522 }
1492 instr = next; 1523 instr = next;
1493 } 1524 }
1494 } 1525 }
1495 1526
1496 1527
1497 bool HGlobalValueNumberer::AllowCodeMotion() { 1528 bool HGlobalValueNumberer::AllowCodeMotion() {
1498 return info()->shared_info()->opt_count() + 1 < Compiler::kDefaultMaxOptCount; 1529 return info()->shared_info()->opt_count() + 1 < Compiler::kDefaultMaxOptCount;
1499 } 1530 }
1500 1531
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1542 while (instr != NULL) { 1573 while (instr != NULL) {
1543 HInstruction* next = instr->next(); 1574 HInstruction* next = instr->next();
1544 GVNFlagSet flags = instr->ChangesFlags(); 1575 GVNFlagSet flags = instr->ChangesFlags();
1545 if (!flags.IsEmpty()) { 1576 if (!flags.IsEmpty()) {
1546 // Clear all instructions in the map that are affected by side effects. 1577 // Clear all instructions in the map that are affected by side effects.
1547 map->Kill(flags); 1578 map->Kill(flags);
1548 TraceGVN("Instruction %d kills\n", instr->id()); 1579 TraceGVN("Instruction %d kills\n", instr->id());
1549 } 1580 }
1550 if (instr->CheckFlag(HValue::kUseGVN)) { 1581 if (instr->CheckFlag(HValue::kUseGVN)) {
1551 ASSERT(!instr->HasObservableSideEffects()); 1582 ASSERT(!instr->HasObservableSideEffects());
1583 ASSERT(!instr->HasSideEffects() || instr->HasOneTimeSideEffects());
1552 HValue* other = map->Lookup(instr); 1584 HValue* other = map->Lookup(instr);
1553 if (other != NULL) { 1585 if (other != NULL) {
1554 ASSERT(instr->Equals(other) && other->Equals(instr)); 1586 ASSERT(instr->Equals(other) && other->Equals(instr));
1555 TraceGVN("Replacing value %d (%s) with value %d (%s)\n", 1587 TraceGVN("Replacing value %d (%s) with value %d (%s)\n",
1556 instr->id(), 1588 instr->id(),
1557 instr->Mnemonic(), 1589 instr->Mnemonic(),
1558 other->id(), 1590 other->id(),
1559 other->Mnemonic()); 1591 other->Mnemonic());
1560 if (instr->HasSideEffects()) removed_side_effects_ = true; 1592 if (instr->HasSideEffects()) removed_side_effects_ = true;
1561 instr->DeleteAndReplaceWith(other); 1593 instr->DeleteAndReplaceWith(other);
(...skipping 823 matching lines...) Expand 10 before | Expand all | Expand 10 after
2385 graph()->Canonicalize(); 2417 graph()->Canonicalize();
2386 2418
2387 // Perform common subexpression elimination and loop-invariant code motion. 2419 // Perform common subexpression elimination and loop-invariant code motion.
2388 if (FLAG_use_gvn) { 2420 if (FLAG_use_gvn) {
2389 HPhase phase("Global value numbering", graph()); 2421 HPhase phase("Global value numbering", graph());
2390 HGlobalValueNumberer gvn(graph(), info()); 2422 HGlobalValueNumberer gvn(graph(), info());
2391 bool removed_side_effects = gvn.Analyze(); 2423 bool removed_side_effects = gvn.Analyze();
2392 // Trigger a second analysis pass to further eliminate duplicate values that 2424 // Trigger a second analysis pass to further eliminate duplicate values that
2393 // could only be discovered by removing side-effect-generating instructions 2425 // could only be discovered by removing side-effect-generating instructions
2394 // during the first pass. 2426 // during the first pass.
2395 if (FLAG_smi_only_arrays && removed_side_effects) { 2427 if (FLAG_smi_only_arrays) {
2396 gvn.Analyze(); 2428 if (removed_side_effects) {
2429 removed_side_effects = gvn.Analyze();
2430 }
2431 ASSERT(!removed_side_effects);
2397 } 2432 }
2398 } 2433 }
2399 2434
2400 if (FLAG_use_range) { 2435 if (FLAG_use_range) {
2401 HRangeAnalysis rangeAnalysis(graph()); 2436 HRangeAnalysis rangeAnalysis(graph());
2402 rangeAnalysis.Analyze(); 2437 rangeAnalysis.Analyze();
2403 } 2438 }
2404 graph()->ComputeMinusZeroChecks(); 2439 graph()->ComputeMinusZeroChecks();
2405 2440
2406 // Eliminate redundant stack checks on backwards branches. 2441 // Eliminate redundant stack checks on backwards branches.
(...skipping 5005 matching lines...) Expand 10 before | Expand all | Expand 10 after
7412 } 7447 }
7413 } 7448 }
7414 7449
7415 #ifdef DEBUG 7450 #ifdef DEBUG
7416 if (graph_ != NULL) graph_->Verify(false); // No full verify. 7451 if (graph_ != NULL) graph_->Verify(false); // No full verify.
7417 if (allocator_ != NULL) allocator_->Verify(); 7452 if (allocator_ != NULL) allocator_->Verify();
7418 #endif 7453 #endif
7419 } 7454 }
7420 7455
7421 } } // namespace v8::internal 7456 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | src/hydrogen-instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698