OLD | NEW |
---|---|
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/flow_graph_allocator.h" | 5 #include "vm/flow_graph_allocator.h" |
6 | 6 |
7 #include "vm/bit_vector.h" | |
7 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
9 #include "vm/flow_graph_compiler.h" | |
8 | 10 |
9 namespace dart { | 11 namespace dart { |
10 | 12 |
13 DEFINE_FLAG(bool, print_ssa_liveness, false, | |
14 "Print liveness for ssa variables."); | |
15 | |
16 FlowGraphAllocator::FlowGraphAllocator( | |
17 const GrowableArray<BlockEntryInstr*>& postorder, | |
18 intptr_t max_ssa_temp_index) | |
19 : live_out_(postorder.length()), | |
20 kill_(postorder.length()), | |
21 gen_(postorder.length()), | |
22 live_in_(postorder.length()), | |
23 postorder_(postorder), | |
24 vreg_count_(max_ssa_temp_index) { | |
25 } | |
26 | |
27 | |
11 void FlowGraphAllocator::ResolveConstraints() { | 28 void FlowGraphAllocator::ResolveConstraints() { |
12 // TODO(fschneider): Resolve register constraints. | 29 // TODO(fschneider): Resolve register constraints. |
13 } | 30 } |
14 | 31 |
32 | |
33 static intptr_t ToVirtualRegister(Instruction* instr) { | |
34 const Definition* def = instr->AsDefinition(); | |
35 if (def == 0) return -1; | |
Florian Schneider
2012/06/25 14:38:29
Better def == NULL?
Vyacheslav Egorov (Google)
2012/06/25 16:58:26
Done.
| |
36 return def->ssa_temp_index(); | |
37 } | |
srdjan
2012/06/25 17:30:05
return (def == NULL) ? -1 : def->ssa_temp_index();
| |
38 | |
39 | |
40 void FlowGraphAllocator::ComputeKillAndGenSets() { | |
41 const intptr_t block_count = postorder_.length(); | |
42 for (intptr_t i = 0; i < block_count; i++) { | |
43 BlockEntryInstr* block = postorder_[i]; | |
44 | |
45 BitVector* kill = kill_[i]; | |
46 BitVector* gen = gen_[i]; | |
srdjan
2012/06/25 17:30:05
ASSERT kill and gen are not NULL.
| |
47 | |
48 if (block->IsJoinEntry()) { | |
49 JoinEntryInstr* join = block->AsJoinEntry(); | |
50 for (intptr_t j = 0; j < join->phis()->length(); j++) { | |
Florian Schneider
2012/06/25 14:38:29
Missing NULL check: join->phis() can be NULL for j
Vyacheslav Egorov (Google)
2012/06/25 16:58:26
Done.
| |
51 PhiInstr* phi = (*join->phis())[j]; | |
52 if (phi == NULL) continue; | |
53 | |
54 const intptr_t def = ToVirtualRegister(phi); | |
55 if (def >= 0) kill->Add(def); | |
56 | |
57 for (intptr_t k = 0; k < phi->InputCount(); k++) { | |
58 Value* val = phi->InputAt(k); | |
59 if (!val->IsUse()) continue; | |
60 const intptr_t use = ToVirtualRegister(val->AsUse()->definition()); | |
61 if (use >= 0) { | |
62 BlockEntryInstr* pred = block->PredecessorAt(k); | |
63 live_out_[pred->postorder_number()]->Add(use); | |
64 } | |
65 } | |
66 } | |
67 } | |
68 | |
69 Instruction* current = block->StraightLineSuccessor(); | |
70 // TODO(vegorov): iterate backwards. | |
71 while ((current != NULL) && !current->IsBlockEntry()) { | |
72 for (intptr_t j = 0; j < current->InputCount(); j++) { | |
73 Value* input = current->InputAt(j); | |
74 if (!input->IsUse()) continue; | |
75 const intptr_t use = ToVirtualRegister(input->AsUse()->definition()); | |
76 if (use >= 0 && !kill->Contains(use)) gen->Add(use); | |
77 } | |
78 | |
79 const intptr_t def = ToVirtualRegister(current); | |
80 if (def >= 0) kill->Add(def); | |
81 | |
82 current = current->StraightLineSuccessor(); | |
83 } | |
84 | |
85 live_in_[i]->AddAll(gen); | |
86 UpdateLiveIn(block); | |
87 } | |
88 } | |
89 | |
90 | |
91 bool FlowGraphAllocator::UpdateLiveOut(BlockEntryInstr* instr) { | |
92 BitVector* live_out = live_out_[instr->postorder_number()]; | |
93 bool changed = false; | |
94 Instruction* last = instr->last_instruction(); | |
srdjan
2012/06/25 17:30:05
ASSERT (last != NULL, live_out != NULL) ?
Vyacheslav Egorov (Google)
2012/06/25 17:42:23
live_out_ != NULL is a fundamental property of ini
srdjan
2012/06/25 17:51:44
Agree with the fundamental property. SIGSEGV is mu
| |
95 for (intptr_t i = 0; i < last->SuccessorCount(); i++) { | |
srdjan
2012/06/25 17:30:05
SuccessotCount can be 0 or 1, is a loop necessary?
Vyacheslav Egorov (Google)
2012/06/25 17:42:23
it can be 0, 1 (implicit goto), 2 (branch), 1 + #c
srdjan
2012/06/25 17:51:44
Mea culpa.
| |
96 BlockEntryInstr* succ = last->SuccessorAt(i); | |
srdjan
2012/06/25 17:30:05
ASSERT(succ != NULL) ?
| |
97 if (live_out->AddAll(live_in_[succ->postorder_number()])) { | |
98 changed = true; | |
99 } | |
100 } | |
101 return changed; | |
102 } | |
103 | |
104 | |
105 bool FlowGraphAllocator::UpdateLiveIn(BlockEntryInstr* instr) { | |
106 BitVector* live_out = live_out_[instr->postorder_number()]; | |
107 BitVector* kill = kill_[instr->postorder_number()]; | |
108 BitVector* live_in = live_in_[instr->postorder_number()]; | |
109 return live_in->KillAndAdd(kill, live_out); | |
110 } | |
111 | |
112 | |
113 void FlowGraphAllocator::ComputeLiveInAndLiveOutSets() { | |
114 const intptr_t block_count = postorder_.length(); | |
115 bool changed; | |
srdjan
2012/06/25 17:30:05
bool changed = false;
| |
116 do { | |
117 changed = false; | |
srdjan
2012/06/25 17:30:05
Remove this line.
Vyacheslav Egorov (Google)
2012/06/25 17:42:23
I need to reset changed to false after each iterat
srdjan
2012/06/25 17:51:44
I negated the condition while reading. Mea Culpa
| |
118 | |
119 for (intptr_t i = 0; i < block_count; i++) { | |
120 BlockEntryInstr* block = postorder_[i]; | |
srdjan
2012/06/25 17:30:05
Maybe add comments that you do not need to update
| |
121 if (UpdateLiveOut(block) && UpdateLiveIn(block)) { | |
122 changed = true; | |
123 } | |
124 } | |
125 } while (changed); | |
126 } | |
127 | |
128 | |
129 void FlowGraphAllocator::AnalyzeLiveness() { | |
130 const intptr_t block_count = postorder_.length(); | |
131 for (intptr_t i = 0; i < block_count; i++) { | |
132 live_out_.Add(new BitVector(vreg_count_)); | |
133 kill_.Add(new BitVector(vreg_count_)); | |
134 gen_.Add(new BitVector(vreg_count_)); | |
135 live_in_.Add(new BitVector(vreg_count_)); | |
136 } | |
137 | |
138 ComputeKillAndGenSets(); | |
139 ComputeLiveInAndLiveOutSets(); | |
140 | |
141 if (FLAG_print_ssa_liveness) { | |
142 DumpLiveness(); | |
143 } | |
144 } | |
145 | |
146 | |
147 static void PrintBitVector(const char* tag, BitVector* v) { | |
148 printf("%s:", tag); | |
Florian Schneider
2012/06/25 14:38:29
Use OS::Print instead.
Vyacheslav Egorov (Google)
2012/06/25 16:58:26
Done.
| |
149 for (BitVector::Iterator it(v); !it.Done(); it.Advance()) { | |
150 printf(" %d", it.Current()); | |
Florian Schneider
2012/06/25 14:38:29
OS::Print
Vyacheslav Egorov (Google)
2012/06/25 16:58:26
Done.
| |
151 } | |
152 printf("\n"); | |
Florian Schneider
2012/06/25 14:38:29
OS::Print
Vyacheslav Egorov (Google)
2012/06/25 16:58:26
Done.
| |
153 } | |
154 | |
155 | |
156 void FlowGraphAllocator::DumpLiveness() { | |
157 const intptr_t block_count = postorder_.length(); | |
158 for (intptr_t i = 0; i < block_count; i++) { | |
159 BlockEntryInstr* block = postorder_[i]; | |
160 printf("block @%d -> ", block->block_id()); | |
srdjan
2012/06/25 17:30:05
OS::Print here as well.
| |
161 | |
162 Instruction* last = block->last_instruction(); | |
163 for (intptr_t j = 0; j < last->SuccessorCount(); j++) { | |
164 BlockEntryInstr* succ = last->SuccessorAt(j); | |
165 printf(" @%d", succ->block_id()); | |
166 } | |
167 printf("\n"); | |
168 | |
169 PrintBitVector(" live out", live_out_[i]); | |
170 PrintBitVector(" kill", kill_[i]); | |
171 PrintBitVector(" gen", gen_[i]); | |
172 PrintBitVector(" live in", live_in_[i]); | |
Florian Schneider
2012/06/25 14:38:29
Maybe print in a different order? e.g. live_in, ge
Vyacheslav Egorov (Google)
2012/06/25 16:58:26
We print blocks in post order so printing live out
| |
173 } | |
174 } | |
175 | |
176 | |
15 } // namespace dart | 177 } // namespace dart |
OLD | NEW |