Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 63 predecessors_(2), | 63 predecessors_(2), |
| 64 dominator_(NULL), | 64 dominator_(NULL), |
| 65 dominated_blocks_(4), | 65 dominated_blocks_(4), |
| 66 last_environment_(NULL), | 66 last_environment_(NULL), |
| 67 argument_count_(-1), | 67 argument_count_(-1), |
| 68 first_instruction_index_(-1), | 68 first_instruction_index_(-1), |
| 69 last_instruction_index_(-1), | 69 last_instruction_index_(-1), |
| 70 deleted_phis_(4), | 70 deleted_phis_(4), |
| 71 parent_loop_header_(NULL), | 71 parent_loop_header_(NULL), |
| 72 is_inline_return_target_(false), | 72 is_inline_return_target_(false), |
| 73 is_deoptimizing_(false) { } | 73 is_deoptimizing_(false), |
| 74 dominates_loop_successors_(false) { } | |
| 74 | 75 |
| 75 | 76 |
| 76 void HBasicBlock::AttachLoopInformation() { | 77 void HBasicBlock::AttachLoopInformation() { |
| 77 ASSERT(!IsLoopHeader()); | 78 ASSERT(!IsLoopHeader()); |
| 78 loop_information_ = new(zone()) HLoopInformation(this); | 79 loop_information_ = new(zone()) HLoopInformation(this); |
| 79 } | 80 } |
| 80 | 81 |
| 81 | 82 |
| 82 void HBasicBlock::DetachLoopInformation() { | 83 void HBasicBlock::DetachLoopInformation() { |
| 83 ASSERT(IsLoopHeader()); | 84 ASSERT(IsLoopHeader()); |
| (...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 308 if (dominator_ != first) { | 309 if (dominator_ != first) { |
| 309 ASSERT(dominator_->dominated_blocks_.Contains(this)); | 310 ASSERT(dominator_->dominated_blocks_.Contains(this)); |
| 310 dominator_->dominated_blocks_.RemoveElement(this); | 311 dominator_->dominated_blocks_.RemoveElement(this); |
| 311 dominator_ = first; | 312 dominator_ = first; |
| 312 first->AddDominatedBlock(this); | 313 first->AddDominatedBlock(this); |
| 313 } | 314 } |
| 314 } | 315 } |
| 315 } | 316 } |
| 316 | 317 |
| 317 | 318 |
| 319 void HBasicBlock::AssignLoopSuccessorDominators() { | |
| 320 // Mark blocks that dominate all subsequent reachable blocks inside their | |
| 321 // loop. Exploit the fact that blocks are sorted in reverse post order. When | |
| 322 // the loop is visited in increasing block id order, if the number of | |
| 323 // non-loop-exiting successor edges at the dominator_candidate block doesn't | |
| 324 // exceed the number of previously encountered predecessor edges, there is no | |
| 325 // path from the loop header to any block with higher id that doesn't go | |
| 326 // through the dominator_candidate block. In this case, the | |
| 327 // dominator_candidate block is guaranteed to dominate all blocks reachable | |
| 328 // from it with higher ids. | |
| 329 HBasicBlock* last = loop_information()->GetLastBackEdge(); | |
| 330 int outstanding_sucsessors = 1; // one edge from the pre-header | |
|
fschneider
2012/02/02 14:59:50
s/sucsessors/successors/g
danno
2012/02/06 16:54:57
Done.
| |
| 331 // Header always dominates everything. | |
| 332 MarkAsLoopSuccessorDominator(); | |
| 333 for (int j = block_id(); j <= last->block_id(); ++j) { | |
|
fschneider
2012/02/02 14:59:50
Maybe this be simplified: The header is always mar
danno
2012/02/06 16:54:57
You have to iterate over every block's successors,
| |
| 334 HBasicBlock* dominator_candidate = graph_->blocks()->at(j); | |
| 335 const ZoneList<HBasicBlock*>* predecessor_list = | |
| 336 dominator_candidate->predecessors(); | |
| 337 int predecessor_count = predecessor_list->length(); | |
| 338 for (int i = 0; i < predecessor_count; ++i) { | |
|
fschneider
2012/02/02 14:59:50
Maybe it would make sense to introduce a HPredeces
danno
2012/02/06 16:54:57
Done.
| |
| 339 HBasicBlock* predecessor = predecessor_list->at(i); | |
| 340 // Don't count back edges. | |
| 341 if (predecessor->block_id() < dominator_candidate->block_id()) { | |
| 342 outstanding_sucsessors--; | |
| 343 } | |
| 344 } | |
| 345 | |
| 346 // If more successors than predecessors have been seen in the loop up to | |
| 347 // now, it's not possible to guarantee that the current block dominates | |
| 348 // all of the blocks with higher IDs. In this case, assume conservatively | |
| 349 // that those paths through loop that don't go through the current block | |
| 350 // contain all of the loop's dependencies. Also be careful to record | |
| 351 // dominator information about the current loop that's being processed, | |
| 352 // and not nested loops, which will be processed when | |
| 353 // AssignLoopSuccessorDominators gets called on their header. | |
| 354 ASSERT(outstanding_sucsessors >= 0); | |
| 355 HBasicBlock* parent_loop_header = dominator_candidate->parent_loop_header(); | |
| 356 if (outstanding_sucsessors == 0 && | |
| 357 (parent_loop_header == this && !dominator_candidate->IsLoopHeader())) { | |
| 358 MarkAsLoopSuccessorDominator(); | |
|
fschneider
2012/02/02 14:59:50
I guess this should be:
candidate_dominator->Mark
danno
2012/02/06 16:54:57
Done.
| |
| 359 } | |
| 360 HControlInstruction* end_instr = dominator_candidate->end(); | |
| 361 int successor_count = end_instr->SuccessorCount(); | |
| 362 for (int current = 0; current < successor_count; ++current) { | |
|
fschneider
2012/02/02 14:59:50
You can use HSuccessorIterator here.
danno
2012/02/06 16:54:57
Done.
| |
| 363 HBasicBlock* successor = end_instr->SuccessorAt(current); | |
| 364 // Only count successors that remain inside the loop and don't loop back | |
| 365 // to a loop header. | |
| 366 if (successor->block_id() > dominator_candidate->block_id() && | |
| 367 successor->block_id() <= last->block_id()) { | |
| 368 // Backwards edges must land on loop headers. | |
| 369 ASSERT(successor->block_id() > dominator_candidate->block_id() || | |
| 370 successor->IsLoopHeader()); | |
| 371 outstanding_sucsessors++; | |
| 372 } | |
| 373 } | |
| 374 } | |
| 375 } | |
| 376 | |
| 377 | |
| 318 int HBasicBlock::PredecessorIndexOf(HBasicBlock* predecessor) const { | 378 int HBasicBlock::PredecessorIndexOf(HBasicBlock* predecessor) const { |
| 319 for (int i = 0; i < predecessors_.length(); ++i) { | 379 for (int i = 0; i < predecessors_.length(); ++i) { |
| 320 if (predecessors_[i] == predecessor) return i; | 380 if (predecessors_[i] == predecessor) return i; |
| 321 } | 381 } |
| 322 UNREACHABLE(); | 382 UNREACHABLE(); |
| 323 return -1; | 383 return -1; |
| 324 } | 384 } |
| 325 | 385 |
| 326 | 386 |
| 327 #ifdef DEBUG | 387 #ifdef DEBUG |
| (...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 747 ASSERT(block->end()->SecondSuccessor() == NULL || | 807 ASSERT(block->end()->SecondSuccessor() == NULL || |
| 748 order->Contains(block->end()->SecondSuccessor()) || | 808 order->Contains(block->end()->SecondSuccessor()) || |
| 749 block->end()->SecondSuccessor()->IsLoopHeader()); | 809 block->end()->SecondSuccessor()->IsLoopHeader()); |
| 750 order->Add(block); | 810 order->Add(block); |
| 751 } | 811 } |
| 752 | 812 |
| 753 | 813 |
| 754 void HGraph::AssignDominators() { | 814 void HGraph::AssignDominators() { |
| 755 HPhase phase("Assign dominators", this); | 815 HPhase phase("Assign dominators", this); |
| 756 for (int i = 0; i < blocks_.length(); ++i) { | 816 for (int i = 0; i < blocks_.length(); ++i) { |
| 757 if (blocks_[i]->IsLoopHeader()) { | 817 HBasicBlock* block = blocks_[i]; |
| 818 if (block->IsLoopHeader()) { | |
| 758 // Only the first predecessor of a loop header is from outside the loop. | 819 // Only the first predecessor of a loop header is from outside the loop. |
| 759 // All others are back edges, and thus cannot dominate the loop header. | 820 // All others are back edges, and thus cannot dominate the loop header. |
| 760 blocks_[i]->AssignCommonDominator(blocks_[i]->predecessors()->first()); | 821 block->AssignCommonDominator(block->predecessors()->first()); |
| 822 block->AssignLoopSuccessorDominators(); | |
| 761 } else { | 823 } else { |
| 762 for (int j = blocks_[i]->predecessors()->length() - 1; j >= 0; --j) { | 824 for (int j = blocks_[i]->predecessors()->length() - 1; j >= 0; --j) { |
| 763 blocks_[i]->AssignCommonDominator(blocks_[i]->predecessors()->at(j)); | 825 blocks_[i]->AssignCommonDominator(blocks_[i]->predecessors()->at(j)); |
| 764 } | 826 } |
| 765 } | 827 } |
| 766 } | 828 } |
| 767 } | 829 } |
| 768 | 830 |
| 769 // Mark all blocks that are dominated by an unconditional soft deoptimize to | 831 // Mark all blocks that are dominated by an unconditional soft deoptimize to |
| 770 // prevent code motion across those blocks. | 832 // prevent code motion across those blocks. |
| (...skipping 597 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1368 | 1430 |
| 1369 private: | 1431 private: |
| 1370 GVNFlagSet CollectSideEffectsOnPathsToDominatedBlock( | 1432 GVNFlagSet CollectSideEffectsOnPathsToDominatedBlock( |
| 1371 HBasicBlock* dominator, | 1433 HBasicBlock* dominator, |
| 1372 HBasicBlock* dominated); | 1434 HBasicBlock* dominated); |
| 1373 void AnalyzeBlock(HBasicBlock* block, HValueMap* map); | 1435 void AnalyzeBlock(HBasicBlock* block, HValueMap* map); |
| 1374 void ComputeBlockSideEffects(); | 1436 void ComputeBlockSideEffects(); |
| 1375 void LoopInvariantCodeMotion(); | 1437 void LoopInvariantCodeMotion(); |
| 1376 void ProcessLoopBlock(HBasicBlock* block, | 1438 void ProcessLoopBlock(HBasicBlock* block, |
| 1377 HBasicBlock* before_loop, | 1439 HBasicBlock* before_loop, |
| 1378 GVNFlagSet loop_kills); | 1440 GVNFlagSet loop_kills, |
| 1441 GVNFlagSet* accumulated_first_time_depends); | |
| 1379 bool AllowCodeMotion(); | 1442 bool AllowCodeMotion(); |
| 1380 bool ShouldMove(HInstruction* instr, HBasicBlock* loop_header); | 1443 bool ShouldMove(HInstruction* instr, HBasicBlock* loop_header); |
| 1381 | 1444 |
| 1382 HGraph* graph() { return graph_; } | 1445 HGraph* graph() { return graph_; } |
| 1383 CompilationInfo* info() { return info_; } | 1446 CompilationInfo* info() { return info_; } |
| 1384 Zone* zone() { return graph_->zone(); } | 1447 Zone* zone() { return graph_->zone(); } |
| 1385 | 1448 |
| 1386 HGraph* graph_; | 1449 HGraph* graph_; |
| 1387 CompilationInfo* info_; | 1450 CompilationInfo* info_; |
| 1388 bool removed_side_effects_; | 1451 bool removed_side_effects_; |
| 1389 | 1452 |
| 1390 // A map of block IDs to their side effects. | 1453 // A map of block IDs to their side effects. |
| 1391 ZoneList<GVNFlagSet> block_side_effects_; | 1454 ZoneList<GVNFlagSet> block_side_effects_; |
| 1392 | 1455 |
| 1393 // A map of loop header block IDs to their loop's side effects. | 1456 // A map of loop header block IDs to their loop's side effects. |
| 1394 ZoneList<GVNFlagSet> loop_side_effects_; | 1457 ZoneList<GVNFlagSet> loop_side_effects_; |
| 1395 | 1458 |
| 1396 // Used when collecting side effects on paths from dominator to | 1459 // Used when collecting side effects on paths from dominator to |
| 1397 // dominated. | 1460 // dominated. |
| 1398 SparseSet visited_on_paths_; | 1461 SparseSet visited_on_paths_; |
| 1399 }; | 1462 }; |
| 1400 | 1463 |
| 1401 | 1464 |
| 1402 bool HGlobalValueNumberer::Analyze() { | 1465 bool HGlobalValueNumberer::Analyze() { |
| 1466 removed_side_effects_ = false; | |
| 1403 ComputeBlockSideEffects(); | 1467 ComputeBlockSideEffects(); |
| 1404 if (FLAG_loop_invariant_code_motion) { | 1468 if (FLAG_loop_invariant_code_motion) { |
| 1405 LoopInvariantCodeMotion(); | 1469 LoopInvariantCodeMotion(); |
| 1406 } | 1470 } |
| 1407 HValueMap* map = new(zone()) HValueMap(); | 1471 HValueMap* map = new(zone()) HValueMap(); |
| 1408 AnalyzeBlock(graph_->entry_block(), map); | 1472 AnalyzeBlock(graph_->entry_block(), map); |
| 1409 return removed_side_effects_; | 1473 return removed_side_effects_; |
| 1410 } | 1474 } |
| 1411 | 1475 |
| 1412 | 1476 |
| 1413 void HGlobalValueNumberer::ComputeBlockSideEffects() { | 1477 void HGlobalValueNumberer::ComputeBlockSideEffects() { |
| 1478 for (int i = 0; i < loop_side_effects_.length(); ++i) { | |
|
fschneider
2012/02/02 14:59:50
Comment on why resetting the loop side effect sets
danno
2012/02/06 16:54:57
Done.
| |
| 1479 loop_side_effects_[i].RemoveAll(); | |
| 1480 } | |
| 1414 for (int i = graph_->blocks()->length() - 1; i >= 0; --i) { | 1481 for (int i = graph_->blocks()->length() - 1; i >= 0; --i) { |
| 1415 // Compute side effects for the block. | 1482 // Compute side effects for the block. |
| 1416 HBasicBlock* block = graph_->blocks()->at(i); | 1483 HBasicBlock* block = graph_->blocks()->at(i); |
| 1417 HInstruction* instr = block->first(); | 1484 HInstruction* instr = block->first(); |
| 1418 int id = block->block_id(); | 1485 int id = block->block_id(); |
| 1419 GVNFlagSet side_effects; | 1486 GVNFlagSet side_effects; |
| 1420 while (instr != NULL) { | 1487 while (instr != NULL) { |
| 1421 side_effects.Add(instr->ChangesFlags()); | 1488 side_effects.Add(instr->ChangesFlags()); |
| 1422 instr = instr->next(); | 1489 instr = instr->next(); |
| 1423 } | 1490 } |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 1441 | 1508 |
| 1442 void HGlobalValueNumberer::LoopInvariantCodeMotion() { | 1509 void HGlobalValueNumberer::LoopInvariantCodeMotion() { |
| 1443 for (int i = graph_->blocks()->length() - 1; i >= 0; --i) { | 1510 for (int i = graph_->blocks()->length() - 1; i >= 0; --i) { |
| 1444 HBasicBlock* block = graph_->blocks()->at(i); | 1511 HBasicBlock* block = graph_->blocks()->at(i); |
| 1445 if (block->IsLoopHeader()) { | 1512 if (block->IsLoopHeader()) { |
| 1446 GVNFlagSet side_effects = loop_side_effects_[block->block_id()]; | 1513 GVNFlagSet side_effects = loop_side_effects_[block->block_id()]; |
| 1447 TraceGVN("Try loop invariant motion for block B%d effects=0x%x\n", | 1514 TraceGVN("Try loop invariant motion for block B%d effects=0x%x\n", |
| 1448 block->block_id(), | 1515 block->block_id(), |
| 1449 side_effects.ToIntegral()); | 1516 side_effects.ToIntegral()); |
| 1450 | 1517 |
| 1518 GVNFlagSet accumulated_first_time_depends; | |
| 1451 HBasicBlock* last = block->loop_information()->GetLastBackEdge(); | 1519 HBasicBlock* last = block->loop_information()->GetLastBackEdge(); |
| 1452 for (int j = block->block_id(); j <= last->block_id(); ++j) { | 1520 for (int j = block->block_id(); j <= last->block_id(); ++j) { |
| 1453 ProcessLoopBlock(graph_->blocks()->at(j), block, side_effects); | 1521 ProcessLoopBlock(graph_->blocks()->at(j), block, side_effects, |
| 1522 &accumulated_first_time_depends); | |
| 1454 } | 1523 } |
| 1455 } | 1524 } |
| 1456 } | 1525 } |
| 1457 } | 1526 } |
| 1458 | 1527 |
| 1459 | 1528 |
| 1460 void HGlobalValueNumberer::ProcessLoopBlock(HBasicBlock* block, | 1529 void HGlobalValueNumberer::ProcessLoopBlock( |
| 1461 HBasicBlock* loop_header, | 1530 HBasicBlock* block, |
| 1462 GVNFlagSet loop_kills) { | 1531 HBasicBlock* loop_header, |
| 1532 GVNFlagSet loop_kills, | |
| 1533 GVNFlagSet* accumulated_first_time_depends) { | |
| 1463 HBasicBlock* pre_header = loop_header->predecessors()->at(0); | 1534 HBasicBlock* pre_header = loop_header->predecessors()->at(0); |
| 1464 GVNFlagSet depends_flags = HValue::ConvertChangesToDependsFlags(loop_kills); | 1535 GVNFlagSet depends_flags = HValue::ConvertChangesToDependsFlags(loop_kills); |
| 1465 TraceGVN("Loop invariant motion for B%d depends_flags=0x%x\n", | 1536 TraceGVN("Loop invariant motion for B%d depends_flags=0x%x\n", |
| 1466 block->block_id(), | 1537 block->block_id(), |
| 1467 depends_flags.ToIntegral()); | 1538 depends_flags.ToIntegral()); |
| 1468 HInstruction* instr = block->first(); | 1539 HInstruction* instr = block->first(); |
| 1469 while (instr != NULL) { | 1540 while (instr != NULL) { |
| 1470 HInstruction* next = instr->next(); | 1541 HInstruction* next = instr->next(); |
| 1471 if (instr->CheckFlag(HValue::kUseGVN) && | 1542 bool hoisted = false; |
| 1472 !instr->gvn_flags().ContainsAnyOf(depends_flags)) { | 1543 if (instr->CheckFlag(HValue::kUseGVN)) { |
| 1473 TraceGVN("Checking instruction %d (%s)\n", | 1544 TraceGVN("Checking instruction %d (%s) instruction GVN flags 0x%X, " |
| 1545 "loop kills 0x%X\n", | |
| 1474 instr->id(), | 1546 instr->id(), |
| 1475 instr->Mnemonic()); | 1547 instr->Mnemonic(), |
| 1476 bool inputs_loop_invariant = true; | 1548 instr->gvn_flags().ToIntegral(), |
| 1477 for (int i = 0; i < instr->OperandCount(); ++i) { | 1549 depends_flags.ToIntegral()); |
| 1478 if (instr->OperandAt(i)->IsDefinedAfter(pre_header)) { | 1550 bool can_hoist = !instr->gvn_flags().ContainsAnyOf(depends_flags); |
| 1479 inputs_loop_invariant = false; | 1551 if (!can_hoist && |
| 1552 !instr->HasObservableSideEffects() && | |
|
fschneider
2012/02/02 14:59:50
maybe just say:
if (!can_hoist && instr->IsTrans
danno
2012/02/06 16:54:57
Done.
| |
| 1553 instr->HasOneTimeSideEffects()) { | |
| 1554 // It's only possible to hoist one time side effects if there are no | |
| 1555 // dependencies on their changes from the loop header to the current | |
| 1556 // instruction. | |
| 1557 GVNFlagSet converted_changes = | |
| 1558 HValue::ConvertChangesToDependsFlags(instr->ChangesFlags()); | |
| 1559 TraceGVN("Checking dependencies on one-time instruction %d (%s) " | |
| 1560 "converted changes 0x%X, accumulated depends 0x%X\n", | |
| 1561 instr->id(), | |
| 1562 instr->Mnemonic(), | |
| 1563 converted_changes.ToIntegral(), | |
| 1564 accumulated_first_time_depends->ToIntegral()); | |
| 1565 // It's possible to hoist one-time side effects from the current loop | |
| 1566 // loop only if they dominate all of the successor blocks in the same | |
| 1567 // loop and there are not any instructions that have Changes/DependsOn | |
| 1568 // that intervene between it and the beginning of the loop header. | |
| 1569 bool not_in_nested_loop = block == loop_header || | |
| 1570 (block->parent_loop_header() == | |
| 1571 loop_header && !block->IsLoopHeader()); | |
| 1572 can_hoist = !not_in_nested_loop && | |
|
fschneider
2012/02/02 14:59:50
The double negation !not... should be avoided for
danno
2012/02/06 16:54:57
Done.
| |
| 1573 block->IsLoopSuccessorDominator() && | |
| 1574 !accumulated_first_time_depends->ContainsAnyOf(converted_changes); | |
| 1575 } | |
| 1576 | |
| 1577 if (can_hoist) { | |
| 1578 bool inputs_loop_invariant = true; | |
| 1579 for (int i = 0; i < instr->OperandCount(); ++i) { | |
| 1580 if (instr->OperandAt(i)->IsDefinedAfter(pre_header)) { | |
| 1581 inputs_loop_invariant = false; | |
| 1582 } | |
| 1583 } | |
| 1584 | |
| 1585 if (inputs_loop_invariant && ShouldMove(instr, loop_header)) { | |
| 1586 TraceGVN("Hoisting loop invariant instruction %d\n", instr->id()); | |
| 1587 // Move the instruction out of the loop. | |
| 1588 instr->Unlink(); | |
| 1589 instr->InsertBefore(pre_header->end()); | |
| 1590 if (instr->HasSideEffects()) removed_side_effects_ = true; | |
| 1591 hoisted = true; | |
| 1480 } | 1592 } |
| 1481 } | 1593 } |
| 1482 | 1594 } |
| 1483 if (inputs_loop_invariant && ShouldMove(instr, loop_header)) { | 1595 if (!hoisted) { |
| 1484 TraceGVN("Found loop invariant instruction %d\n", instr->id()); | 1596 // Hoisting an instruction to the preheader causes its DependsOn or |
| 1485 // Move the instruction out of the loop. | 1597 // SideEffects flags to not prevent hosting OneTimeSideEffecct |
|
fschneider
2012/02/02 14:59:50
I find the double negation in the comment confusin
danno
2012/02/06 16:54:57
Done.
| |
| 1486 instr->Unlink(); | 1598 // instructions. |
| 1487 instr->InsertBefore(pre_header->end()); | 1599 accumulated_first_time_depends->Add(instr->DependsOnFlags()); |
| 1488 } | 1600 GVNFlagSet converted_changes = |
| 1601 HValue::ConvertChangesToDependsFlags(instr->SideEffectFlags()); | |
| 1602 accumulated_first_time_depends->Add(converted_changes); | |
| 1489 } | 1603 } |
| 1490 instr = next; | 1604 instr = next; |
| 1491 } | 1605 } |
| 1492 } | 1606 } |
| 1493 | 1607 |
| 1494 | 1608 |
| 1495 bool HGlobalValueNumberer::AllowCodeMotion() { | 1609 bool HGlobalValueNumberer::AllowCodeMotion() { |
| 1496 return info()->shared_info()->opt_count() + 1 < Compiler::kDefaultMaxOptCount; | 1610 return info()->shared_info()->opt_count() + 1 < Compiler::kDefaultMaxOptCount; |
| 1497 } | 1611 } |
| 1498 | 1612 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1540 while (instr != NULL) { | 1654 while (instr != NULL) { |
| 1541 HInstruction* next = instr->next(); | 1655 HInstruction* next = instr->next(); |
| 1542 GVNFlagSet flags = instr->ChangesFlags(); | 1656 GVNFlagSet flags = instr->ChangesFlags(); |
| 1543 if (!flags.IsEmpty()) { | 1657 if (!flags.IsEmpty()) { |
| 1544 // Clear all instructions in the map that are affected by side effects. | 1658 // Clear all instructions in the map that are affected by side effects. |
| 1545 map->Kill(flags); | 1659 map->Kill(flags); |
| 1546 TraceGVN("Instruction %d kills\n", instr->id()); | 1660 TraceGVN("Instruction %d kills\n", instr->id()); |
| 1547 } | 1661 } |
| 1548 if (instr->CheckFlag(HValue::kUseGVN)) { | 1662 if (instr->CheckFlag(HValue::kUseGVN)) { |
| 1549 ASSERT(!instr->HasObservableSideEffects()); | 1663 ASSERT(!instr->HasObservableSideEffects()); |
| 1664 ASSERT(!instr->HasSideEffects() || instr->HasOneTimeSideEffects()); | |
| 1550 HValue* other = map->Lookup(instr); | 1665 HValue* other = map->Lookup(instr); |
| 1551 if (other != NULL) { | 1666 if (other != NULL) { |
| 1552 ASSERT(instr->Equals(other) && other->Equals(instr)); | 1667 ASSERT(instr->Equals(other) && other->Equals(instr)); |
| 1553 TraceGVN("Replacing value %d (%s) with value %d (%s)\n", | 1668 TraceGVN("Replacing value %d (%s) with value %d (%s)\n", |
| 1554 instr->id(), | 1669 instr->id(), |
| 1555 instr->Mnemonic(), | 1670 instr->Mnemonic(), |
| 1556 other->id(), | 1671 other->id(), |
| 1557 other->Mnemonic()); | 1672 other->Mnemonic()); |
| 1558 if (instr->HasSideEffects()) removed_side_effects_ = true; | 1673 if (instr->HasSideEffects()) removed_side_effects_ = true; |
| 1559 instr->DeleteAndReplaceWith(other); | 1674 instr->DeleteAndReplaceWith(other); |
| (...skipping 827 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2387 | 2502 |
| 2388 // Perform common subexpression elimination and loop-invariant code motion. | 2503 // Perform common subexpression elimination and loop-invariant code motion. |
| 2389 if (FLAG_use_gvn) { | 2504 if (FLAG_use_gvn) { |
| 2390 HPhase phase("Global value numbering", graph()); | 2505 HPhase phase("Global value numbering", graph()); |
| 2391 HGlobalValueNumberer gvn(graph(), info()); | 2506 HGlobalValueNumberer gvn(graph(), info()); |
| 2392 bool removed_side_effects = gvn.Analyze(); | 2507 bool removed_side_effects = gvn.Analyze(); |
| 2393 // Trigger a second analysis pass to further eliminate duplicate values that | 2508 // Trigger a second analysis pass to further eliminate duplicate values that |
| 2394 // could only be discovered by removing side-effect-generating instructions | 2509 // could only be discovered by removing side-effect-generating instructions |
| 2395 // during the first pass. | 2510 // during the first pass. |
| 2396 if (FLAG_smi_only_arrays && removed_side_effects) { | 2511 if (FLAG_smi_only_arrays && removed_side_effects) { |
| 2397 gvn.Analyze(); | 2512 removed_side_effects = gvn.Analyze(); |
| 2513 ASSERT(!removed_side_effects); | |
| 2398 } | 2514 } |
| 2399 } | 2515 } |
| 2400 | 2516 |
| 2401 if (FLAG_use_range) { | 2517 if (FLAG_use_range) { |
| 2402 HRangeAnalysis rangeAnalysis(graph()); | 2518 HRangeAnalysis rangeAnalysis(graph()); |
| 2403 rangeAnalysis.Analyze(); | 2519 rangeAnalysis.Analyze(); |
| 2404 } | 2520 } |
| 2405 graph()->ComputeMinusZeroChecks(); | 2521 graph()->ComputeMinusZeroChecks(); |
| 2406 | 2522 |
| 2407 // Eliminate redundant stack checks on backwards branches. | 2523 // Eliminate redundant stack checks on backwards branches. |
| (...skipping 5047 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7455 } | 7571 } |
| 7456 } | 7572 } |
| 7457 | 7573 |
| 7458 #ifdef DEBUG | 7574 #ifdef DEBUG |
| 7459 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 7575 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
| 7460 if (allocator_ != NULL) allocator_->Verify(); | 7576 if (allocator_ != NULL) allocator_->Verify(); |
| 7461 #endif | 7577 #endif |
| 7462 } | 7578 } |
| 7463 | 7579 |
| 7464 } } // namespace v8::internal | 7580 } } // namespace v8::internal |
| OLD | NEW |