Flutter Engine
The Flutter Engine
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
Public Member Functions | List of all members
dart::LICM Class Reference

#include <redundancy_elimination.h>

Inheritance diagram for dart::LICM:
dart::ValueObject

Public Member Functions

 LICM (FlowGraph *flow_graph)
 
void Optimize ()
 
void OptimisticallySpecializeSmiPhis ()
 
- Public Member Functions inherited from dart::ValueObject
 ValueObject ()
 
 ~ValueObject ()
 

Detailed Description

Definition at line 131 of file redundancy_elimination.h.

Constructor & Destructor Documentation

◆ LICM()

dart::LICM::LICM ( FlowGraph flow_graph)
explicit

Definition at line 1447 of file redundancy_elimination.cc.

1447 : flow_graph_(flow_graph) {
1448 ASSERT(flow_graph->is_licm_allowed());
1449}
bool is_licm_allowed() const
Definition: flow_graph.h:404
#define ASSERT(E)

Member Function Documentation

◆ OptimisticallySpecializeSmiPhis()

void dart::LICM::OptimisticallySpecializeSmiPhis ( )

Definition at line 1526 of file redundancy_elimination.cc.

1526 {
1527 if (flow_graph()->function().ProhibitsInstructionHoisting() ||
1528 CompilerState::Current().is_aot()) {
1529 // Do not hoist any: Either deoptimized on a hoisted check,
1530 // or compiling precompiled code where we can't do optimistic
1531 // hoisting of checks.
1532 return;
1533 }
1534
1535 const ZoneGrowableArray<BlockEntryInstr*>& loop_headers =
1536 flow_graph()->GetLoopHierarchy().headers();
1537
1538 for (intptr_t i = 0; i < loop_headers.length(); ++i) {
1539 JoinEntryInstr* header = loop_headers[i]->AsJoinEntry();
1540 // Skip loop that don't have a pre-header block.
1541 BlockEntryInstr* pre_header = header->ImmediateDominator();
1542 if (pre_header == nullptr) continue;
1543
1544 for (PhiIterator it(header); !it.Done(); it.Advance()) {
1545 TrySpecializeSmiPhi(it.Current(), header, pre_header);
1546 }
1547 }
1548}
static CompilerState & Current()
const LoopHierarchy & GetLoopHierarchy()
Definition: flow_graph.h:430
const ZoneGrowableArray< BlockEntryInstr * > & headers() const
Definition: loops.h:329
Dart_NativeFunction function
Definition: fuchsia.cc:51
static const char header[]
Definition: skpbench.cpp:88

◆ Optimize()

void dart::LICM::Optimize ( )

Definition at line 1550 of file redundancy_elimination.cc.

1550 {
1551 if (flow_graph()->function().ProhibitsInstructionHoisting()) {
1552 // Do not hoist any.
1553 return;
1554 }
1555
1556 // Compute loops and induction in flow graph.
1557 const LoopHierarchy& loop_hierarchy = flow_graph()->GetLoopHierarchy();
1558 const ZoneGrowableArray<BlockEntryInstr*>& loop_headers =
1559 loop_hierarchy.headers();
1560 loop_hierarchy.ComputeInduction();
1561
1562 ZoneGrowableArray<BitVector*>* loop_invariant_loads =
1563 flow_graph()->loop_invariant_loads();
1564
1565 // Iterate over all loops.
1566 for (intptr_t i = 0; i < loop_headers.length(); ++i) {
1567 BlockEntryInstr* header = loop_headers[i];
1568
1569 // Skip loops that don't have a pre-header block.
1570 BlockEntryInstr* pre_header = header->ImmediateDominator();
1571 if (pre_header == nullptr) {
1572 continue;
1573 }
1574
1575 // Flag that remains true as long as the loop has not seen any instruction
1576 // that may have a "visible" effect (write, throw, or other side-effect).
1577 bool seen_visible_effect = false;
1578
1579 // Iterate over all blocks in the loop.
1580 LoopInfo* loop = header->loop_info();
1581 for (BitVector::Iterator loop_it(loop->blocks()); !loop_it.Done();
1582 loop_it.Advance()) {
1583 BlockEntryInstr* block = flow_graph()->preorder()[loop_it.Current()];
1584
1585 // Preserve the "visible" effect flag as long as the preorder traversal
1586 // sees always-taken blocks. This way, we can only hoist invariant
1587 // may-throw instructions that are always seen during the first iteration.
1588 if (!seen_visible_effect && !loop->IsAlwaysTaken(block)) {
1589 seen_visible_effect = true;
1590 }
1591 // Iterate over all instructions in the block.
1592 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
1593 Instruction* current = it.Current();
1594
1595 // Treat loads of static final fields specially: we can CSE them but
1596 // we should not move them around unless the field is initialized.
1597 // Otherwise we might move load past the initialization.
1598 if (LoadStaticFieldInstr* load = current->AsLoadStaticField()) {
1599 if (load->AllowsCSE()) {
1600 seen_visible_effect = true;
1601 continue;
1602 }
1603 }
1604
1605 // Determine if we can hoist loop invariant code. Even may-throw
1606 // instructions can be hoisted as long as its exception is still
1607 // the very first "visible" effect of the loop.
1608 bool is_loop_invariant = false;
1609 if ((current->AllowsCSE() ||
1610 IsLoopInvariantLoad(loop_invariant_loads, i, current)) &&
1611 (!seen_visible_effect || !current->MayHaveVisibleEffect())) {
1612 is_loop_invariant = true;
1613 for (intptr_t i = 0; i < current->InputCount(); ++i) {
1614 Definition* input_def = current->InputAt(i)->definition();
1615 if (!input_def->GetBlock()->Dominates(pre_header)) {
1616 is_loop_invariant = false;
1617 break;
1618 }
1619 }
1620 }
1621
1622 // Hoist if all inputs are loop invariant. If not hoisted, any
1623 // instruction that writes, may throw, or has an unknown side
1624 // effect invalidates the first "visible" effect flag.
1625 if (is_loop_invariant) {
1626 Hoist(&it, pre_header, current);
1627 } else if (!seen_visible_effect && current->MayHaveVisibleEffect()) {
1628 seen_visible_effect = true;
1629 }
1630 }
1631 }
1632 }
1633}
SI T load(const P *ptr)
Definition: Transform_inl.h:98
const GrowableArray< BlockEntryInstr * > & preorder() const
Definition: flow_graph.h:203
ZoneGrowableArray< BitVector * > * loop_invariant_loads() const
Definition: flow_graph.h:452
static bool IsLoopInvariantLoad(ZoneGrowableArray< BitVector * > *sets, intptr_t loop_header_index, Instruction *instr)

The documentation for this class was generated from the following files: