diff options
Diffstat (limited to 'compiler/optimizing/instruction_simplifier.cc')
-rw-r--r-- | compiler/optimizing/instruction_simplifier.cc | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc index 439e3b66db..1d3c5bf9c4 100644 --- a/compiler/optimizing/instruction_simplifier.cc +++ b/compiler/optimizing/instruction_simplifier.cc @@ -1118,7 +1118,66 @@ void InstructionSimplifierVisitor::VisitAboveOrEqual(HAboveOrEqual* condition) { VisitCondition(condition); } +// Recognize the following pattern: +// obj.getClass() ==/!= Foo.class +// And replace it with a constant value if the type of `obj` is statically known. +static bool RecognizeAndSimplifyClassCheck(HCondition* condition) { + HInstruction* input_one = condition->InputAt(0); + HInstruction* input_two = condition->InputAt(1); + HLoadClass* load_class = input_one->IsLoadClass() + ? input_one->AsLoadClass() + : input_two->AsLoadClass(); + if (load_class == nullptr) { + return false; + } + + ReferenceTypeInfo class_rti = load_class->GetLoadedClassRTI(); + if (!class_rti.IsValid()) { + // Unresolved class. + return false; + } + + HInstanceFieldGet* field_get = (load_class == input_one) + ? input_two->AsInstanceFieldGet() + : input_one->AsInstanceFieldGet(); + if (field_get == nullptr) { + return false; + } + + HInstruction* receiver = field_get->InputAt(0); + ReferenceTypeInfo receiver_type = receiver->GetReferenceTypeInfo(); + if (!receiver_type.IsExact()) { + return false; + } + + { + ScopedObjectAccess soa(Thread::Current()); + ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); + ArtField* field = class_linker->GetClassRoot(ClassLinker::kJavaLangObject)->GetInstanceField(0); + DCHECK_EQ(std::string(field->GetName()), "shadow$_klass_"); + if (field_get->GetFieldInfo().GetField() != field) { + return false; + } + + // We can replace the compare. + int value = 0; + if (receiver_type.IsEqual(class_rti)) { + value = condition->IsEqual() ? 1 : 0; + } else { + value = condition->IsNotEqual() ? 1 : 0; + } + condition->ReplaceWith(condition->GetBlock()->GetGraph()->GetIntConstant(value)); + return true; + } +} + void InstructionSimplifierVisitor::VisitCondition(HCondition* condition) { + if (condition->IsEqual() || condition->IsNotEqual()) { + if (RecognizeAndSimplifyClassCheck(condition)) { + return; + } + } + // Reverse condition if left is constant. Our code generators prefer constant // on the right hand side. if (condition->GetLeft()->IsConstant() && !condition->GetRight()->IsConstant()) { |