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