summaryrefslogtreecommitdiffstats
path: root/compiler/optimizing
diff options
context:
space:
mode:
authorCalin Juravle <calin@google.com>2015-04-21 13:00:25 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2015-04-21 13:00:25 +0000
commit2b25ba3ca9452415cdce88478726272aeec3f77c (patch)
tree7ccf54417f44f4442a9e41fd6d18d8a716d9b8d4 /compiler/optimizing
parentc2ea806908e205a808182b2255b6ef5433695375 (diff)
parentb3306642f42d47ddb4d021a2f48ce9b1bd235857 (diff)
downloadart-2b25ba3ca9452415cdce88478726272aeec3f77c.zip
art-2b25ba3ca9452415cdce88478726272aeec3f77c.tar.gz
art-2b25ba3ca9452415cdce88478726272aeec3f77c.tar.bz2
Merge "[optimzing] Fix codegen bug and improve type propagation"
Diffstat (limited to 'compiler/optimizing')
-rw-r--r--compiler/optimizing/code_generator_x86.cc2
-rw-r--r--compiler/optimizing/reference_type_propagation.cc87
2 files changed, 52 insertions, 37 deletions
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 87c74fb..86e84ac 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -877,7 +877,7 @@ void InstructionCodeGeneratorX86::GenerateTestAndBranch(HInstruction* instructio
if (rhs.IsRegister()) {
__ cmpl(lhs.AsRegister<Register>(), rhs.AsRegister<Register>());
} else if (rhs.IsConstant()) {
- int32_t constant = rhs.GetConstant()->AsIntConstant()->GetValue();
+ int32_t constant = CodeGenerator::GetInt32ValueOf(rhs.GetConstant());
if (constant == 0) {
__ testl(lhs.AsRegister<Register>(), lhs.AsRegister<Register>());
} else {
diff --git a/compiler/optimizing/reference_type_propagation.cc b/compiler/optimizing/reference_type_propagation.cc
index 31ddbb7..de6941c 100644
--- a/compiler/optimizing/reference_type_propagation.cc
+++ b/compiler/optimizing/reference_type_propagation.cc
@@ -58,11 +58,11 @@ void ReferenceTypePropagation::VisitBasicBlock(HBasicBlock* block) {
}
void ReferenceTypePropagation::BoundTypeForIfNotNull(HBasicBlock* block) {
- HInstruction* lastInstruction = block->GetLastInstruction();
- if (!lastInstruction->IsIf()) {
+ HIf* ifInstruction = block->GetLastInstruction()->AsIf();
+ if (ifInstruction == nullptr) {
return;
}
- HInstruction* ifInput = lastInstruction->InputAt(0);
+ HInstruction* ifInput = ifInstruction->InputAt(0);
if (!ifInput->IsNotEqual() && !ifInput->IsEqual()) {
return;
}
@@ -78,16 +78,20 @@ void ReferenceTypePropagation::BoundTypeForIfNotNull(HBasicBlock* block) {
return;
}
- HBoundType* bound_type =
- new (graph_->GetArena()) HBoundType(obj, ReferenceTypeInfo::CreateTop(false));
-
- block->InsertInstructionBefore(bound_type, lastInstruction);
+ // We only need to bound the type if we have uses in the relevant block.
+ // So start with null and create the HBoundType lazily, only if it's needed.
+ HBoundType* bound_type = nullptr;
HBasicBlock* notNullBlock = ifInput->IsNotEqual()
- ? lastInstruction->AsIf()->IfTrueSuccessor()
- : lastInstruction->AsIf()->IfFalseSuccessor();
+ ? ifInstruction->IfTrueSuccessor()
+ : ifInstruction->IfFalseSuccessor();
+
for (HUseIterator<HInstruction*> it(obj->GetUses()); !it.Done(); it.Advance()) {
HInstruction* user = it.Current()->GetUser();
if (notNullBlock->Dominates(user->GetBlock())) {
+ if (bound_type == nullptr) {
+ bound_type = new (graph_->GetArena()) HBoundType(obj, ReferenceTypeInfo::CreateTop(false));
+ notNullBlock->InsertInstructionBefore(bound_type, notNullBlock->GetFirstInstruction());
+ }
user->ReplaceInput(bound_type, it.Current()->GetIndex());
}
}
@@ -98,47 +102,58 @@ void ReferenceTypePropagation::BoundTypeForIfNotNull(HBasicBlock* block) {
// If that's the case insert an HBoundType instruction to bound the type of `x`
// to `ClassX` in the scope of the dominated blocks.
void ReferenceTypePropagation::BoundTypeForIfInstanceOf(HBasicBlock* block) {
- HInstruction* lastInstruction = block->GetLastInstruction();
- if (!lastInstruction->IsIf()) {
+ HIf* ifInstruction = block->GetLastInstruction()->AsIf();
+ if (ifInstruction == nullptr) {
return;
}
-
- HInstruction* ifInput = lastInstruction->InputAt(0);
- HInstruction* instanceOf;
- HBasicBlock* instanceOfTrueBlock;
+ HInstruction* ifInput = ifInstruction->InputAt(0);
+ HInstruction* instanceOf = nullptr;
+ HBasicBlock* instanceOfTrueBlock = nullptr;
+
+ // The instruction simplifier has transformed:
+ // - `if (a instanceof A)` into an HIf with an HInstanceOf input
+ // - `if (!(a instanceof A)` into an HIf with an HBooleanNot input (which in turn
+ // has an HInstanceOf input)
+ // So we should not see the usual HEqual here.
if (ifInput->IsInstanceOf()) {
instanceOf = ifInput;
- instanceOfTrueBlock = lastInstruction->AsIf()->IfTrueSuccessor();
+ instanceOfTrueBlock = ifInstruction->IfTrueSuccessor();
} else if (ifInput->IsBooleanNot() && ifInput->InputAt(0)->IsInstanceOf()) {
instanceOf = ifInput->InputAt(0);
- instanceOfTrueBlock = lastInstruction->AsIf()->IfFalseSuccessor();
+ instanceOfTrueBlock = ifInstruction->IfFalseSuccessor();
} else {
return;
}
- HInstruction* obj = instanceOf->InputAt(0);
- HLoadClass* load_class = instanceOf->InputAt(1)->AsLoadClass();
-
- ReferenceTypeInfo obj_rti = obj->GetReferenceTypeInfo();
- ReferenceTypeInfo class_rti = load_class->GetLoadedClassRTI();
- HBoundType* bound_type = new (graph_->GetArena()) HBoundType(obj, class_rti);
-
- // Narrow the type as much as possible.
- {
- ScopedObjectAccess soa(Thread::Current());
- if (!load_class->IsResolved() || class_rti.IsSupertypeOf(obj_rti)) {
- bound_type->SetReferenceTypeInfo(obj_rti);
- } else {
- bound_type->SetReferenceTypeInfo(
- ReferenceTypeInfo::Create(class_rti.GetTypeHandle(), /* is_exact */ false));
- }
- }
-
- block->InsertInstructionBefore(bound_type, lastInstruction);
+ // We only need to bound the type if we have uses in the relevant block.
+ // So start with null and create the HBoundType lazily, only if it's needed.
+ HBoundType* bound_type = nullptr;
+ HInstruction* obj = instanceOf->InputAt(0);
for (HUseIterator<HInstruction*> it(obj->GetUses()); !it.Done(); it.Advance()) {
HInstruction* user = it.Current()->GetUser();
if (instanceOfTrueBlock->Dominates(user->GetBlock())) {
+ if (bound_type == nullptr) {
+ HLoadClass* load_class = instanceOf->InputAt(1)->AsLoadClass();
+
+ ReferenceTypeInfo obj_rti = obj->GetReferenceTypeInfo();
+ ReferenceTypeInfo class_rti = load_class->GetLoadedClassRTI();
+ bound_type = new (graph_->GetArena()) HBoundType(obj, class_rti);
+
+ // Narrow the type as much as possible.
+ {
+ ScopedObjectAccess soa(Thread::Current());
+ if (!load_class->IsResolved() || class_rti.IsSupertypeOf(obj_rti)) {
+ bound_type->SetReferenceTypeInfo(obj_rti);
+ } else {
+ bound_type->SetReferenceTypeInfo(
+ ReferenceTypeInfo::Create(class_rti.GetTypeHandle(), /* is_exact */ false));
+ }
+ }
+
+ instanceOfTrueBlock->InsertInstructionBefore(
+ bound_type, instanceOfTrueBlock->GetFirstInstruction());
+ }
user->ReplaceInput(bound_type, it.Current()->GetIndex());
}
}