diff options
| -rw-r--r-- | compiler/optimizing/reference_type_propagation.cc | 25 | ||||
| -rw-r--r-- | test/450-checker-types/src/Main.java | 48 |
2 files changed, 62 insertions, 11 deletions
diff --git a/compiler/optimizing/reference_type_propagation.cc b/compiler/optimizing/reference_type_propagation.cc index ecc085b985..3b78264727 100644 --- a/compiler/optimizing/reference_type_propagation.cc +++ b/compiler/optimizing/reference_type_propagation.cc @@ -719,14 +719,35 @@ void ReferenceTypePropagation::UpdateBoundType(HBoundType* instr) { instr->SetReferenceTypeInfo(new_rti); } +// NullConstant inputs are ignored during merging as they do not provide any useful information. +// If all the inputs are NullConstants then the type of the phi will be set to Object. void ReferenceTypePropagation::UpdatePhi(HPhi* instr) { - ReferenceTypeInfo new_rti = instr->InputAt(0)->GetReferenceTypeInfo(); + size_t input_count = instr->InputCount(); + size_t first_input_index_not_null = 0; + while (first_input_index_not_null < input_count && + instr->InputAt(first_input_index_not_null)->IsNullConstant()) { + first_input_index_not_null++; + } + if (first_input_index_not_null == input_count) { + // All inputs are NullConstants, set the type to object. + // This may happen in the presence of inlining. + instr->SetReferenceTypeInfo( + ReferenceTypeInfo::Create(object_class_handle_, /* is_exact */ false)); + return; + } + + ReferenceTypeInfo new_rti = instr->InputAt(first_input_index_not_null)->GetReferenceTypeInfo(); + if (new_rti.IsValid() && new_rti.IsObjectClass() && !new_rti.IsExact()) { // Early return if we are Object and inexact. instr->SetReferenceTypeInfo(new_rti); return; } - for (size_t i = 1; i < instr->InputCount(); i++) { + + for (size_t i = first_input_index_not_null + 1; i < input_count; i++) { + if (instr->InputAt(i)->IsNullConstant()) { + continue; + } new_rti = MergeTypes(new_rti, instr->InputAt(i)->GetReferenceTypeInfo()); if (new_rti.IsValid() && new_rti.IsObjectClass()) { if (!new_rti.IsExact()) { diff --git a/test/450-checker-types/src/Main.java b/test/450-checker-types/src/Main.java index accf70ba38..cd5e5a7786 100644 --- a/test/450-checker-types/src/Main.java +++ b/test/450-checker-types/src/Main.java @@ -22,6 +22,9 @@ class Super implements Interface { public void $noinline$f() { throw new RuntimeException(); } + + public int instanceField; + } class SubclassA extends Super { @@ -549,32 +552,39 @@ public class Main { } /// CHECK-START: Main Main.getMain(boolean) reference_type_propagation (after) - /// CHECK: <<Phi:l\d+>> Phi klass:java.lang.Object + /// CHECK: <<Phi:l\d+>> Phi klass:Main /// CHECK: Return [<<Phi>>] private Main getMain(boolean cond) { return cond ? null : new Main(); } + /// CHECK-START: Super Main.getSuper(boolean, SubclassA, SubclassB) reference_type_propagation (after) + /// CHECK: <<Phi:l\d+>> Phi klass:java.lang.Object + /// CHECK: Return [<<Phi>>] + private Super getSuper(boolean cond, SubclassA a, SubclassB b) { + return cond ? a : b; + } + private Main getNull() { return null; } private int mainField = 0; - /// CHECK-START: void Main.testInlinerWidensReturnType(boolean) inliner (before) + /// CHECK-START: void Main.testInlinerWidensReturnType(boolean, SubclassA, SubclassB) inliner (before) /// CHECK: <<Int:i\d+>> IntConstant 0 - /// CHECK: <<Invoke:l\d+>> InvokeStaticOrDirect klass:Main - /// CHECK: <<NullCheck:l\d+>> NullCheck [<<Invoke>>] klass:Main exact:false + /// CHECK: <<Invoke:l\d+>> InvokeStaticOrDirect klass:Super + /// CHECK: <<NullCheck:l\d+>> NullCheck [<<Invoke>>] klass:Super exact:false /// CHECK: InstanceFieldSet [<<NullCheck>>,<<Int>>] - /// CHECK-START: void Main.testInlinerWidensReturnType(boolean) inliner (after) + /// CHECK-START: void Main.testInlinerWidensReturnType(boolean, SubclassA, SubclassB) inliner (after) /// CHECK: <<Int:i\d+>> IntConstant 0 /// CHECK: <<Phi:l\d+>> Phi klass:java.lang.Object - /// CHECK: <<NullCheck:l\d+>> NullCheck [<<Phi>>] klass:Main exact:false + /// CHECK: <<NullCheck:l\d+>> NullCheck [<<Phi>>] klass:Super exact:false /// CHECK: InstanceFieldSet [<<NullCheck>>,<<Int>>] - private void testInlinerWidensReturnType(boolean cond) { - Main o = getMain(cond); - o.mainField = 0; + private void testInlinerWidensReturnType(boolean cond, SubclassA a, SubclassB b) { + Super o = getSuper(cond, a, b); + o.instanceField = 0; } /// CHECK-START: void Main.testInlinerReturnsNull() inliner (before) @@ -593,6 +603,26 @@ public class Main { o.mainField = 0; } + /// CHECK-START: void Main.testPhiHasOnlyNullInputs(boolean) inliner (before) + /// CHECK: <<Int:i\d+>> IntConstant 0 + /// CHECK: <<Phi:l\d+>> Phi klass:Main exact:false + /// CHECK: <<NullCheck:l\d+>> NullCheck [<<Phi>>] klass:Main exact:false + /// CHECK: InstanceFieldSet [<<NullCheck>>,<<Int>>] + + /// CHECK-START: void Main.testPhiHasOnlyNullInputs(boolean) inliner (after) + /// CHECK: <<Int:i\d+>> IntConstant 0 + /// CHECK: <<Null:l\d+>> NullConstant klass:java.lang.Object + /// CHECK: <<Phi:l\d+>> Phi [<<Null>>,<<Null>>] klass:java.lang.Object exact:false + /// CHECK: <<NullCheck:l\d+>> NullCheck [<<Phi>>] klass:java.lang.Object exact:false + /// CHECK: InstanceFieldSet [<<NullCheck>>,<<Int>>] + private void testPhiHasOnlyNullInputs(boolean cond) { + Main o = cond ? null : getNull(); + o.mainField = 0; + // getSuper() will force a type propagation after inlining + // because returns a more precise type. + getSuper(); + } + public static void main(String[] args) { } } |