Revision f230a1cf deps/v8/src/hydrogen-redundant-phi.cc
deps/v8/src/hydrogen-redundant-phi.cc | ||
---|---|---|
31 | 31 |
namespace internal { |
32 | 32 |
|
33 | 33 |
void HRedundantPhiEliminationPhase::Run() { |
34 |
// We do a simple fixed point iteration without any work list, because |
|
35 |
// machine-generated JavaScript can lead to a very dense Hydrogen graph with |
|
36 |
// an enormous work list and will consequently result in OOM. Experiments |
|
37 |
// showed that this simple algorithm is good enough, and even e.g. tracking |
|
38 |
// the set or range of blocks to consider is not a real improvement. |
|
39 |
bool need_another_iteration; |
|
34 |
// Gather all phis from all blocks first. |
|
40 | 35 |
const ZoneList<HBasicBlock*>* blocks(graph()->blocks()); |
41 |
ZoneList<HPhi*> redundant_phis(blocks->length(), zone()); |
|
42 |
do { |
|
43 |
need_another_iteration = false; |
|
44 |
for (int i = 0; i < blocks->length(); ++i) { |
|
45 |
HBasicBlock* block = blocks->at(i); |
|
46 |
for (int j = 0; j < block->phis()->length(); j++) { |
|
47 |
HPhi* phi = block->phis()->at(j); |
|
48 |
HValue* replacement = phi->GetRedundantReplacement(); |
|
49 |
if (replacement != NULL) { |
|
50 |
// Remember phi to avoid concurrent modification of the block's phis. |
|
51 |
redundant_phis.Add(phi, zone()); |
|
52 |
for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) { |
|
53 |
HValue* value = it.value(); |
|
54 |
value->SetOperandAt(it.index(), replacement); |
|
55 |
need_another_iteration |= value->IsPhi(); |
|
56 |
} |
|
57 |
} |
|
58 |
} |
|
59 |
for (int i = 0; i < redundant_phis.length(); i++) { |
|
60 |
block->RemovePhi(redundant_phis[i]); |
|
61 |
} |
|
62 |
redundant_phis.Clear(); |
|
36 |
ZoneList<HPhi*> all_phis(blocks->length(), zone()); |
|
37 |
for (int i = 0; i < blocks->length(); ++i) { |
|
38 |
HBasicBlock* block = blocks->at(i); |
|
39 |
for (int j = 0; j < block->phis()->length(); j++) { |
|
40 |
all_phis.Add(block->phis()->at(j), zone()); |
|
63 | 41 |
} |
64 |
} while (need_another_iteration); |
|
42 |
} |
|
43 |
|
|
44 |
// Iteratively reduce all phis in the list. |
|
45 |
ProcessPhis(&all_phis); |
|
65 | 46 |
|
66 | 47 |
#if DEBUG |
67 | 48 |
// Make sure that we *really* removed all redundant phis. |
... | ... | |
73 | 54 |
#endif |
74 | 55 |
} |
75 | 56 |
|
57 |
|
|
58 |
void HRedundantPhiEliminationPhase::ProcessBlock(HBasicBlock* block) { |
|
59 |
ProcessPhis(block->phis()); |
|
60 |
} |
|
61 |
|
|
62 |
|
|
63 |
void HRedundantPhiEliminationPhase::ProcessPhis(const ZoneList<HPhi*>* phis) { |
|
64 |
bool updated; |
|
65 |
do { |
|
66 |
// Iterately replace all redundant phis in the given list. |
|
67 |
updated = false; |
|
68 |
for (int i = 0; i < phis->length(); i++) { |
|
69 |
HPhi* phi = phis->at(i); |
|
70 |
if (phi->CheckFlag(HValue::kIsDead)) continue; // Already replaced. |
|
71 |
|
|
72 |
HValue* replacement = phi->GetRedundantReplacement(); |
|
73 |
if (replacement != NULL) { |
|
74 |
phi->SetFlag(HValue::kIsDead); |
|
75 |
for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) { |
|
76 |
HValue* value = it.value(); |
|
77 |
value->SetOperandAt(it.index(), replacement); |
|
78 |
// Iterate again if used in another non-dead phi. |
|
79 |
updated |= value->IsPhi() && !value->CheckFlag(HValue::kIsDead); |
|
80 |
} |
|
81 |
phi->block()->RemovePhi(phi); |
|
82 |
} |
|
83 |
} |
|
84 |
} while (updated); |
|
85 |
} |
|
86 |
|
|
87 |
|
|
76 | 88 |
} } // namespace v8::internal |
Also available in: Unified diff