| /* |
| * 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. |
| */ |
| |
| public class Main { |
| |
| /// CHECK-START: Main Main.keepTest(Main) instruction_simplifier (before) |
| /// CHECK: NullCheck |
| /// CHECK: InvokeStaticOrDirect |
| |
| /// CHECK-START: Main Main.keepTest(Main) instruction_simplifier (after) |
| /// CHECK: NullCheck |
| /// CHECK: InvokeStaticOrDirect |
| public Main keepTest(Main m) { |
| return m.g(); |
| } |
| |
| /// CHECK-START: Main Main.thisTest() builder (after) |
| /// CHECK-NOT: NullCheck |
| /// CHECK: InvokeStaticOrDirect |
| public Main thisTest() { |
| return g(); |
| } |
| |
| /// CHECK-START: Main Main.newInstanceRemoveTest() builder (after) |
| /// CHECK: NewInstance |
| /// CHECK: InvokeStaticOrDirect |
| /// CHECK: InvokeStaticOrDirect |
| |
| /// CHECK-START: Main Main.newInstanceRemoveTest() builder (after) |
| /// CHECK-NOT: NullCheck |
| public Main newInstanceRemoveTest() { |
| Main m = new Main(); |
| return m.g(); |
| } |
| |
| /// CHECK-START: Main Main.newArrayRemoveTest() builder (after) |
| /// CHECK: NewArray |
| /// CHECK: ArrayGet |
| |
| /// CHECK-START: Main Main.newArrayRemoveTest() builder (after) |
| /// CHECK-NOT: NullCheck |
| public Main newArrayRemoveTest() { |
| Main[] ms = new Main[1]; |
| return ms[0]; |
| } |
| |
| /// CHECK-START: Main Main.ifRemoveTest(boolean) instruction_simplifier (before) |
| /// CHECK: NewInstance |
| /// CHECK: NullCheck |
| |
| /// CHECK-START: Main Main.ifRemoveTest(boolean) instruction_simplifier (after) |
| /// CHECK: NewInstance |
| /// CHECK-NOT: NullCheck |
| public Main ifRemoveTest(boolean flag) { |
| Main m = null; |
| if (flag) { |
| m = new Main(); |
| } else { |
| m = new Main(1); |
| } |
| return m.g(); |
| } |
| |
| /// CHECK-START: Main Main.ifKeepTest(boolean) instruction_simplifier (before) |
| /// CHECK: NewInstance |
| /// CHECK: NullCheck |
| |
| /// CHECK-START: Main Main.ifKeepTest(boolean) instruction_simplifier (after) |
| /// CHECK: NewInstance |
| /// CHECK: NullCheck |
| public Main ifKeepTest(boolean flag) { |
| Main m = null; |
| if (flag) { |
| m = new Main(1); |
| } |
| return m.g(); |
| } |
| |
| /// CHECK-START: Main Main.forRemoveTest(int) instruction_simplifier (before) |
| /// CHECK: NullCheck |
| |
| /// CHECK-START: Main Main.forRemoveTest(int) instruction_simplifier (after) |
| /// CHECK-NOT: NullCheck |
| public Main forRemoveTest(int count) { |
| Main a = new Main(); |
| Main m = new Main(); |
| for (int i = 0; i < count; i++) { |
| if (i % 2 == 0) { |
| m = a; |
| } |
| } |
| return m.g(); |
| } |
| |
| /// CHECK-START: Main Main.forKeepTest(int) instruction_simplifier (before) |
| /// CHECK: NullCheck |
| |
| /// CHECK-START: Main Main.forKeepTest(int) instruction_simplifier (after) |
| /// CHECK: NullCheck |
| public Main forKeepTest(int count) { |
| Main a = new Main(); |
| Main m = new Main(); |
| for (int i = 0; i < count; i++) { |
| if (i % 2 == 0) { |
| m = a; |
| } else { |
| m = null; |
| } |
| } |
| return m.g(); |
| } |
| |
| /// CHECK-START: Main Main.phiFlowRemoveTest(int) instruction_simplifier (before) |
| /// CHECK: NullCheck |
| |
| /// CHECK-START: Main Main.phiFlowRemoveTest(int) instruction_simplifier (after) |
| /// CHECK-NOT: NullCheck |
| public Main phiFlowRemoveTest(int count) { |
| Main a = new Main(); |
| Main m = new Main(); |
| for (int i = 0; i < count; i++) { |
| if (i % 2 == 0) { |
| m = a; |
| } |
| } |
| Main n = new Main(); |
| for (int i = 0; i < count; i++) { |
| if (i % 3 == 0) { |
| n = m; |
| } |
| } |
| return n.g(); |
| } |
| |
| /// CHECK-START: Main Main.phiFlowKeepTest(int) instruction_simplifier (before) |
| /// CHECK: NullCheck |
| |
| /// CHECK-START: Main Main.phiFlowKeepTest(int) instruction_simplifier (after) |
| /// CHECK: NullCheck |
| public Main phiFlowKeepTest(int count) { |
| Main a = new Main(); |
| Main m = new Main(); |
| for (int i = 0; i < count; i++) { |
| if (i % 2 == 0) { |
| m = a; |
| } else { |
| m = null; |
| } |
| } |
| Main n = new Main(); |
| for (int i = 0; i < count; i++) { |
| if (i % 3 == 0) { |
| n = m; |
| } |
| } |
| return n.g(); |
| } |
| |
| /// CHECK-START: Main Main.scopeRemoveTest(int, Main) builder (after) |
| /// CHECK-NOT: NullCheck |
| public Main scopeRemoveTest(int count, Main a) { |
| Main m = null; |
| for (int i = 0; i < count; i++) { |
| if (i % 2 == 0) { |
| m = new Main(); |
| m.g(); |
| } else { |
| m = a; |
| } |
| } |
| return m; |
| } |
| |
| /// CHECK-START: Main Main.scopeKeepTest(int, Main) instruction_simplifier (before) |
| /// CHECK: NullCheck |
| |
| /// CHECK-START: Main Main.scopeKeepTest(int, Main) instruction_simplifier (after) |
| /// CHECK: NullCheck |
| public Main scopeKeepTest(int count, Main a) { |
| Main m = new Main(); |
| for (int i = 0; i < count; i++) { |
| if (i % 2 == 0) { |
| m = a; |
| } else { |
| m = a; |
| m.g(); |
| } |
| } |
| return m; |
| } |
| |
| /// CHECK-START: Main Main.scopeIfNotNullRemove(Main) instruction_simplifier (before) |
| /// CHECK: NullCheck |
| |
| /// CHECK-START: Main Main.scopeIfNotNullRemove(Main) instruction_simplifier (after) |
| /// CHECK-NOT: NullCheck |
| public Main scopeIfNotNullRemove(Main m) { |
| if (m != null) { |
| return m.g(); |
| } |
| return m; |
| } |
| |
| /// CHECK-START: Main Main.scopeIfKeep(Main) instruction_simplifier (before) |
| /// CHECK: NullCheck |
| |
| /// CHECK-START: Main Main.scopeIfKeep(Main) instruction_simplifier (after) |
| /// CHECK: NullCheck |
| public Main scopeIfKeep(Main m) { |
| if (m == null) { |
| m = new Main(); |
| } |
| return m.g(); |
| } |
| |
| public Main() {} |
| public Main(int unused) {} |
| |
| private Main g() { |
| // avoids inlining |
| throw new RuntimeException(); |
| } |
| |
| public static void main(String[] args) { |
| new Main(); |
| } |
| |
| } |
| |
| // Regression for when we created and kept equivalent phis with the same type. |
| // The phi used in comparison would be different then the one used for access |
| // so we could not safely discard it. |
| class ListElement { |
| private ListElement next; |
| |
| /// CHECK-START: boolean ListElement.isShorter(ListElement, ListElement) instruction_simplifier (before) |
| /// CHECK: NullCheck |
| /// CHECK: NullCheck |
| |
| /// CHECK-START: boolean ListElement.isShorter(ListElement, ListElement) instruction_simplifier (after) |
| /// CHECK-NOT: NullCheck |
| static boolean isShorter(ListElement x, ListElement y) { |
| ListElement xTail = x; |
| ListElement yTail = y; |
| while (yTail != null) { |
| if (xTail == null) return true; |
| xTail = xTail.next; |
| yTail = yTail.next; |
| } |
| return false; |
| } |
| } |