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 |