blob: 34e82831a89233920c5ff0eaec7748b5dfce34ce [file] [log] [blame]
Aart Bikff7d89c2016-11-07 08:49:28 -08001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/**
18 * Tests properties of some string operations represented by intrinsics.
19 */
20public class Main {
21
22 static final String ABC = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
23 static final String XYZ = "XYZ";
24
25 //
26 // Variant intrinsics remain in the loop, but invariant references are hoisted out of the loop.
27 //
28 /// CHECK-START: int Main.liveIndexOf() licm (before)
29 /// CHECK-DAG: InvokeVirtual intrinsic:StringIndexOf loop:{{B\d+}} outer_loop:none
30 /// CHECK-DAG: InvokeVirtual intrinsic:StringIndexOfAfter loop:{{B\d+}} outer_loop:none
31 /// CHECK-DAG: InvokeVirtual intrinsic:StringStringIndexOf loop:{{B\d+}} outer_loop:none
32 /// CHECK-DAG: InvokeVirtual intrinsic:StringStringIndexOfAfter loop:{{B\d+}} outer_loop:none
33 //
34 /// CHECK-START: int Main.liveIndexOf() licm (after)
35 /// CHECK-DAG: InvokeVirtual intrinsic:StringIndexOf loop:{{B\d+}} outer_loop:none
36 /// CHECK-DAG: InvokeVirtual intrinsic:StringIndexOfAfter loop:{{B\d+}} outer_loop:none
37 /// CHECK-DAG: InvokeVirtual intrinsic:StringStringIndexOf loop:none
38 /// CHECK-DAG: InvokeVirtual intrinsic:StringStringIndexOfAfter loop:none
39 static int liveIndexOf() {
40 int k = ABC.length() + XYZ.length(); // does LoadString before loops
41 for (char c = 'A'; c <= 'Z'; c++) {
42 k += ABC.indexOf(c);
43 }
44 for (char c = 'A'; c <= 'Z'; c++) {
45 k += ABC.indexOf(c, 4);
46 }
47 for (char c = 'A'; c <= 'Z'; c++) {
48 k += ABC.indexOf(XYZ);
49 }
50 for (char c = 'A'; c <= 'Z'; c++) {
51 k += ABC.indexOf(XYZ, 2);
52 }
53 return k;
54 }
55
56 //
57 // All dead intrinsics can be removed completely.
58 //
59 /// CHECK-START: int Main.deadIndexOf() dead_code_elimination$initial (before)
60 /// CHECK-DAG: InvokeVirtual intrinsic:StringIndexOf loop:{{B\d+}} outer_loop:none
61 /// CHECK-DAG: InvokeVirtual intrinsic:StringIndexOfAfter loop:{{B\d+}} outer_loop:none
62 /// CHECK-DAG: InvokeVirtual intrinsic:StringStringIndexOf loop:{{B\d+}} outer_loop:none
63 /// CHECK-DAG: InvokeVirtual intrinsic:StringStringIndexOfAfter loop:{{B\d+}} outer_loop:none
64 //
65 /// CHECK-START: int Main.deadIndexOf() dead_code_elimination$initial (after)
66 /// CHECK-NOT: InvokeVirtual intrinsic:StringIndexOf
67 /// CHECK-NOT: InvokeVirtual intrinsic:StringIndexOfAfter
68 /// CHECK-NOT: InvokeVirtual intrinsic:StringStringIndexOf
69 /// CHECK-NOT: InvokeVirtual intrinsic:StringStringIndexOfAfter
70 static int deadIndexOf() {
71 int k = ABC.length() + XYZ.length(); // does LoadString before loops
72 for (char c = 'A'; c <= 'Z'; c++) {
73 int d = ABC.indexOf(c);
74 }
75 for (char c = 'A'; c <= 'Z'; c++) {
76 int d = ABC.indexOf(c, 4);
77 }
78 for (char c = 'A'; c <= 'Z'; c++) {
79 int d = ABC.indexOf(XYZ);
80 }
81 for (char c = 'A'; c <= 'Z'; c++) {
82 int d = ABC.indexOf(XYZ, 2);
83 }
84 return k;
85 }
86
87 //
88 // Explicit null check on receiver, implicit null check on argument prevents hoisting.
89 //
90 /// CHECK-START: int Main.indexOfExceptions(java.lang.String, java.lang.String) licm (after)
91 /// CHECK-DAG: <<String:l\d+>> NullCheck loop:<<Loop:B\d+>> outer_loop:none
92 /// CHECK-DAG: InvokeVirtual [<<String>>,{{l\d+}}] intrinsic:StringStringIndexOf loop:<<Loop>> outer_loop:none
93 static int indexOfExceptions(String s, String t) {
94 int k = 0;
95 for (char c = 'A'; c <= 'Z'; c++) {
96 k += s.indexOf(t);
97 }
98 return k;
99 }
100
101 public static void main(String[] args) {
102 expectEquals(1865, liveIndexOf());
103 expectEquals(29, deadIndexOf());
104 try {
105 indexOfExceptions(null, XYZ);
106 throw new Error("Expected: NPE");
107 } catch (NullPointerException e) {
108 }
109 try {
110 indexOfExceptions(ABC, null);
111 throw new Error("Expected: NPE");
112 } catch (NullPointerException e) {
113 }
114 expectEquals(598, indexOfExceptions(ABC, XYZ));
115
116 System.out.println("passed");
117 }
118
119 private static void expectEquals(int expected, int result) {
120 if (expected != result) {
121 throw new Error("Expected: " + expected + ", found: " + result);
122 }
123 }
124}