summaryrefslogtreecommitdiff
path: root/compiler/optimizing
diff options
context:
space:
mode:
author Nicolas Geoffray <ngeoffray@google.com> 2015-06-29 10:56:34 +0100
committer Nicolas Geoffray <ngeoffray@google.com> 2015-06-29 10:59:19 +0100
commit30eb58c548bee08468f68eb140a74a51dd7d9b43 (patch)
tree28412484547b9bfb4a4773df103cef5f485c3a67 /compiler/optimizing
parent8d1a8c00b89775a251ac5e26a557f81ac1491a44 (diff)
Do not update the type of something we already know.
This is both an optimization to avoid unneeded nodes, and correctness to avoid replacing the second input of `HInstanceOf` and `HCheckCast` to something that is not `HLoadClass`. bug:22116987 Change-Id: I4907197a9002883d7cae8265a9642512b6201396
Diffstat (limited to 'compiler/optimizing')
-rw-r--r--compiler/optimizing/graph_checker.cc26
-rw-r--r--compiler/optimizing/graph_checker.h4
-rw-r--r--compiler/optimizing/graph_visualizer.cc2
-rw-r--r--compiler/optimizing/reference_type_propagation.cc9
4 files changed, 40 insertions, 1 deletions
diff --git a/compiler/optimizing/graph_checker.cc b/compiler/optimizing/graph_checker.cc
index d7e6bd8161..9679d0ab70 100644
--- a/compiler/optimizing/graph_checker.cc
+++ b/compiler/optimizing/graph_checker.cc
@@ -257,6 +257,7 @@ void GraphChecker::VisitInvokeStaticOrDirect(HInvokeStaticOrDirect* invoke) {
}
void GraphChecker::VisitReturn(HReturn* ret) {
+ VisitInstruction(ret);
if (!ret->GetBlock()->GetSingleSuccessor()->IsExitBlock()) {
AddError(StringPrintf("%s:%d does not jump to the exit block.",
ret->DebugName(),
@@ -265,6 +266,7 @@ void GraphChecker::VisitReturn(HReturn* ret) {
}
void GraphChecker::VisitReturnVoid(HReturnVoid* ret) {
+ VisitInstruction(ret);
if (!ret->GetBlock()->GetSingleSuccessor()->IsExitBlock()) {
AddError(StringPrintf("%s:%d does not jump to the exit block.",
ret->DebugName(),
@@ -272,6 +274,30 @@ void GraphChecker::VisitReturnVoid(HReturnVoid* ret) {
}
}
+void GraphChecker::VisitCheckCast(HCheckCast* check) {
+ VisitInstruction(check);
+ HInstruction* input = check->InputAt(1);
+ if (!input->IsLoadClass()) {
+ AddError(StringPrintf("%s:%d expects a HLoadClass as second input, not %s:%d.",
+ check->DebugName(),
+ check->GetId(),
+ input->DebugName(),
+ input->GetId()));
+ }
+}
+
+void GraphChecker::VisitInstanceOf(HInstanceOf* instruction) {
+ VisitInstruction(instruction);
+ HInstruction* input = instruction->InputAt(1);
+ if (!input->IsLoadClass()) {
+ AddError(StringPrintf("%s:%d expects a HLoadClass as second input, not %s:%d.",
+ instruction->DebugName(),
+ instruction->GetId(),
+ input->DebugName(),
+ input->GetId()));
+ }
+}
+
void SSAChecker::VisitBasicBlock(HBasicBlock* block) {
super_type::VisitBasicBlock(block);
diff --git a/compiler/optimizing/graph_checker.h b/compiler/optimizing/graph_checker.h
index bafa69d422..7c72e23e2d 100644
--- a/compiler/optimizing/graph_checker.h
+++ b/compiler/optimizing/graph_checker.h
@@ -48,6 +48,10 @@ class GraphChecker : public HGraphDelegateVisitor {
// Check that the HasBoundsChecks() flag is set for bounds checks.
void VisitBoundsCheck(HBoundsCheck* check) OVERRIDE;
+ // Check that HCheckCast and HInstanceOf have HLoadClass as second input.
+ void VisitCheckCast(HCheckCast* check) OVERRIDE;
+ void VisitInstanceOf(HInstanceOf* check) OVERRIDE;
+
// Check that the Return and ReturnVoid jump to the exit block.
void VisitReturn(HReturn* ret) OVERRIDE;
void VisitReturnVoid(HReturnVoid* ret) OVERRIDE;
diff --git a/compiler/optimizing/graph_visualizer.cc b/compiler/optimizing/graph_visualizer.cc
index 30d61ef040..c41574c93c 100644
--- a/compiler/optimizing/graph_visualizer.cc
+++ b/compiler/optimizing/graph_visualizer.cc
@@ -462,7 +462,7 @@ class HGraphVisualizerPrinter : public HGraphVisitor {
ReferenceTypeInfo info = instruction->AsLoadClass()->GetLoadedClassRTI();
ScopedObjectAccess soa(Thread::Current());
if (info.GetTypeHandle().GetReference() != nullptr) {
- StartAttributeStream("klass") << info.GetTypeHandle().Get();
+ StartAttributeStream("klass") << PrettyClass(info.GetTypeHandle().Get());
} else {
StartAttributeStream("klass") << "unresolved";
}
diff --git a/compiler/optimizing/reference_type_propagation.cc b/compiler/optimizing/reference_type_propagation.cc
index 67840984b1..3d6606b8dc 100644
--- a/compiler/optimizing/reference_type_propagation.cc
+++ b/compiler/optimizing/reference_type_propagation.cc
@@ -151,6 +151,15 @@ void ReferenceTypePropagation::BoundTypeForIfInstanceOf(HBasicBlock* block) {
HBoundType* bound_type = nullptr;
HInstruction* obj = instanceOf->InputAt(0);
+ if (obj->GetReferenceTypeInfo().IsExact() && !obj->IsPhi()) {
+ // This method is being called while doing a fixed-point calculation
+ // over phis. Non-phis instruction whose type is already known do
+ // not need to be bound to another type.
+ // Not that this also prevents replacing `HLoadClass` with a `HBoundType`.
+ // `HCheckCast` and `HInstanceOf` expect a `HLoadClass` as a second
+ // input.
+ return;
+ }
for (HUseIterator<HInstruction*> it(obj->GetUses()); !it.Done(); it.Advance()) {
HInstruction* user = it.Current()->GetUser();
if (instanceOfTrueBlock->Dominates(user->GetBlock())) {