summaryrefslogtreecommitdiffstats
path: root/compiler/optimizing/ssa_builder.cc
diff options
context:
space:
mode:
authorNicolas Geoffray <ngeoffray@google.com>2014-05-22 12:50:17 +0100
committerNicolas Geoffray <ngeoffray@google.com>2014-05-26 11:31:38 +0100
commita7062e05e6048c7f817d784a5b94e3122e25b1ec (patch)
treea5d6b64ae6d5352f761fc2547bda863281adbe40 /compiler/optimizing/ssa_builder.cc
parent8b5b1e5593ffa77c393e4172b71a3d5a821d2ed8 (diff)
downloadart-a7062e05e6048c7f817d784a5b94e3122e25b1ec.zip
art-a7062e05e6048c7f817d784a5b94e3122e25b1ec.tar.gz
art-a7062e05e6048c7f817d784a5b94e3122e25b1ec.tar.bz2
Add a linear scan register allocator to the optimizing compiler.
This is a "by-the-book" implementation. It currently only deals with allocating registers, with no hint optimizations. The changes remaining to make it functional are: - Allocate spill slots. - Resolution and placements of Move instructions. - Connect it to the code generator. Change-Id: Ie0b2f6ba1b98da85425be721ce4afecd6b4012a4
Diffstat (limited to 'compiler/optimizing/ssa_builder.cc')
-rw-r--r--compiler/optimizing/ssa_builder.cc30
1 files changed, 26 insertions, 4 deletions
diff --git a/compiler/optimizing/ssa_builder.cc b/compiler/optimizing/ssa_builder.cc
index 50e3254..33084df 100644
--- a/compiler/optimizing/ssa_builder.cc
+++ b/compiler/optimizing/ssa_builder.cc
@@ -19,6 +19,18 @@
namespace art {
+static Primitive::Type MergeTypes(Primitive::Type existing, Primitive::Type new_type) {
+ // We trust the verifier has already done the necessary checking.
+ switch (existing) {
+ case Primitive::kPrimFloat:
+ case Primitive::kPrimDouble:
+ case Primitive::kPrimNot:
+ return existing;
+ default:
+ return new_type;
+ }
+}
+
void SsaBuilder::BuildSsa() {
// 1) Visit in reverse post order. We need to have all predecessors of a block visited
// (with the exception of loops) in order to create the right environment for that
@@ -32,11 +44,16 @@ void SsaBuilder::BuildSsa() {
HBasicBlock* block = loop_headers_.Get(i);
for (HInstructionIterator it(block->GetPhis()); !it.Done(); it.Advance()) {
HPhi* phi = it.Current()->AsPhi();
+ Primitive::Type type = Primitive::kPrimVoid;
for (size_t pred = 0; pred < block->GetPredecessors().Size(); pred++) {
- phi->AddInput(ValueOfLocal(block->GetPredecessors().Get(pred), phi->GetRegNumber()));
+ HInstruction* input = ValueOfLocal(block->GetPredecessors().Get(pred), phi->GetRegNumber());
+ phi->AddInput(input);
+ type = MergeTypes(type, input->GetType());
}
+ phi->SetType(type);
}
}
+ // TODO: Now that the type of loop phis is set, we need a type propagation phase.
// 3) Clear locals.
// TODO: Move this to a dead code eliminator phase.
@@ -65,7 +82,6 @@ void SsaBuilder::VisitBasicBlock(HBasicBlock* block) {
for (size_t local = 0; local < current_locals_->Size(); local++) {
HInstruction* incoming = ValueOfLocal(block->GetLoopInformation()->GetPreHeader(), local);
if (incoming != nullptr) {
- // TODO: Compute union type.
HPhi* phi = new (GetGraph()->GetArena()) HPhi(
GetGraph()->GetArena(), local, 0, Primitive::kPrimVoid);
block->AddPhi(phi);
@@ -88,12 +104,18 @@ void SsaBuilder::VisitBasicBlock(HBasicBlock* block) {
}
}
if (is_different) {
- // TODO: Compute union type.
HPhi* phi = new (GetGraph()->GetArena()) HPhi(
GetGraph()->GetArena(), local, block->GetPredecessors().Size(), Primitive::kPrimVoid);
+ Primitive::Type type = Primitive::kPrimVoid;
for (size_t i = 0; i < block->GetPredecessors().Size(); i++) {
- phi->SetRawInputAt(i, ValueOfLocal(block->GetPredecessors().Get(i), local));
+ HInstruction* value = ValueOfLocal(block->GetPredecessors().Get(i), local);
+ // We need to merge the incoming types, as the Dex format does not
+ // guarantee the inputs have the same type. In particular the 0 constant is
+ // used for all types, but the graph builder treats it as an int.
+ type = MergeTypes(type, value->GetType());
+ phi->SetRawInputAt(i, value);
}
+ phi->SetType(type);
block->AddPhi(phi);
value = phi;
}