Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(185)

Side by Side Diff: runtime/vm/flow_graph_allocator.cc

Issue 10666026: Simple iterative liveness analysis over SSA. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698