/* * Copyright (C) 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ interface SuperInterface { void superInterfaceMethod(); } interface OtherInterface extends SuperInterface { } interface Interface extends SuperInterface { void $noinline$f(); } class Super implements Interface { public void superInterfaceMethod() {} public void $noinline$f() { throw new RuntimeException(); } public int $inline$h(boolean cond) { Super obj = (cond ? this : null); return obj.$noinline$hashCode(); } public int $noinline$hashCode() { return hashCode(); } } class SubclassA extends Super { public void $noinline$f() { throw new RuntimeException(); } public String $noinline$h() { throw new RuntimeException(); } void $noinline$g() { throw new RuntimeException(); } } class SubclassC extends SubclassA { } class SubclassB extends Super { public void $noinline$f() { throw new RuntimeException(); } void $noinline$g() { throw new RuntimeException(); } } class Generic { private A a = null; public A get() { return a; } } final class Final {} final class FinalException extends Exception {} public class Main { /// CHECK-START: void Main.testSimpleRemove() instruction_simplifier (before) /// CHECK: CheckCast /// CHECK-START: void Main.testSimpleRemove() instruction_simplifier (after) /// CHECK-NOT: CheckCast public void testSimpleRemove() { Super s = new SubclassA(); ((SubclassA)s).$noinline$g(); } /// CHECK-START: void Main.testSimpleKeep(Super) instruction_simplifier (before) /// CHECK: CheckCast /// CHECK-START: void Main.testSimpleKeep(Super) instruction_simplifier (after) /// CHECK: CheckCast public void testSimpleKeep(Super s) { ((SubclassA)s).$noinline$f(); } /// CHECK-START: java.lang.String Main.testClassRemove() instruction_simplifier (before) /// CHECK: CheckCast /// CHECK-START: java.lang.String Main.testClassRemove() instruction_simplifier (after) /// CHECK-NOT: CheckCast public String testClassRemove() { Object s = SubclassA.class; return ((Class)s).getName(); } /// CHECK-START: java.lang.String Main.testClassKeep() instruction_simplifier (before) /// CHECK: CheckCast /// CHECK-START: java.lang.String Main.testClassKeep() instruction_simplifier (after) /// CHECK: CheckCast public String testClassKeep() { Object s = SubclassA.class; return ((SubclassA)s).$noinline$h(); } /// CHECK-START: void Main.testIfRemove(int) instruction_simplifier (before) /// CHECK: CheckCast /// CHECK-START: void Main.testIfRemove(int) instruction_simplifier (after) /// CHECK-NOT: CheckCast public void testIfRemove(int x) { Super s; if (x % 2 == 0) { s = new SubclassA(); } else { s = new SubclassC(); } ((SubclassA)s).$noinline$g(); } /// CHECK-START: void Main.testIfKeep(int) instruction_simplifier (before) /// CHECK: CheckCast /// CHECK-START: void Main.testIfKeep(int) instruction_simplifier (after) /// CHECK: CheckCast public void testIfKeep(int x) { Super s; if (x % 2 == 0) { s = new SubclassA(); } else { s = new SubclassB(); } ((SubclassA)s).$noinline$g(); } /// CHECK-START: void Main.testForRemove(int) instruction_simplifier (before) /// CHECK: CheckCast /// CHECK-START: void Main.testForRemove(int) instruction_simplifier (after) /// CHECK-NOT: CheckCast public void testForRemove(int x) { Super s = new SubclassA(); for (int i = 0 ; i < x; i++) { if (x % 2 == 0) { s = new SubclassC(); } } ((SubclassA)s).$noinline$g(); } /// CHECK-START: void Main.testForKeep(int) instruction_simplifier (before) /// CHECK: CheckCast /// CHECK-START: void Main.testForKeep(int) instruction_simplifier (after) /// CHECK: CheckCast public void testForKeep(int x) { Super s = new SubclassA(); for (int i = 0 ; i < x; i++) { if (x % 2 == 0) { s = new SubclassC(); } } ((SubclassC)s).$noinline$g(); } /// CHECK-START: void Main.testPhiFromCall(int) instruction_simplifier (before) /// CHECK: CheckCast /// CHECK-START: void Main.testPhiFromCall(int) instruction_simplifier (after) /// CHECK: CheckCast public void testPhiFromCall(int i) { Object x; if (i % 2 == 0) { x = new SubclassC(); } else { x = newObject(); // this one will have an unknown type. } ((SubclassC)x).$noinline$g(); } /// CHECK-START: void Main.testInstanceOf(java.lang.Object) instruction_simplifier (before) /// CHECK: CheckCast /// CHECK: CheckCast /// CHECK-NOT: CheckCast /// CHECK-START: void Main.testInstanceOf(java.lang.Object) instruction_simplifier (after) /// CHECK-NOT: CheckCast public void testInstanceOf(Object o) { if (o instanceof SubclassC) { ((SubclassC)o).$noinline$g(); } if (o instanceof SubclassB) { ((SubclassB)o).$noinline$g(); } } public static boolean $inline$InstanceofSubclassB(Object o) { return o instanceof SubclassB; } public static boolean $inline$InstanceofSubclassC(Object o) { return o instanceof SubclassC; } /// CHECK-START: void Main.testInstanceOf_NotInlined(java.lang.Object) builder (after) /// CHECK-DAG: <> IntConstant 0 /// CHECK-DAG: <> IntConstant 1 /// CHECK-DAG: <> InstanceOf /// CHECK-DAG: NotEqual [<>,<>] /// CHECK-DAG: <> InstanceOf /// CHECK-DAG: Equal [<>,<>] /// CHECK-START: void Main.testInstanceOf_NotInlined(java.lang.Object) instruction_simplifier (before) /// CHECK: CheckCast /// CHECK: CheckCast /// CHECK-NOT: CheckCast /// CHECK-START: void Main.testInstanceOf_NotInlined(java.lang.Object) instruction_simplifier (after) /// CHECK-NOT: CheckCast public void testInstanceOf_NotInlined(Object o) { if ((o instanceof SubclassC) == true) { ((SubclassC)o).$noinline$g(); } if ((o instanceof SubclassB) != false) { ((SubclassB)o).$noinline$g(); } } /// CHECK-START: void Main.testNotInstanceOf_NotInlined(java.lang.Object) builder (after) /// CHECK-DAG: <> IntConstant 0 /// CHECK-DAG: <> IntConstant 1 /// CHECK-DAG: <> InstanceOf /// CHECK-DAG: Equal [<>,<>] /// CHECK-DAG: <> InstanceOf /// CHECK-DAG: NotEqual [<>,<>] /// CHECK-START: void Main.testNotInstanceOf_NotInlined(java.lang.Object) instruction_simplifier (before) /// CHECK: CheckCast /// CHECK: CheckCast /// CHECK-NOT: CheckCast /// CHECK-START: void Main.testNotInstanceOf_NotInlined(java.lang.Object) instruction_simplifier (after) /// CHECK-NOT: CheckCast public void testNotInstanceOf_NotInlined(Object o) { if ((o instanceof SubclassC) != true) { // Empty branch to flip the condition. } else { ((SubclassC)o).$noinline$g(); } if ((o instanceof SubclassB) == false) { // Empty branch to flip the condition. } else { ((SubclassB)o).$noinline$g(); } } /// CHECK-START: void Main.testInstanceOf_Inlined(java.lang.Object) inliner (after) /// CHECK-DAG: <> InstanceOf /// CHECK-DAG: If [<>] /// CHECK-START: void Main.testInstanceOf_Inlined(java.lang.Object) instruction_simplifier$after_inlining (before) /// CHECK: CheckCast /// CHECK-NOT: CheckCast /// CHECK-START: void Main.testInstanceOf_Inlined(java.lang.Object) instruction_simplifier$after_inlining (after) /// CHECK-NOT: CheckCast public void testInstanceOf_Inlined(Object o) { if (!$inline$InstanceofSubclassC(o)) { // Empty branch to flip the condition. } else { ((SubclassC)o).$noinline$g(); } } /// CHECK-START: void Main.testInstanceOfKeep(java.lang.Object) instruction_simplifier (before) /// CHECK: CheckCast /// CHECK: CheckCast /// CHECK-START: void Main.testInstanceOfKeep(java.lang.Object) instruction_simplifier (after) /// CHECK: CheckCast /// CHECK: CheckCast public void testInstanceOfKeep(Object o) { if (o instanceof SubclassC) { ((SubclassB)o).$noinline$g(); } if (o instanceof SubclassB) { ((SubclassA)o).$noinline$g(); } } /// CHECK-START: void Main.testInstanceOfNested(java.lang.Object) instruction_simplifier (before) /// CHECK: CheckCast /// CHECK: CheckCast /// CHECK-START: void Main.testInstanceOfNested(java.lang.Object) instruction_simplifier (after) /// CHECK-NOT: CheckCast public void testInstanceOfNested(Object o) { if (o instanceof SubclassC) { if (o instanceof SubclassB) { ((SubclassB)o).$noinline$g(); } else { ((SubclassC)o).$noinline$g(); } } } /// CHECK-START: void Main.testInstanceOfWithPhi(int) instruction_simplifier (before) /// CHECK: CheckCast /// CHECK-START: void Main.testInstanceOfWithPhi(int) instruction_simplifier (after) /// CHECK-NOT: CheckCast public void testInstanceOfWithPhi(int i) { Object o; if (i == 0) { o = new SubclassA(); } else { o = new SubclassB(); } if (o instanceof SubclassB) { ((SubclassB)o).$noinline$g(); } } /// CHECK-START: void Main.testInstanceOfInFor(int) instruction_simplifier (before) /// CHECK: CheckCast /// CHECK-START: void Main.testInstanceOfInFor(int) instruction_simplifier (after) /// CHECK-NOT: CheckCast public void testInstanceOfInFor(int n) { Object o = new SubclassA(); for (int i = 0; i < n; i++) { if (i / 2 == 0) { o = new SubclassB(); } if (o instanceof SubclassB) { ((SubclassB)o).$noinline$g(); } } } /// CHECK-START: void Main.testInstanceOfSubclass() instruction_simplifier (before) /// CHECK: CheckCast /// CHECK-START: void Main.testInstanceOfSubclass() instruction_simplifier (after) /// CHECK-NOT: CheckCast public void testInstanceOfSubclass() { Object o = new SubclassA(); if (o instanceof Super) { ((SubclassA)o).$noinline$g(); } } /// CHECK-START: void Main.testInstanceOfWithPhiSubclass(int) instruction_simplifier (before) /// CHECK: CheckCast /// CHECK-START: void Main.testInstanceOfWithPhiSubclass(int) instruction_simplifier (after) /// CHECK-NOT: CheckCast public void testInstanceOfWithPhiSubclass(int i) { Object o; if (i == 0) { o = new SubclassA(); } else { o = new SubclassC(); } if (o instanceof Super) { ((SubclassA)o).$noinline$g(); } } /// CHECK-START: void Main.testInstanceOfWithPhiTop(int) instruction_simplifier (before) /// CHECK: CheckCast /// CHECK-START: void Main.testInstanceOfWithPhiTop(int) instruction_simplifier (after) /// CHECK-NOT: CheckCast public void testInstanceOfWithPhiTop(int i) { Object o; if (i == 0) { o = new Object(); } else { o = new SubclassC(); } if (o instanceof Super) { ((Super)o).$noinline$f(); } } /// CHECK-START: void Main.testInstanceOfSubclassInFor(int) instruction_simplifier (before) /// CHECK: CheckCast /// CHECK-START: void Main.testInstanceOfSubclassInFor(int) instruction_simplifier (after) /// CHECK-NOT: CheckCast public void testInstanceOfSubclassInFor(int n) { Object o = new SubclassA(); for (int i = 0; i < n; i++) { if (o instanceof Super) { ((SubclassA)o).$noinline$g(); } if (i / 2 == 0) { o = new SubclassC(); } } } /// CHECK-START: void Main.testInstanceOfTopInFor(int) instruction_simplifier (before) /// CHECK: CheckCast /// CHECK-START: void Main.testInstanceOfTopInFor(int) instruction_simplifier (after) /// CHECK-NOT: CheckCast public void testInstanceOfTopInFor(int n) { Object o = new SubclassA(); for (int i = 0; i < n; i++) { if (o instanceof Super) { ((Super)o).$noinline$f(); } if (i / 2 == 0) { o = new Object(); } } } public Object newObject() { try { return Object.class.newInstance(); } catch (Exception e) { return null; } } public SubclassA a = new SubclassA(); public static SubclassA b = new SubclassA(); /// CHECK-START: void Main.testInstanceFieldGetSimpleRemove() instruction_simplifier (before) /// CHECK: CheckCast /// CHECK-START: void Main.testInstanceFieldGetSimpleRemove() instruction_simplifier (after) /// CHECK-NOT: CheckCast public void testInstanceFieldGetSimpleRemove() { Main m = new Main(); Super a = m.a; ((SubclassA)a).$noinline$g(); } /// CHECK-START: void Main.testStaticFieldGetSimpleRemove() instruction_simplifier (before) /// CHECK: CheckCast /// CHECK-START: void Main.testStaticFieldGetSimpleRemove() instruction_simplifier (after) /// CHECK-NOT: CheckCast public void testStaticFieldGetSimpleRemove() { Super b = Main.b; ((SubclassA)b).$noinline$g(); } public SubclassA $noinline$getSubclass() { throw new RuntimeException(); } /// CHECK-START: void Main.testArraySimpleRemove() instruction_simplifier (before) /// CHECK: CheckCast /// CHECK-START: void Main.testArraySimpleRemove() instruction_simplifier (after) /// CHECK-NOT: CheckCast public void testArraySimpleRemove() { Super[] b = new SubclassA[10]; SubclassA[] c = (SubclassA[])b; } /// CHECK-START: void Main.testInvokeSimpleRemove() instruction_simplifier (before) /// CHECK: CheckCast /// CHECK-START: void Main.testInvokeSimpleRemove() instruction_simplifier (after) /// CHECK-NOT: CheckCast public void testInvokeSimpleRemove() { Super b = $noinline$getSubclass(); ((SubclassA)b).$noinline$g(); } /// CHECK-START: void Main.testArrayGetSimpleRemove() instruction_simplifier (before) /// CHECK: CheckCast /// CHECK-START: void Main.testArrayGetSimpleRemove() instruction_simplifier (after) /// CHECK-NOT: CheckCast public void testArrayGetSimpleRemove() { Super[] a = new SubclassA[10]; ((SubclassA)a[0]).$noinline$g(); } /// CHECK-START: int Main.testLoadExceptionInCatchNonExact(int, int) builder (after) /// CHECK: LoadException klass:java.lang.ArithmeticException can_be_null:false exact:false public int testLoadExceptionInCatchNonExact(int x, int y) { try { return x / y; } catch (ArithmeticException ex) { return ex.hashCode(); } } /// CHECK-START: int Main.testLoadExceptionInCatchExact(int) builder (after) /// CHECK: LoadException klass:FinalException can_be_null:false exact:true public int testLoadExceptionInCatchExact(int x) { try { if (x == 42) { throw new FinalException(); } else { return x; } } catch (FinalException ex) { return ex.hashCode(); } } /// CHECK-START: int Main.testLoadExceptionInCatchAll(int, int) builder (after) /// CHECK: LoadException klass:java.lang.Throwable can_be_null:false exact:false public int testLoadExceptionInCatchAll(int x, int y) { try { x = x / y; } finally { return x; } } private Generic genericC = new Generic(); private Generic genericFinal = new Generic(); private SubclassC get() { return genericC.get(); } private Final getFinal() { return genericFinal.get(); } /// CHECK-START: SubclassC Main.inlineGenerics() builder (after) /// CHECK: <> InvokeStaticOrDirect klass:SubclassC exact:false /// CHECK-NEXT: Return [<>] /// CHECK-START: SubclassC Main.inlineGenerics() inliner (after) /// CHECK: <> BoundType klass:SubclassC exact:false /// CHECK: Return [<>] private SubclassC inlineGenerics() { SubclassC c = get(); return c; } /// CHECK-START: Final Main.inlineGenericsFinal() builder (after) /// CHECK: <> InvokeStaticOrDirect klass:Final exact:true /// CHECK-NEXT: Return [<>] /// CHECK-START: Final Main.inlineGenericsFinal() inliner (after) /// CHECK: <> BoundType klass:Final exact:true /// CHECK: Return [<>] private Final inlineGenericsFinal() { Final f = getFinal(); return f; } /// CHECK-START: void Main.boundOnlyOnceIfNotNull(java.lang.Object) inliner (after) /// CHECK: BoundType /// CHECK-NOT: BoundType private void boundOnlyOnceIfNotNull(Object o) { if (o != null) { o.toString(); } } /// CHECK-START: void Main.boundOnlyOnceIfInstanceOf(java.lang.Object) inliner (after) /// CHECK: BoundType /// CHECK-NOT: BoundType private void boundOnlyOnceIfInstanceOf(Object o) { if (o instanceof Main) { o.toString(); } } /// CHECK-START: Final Main.boundOnlyOnceCheckCast(Generic) inliner (after) /// CHECK: BoundType /// CHECK-NOT: BoundType private Final boundOnlyOnceCheckCast(Generic o) { Final f = o.get(); return f; } private Super getSuper() { return new SubclassA(); } /// CHECK-START: void Main.updateNodesInTheSameBlockAsPhi(boolean) builder (after) /// CHECK: <> Phi klass:Super /// CHECK: NullCheck [<>] klass:Super /// CHECK-START: void Main.updateNodesInTheSameBlockAsPhi(boolean) inliner (after) /// CHECK: <> Phi klass:SubclassA /// CHECK: NullCheck [<>] klass:SubclassA private void updateNodesInTheSameBlockAsPhi(boolean cond) { Super s = getSuper(); if (cond) { s = new SubclassA(); } s.$noinline$f(); } /// CHECK-START: java.lang.String Main.checkcastPreserveNullCheck(java.lang.Object) inliner (after) /// CHECK: <> ParameterValue /// CHECK: <> ParameterValue /// CHECK: <> LoadClass /// CHECK: CheckCast [<>,<>] /// CHECK: BoundType [<>] can_be_null:true /// CHECK-START: java.lang.String Main.checkcastPreserveNullCheck(java.lang.Object) instruction_simplifier (after) /// CHECK: <> ParameterValue /// CHECK: <> ParameterValue /// CHECK: <> LoadClass /// CHECK: CheckCast [<>,<>] /// CHECK: <> BoundType [<>] /// CHECK: NullCheck [<>] public String checkcastPreserveNullCheck(Object a) { return ((SubclassA)a).toString(); } /// CHECK-START: void Main.argumentCheck(Super, double, SubclassA, Final) builder (after) /// CHECK: ParameterValue klass:Main can_be_null:false exact:false /// CHECK: ParameterValue klass:Super can_be_null:true exact:false /// CHECK: ParameterValue /// CHECK: ParameterValue klass:SubclassA can_be_null:true exact:false /// CHECK: ParameterValue klass:Final can_be_null:true exact:true /// CHECK-NOT: ParameterValue private void argumentCheck(Super s, double d, SubclassA a, Final f) { } private Main getNull() { return null; } private int mainField = 0; /// CHECK-START: SuperInterface Main.getWiderType(boolean, Interface, OtherInterface) builder (after) /// CHECK: <> Phi klass:java.lang.Object /// CHECK: Return [<>] private SuperInterface getWiderType(boolean cond, Interface a, OtherInterface b) { return cond ? a : b; } /// CHECK-START: void Main.testInlinerWidensReturnType(boolean, Interface, OtherInterface) inliner (before) /// CHECK: <> InvokeStaticOrDirect klass:SuperInterface /// CHECK: <> NullCheck [<>] klass:SuperInterface exact:false /// CHECK: InvokeInterface [<>] /// CHECK-START: void Main.testInlinerWidensReturnType(boolean, Interface, OtherInterface) inliner (after) /// CHECK: <> Phi klass:java.lang.Object /// CHECK: <> NullCheck [<>] klass:SuperInterface exact:false /// CHECK: InvokeInterface [<>] private void testInlinerWidensReturnType(boolean cond, Interface a, OtherInterface b) { getWiderType(cond, a, b).superInterfaceMethod(); } /// CHECK-START: void Main.testInlinerReturnsNull() inliner (before) /// CHECK: <> IntConstant 0 /// CHECK: <> InvokeStaticOrDirect klass:Main /// CHECK: <> NullCheck [<>] klass:Main exact:false /// CHECK: InstanceFieldSet [<>,<>] /// CHECK-START: void Main.testInlinerReturnsNull() inliner (after) /// CHECK: <> IntConstant 0 /// CHECK: <> NullConstant klass:java.lang.Object /// CHECK: <> NullCheck [<>] klass:Main exact:false /// CHECK: InstanceFieldSet [<>,<>] private void testInlinerReturnsNull() { Main o = getNull(); o.mainField = 0; } /// CHECK-START: void Main.testThisArgumentMoreSpecific(boolean) inliner (before) /// CHECK-DAG: <> NewInstance /// CHECK-DAG: InvokeVirtual [<>,{{z\d+}}] method_name:Super.$inline$h /// CHECK-START: void Main.testThisArgumentMoreSpecific(boolean) inliner (after) /// CHECK-DAG: <> NewInstance /// CHECK-DAG: <> NullConstant /// CHECK-DAG: <> Phi [<>,<>] klass:SubclassA /// CHECK-DAG: <> NullCheck [<>] /// CHECK-DAG: InvokeVirtual [<>] method_name:Super.$noinline$hashCode public void testThisArgumentMoreSpecific(boolean cond) { // Inlining method from Super will build it with `this` typed as Super. // Running RTP will sharpen it to SubclassA. SubclassA obj = new SubclassA(); ((Super) obj).$inline$h(cond); } public static int $inline$hashCode(Super obj) { return obj.hashCode(); } /// CHECK-START: void Main.testExplicitArgumentMoreSpecific(SubclassA) inliner (before) /// CHECK-DAG: <> ParameterValue klass:SubclassA // Note: The ArtMethod* (typed as int or long) is optional after sharpening. /// CHECK-DAG: InvokeStaticOrDirect [<>{{(,[ij]\d+)?}}] method_name:Main.$inline$hashCode /// CHECK-START: void Main.testExplicitArgumentMoreSpecific(SubclassA) inliner (after) /// CHECK-DAG: <> ParameterValue klass:SubclassA /// CHECK-DAG: <> NullCheck [<>] klass:SubclassA /// CHECK-DAG: InvokeVirtual [<>] method_name:java.lang.Object.hashCode public static void testExplicitArgumentMoreSpecific(SubclassA obj) { // Inlining a method will build it with reference types from its signature, // here the callee graph is built with Super as the type of its only argument. // Running RTP after its ParameterValue instructions are replaced with actual // arguments will type the inner graph more precisely. $inline$hashCode(obj); } /// CHECK-START: void Main.testPhiHasOnlyNullInputs(boolean) inliner (before) /// CHECK: <> IntConstant 0 /// CHECK: <> Phi klass:Main exact:false /// CHECK: <> NullCheck [<>] klass:Main exact:false /// CHECK: InstanceFieldSet [<>,<>] /// CHECK-START: void Main.testPhiHasOnlyNullInputs(boolean) inliner (after) /// CHECK: <> IntConstant 0 /// CHECK: <> NullConstant klass:java.lang.Object /// CHECK: <> Phi [<>,<>] klass:java.lang.Object exact:false /// CHECK: <> NullCheck [<>] klass:java.lang.Object exact:false /// CHECK: InstanceFieldSet [<>,<>] 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(); } /// CHECK-START: void Main.testLoopPhiWithNullFirstInput(boolean) builder (after) /// CHECK-DAG: <> NullConstant /// CHECK-DAG: <> NewInstance klass:Main exact:true /// CHECK-DAG: <> Phi [<>,<>,<
>] klass:Main exact:true private void testLoopPhiWithNullFirstInput(boolean cond) { Main a = null; while (a == null) { if (cond) { a = new Main(); } } } /// CHECK-START: java.lang.Object[] Main.testInstructionsWithUntypedParent() builder (after) /// CHECK-DAG: <> NullConstant /// CHECK-DAG: <> Phi [<>,<>] klass:java.lang.Object[] exact:true /// CHECK-DAG: <> NewArray klass:java.lang.Object[] exact:true /// CHECK-DAG: <> Phi [<>,<>] klass:java.lang.Object[] exact:true /// CHECK-DAG: <> NullCheck [<>] klass:java.lang.Object[] exact:true /// CHECK-DAG: ArrayGet [<>,{{i\d+}}] klass:java.lang.Object exact:false private Object[] testInstructionsWithUntypedParent() { Object[] array = null; boolean cond = true; for (int i = 0; i < 10; ++i) { if (cond) { array = new Object[10]; array[0] = new Object(); cond = false; } else { array[i] = array[0]; } } return array; } public static void main(String[] args) { } }