OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
| 5 #include "hydrogen-flow-engine.h" |
| 6 #include "hydrogen-instructions.h" |
5 #include "hydrogen-removable-simulates.h" | 7 #include "hydrogen-removable-simulates.h" |
6 | 8 |
7 namespace v8 { | 9 namespace v8 { |
8 namespace internal { | 10 namespace internal { |
9 | 11 |
10 void HMergeRemovableSimulatesPhase::Run() { | 12 class State : public ZoneObject { |
11 ZoneList<HSimulate*> mergelist(2, zone()); | 13 public: |
12 for (int i = 0; i < graph()->blocks()->length(); ++i) { | 14 explicit State(Zone* zone) |
13 HBasicBlock* block = graph()->blocks()->at(i); | 15 : zone_(zone), mergelist_(2, zone), first_(true), mode_(NORMAL) { } |
| 16 |
| 17 State* Process(HInstruction* instr, Zone* zone) { |
| 18 if (FLAG_trace_removable_simulates) { |
| 19 PrintF("[State::Process %s #%d %s]\n", |
| 20 mode_ == NORMAL ? "normal" : "collect", |
| 21 instr->id(), instr->Mnemonic()); |
| 22 } |
| 23 // Forward-merge "trains" of simulates after an instruction with observable |
| 24 // side effects to keep live ranges short. |
| 25 if (mode_ == COLLECT_CONSECUTIVE_SIMULATES) { |
| 26 if (instr->IsSimulate()) { |
| 27 HSimulate* current_simulate = HSimulate::cast(instr); |
| 28 if (current_simulate->is_candidate_for_removal() && |
| 29 !current_simulate->ast_id().IsNone()) { |
| 30 Remember(current_simulate); |
| 31 return this; |
| 32 } |
| 33 } |
| 34 FlushSimulates(); |
| 35 mode_ = NORMAL; |
| 36 } |
| 37 // Ensure there's a non-foldable HSimulate before an HEnterInlined to avoid |
| 38 // folding across HEnterInlined. |
| 39 ASSERT(!(instr->IsEnterInlined() && |
| 40 HSimulate::cast(instr->previous())->is_candidate_for_removal())); |
| 41 if (instr->IsLeaveInlined() || instr->IsReturn()) { |
| 42 // Never fold simulates from inlined environments into simulates in the |
| 43 // outer environment. Simply remove all accumulated simulates without |
| 44 // merging. This is safe because simulates after instructions with side |
| 45 // effects are never added to the merge list. The same reasoning holds for |
| 46 // return instructions. |
| 47 RemoveSimulates(); |
| 48 return this; |
| 49 } |
| 50 if (instr->IsControlInstruction()) { |
| 51 // Merge the accumulated simulates at the end of the block. |
| 52 FlushSimulates(); |
| 53 return this; |
| 54 } |
| 55 // Skip the non-simulates and the first simulate. |
| 56 if (!instr->IsSimulate()) return this; |
| 57 if (first_) { |
| 58 first_ = false; |
| 59 return this; |
| 60 } |
| 61 HSimulate* current_simulate = HSimulate::cast(instr); |
| 62 if (!current_simulate->is_candidate_for_removal()) { |
| 63 Remember(current_simulate); |
| 64 FlushSimulates(); |
| 65 } else if (current_simulate->ast_id().IsNone()) { |
| 66 ASSERT(current_simulate->next()->IsEnterInlined()); |
| 67 FlushSimulates(); |
| 68 } else if (current_simulate->previous()->HasObservableSideEffects()) { |
| 69 Remember(current_simulate); |
| 70 mode_ = COLLECT_CONSECUTIVE_SIMULATES; |
| 71 } else { |
| 72 Remember(current_simulate); |
| 73 } |
| 74 |
| 75 return this; |
| 76 } |
| 77 |
| 78 static State* Merge(State* succ_state, |
| 79 HBasicBlock* succ_block, |
| 80 State* pred_state, |
| 81 HBasicBlock* pred_block, |
| 82 Zone* zone) { |
| 83 if (FLAG_trace_removable_simulates) { |
| 84 PrintF("[State::Merge predecessor block %d, successor block %d\n", |
| 85 pred_block->block_id(), succ_block->block_id()); |
| 86 } |
| 87 return pred_state; |
| 88 } |
| 89 |
| 90 static State* Finish(State* state, HBasicBlock* block, Zone* zone) { |
| 91 if (FLAG_trace_removable_simulates) { |
| 92 PrintF("[State::Finish block %d]\n", block->block_id()); } |
14 // Make sure the merge list is empty at the start of a block. | 93 // Make sure the merge list is empty at the start of a block. |
15 ASSERT(mergelist.is_empty()); | 94 ASSERT(state->mergelist_.is_empty()); |
16 // Nasty heuristic: Never remove the first simulate in a block. This | 95 // Nasty heuristic: Never remove the first simulate in a block. This |
17 // just so happens to have a beneficial effect on register allocation. | 96 // just so happens to have a beneficial effect on register allocation. |
18 bool first = true; | 97 state->first_ = true; |
19 for (HInstructionIterator it(block); !it.Done(); it.Advance()) { | 98 return state; |
20 HInstruction* current = it.Current(); | 99 } |
21 if (current->IsEnterInlined()) { | |
22 // Ensure there's a non-foldable HSimulate before an HEnterInlined to | |
23 // avoid folding across HEnterInlined. | |
24 ASSERT(!HSimulate::cast(current->previous())-> | |
25 is_candidate_for_removal()); | |
26 } | |
27 if (current->IsLeaveInlined()) { | |
28 // Never fold simulates from inlined environments into simulates in the | |
29 // outer environment. Simply remove all accumulated simulates without | |
30 // merging. This is safe because simulates after instructions with side | |
31 // effects are never added to the merge list. | |
32 while (!mergelist.is_empty()) { | |
33 mergelist.RemoveLast()->DeleteAndReplaceWith(NULL); | |
34 } | |
35 continue; | |
36 } | |
37 if (current->IsReturn()) { | |
38 // Drop mergeable simulates in the list. This is safe because | |
39 // simulates after instructions with side effects are never added | |
40 // to the merge list. | |
41 while (!mergelist.is_empty()) { | |
42 mergelist.RemoveLast()->DeleteAndReplaceWith(NULL); | |
43 } | |
44 continue; | |
45 } | |
46 // Skip the non-simulates and the first simulate. | |
47 if (!current->IsSimulate()) continue; | |
48 if (first) { | |
49 first = false; | |
50 continue; | |
51 } | |
52 HSimulate* current_simulate = HSimulate::cast(current); | |
53 if (!current_simulate->is_candidate_for_removal()) { | |
54 current_simulate->MergeWith(&mergelist); | |
55 } else if (current_simulate->ast_id().IsNone()) { | |
56 ASSERT(current_simulate->next()->IsEnterInlined()); | |
57 if (!mergelist.is_empty()) { | |
58 HSimulate* last = mergelist.RemoveLast(); | |
59 last->MergeWith(&mergelist); | |
60 } | |
61 } else if (current_simulate->previous()->HasObservableSideEffects()) { | |
62 while (current_simulate->next()->IsSimulate()) { | |
63 it.Advance(); | |
64 HSimulate* next_simulate = HSimulate::cast(it.Current()); | |
65 if (next_simulate->ast_id().IsNone()) break; | |
66 mergelist.Add(current_simulate, zone()); | |
67 current_simulate = next_simulate; | |
68 if (!current_simulate->is_candidate_for_removal()) break; | |
69 } | |
70 current_simulate->MergeWith(&mergelist); | |
71 } else { | |
72 // Accumulate this simulate for folding later on. | |
73 mergelist.Add(current_simulate, zone()); | |
74 } | |
75 } | |
76 | 100 |
77 if (!mergelist.is_empty()) { | 101 private: |
78 // Merge the accumulated simulates at the end of the block. | 102 enum Mode { NORMAL, COLLECT_CONSECUTIVE_SIMULATES }; |
79 HSimulate* last = mergelist.RemoveLast(); | 103 |
80 last->MergeWith(&mergelist); | 104 void Remember(HSimulate* sim) { |
| 105 mergelist_.Add(sim, zone_); |
| 106 } |
| 107 |
| 108 void FlushSimulates() { |
| 109 if (!mergelist_.is_empty()) { |
| 110 mergelist_.RemoveLast()->MergeWith(&mergelist_); |
81 } | 111 } |
82 } | 112 } |
| 113 |
| 114 void RemoveSimulates() { |
| 115 while (!mergelist_.is_empty()) { |
| 116 mergelist_.RemoveLast()->DeleteAndReplaceWith(NULL); |
| 117 } |
| 118 } |
| 119 |
| 120 Zone* zone_; |
| 121 ZoneList<HSimulate*> mergelist_; |
| 122 bool first_; |
| 123 Mode mode_; |
| 124 }; |
| 125 |
| 126 |
| 127 // We don't use effects here. |
| 128 class Effects : public ZoneObject { |
| 129 public: |
| 130 explicit Effects(Zone* zone) { } |
| 131 bool Disabled() { return true; } |
| 132 void Process(HInstruction* instr, Zone* zone) { } |
| 133 void Apply(State* state) { } |
| 134 void Union(Effects* that, Zone* zone) { } |
| 135 }; |
| 136 |
| 137 |
| 138 void HMergeRemovableSimulatesPhase::Run() { |
| 139 HFlowEngine<State, Effects> engine(graph(), zone()); |
| 140 State* state = new(zone()) State(zone()); |
| 141 engine.AnalyzeDominatedBlocks(graph()->blocks()->at(0), state); |
83 } | 142 } |
84 | 143 |
85 } } // namespace v8::internal | 144 } } // namespace v8::internal |
OLD | NEW |