Ignore NullConstants when computing the type for Phis.
NullConstants are always typed as Object and they widen the
type of Phis unnecessarily.
Change-Id: I2b29e67617a22120642cb23d2bc6c1ff75b4e7c2
diff --git a/compiler/optimizing/reference_type_propagation.cc b/compiler/optimizing/reference_type_propagation.cc
index ecc085b..3b78264 100644
--- a/compiler/optimizing/reference_type_propagation.cc
+++ b/compiler/optimizing/reference_type_propagation.cc
@@ -719,14 +719,35 @@
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 accf70b..cd5e5a7 100644
--- a/test/450-checker-types/src/Main.java
+++ b/test/450-checker-types/src/Main.java
@@ -22,6 +22,9 @@
public void $noinline$f() {
throw new RuntimeException();
}
+
+ public int instanceField;
+
}
class SubclassA extends Super {
@@ -549,32 +552,39 @@
}
/// 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 @@
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) {
}
}