summaryrefslogtreecommitdiff
path: root/compiler/optimizing
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/optimizing')
-rw-r--r--compiler/optimizing/code_generator_mips64.cc11
-rw-r--r--compiler/optimizing/ssa_builder.cc57
-rw-r--r--compiler/optimizing/ssa_builder.h25
3 files changed, 60 insertions, 33 deletions
diff --git a/compiler/optimizing/code_generator_mips64.cc b/compiler/optimizing/code_generator_mips64.cc
index 4722e42694..f4f53d5f32 100644
--- a/compiler/optimizing/code_generator_mips64.cc
+++ b/compiler/optimizing/code_generator_mips64.cc
@@ -971,11 +971,11 @@ size_t CodeGeneratorMIPS64::RestoreFloatingPointRegister(size_t stack_index, uin
}
void CodeGeneratorMIPS64::DumpCoreRegister(std::ostream& stream, int reg) const {
- stream << Mips64ManagedRegister::FromGpuRegister(GpuRegister(reg));
+ stream << GpuRegister(reg);
}
void CodeGeneratorMIPS64::DumpFloatingPointRegister(std::ostream& stream, int reg) const {
- stream << Mips64ManagedRegister::FromFpuRegister(FpuRegister(reg));
+ stream << FpuRegister(reg);
}
void CodeGeneratorMIPS64::InvokeRuntime(QuickEntrypointEnum entrypoint,
@@ -1444,12 +1444,11 @@ void InstructionCodeGeneratorMIPS64::VisitArrayLength(HArrayLength* instruction)
}
void LocationsBuilderMIPS64::VisitArraySet(HArraySet* instruction) {
- Primitive::Type value_type = instruction->GetComponentType();
- bool is_object = value_type == Primitive::kPrimNot;
+ bool needs_runtime_call = instruction->NeedsTypeCheck();
LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(
instruction,
- is_object ? LocationSummary::kCall : LocationSummary::kNoCall);
- if (is_object) {
+ needs_runtime_call ? LocationSummary::kCall : LocationSummary::kNoCall);
+ if (needs_runtime_call) {
InvokeRuntimeCallingConvention calling_convention;
locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0)));
locations->SetInAt(1, Location::RegisterLocation(calling_convention.GetRegisterAt(1)));
diff --git a/compiler/optimizing/ssa_builder.cc b/compiler/optimizing/ssa_builder.cc
index 6f71ea3d6b..0ef86d80ed 100644
--- a/compiler/optimizing/ssa_builder.cc
+++ b/compiler/optimizing/ssa_builder.cc
@@ -57,8 +57,13 @@ class DeadPhiHandling : public ValueObject {
};
bool DeadPhiHandling::UpdateType(HPhi* phi) {
+ if (phi->IsDead()) {
+ // Phi was rendered dead while waiting in the worklist because it was replaced
+ // with an equivalent.
+ return false;
+ }
+
Primitive::Type existing = phi->GetType();
- DCHECK(phi->IsLive());
bool conflict = false;
Primitive::Type new_type = existing;
@@ -112,11 +117,26 @@ bool DeadPhiHandling::UpdateType(HPhi* phi) {
phi->SetType(Primitive::kPrimVoid);
phi->SetDead();
return true;
- } else {
- DCHECK(phi->IsLive());
- phi->SetType(new_type);
- return existing != new_type;
+ } else if (existing == new_type) {
+ return false;
+ }
+
+ DCHECK(phi->IsLive());
+ phi->SetType(new_type);
+
+ // There might exist a `new_type` equivalent of `phi` already. In that case,
+ // we replace the equivalent with the, now live, `phi`.
+ HPhi* equivalent = phi->GetNextEquivalentPhiWithSameType();
+ if (equivalent != nullptr) {
+ // There cannot be more than two equivalents with the same type.
+ DCHECK(equivalent->GetNextEquivalentPhiWithSameType() == nullptr);
+ // If doing fix-point iteration, the equivalent might be in `worklist_`.
+ // Setting it dead will make UpdateType skip it.
+ equivalent->SetDead();
+ equivalent->ReplaceWith(phi);
}
+
+ return true;
}
void DeadPhiHandling::VisitBasicBlock(HBasicBlock* block) {
@@ -345,6 +365,33 @@ void SsaBuilder::BuildSsa() {
}
}
+ArenaVector<HInstruction*>* SsaBuilder::GetLocalsFor(HBasicBlock* block) {
+ DCHECK_LT(block->GetBlockId(), locals_for_.size());
+ ArenaVector<HInstruction*>* locals = &locals_for_[block->GetBlockId()];
+ const size_t vregs = GetGraph()->GetNumberOfVRegs();
+ if (locals->empty() && vregs != 0u) {
+ locals->resize(vregs, nullptr);
+
+ if (block->IsCatchBlock()) {
+ ArenaAllocator* arena = GetGraph()->GetArena();
+ // We record incoming inputs of catch phis at throwing instructions and
+ // must therefore eagerly create the phis. Phis for undefined vregs will
+ // be deleted when the first throwing instruction with the vreg undefined
+ // is encountered. Unused phis will be removed by dead phi analysis.
+ for (size_t i = 0; i < vregs; ++i) {
+ // No point in creating the catch phi if it is already undefined at
+ // the first throwing instruction.
+ if ((*current_locals_)[i] != nullptr) {
+ HPhi* phi = new (arena) HPhi(arena, i, 0, Primitive::kPrimVoid);
+ block->AddPhi(phi);
+ (*locals)[i] = phi;
+ }
+ }
+ }
+ }
+ return locals;
+}
+
HInstruction* SsaBuilder::ValueOfLocal(HBasicBlock* block, size_t local) {
ArenaVector<HInstruction*>* locals = GetLocalsFor(block);
DCHECK_LT(local, locals->size());
diff --git a/compiler/optimizing/ssa_builder.h b/compiler/optimizing/ssa_builder.h
index 804296f7ba..79f1a28ac8 100644
--- a/compiler/optimizing/ssa_builder.h
+++ b/compiler/optimizing/ssa_builder.h
@@ -61,28 +61,9 @@ class SsaBuilder : public HGraphVisitor {
void BuildSsa();
- ArenaVector<HInstruction*>* GetLocalsFor(HBasicBlock* block) {
- DCHECK_LT(block->GetBlockId(), locals_for_.size());
- ArenaVector<HInstruction*>* locals = &locals_for_[block->GetBlockId()];
- if (locals->empty() && GetGraph()->GetNumberOfVRegs() != 0u) {
- const size_t vregs = GetGraph()->GetNumberOfVRegs();
- locals->resize(vregs, nullptr);
-
- if (block->IsCatchBlock()) {
- // We record incoming inputs of catch phis at throwing instructions and
- // must therefore eagerly create the phis. Unused phis will be removed
- // in the dead phi analysis.
- ArenaAllocator* arena = GetGraph()->GetArena();
- for (size_t i = 0; i < vregs; ++i) {
- HPhi* phi = new (arena) HPhi(arena, i, 0, Primitive::kPrimVoid);
- block->AddPhi(phi);
- (*locals)[i] = phi;
- }
- }
- }
- return locals;
- }
-
+ // Returns locals vector for `block`. If it is a catch block, the vector will be
+ // prepopulated with catch phis for vregs which are defined in `current_locals_`.
+ ArenaVector<HInstruction*>* GetLocalsFor(HBasicBlock* block);
HInstruction* ValueOfLocal(HBasicBlock* block, size_t local);
void VisitBasicBlock(HBasicBlock* block);