Chromium Code Reviews| 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 |