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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: runtime/vm/flow_graph_allocator.cc
diff --git a/runtime/vm/flow_graph_allocator.cc b/runtime/vm/flow_graph_allocator.cc
index 553e8866891ae0fab1f67f671c5f1bedf73d88c2..3b5446c2d3f376b4f4afba5f9a8bf705f9c745c8 100644
--- a/runtime/vm/flow_graph_allocator.cc
+++ b/runtime/vm/flow_graph_allocator.cc
@@ -4,12 +4,174 @@
#include "vm/flow_graph_allocator.h"
+#include "vm/bit_vector.h"
#include "vm/intermediate_language.h"
+#include "vm/flow_graph_compiler.h"
namespace dart {
+DEFINE_FLAG(bool, print_ssa_liveness, false,
+ "Print liveness for ssa variables.");
+
+FlowGraphAllocator::FlowGraphAllocator(
+ const GrowableArray<BlockEntryInstr*>& postorder,
+ intptr_t max_ssa_temp_index)
+ : live_out_(postorder.length()),
+ kill_(postorder.length()),
+ gen_(postorder.length()),
+ live_in_(postorder.length()),
+ postorder_(postorder),
+ vreg_count_(max_ssa_temp_index) {
+}
+
+
void FlowGraphAllocator::ResolveConstraints() {
// TODO(fschneider): Resolve register constraints.
}
+
+static intptr_t ToVirtualRegister(Instruction* instr) {
+ const Definition* def = instr->AsDefinition();
+ 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.
+ return def->ssa_temp_index();
+}
srdjan 2012/06/25 17:30:05 return (def == NULL) ? -1 : def->ssa_temp_index();
+
+
+void FlowGraphAllocator::ComputeKillAndGenSets() {
+ const intptr_t block_count = postorder_.length();
+ for (intptr_t i = 0; i < block_count; i++) {
+ BlockEntryInstr* block = postorder_[i];
+
+ BitVector* kill = kill_[i];
+ BitVector* gen = gen_[i];
srdjan 2012/06/25 17:30:05 ASSERT kill and gen are not NULL.
+
+ if (block->IsJoinEntry()) {
+ JoinEntryInstr* join = block->AsJoinEntry();
+ 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.
+ PhiInstr* phi = (*join->phis())[j];
+ if (phi == NULL) continue;
+
+ const intptr_t def = ToVirtualRegister(phi);
+ if (def >= 0) kill->Add(def);
+
+ for (intptr_t k = 0; k < phi->InputCount(); k++) {
+ Value* val = phi->InputAt(k);
+ if (!val->IsUse()) continue;
+ const intptr_t use = ToVirtualRegister(val->AsUse()->definition());
+ if (use >= 0) {
+ BlockEntryInstr* pred = block->PredecessorAt(k);
+ live_out_[pred->postorder_number()]->Add(use);
+ }
+ }
+ }
+ }
+
+ Instruction* current = block->StraightLineSuccessor();
+ // TODO(vegorov): iterate backwards.
+ while ((current != NULL) && !current->IsBlockEntry()) {
+ for (intptr_t j = 0; j < current->InputCount(); j++) {
+ Value* input = current->InputAt(j);
+ if (!input->IsUse()) continue;
+ const intptr_t use = ToVirtualRegister(input->AsUse()->definition());
+ if (use >= 0 && !kill->Contains(use)) gen->Add(use);
+ }
+
+ const intptr_t def = ToVirtualRegister(current);
+ if (def >= 0) kill->Add(def);
+
+ current = current->StraightLineSuccessor();
+ }
+
+ live_in_[i]->AddAll(gen);
+ UpdateLiveIn(block);
+ }
+}
+
+
+bool FlowGraphAllocator::UpdateLiveOut(BlockEntryInstr* instr) {
+ BitVector* live_out = live_out_[instr->postorder_number()];
+ bool changed = false;
+ 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
+ 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.
+ BlockEntryInstr* succ = last->SuccessorAt(i);
srdjan 2012/06/25 17:30:05 ASSERT(succ != NULL) ?
+ if (live_out->AddAll(live_in_[succ->postorder_number()])) {
+ changed = true;
+ }
+ }
+ return changed;
+}
+
+
+bool FlowGraphAllocator::UpdateLiveIn(BlockEntryInstr* instr) {
+ BitVector* live_out = live_out_[instr->postorder_number()];
+ BitVector* kill = kill_[instr->postorder_number()];
+ BitVector* live_in = live_in_[instr->postorder_number()];
+ return live_in->KillAndAdd(kill, live_out);
+}
+
+
+void FlowGraphAllocator::ComputeLiveInAndLiveOutSets() {
+ const intptr_t block_count = postorder_.length();
+ bool changed;
srdjan 2012/06/25 17:30:05 bool changed = false;
+ do {
+ 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
+
+ for (intptr_t i = 0; i < block_count; i++) {
+ BlockEntryInstr* block = postorder_[i];
srdjan 2012/06/25 17:30:05 Maybe add comments that you do not need to update
+ if (UpdateLiveOut(block) && UpdateLiveIn(block)) {
+ changed = true;
+ }
+ }
+ } while (changed);
+}
+
+
+void FlowGraphAllocator::AnalyzeLiveness() {
+ const intptr_t block_count = postorder_.length();
+ for (intptr_t i = 0; i < block_count; i++) {
+ live_out_.Add(new BitVector(vreg_count_));
+ kill_.Add(new BitVector(vreg_count_));
+ gen_.Add(new BitVector(vreg_count_));
+ live_in_.Add(new BitVector(vreg_count_));
+ }
+
+ ComputeKillAndGenSets();
+ ComputeLiveInAndLiveOutSets();
+
+ if (FLAG_print_ssa_liveness) {
+ DumpLiveness();
+ }
+}
+
+
+static void PrintBitVector(const char* tag, BitVector* v) {
+ 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.
+ for (BitVector::Iterator it(v); !it.Done(); it.Advance()) {
+ printf(" %d", it.Current());
Florian Schneider 2012/06/25 14:38:29 OS::Print
Vyacheslav Egorov (Google) 2012/06/25 16:58:26 Done.
+ }
+ printf("\n");
Florian Schneider 2012/06/25 14:38:29 OS::Print
Vyacheslav Egorov (Google) 2012/06/25 16:58:26 Done.
+}
+
+
+void FlowGraphAllocator::DumpLiveness() {
+ const intptr_t block_count = postorder_.length();
+ for (intptr_t i = 0; i < block_count; i++) {
+ BlockEntryInstr* block = postorder_[i];
+ printf("block @%d -> ", block->block_id());
srdjan 2012/06/25 17:30:05 OS::Print here as well.
+
+ Instruction* last = block->last_instruction();
+ for (intptr_t j = 0; j < last->SuccessorCount(); j++) {
+ BlockEntryInstr* succ = last->SuccessorAt(j);
+ printf(" @%d", succ->block_id());
+ }
+ printf("\n");
+
+ PrintBitVector(" live out", live_out_[i]);
+ PrintBitVector(" kill", kill_[i]);
+ PrintBitVector(" gen", gen_[i]);
+ 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
+ }
+}
+
+
} // namespace dart

Powered by Google App Engine
This is Rietveld 408576698