xref: /aosp_15_r20/art/test/624-checker-stringops/src/Main.java (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2016 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker import java.lang.reflect.Method;
17*795d594fSAndroid Build Coastguard Worker 
18*795d594fSAndroid Build Coastguard Worker /**
19*795d594fSAndroid Build Coastguard Worker  * Tests properties of some string operations represented by intrinsics.
20*795d594fSAndroid Build Coastguard Worker  */
21*795d594fSAndroid Build Coastguard Worker public class Main {
22*795d594fSAndroid Build Coastguard Worker 
23*795d594fSAndroid Build Coastguard Worker   static final String ABC = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
24*795d594fSAndroid Build Coastguard Worker   static final String XYZ = "XYZ";
25*795d594fSAndroid Build Coastguard Worker 
26*795d594fSAndroid Build Coastguard Worker   //
27*795d594fSAndroid Build Coastguard Worker   // Variant intrinsics remain in the loop, but invariant references are hoisted out of the loop.
28*795d594fSAndroid Build Coastguard Worker   //
29*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: int Main.liveIndexOf() licm (before)
30*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: InvokeVirtual intrinsic:StringIndexOf                   loop:{{B\d+}} outer_loop:none
31*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: InvokeVirtual intrinsic:StringIndexOfAfter              loop:{{B\d+}} outer_loop:none
32*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: InvokeStaticOrDirect intrinsic:StringStringIndexOf      loop:{{B\d+}} outer_loop:none
33*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: InvokeStaticOrDirect intrinsic:StringStringIndexOfAfter loop:{{B\d+}} outer_loop:none
34*795d594fSAndroid Build Coastguard Worker   //
35*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: int Main.liveIndexOf() licm (after)
36*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: InvokeVirtual intrinsic:StringIndexOf                   loop:{{B\d+}} outer_loop:none
37*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: InvokeVirtual intrinsic:StringIndexOfAfter              loop:{{B\d+}} outer_loop:none
38*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: InvokeStaticOrDirect intrinsic:StringStringIndexOf      loop:none
39*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: InvokeStaticOrDirect intrinsic:StringStringIndexOfAfter loop:none
liveIndexOf()40*795d594fSAndroid Build Coastguard Worker   static int liveIndexOf() {
41*795d594fSAndroid Build Coastguard Worker     int k = ABC.length() + XYZ.length();  // does LoadString before loops
42*795d594fSAndroid Build Coastguard Worker     for (char c = 'A'; c <= 'Z'; c++) {
43*795d594fSAndroid Build Coastguard Worker       k += ABC.indexOf(c);
44*795d594fSAndroid Build Coastguard Worker     }
45*795d594fSAndroid Build Coastguard Worker     for (char c = 'A'; c <= 'Z'; c++) {
46*795d594fSAndroid Build Coastguard Worker       k += ABC.indexOf(c, 4);
47*795d594fSAndroid Build Coastguard Worker     }
48*795d594fSAndroid Build Coastguard Worker     for (char c = 'A'; c <= 'Z'; c++) {
49*795d594fSAndroid Build Coastguard Worker       k += ABC.indexOf(XYZ);
50*795d594fSAndroid Build Coastguard Worker     }
51*795d594fSAndroid Build Coastguard Worker     for (char c = 'A'; c <= 'Z'; c++) {
52*795d594fSAndroid Build Coastguard Worker       k += ABC.indexOf(XYZ, 2);
53*795d594fSAndroid Build Coastguard Worker     }
54*795d594fSAndroid Build Coastguard Worker     return k;
55*795d594fSAndroid Build Coastguard Worker   }
56*795d594fSAndroid Build Coastguard Worker 
57*795d594fSAndroid Build Coastguard Worker   //
58*795d594fSAndroid Build Coastguard Worker   // All dead intrinsics can be removed completely.
59*795d594fSAndroid Build Coastguard Worker   //
60*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: int Main.deadIndexOf() dead_code_elimination$initial (before)
61*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: InvokeVirtual intrinsic:StringIndexOf            loop:{{B\d+}} outer_loop:none
62*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: InvokeVirtual intrinsic:StringIndexOfAfter       loop:{{B\d+}} outer_loop:none
63*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: InvokeVirtual intrinsic:StringStringIndexOf      loop:{{B\d+}} outer_loop:none
64*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: InvokeVirtual intrinsic:StringStringIndexOfAfter loop:{{B\d+}} outer_loop:none
65*795d594fSAndroid Build Coastguard Worker   //
66*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: int Main.deadIndexOf() dead_code_elimination$initial (after)
67*795d594fSAndroid Build Coastguard Worker   /// CHECK-NOT: InvokeVirtual intrinsic:StringIndexOf
68*795d594fSAndroid Build Coastguard Worker   /// CHECK-NOT: InvokeVirtual intrinsic:StringIndexOfAfter
69*795d594fSAndroid Build Coastguard Worker   /// CHECK-NOT: InvokeVirtual intrinsic:StringStringIndexOf
70*795d594fSAndroid Build Coastguard Worker   /// CHECK-NOT: InvokeVirtual intrinsic:StringStringIndexOfAfter
deadIndexOf()71*795d594fSAndroid Build Coastguard Worker   static int deadIndexOf() {
72*795d594fSAndroid Build Coastguard Worker     int k = ABC.length() + XYZ.length();  // does LoadString before loops
73*795d594fSAndroid Build Coastguard Worker     for (char c = 'A'; c <= 'Z'; c++) {
74*795d594fSAndroid Build Coastguard Worker       int d = ABC.indexOf(c);
75*795d594fSAndroid Build Coastguard Worker     }
76*795d594fSAndroid Build Coastguard Worker     for (char c = 'A'; c <= 'Z'; c++) {
77*795d594fSAndroid Build Coastguard Worker       int d = ABC.indexOf(c, 4);
78*795d594fSAndroid Build Coastguard Worker     }
79*795d594fSAndroid Build Coastguard Worker     for (char c = 'A'; c <= 'Z'; c++) {
80*795d594fSAndroid Build Coastguard Worker       int d = ABC.indexOf(XYZ);
81*795d594fSAndroid Build Coastguard Worker     }
82*795d594fSAndroid Build Coastguard Worker     for (char c = 'A'; c <= 'Z'; c++) {
83*795d594fSAndroid Build Coastguard Worker       int d = ABC.indexOf(XYZ, 2);
84*795d594fSAndroid Build Coastguard Worker     }
85*795d594fSAndroid Build Coastguard Worker     return k;
86*795d594fSAndroid Build Coastguard Worker   }
87*795d594fSAndroid Build Coastguard Worker 
88*795d594fSAndroid Build Coastguard Worker   //
89*795d594fSAndroid Build Coastguard Worker   // Explicit null check on receiver, implicit null check on argument prevents hoisting.
90*795d594fSAndroid Build Coastguard Worker   //
91*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: int Main.indexOfExceptions(java.lang.String, java.lang.String) licm (after)
92*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<String:l\d+>> NullCheck                                                                loop:<<Loop:B\d+>> outer_loop:none
93*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                 InvokeStaticOrDirect [<<String>>,{{l\d+}}] intrinsic:StringStringIndexOf loop:<<Loop>>      outer_loop:none
indexOfExceptions(String s, String t)94*795d594fSAndroid Build Coastguard Worker   static int indexOfExceptions(String s, String t) {
95*795d594fSAndroid Build Coastguard Worker     int k = 0;
96*795d594fSAndroid Build Coastguard Worker     for (char c = 'A'; c <= 'Z'; c++) {
97*795d594fSAndroid Build Coastguard Worker       k += s.indexOf(t);
98*795d594fSAndroid Build Coastguard Worker     }
99*795d594fSAndroid Build Coastguard Worker     return k;
100*795d594fSAndroid Build Coastguard Worker   }
101*795d594fSAndroid Build Coastguard Worker 
102*795d594fSAndroid Build Coastguard Worker   //
103*795d594fSAndroid Build Coastguard Worker   // Allows combining of returned "this". Also ensures that similar looking append() calls
104*795d594fSAndroid Build Coastguard Worker   // are not combined somehow through returned result.
105*795d594fSAndroid Build Coastguard Worker   //
106*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: int Main.bufferLen2() instruction_simplifier (before)
107*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<New:l\d+>>     NewInstance
108*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<String1:l\d+>> LoadString
109*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<Append1:l\d+>> InvokeVirtual [<<New>>,<<String1>>]  intrinsic:StringBufferAppend
110*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<String2:l\d+>> LoadString
111*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<Append2:l\d+>> InvokeVirtual [{{l\d+}},<<String2>>] intrinsic:StringBufferAppend
112*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                  InvokeVirtual [{{l\d+}}]             intrinsic:StringBufferLength
113*795d594fSAndroid Build Coastguard Worker   //
114*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: int Main.bufferLen2() instruction_simplifier (after)
115*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<New:l\d+>>     NewInstance
116*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<String1:l\d+>> LoadString
117*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<Append1:l\d+>> InvokeVirtual [<<New>>,<<String1>>] intrinsic:StringBufferAppend
118*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<String2:l\d+>> LoadString
119*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<Append2:l\d+>> InvokeVirtual [<<New>>,<<String2>>] intrinsic:StringBufferAppend
120*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                  InvokeVirtual [<<New>>]             intrinsic:StringBufferLength
bufferLen2()121*795d594fSAndroid Build Coastguard Worker   static int bufferLen2() {
122*795d594fSAndroid Build Coastguard Worker     StringBuffer s = new StringBuffer();
123*795d594fSAndroid Build Coastguard Worker     return s.append("x").append("y").length();
124*795d594fSAndroid Build Coastguard Worker   }
125*795d594fSAndroid Build Coastguard Worker 
bufferLen2Smali()126*795d594fSAndroid Build Coastguard Worker   static int bufferLen2Smali() throws Exception {
127*795d594fSAndroid Build Coastguard Worker     Class<?> c = Class.forName("Smali");
128*795d594fSAndroid Build Coastguard Worker     Method m = c.getMethod("bufferLen2");
129*795d594fSAndroid Build Coastguard Worker     return (Integer) m.invoke(null);
130*795d594fSAndroid Build Coastguard Worker   }
131*795d594fSAndroid Build Coastguard Worker 
132*795d594fSAndroid Build Coastguard Worker   //
133*795d594fSAndroid Build Coastguard Worker   // Allows combining of returned "this". Also ensures that similar looking append() calls
134*795d594fSAndroid Build Coastguard Worker   // are not combined somehow through returned result.
135*795d594fSAndroid Build Coastguard Worker   //
136*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: int Main.builderLen2() instruction_simplifier (before)
137*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<New:l\d+>>     NewInstance
138*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<String1:l\d+>> LoadString
139*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<Append1:l\d+>> InvokeVirtual [<<New>>,<<String1>>]  intrinsic:StringBuilderAppendString
140*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<String2:l\d+>> LoadString
141*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<Append2:l\d+>> InvokeVirtual [{{l\d+}},<<String2>>] intrinsic:StringBuilderAppendString
142*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                  InvokeVirtual [{{l\d+}}]             intrinsic:StringBuilderLength
143*795d594fSAndroid Build Coastguard Worker   //
144*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: int Main.builderLen2() instruction_simplifier (after)
145*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<New:l\d+>>     NewInstance
146*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<String1:l\d+>> LoadString
147*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<Append1:l\d+>> InvokeVirtual [<<New>>,<<String1>>] intrinsic:StringBuilderAppendString
148*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<String2:l\d+>> LoadString
149*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<Append2:l\d+>> InvokeVirtual [<<New>>,<<String2>>] intrinsic:StringBuilderAppendString
150*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                  InvokeVirtual [<<New>>]             intrinsic:StringBuilderLength
builderLen2()151*795d594fSAndroid Build Coastguard Worker   static int builderLen2() {
152*795d594fSAndroid Build Coastguard Worker     StringBuilder s = new StringBuilder();
153*795d594fSAndroid Build Coastguard Worker     return s.append("x").append("y").length();
154*795d594fSAndroid Build Coastguard Worker   }
155*795d594fSAndroid Build Coastguard Worker 
builderLen2Smali()156*795d594fSAndroid Build Coastguard Worker   static int builderLen2Smali() throws Exception {
157*795d594fSAndroid Build Coastguard Worker     Class<?> c = Class.forName("Smali");
158*795d594fSAndroid Build Coastguard Worker     Method m = c.getMethod("builderLen2");
159*795d594fSAndroid Build Coastguard Worker     return (Integer) m.invoke(null);
160*795d594fSAndroid Build Coastguard Worker   }
161*795d594fSAndroid Build Coastguard Worker 
162*795d594fSAndroid Build Coastguard Worker   //
163*795d594fSAndroid Build Coastguard Worker   // Similar situation in a loop.
164*795d594fSAndroid Build Coastguard Worker   //
165*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: int Main.bufferLoopAppender() instruction_simplifier (before)
166*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<New:l\d+>>     NewInstance                                                         loop:none
167*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<String1:l\d+>> LoadString                                                          loop:<<Loop:B\d+>>
168*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<Null1:l\d+>>   NullCheck     [<<New>>]                                             loop:<<Loop>>
169*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<Append1:l\d+>> InvokeVirtual [<<Null1>>,<<String1>>] intrinsic:StringBufferAppend  loop:<<Loop>>
170*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<String2:l\d+>> LoadString                                                          loop:<<Loop>>
171*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<Append2:l\d+>> InvokeVirtual [{{l\d+}},<<String2>>]  intrinsic:StringBufferAppend  loop:<<Loop>>
172*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<String3:l\d+>> LoadString                                                          loop:<<Loop>>
173*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<Append3:l\d+>> InvokeVirtual [{{l\d+}},<<String3>>]  intrinsic:StringBufferAppend  loop:<<Loop>>
174*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                  InvokeVirtual [{{l\d+}}]              intrinsic:StringBufferLength  loop:none
175*795d594fSAndroid Build Coastguard Worker   //
176*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: int Main.bufferLoopAppender() instruction_simplifier (after)
177*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<New:l\d+>>     NewInstance                                                       loop:none
178*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<String1:l\d+>> LoadString                                                        loop:<<Loop:B\d+>>
179*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<Append1:l\d+>> InvokeVirtual [<<New>>,<<String1>>] intrinsic:StringBufferAppend  loop:<<Loop>>
180*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<String2:l\d+>> LoadString                                                        loop:<<Loop>>
181*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<Append2:l\d+>> InvokeVirtual [<<New>>,<<String2>>] intrinsic:StringBufferAppend  loop:<<Loop>>
182*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<String3:l\d+>> LoadString                                                        loop:<<Loop>>
183*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<Append3:l\d+>> InvokeVirtual [<<New>>,<<String3>>] intrinsic:StringBufferAppend  loop:<<Loop>>
184*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                  InvokeVirtual [<<New>>]             intrinsic:StringBufferLength  loop:none
bufferLoopAppender()185*795d594fSAndroid Build Coastguard Worker   static int bufferLoopAppender() {
186*795d594fSAndroid Build Coastguard Worker     StringBuffer b = new StringBuffer();
187*795d594fSAndroid Build Coastguard Worker     for (int i = 0; i < 10; i++) {
188*795d594fSAndroid Build Coastguard Worker       b.append("x").append("y").append("z");
189*795d594fSAndroid Build Coastguard Worker     }
190*795d594fSAndroid Build Coastguard Worker     return b.length();
191*795d594fSAndroid Build Coastguard Worker   }
192*795d594fSAndroid Build Coastguard Worker 
bufferLoopAppenderSmali()193*795d594fSAndroid Build Coastguard Worker   static int bufferLoopAppenderSmali() throws Exception {
194*795d594fSAndroid Build Coastguard Worker     Class<?> c = Class.forName("Smali");
195*795d594fSAndroid Build Coastguard Worker     Method m = c.getMethod("bufferLoopAppender");
196*795d594fSAndroid Build Coastguard Worker     return (Integer) m.invoke(null);
197*795d594fSAndroid Build Coastguard Worker   }
198*795d594fSAndroid Build Coastguard Worker 
199*795d594fSAndroid Build Coastguard Worker   //
200*795d594fSAndroid Build Coastguard Worker   // Similar situation in a loop.
201*795d594fSAndroid Build Coastguard Worker   //
202*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: int Main.builderLoopAppender() instruction_simplifier (before)
203*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<New:l\d+>>     NewInstance                                                               loop:none
204*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<String1:l\d+>> LoadString                                                                loop:<<Loop:B\d+>>
205*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<Null1:l\d+>>   NullCheck     [<<New>>]                                                   loop:<<Loop>>
206*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<Append1:l\d+>> InvokeVirtual [<<Null1>>,<<String1>>] intrinsic:StringBuilderAppendString loop:<<Loop>>
207*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<String2:l\d+>> LoadString                                                                loop:<<Loop>>
208*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<Append2:l\d+>> InvokeVirtual [{{l\d+}},<<String2>>]  intrinsic:StringBuilderAppendString loop:<<Loop>>
209*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<String3:l\d+>> LoadString                                                                loop:<<Loop>>
210*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<Append3:l\d+>> InvokeVirtual [{{l\d+}},<<String3>>]  intrinsic:StringBuilderAppendString loop:<<Loop>>
211*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                  InvokeVirtual [{{l\d+}}]              intrinsic:StringBuilderLength       loop:none
212*795d594fSAndroid Build Coastguard Worker   //
213*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: int Main.builderLoopAppender() instruction_simplifier (after)
214*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<New:l\d+>>     NewInstance                                                             loop:none
215*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<String1:l\d+>> LoadString                                                              loop:<<Loop:B\d+>>
216*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<Append1:l\d+>> InvokeVirtual [<<New>>,<<String1>>] intrinsic:StringBuilderAppendString loop:<<Loop>>
217*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<String2:l\d+>> LoadString                                                              loop:<<Loop>>
218*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<Append2:l\d+>> InvokeVirtual [<<New>>,<<String2>>] intrinsic:StringBuilderAppendString loop:<<Loop>>
219*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<String3:l\d+>> LoadString                                                              loop:<<Loop>>
220*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: <<Append3:l\d+>> InvokeVirtual [<<New>>,<<String3>>] intrinsic:StringBuilderAppendString loop:<<Loop>>
221*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                  InvokeVirtual [<<New>>]             intrinsic:StringBuilderLength       loop:none
builderLoopAppender()222*795d594fSAndroid Build Coastguard Worker   static int builderLoopAppender() {
223*795d594fSAndroid Build Coastguard Worker     StringBuilder b = new StringBuilder();
224*795d594fSAndroid Build Coastguard Worker     for (int i = 0; i < 10; i++) {
225*795d594fSAndroid Build Coastguard Worker       b.append("x").append("y").append("z");
226*795d594fSAndroid Build Coastguard Worker     }
227*795d594fSAndroid Build Coastguard Worker     return b.length();
228*795d594fSAndroid Build Coastguard Worker   }
229*795d594fSAndroid Build Coastguard Worker 
builderLoopAppenderSmali()230*795d594fSAndroid Build Coastguard Worker   static int builderLoopAppenderSmali() throws Exception {
231*795d594fSAndroid Build Coastguard Worker     Class<?> c = Class.forName("Smali");
232*795d594fSAndroid Build Coastguard Worker     Method m = c.getMethod("bufferLoopAppender");
233*795d594fSAndroid Build Coastguard Worker     return (Integer) m.invoke(null);
234*795d594fSAndroid Build Coastguard Worker   }
235*795d594fSAndroid Build Coastguard Worker 
236*795d594fSAndroid Build Coastguard Worker   //
237*795d594fSAndroid Build Coastguard Worker   // All calls in the loop-body are dead and thus loop can be eliminated.
238*795d594fSAndroid Build Coastguard Worker   //
239*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: int Main.bufferDeadLoop() dead_code_elimination$initial (before)
240*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: Phi                                              loop:<<Loop:B\d+>>
241*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: InvokeVirtual intrinsic:StringBufferToString     loop:<<Loop>>
242*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: InvokeVirtual intrinsic:StringStringIndexOfAfter loop:<<Loop>>
243*795d594fSAndroid Build Coastguard Worker   //
244*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: int Main.bufferDeadLoop() dead_code_elimination$initial (after)
245*795d594fSAndroid Build Coastguard Worker   /// CHECK-NOT: InvokeVirtual intrinsic:StringStringIndexOfAfter
246*795d594fSAndroid Build Coastguard Worker   //
247*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: int Main.bufferDeadLoop() instruction_simplifier$after_inlining (before)
248*795d594fSAndroid Build Coastguard Worker   /// CHECK: InvokeStaticOrDirect intrinsic:StringBufferToString
249*795d594fSAndroid Build Coastguard Worker   //
250*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: int Main.bufferDeadLoop() instruction_simplifier$after_inlining (after)
251*795d594fSAndroid Build Coastguard Worker   /// CHECK-NOT: InvokeStaticOrDirect intrinsic:StringBufferToString
252*795d594fSAndroid Build Coastguard Worker   //
253*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: int Main.bufferDeadLoop() loop_optimization (before)
254*795d594fSAndroid Build Coastguard Worker   /// CHECK: Phi
255*795d594fSAndroid Build Coastguard Worker   //
256*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: int Main.bufferDeadLoop() loop_optimization (after)
257*795d594fSAndroid Build Coastguard Worker   /// CHECK-NOT: Phi
bufferDeadLoop()258*795d594fSAndroid Build Coastguard Worker   static int bufferDeadLoop() {
259*795d594fSAndroid Build Coastguard Worker     StringBuffer b = new StringBuffer();
260*795d594fSAndroid Build Coastguard Worker     String x = "x";
261*795d594fSAndroid Build Coastguard Worker     for (int i = 0; i < 10; i++) {
262*795d594fSAndroid Build Coastguard Worker       int d = b.toString().indexOf(x, 1);
263*795d594fSAndroid Build Coastguard Worker     }
264*795d594fSAndroid Build Coastguard Worker     return b.length();
265*795d594fSAndroid Build Coastguard Worker   }
266*795d594fSAndroid Build Coastguard Worker 
267*795d594fSAndroid Build Coastguard Worker   //
268*795d594fSAndroid Build Coastguard Worker   // All calls in the loop-body are dead and thus loop can be eliminated.
269*795d594fSAndroid Build Coastguard Worker   //
270*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: int Main.builderDeadLoop() instruction_simplifier (before)
271*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: Phi                                              loop:<<Loop:B\d+>>
272*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: InvokeVirtual intrinsic:StringBuilderToString    loop:<<Loop>>
273*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: InvokeVirtual intrinsic:StringStringIndexOfAfter loop:<<Loop>>
274*795d594fSAndroid Build Coastguard Worker   //
275*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: int Main.builderDeadLoop() loop_optimization (after)
276*795d594fSAndroid Build Coastguard Worker   /// CHECK-NOT: Phi
277*795d594fSAndroid Build Coastguard Worker   /// CHECK-NOT: InvokeVirtual intrinsic:StringBuilderToString
278*795d594fSAndroid Build Coastguard Worker   /// CHECK-NOT: InvokeVirtual intrinsic:StringStringIndexOfAfter
builderDeadLoop()279*795d594fSAndroid Build Coastguard Worker   static int builderDeadLoop() {
280*795d594fSAndroid Build Coastguard Worker     StringBuilder b = new StringBuilder();
281*795d594fSAndroid Build Coastguard Worker     String x = "x";
282*795d594fSAndroid Build Coastguard Worker     for (int i = 0; i < 10; i++) {
283*795d594fSAndroid Build Coastguard Worker       int d = b.toString().indexOf(x, 1);
284*795d594fSAndroid Build Coastguard Worker     }
285*795d594fSAndroid Build Coastguard Worker     return b.length();
286*795d594fSAndroid Build Coastguard Worker   }
287*795d594fSAndroid Build Coastguard Worker 
288*795d594fSAndroid Build Coastguard Worker   // Regression b/33656359: StringBuffer x is passed to constructor of String
289*795d594fSAndroid Build Coastguard Worker   // (this caused old code to crash due to missing nullptr check).
290*795d594fSAndroid Build Coastguard Worker   //
291*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: void Main.doesNothing() instruction_simplifier (before)
292*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: InvokeVirtual intrinsic:StringBufferToString
293*795d594fSAndroid Build Coastguard Worker   //
294*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: void Main.doesNothing() instruction_simplifier (after)
295*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG: InvokeVirtual intrinsic:StringBufferToString
doesNothing()296*795d594fSAndroid Build Coastguard Worker   static void doesNothing() {
297*795d594fSAndroid Build Coastguard Worker     StringBuffer x = new StringBuffer();
298*795d594fSAndroid Build Coastguard Worker     String y = new String(x);
299*795d594fSAndroid Build Coastguard Worker     x.toString();
300*795d594fSAndroid Build Coastguard Worker   }
301*795d594fSAndroid Build Coastguard Worker 
main(String[] args)302*795d594fSAndroid Build Coastguard Worker   public static void main(String[] args) throws Exception {
303*795d594fSAndroid Build Coastguard Worker     expectEquals(1865, liveIndexOf());
304*795d594fSAndroid Build Coastguard Worker     expectEquals(29, deadIndexOf());
305*795d594fSAndroid Build Coastguard Worker 
306*795d594fSAndroid Build Coastguard Worker     try {
307*795d594fSAndroid Build Coastguard Worker       indexOfExceptions(null, XYZ);
308*795d594fSAndroid Build Coastguard Worker       throw new Error("Expected: NPE");
309*795d594fSAndroid Build Coastguard Worker     } catch (NullPointerException e) {
310*795d594fSAndroid Build Coastguard Worker     }
311*795d594fSAndroid Build Coastguard Worker     try {
312*795d594fSAndroid Build Coastguard Worker       indexOfExceptions(ABC, null);
313*795d594fSAndroid Build Coastguard Worker       throw new Error("Expected: NPE");
314*795d594fSAndroid Build Coastguard Worker     } catch (NullPointerException e) {
315*795d594fSAndroid Build Coastguard Worker     }
316*795d594fSAndroid Build Coastguard Worker     expectEquals(598, indexOfExceptions(ABC, XYZ));
317*795d594fSAndroid Build Coastguard Worker 
318*795d594fSAndroid Build Coastguard Worker     expectEquals(2, bufferLen2());
319*795d594fSAndroid Build Coastguard Worker     expectEquals(2, bufferLen2Smali());
320*795d594fSAndroid Build Coastguard Worker     expectEquals(2, builderLen2());
321*795d594fSAndroid Build Coastguard Worker     expectEquals(2, builderLen2Smali());
322*795d594fSAndroid Build Coastguard Worker     expectEquals(30, bufferLoopAppender());
323*795d594fSAndroid Build Coastguard Worker     expectEquals(30, bufferLoopAppenderSmali());
324*795d594fSAndroid Build Coastguard Worker     expectEquals(30, builderLoopAppender());
325*795d594fSAndroid Build Coastguard Worker     expectEquals(30, builderLoopAppenderSmali());
326*795d594fSAndroid Build Coastguard Worker     expectEquals(0, bufferDeadLoop());
327*795d594fSAndroid Build Coastguard Worker     expectEquals(0, builderDeadLoop());
328*795d594fSAndroid Build Coastguard Worker 
329*795d594fSAndroid Build Coastguard Worker     doesNothing();
330*795d594fSAndroid Build Coastguard Worker 
331*795d594fSAndroid Build Coastguard Worker     System.out.println("passed");
332*795d594fSAndroid Build Coastguard Worker   }
333*795d594fSAndroid Build Coastguard Worker 
expectEquals(int expected, int result)334*795d594fSAndroid Build Coastguard Worker   private static void expectEquals(int expected, int result) {
335*795d594fSAndroid Build Coastguard Worker     if (expected != result) {
336*795d594fSAndroid Build Coastguard Worker       throw new Error("Expected: " + expected + ", found: " + result);
337*795d594fSAndroid Build Coastguard Worker     }
338*795d594fSAndroid Build Coastguard Worker   }
339*795d594fSAndroid Build Coastguard Worker }
340