1*795d594fSAndroid Build Coastguard Worker /* 2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2022 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 17*795d594fSAndroid Build Coastguard Worker class Point { 18*795d594fSAndroid Build Coastguard Worker int x; 19*795d594fSAndroid Build Coastguard Worker int y; 20*795d594fSAndroid Build Coastguard Worker } 21*795d594fSAndroid Build Coastguard Worker 22*795d594fSAndroid Build Coastguard Worker public class Main { main(String[] args)23*795d594fSAndroid Build Coastguard Worker public static void main(String[] args) { 24*795d594fSAndroid Build Coastguard Worker final boolean boolean_throw = false; 25*795d594fSAndroid Build Coastguard Worker final boolean boolean_other_throw = false; 26*795d594fSAndroid Build Coastguard Worker assertEquals(3, 27*795d594fSAndroid Build Coastguard Worker $noinline$testDifferentFields( 28*795d594fSAndroid Build Coastguard Worker new Point(), new Point(), boolean_throw, boolean_other_throw)); 29*795d594fSAndroid Build Coastguard Worker assertEquals(1, $noinline$testRedundantStore(new Point(), boolean_throw, boolean_other_throw)); 30*795d594fSAndroid Build Coastguard Worker assertEquals(1, $noinline$testTryCatchBlocking(new Point(), boolean_throw)); 31*795d594fSAndroid Build Coastguard Worker assertEquals(1, $noinline$testTryCatchPhi(new Point(), boolean_throw)); 32*795d594fSAndroid Build Coastguard Worker assertEquals(2, $noinline$testTryCatchPhiWithTwoCatches(new Point(), new int[0])); 33*795d594fSAndroid Build Coastguard Worker assertEquals(1, $noinline$testKeepStoreInsideTry()); 34*795d594fSAndroid Build Coastguard Worker assertEquals(10, $noinline$testDontKeepStoreInsideCatch(new int[]{10})); 35*795d594fSAndroid Build Coastguard Worker assertEquals(30, $noinline$testDontKeepStoreInsideCatch(new int[]{})); 36*795d594fSAndroid Build Coastguard Worker assertEquals(10, $noinline$testKeepStoreInsideCatchWithOuterTry(new int[]{10})); 37*795d594fSAndroid Build Coastguard Worker assertEquals(30, $noinline$testKeepStoreInsideCatchWithOuterTry(new int[]{})); 38*795d594fSAndroid Build Coastguard Worker assertEquals(40, $noinline$testDontKeepStoreInsideFinally(new int[]{10})); 39*795d594fSAndroid Build Coastguard Worker try { 40*795d594fSAndroid Build Coastguard Worker assertEquals(30, $noinline$testDontKeepStoreInsideFinally(new int[]{})); 41*795d594fSAndroid Build Coastguard Worker throw new Error("Unreachable"); 42*795d594fSAndroid Build Coastguard Worker } catch (ArrayIndexOutOfBoundsException expected) { 43*795d594fSAndroid Build Coastguard Worker } 44*795d594fSAndroid Build Coastguard Worker assertEquals(10, $noinline$testDontKeepStoreInsideOuterCatch(new int[]{10})); 45*795d594fSAndroid Build Coastguard Worker assertEquals(100030, $noinline$testDontKeepStoreInsideOuterCatch(new int[]{})); 46*795d594fSAndroid Build Coastguard Worker assertEquals(150, $noinline$test40()); 47*795d594fSAndroid Build Coastguard Worker } 48*795d594fSAndroid Build Coastguard Worker 49*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testDifferentFields(Point, Point, boolean, boolean) load_store_elimination (before) 50*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: InstanceFieldSet field_name:Point.x 51*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: InstanceFieldSet field_name:Point.y 52*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: InstanceFieldGet field_name:Point.x 53*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: InstanceFieldGet field_name:Point.y 54*795d594fSAndroid Build Coastguard Worker 55*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testDifferentFields(Point, Point, boolean, boolean) load_store_elimination (after) 56*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: InstanceFieldSet field_name:Point.x 57*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: InstanceFieldSet field_name:Point.y 58*795d594fSAndroid Build Coastguard Worker 59*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testDifferentFields(Point, Point, boolean, boolean) load_store_elimination (after) 60*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: InstanceFieldGet field_name:Point.x 61*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: InstanceFieldGet field_name:Point.y 62*795d594fSAndroid Build Coastguard Worker 63*795d594fSAndroid Build Coastguard Worker // Consistency check to make sure the try/catches weren't removed by an earlier pass. 64*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testDifferentFields(Point, Point, boolean, boolean) load_store_elimination (after) 65*795d594fSAndroid Build Coastguard Worker /// CHECK: TryBoundary kind:entry 66*795d594fSAndroid Build Coastguard Worker /// CHECK: TryBoundary kind:entry 67*795d594fSAndroid Build Coastguard Worker 68*795d594fSAndroid Build Coastguard Worker // Different fields shouldn't alias. $noinline$testDifferentFields( Point obj1, Point obj2, boolean boolean_throw, boolean boolean_other_throw)69*795d594fSAndroid Build Coastguard Worker private static int $noinline$testDifferentFields( 70*795d594fSAndroid Build Coastguard Worker Point obj1, Point obj2, boolean boolean_throw, boolean boolean_other_throw) { 71*795d594fSAndroid Build Coastguard Worker try { 72*795d594fSAndroid Build Coastguard Worker if (boolean_throw) { 73*795d594fSAndroid Build Coastguard Worker throw new Error(); 74*795d594fSAndroid Build Coastguard Worker } 75*795d594fSAndroid Build Coastguard Worker } catch (Error e) { 76*795d594fSAndroid Build Coastguard Worker return 0; 77*795d594fSAndroid Build Coastguard Worker } 78*795d594fSAndroid Build Coastguard Worker obj1.x = 1; 79*795d594fSAndroid Build Coastguard Worker obj2.y = 2; 80*795d594fSAndroid Build Coastguard Worker int result = obj1.x + obj2.y; 81*795d594fSAndroid Build Coastguard Worker try { 82*795d594fSAndroid Build Coastguard Worker if (boolean_other_throw) { 83*795d594fSAndroid Build Coastguard Worker throw new Error(); 84*795d594fSAndroid Build Coastguard Worker } 85*795d594fSAndroid Build Coastguard Worker } catch (Error e) { 86*795d594fSAndroid Build Coastguard Worker return 0; 87*795d594fSAndroid Build Coastguard Worker } 88*795d594fSAndroid Build Coastguard Worker return result; 89*795d594fSAndroid Build Coastguard Worker } 90*795d594fSAndroid Build Coastguard Worker 91*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testRedundantStore(Point, boolean, boolean) load_store_elimination (before) 92*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: InstanceFieldSet field_name:Point.y 93*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: InstanceFieldSet field_name:Point.y 94*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: InstanceFieldGet field_name:Point.y 95*795d594fSAndroid Build Coastguard Worker 96*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testRedundantStore(Point, boolean, boolean) load_store_elimination (after) 97*795d594fSAndroid Build Coastguard Worker /// CHECK: InstanceFieldSet field_name:Point.y 98*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: InstanceFieldSet field_name:Point.y 99*795d594fSAndroid Build Coastguard Worker 100*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testRedundantStore(Point, boolean, boolean) load_store_elimination (after) 101*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: InstanceFieldGet field_name:Point.y 102*795d594fSAndroid Build Coastguard Worker 103*795d594fSAndroid Build Coastguard Worker // Consistency check to make sure the try/catches weren't removed by an earlier pass. 104*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testRedundantStore(Point, boolean, boolean) load_store_elimination (after) 105*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: TryBoundary kind:entry 106*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: TryBoundary kind:entry 107*795d594fSAndroid Build Coastguard Worker 108*795d594fSAndroid Build Coastguard Worker // Redundant store of the same value. $noinline$testRedundantStore( Point obj, boolean boolean_throw, boolean boolean_other_throw)109*795d594fSAndroid Build Coastguard Worker private static int $noinline$testRedundantStore( 110*795d594fSAndroid Build Coastguard Worker Point obj, boolean boolean_throw, boolean boolean_other_throw) { 111*795d594fSAndroid Build Coastguard Worker try { 112*795d594fSAndroid Build Coastguard Worker if (boolean_throw) { 113*795d594fSAndroid Build Coastguard Worker throw new Error(); 114*795d594fSAndroid Build Coastguard Worker } 115*795d594fSAndroid Build Coastguard Worker } catch (Error e) { 116*795d594fSAndroid Build Coastguard Worker return 0; 117*795d594fSAndroid Build Coastguard Worker } 118*795d594fSAndroid Build Coastguard Worker obj.y = 1; 119*795d594fSAndroid Build Coastguard Worker obj.y = 1; 120*795d594fSAndroid Build Coastguard Worker try { 121*795d594fSAndroid Build Coastguard Worker if (boolean_other_throw) { 122*795d594fSAndroid Build Coastguard Worker throw new Error(); 123*795d594fSAndroid Build Coastguard Worker } 124*795d594fSAndroid Build Coastguard Worker } catch (Error e) { 125*795d594fSAndroid Build Coastguard Worker return 0; 126*795d594fSAndroid Build Coastguard Worker } 127*795d594fSAndroid Build Coastguard Worker return obj.y; 128*795d594fSAndroid Build Coastguard Worker } 129*795d594fSAndroid Build Coastguard Worker 130*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testTryCatchBlocking(Point, boolean) load_store_elimination (before) 131*795d594fSAndroid Build Coastguard Worker /// CHECK: InstanceFieldSet field_name:Point.y 132*795d594fSAndroid Build Coastguard Worker /// CHECK: InstanceFieldGet field_name:Point.y 133*795d594fSAndroid Build Coastguard Worker 134*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testTryCatchBlocking(Point, boolean) load_store_elimination (after) 135*795d594fSAndroid Build Coastguard Worker /// CHECK: InstanceFieldSet field_name:Point.y 136*795d594fSAndroid Build Coastguard Worker /// CHECK: InstanceFieldGet field_name:Point.y 137*795d594fSAndroid Build Coastguard Worker 138*795d594fSAndroid Build Coastguard Worker // Consistency check to make sure the try/catch wasn't removed by an earlier pass. 139*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testTryCatchBlocking(Point, boolean) load_store_elimination (after) 140*795d594fSAndroid Build Coastguard Worker /// CHECK: TryBoundary kind:entry 141*795d594fSAndroid Build Coastguard Worker 142*795d594fSAndroid Build Coastguard Worker // We cannot remove the Get since we might have thrown. $noinline$testTryCatchBlocking(Point obj, boolean boolean_throw)143*795d594fSAndroid Build Coastguard Worker private static int $noinline$testTryCatchBlocking(Point obj, boolean boolean_throw) { 144*795d594fSAndroid Build Coastguard Worker obj.y = 1; 145*795d594fSAndroid Build Coastguard Worker try { 146*795d594fSAndroid Build Coastguard Worker if (boolean_throw) { 147*795d594fSAndroid Build Coastguard Worker throw new Error(); 148*795d594fSAndroid Build Coastguard Worker } 149*795d594fSAndroid Build Coastguard Worker } catch (Error e) { 150*795d594fSAndroid Build Coastguard Worker } 151*795d594fSAndroid Build Coastguard Worker return obj.y; 152*795d594fSAndroid Build Coastguard Worker } 153*795d594fSAndroid Build Coastguard Worker 154*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testTryCatchPhi(Point, boolean) load_store_elimination (before) 155*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: InstanceFieldSet field_name:Point.y 156*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: InstanceFieldSet field_name:Point.y 157*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: InstanceFieldGet field_name:Point.y 158*795d594fSAndroid Build Coastguard Worker 159*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testTryCatchPhi(Point, boolean) load_store_elimination (after) 160*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: InstanceFieldSet field_name:Point.y 161*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: InstanceFieldSet field_name:Point.y 162*795d594fSAndroid Build Coastguard Worker 163*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testTryCatchPhi(Point, boolean) load_store_elimination (after) 164*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: InstanceFieldGet field_name:Point.y 165*795d594fSAndroid Build Coastguard Worker 166*795d594fSAndroid Build Coastguard Worker // Consistency check to make sure the try/catch wasn't removed by an earlier pass. 167*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testTryCatchPhi(Point, boolean) load_store_elimination (after) 168*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: TryBoundary kind:entry 169*795d594fSAndroid Build Coastguard Worker 170*795d594fSAndroid Build Coastguard Worker // We either threw and we set the value in the catch, or we didn't throw and we set the value 171*795d594fSAndroid Build Coastguard Worker // before the catch. We can solve that with a Phi and skip the get. $noinline$testTryCatchPhi(Point obj, boolean boolean_throw)172*795d594fSAndroid Build Coastguard Worker private static int $noinline$testTryCatchPhi(Point obj, boolean boolean_throw) { 173*795d594fSAndroid Build Coastguard Worker obj.y = 1; 174*795d594fSAndroid Build Coastguard Worker try { 175*795d594fSAndroid Build Coastguard Worker if (boolean_throw) { 176*795d594fSAndroid Build Coastguard Worker throw new Error(); 177*795d594fSAndroid Build Coastguard Worker } 178*795d594fSAndroid Build Coastguard Worker } catch (Error e) { 179*795d594fSAndroid Build Coastguard Worker obj.y = 2; 180*795d594fSAndroid Build Coastguard Worker } 181*795d594fSAndroid Build Coastguard Worker return obj.y; 182*795d594fSAndroid Build Coastguard Worker } 183*795d594fSAndroid Build Coastguard Worker 184*795d594fSAndroid Build Coastguard Worker 185*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testTryCatchPhiWithTwoCatches(Point, int[]) load_store_elimination (before) 186*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: InstanceFieldSet field_name:Point.y 187*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: InstanceFieldSet field_name:Point.y 188*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: InstanceFieldSet field_name:Point.y 189*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: InstanceFieldGet field_name:Point.y 190*795d594fSAndroid Build Coastguard Worker 191*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testTryCatchPhiWithTwoCatches(Point, int[]) load_store_elimination (after) 192*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: InstanceFieldSet field_name:Point.y 193*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: InstanceFieldSet field_name:Point.y 194*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: InstanceFieldSet field_name:Point.y 195*795d594fSAndroid Build Coastguard Worker 196*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testTryCatchPhiWithTwoCatches(Point, int[]) load_store_elimination (after) 197*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: InstanceFieldGet field_name:Point.y 198*795d594fSAndroid Build Coastguard Worker 199*795d594fSAndroid Build Coastguard Worker // Consistency check to make sure the try/catch wasn't removed by an earlier pass. 200*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testTryCatchPhiWithTwoCatches(Point, int[]) load_store_elimination (after) 201*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: TryBoundary kind:entry $noinline$testTryCatchPhiWithTwoCatches(Point obj, int[] numbers)202*795d594fSAndroid Build Coastguard Worker private static int $noinline$testTryCatchPhiWithTwoCatches(Point obj, int[] numbers) { 203*795d594fSAndroid Build Coastguard Worker obj.y = 1; 204*795d594fSAndroid Build Coastguard Worker try { 205*795d594fSAndroid Build Coastguard Worker if (numbers[0] == 1) { 206*795d594fSAndroid Build Coastguard Worker throw new Error(); 207*795d594fSAndroid Build Coastguard Worker } 208*795d594fSAndroid Build Coastguard Worker } catch (ArrayIndexOutOfBoundsException e) { 209*795d594fSAndroid Build Coastguard Worker obj.y = 2; 210*795d594fSAndroid Build Coastguard Worker } catch (Error e) { 211*795d594fSAndroid Build Coastguard Worker obj.y = 3; 212*795d594fSAndroid Build Coastguard Worker } 213*795d594fSAndroid Build Coastguard Worker return obj.y; 214*795d594fSAndroid Build Coastguard Worker } 215*795d594fSAndroid Build Coastguard Worker 216*795d594fSAndroid Build Coastguard Worker // Check that we don't eliminate the first store to `main.sumForKeepStoreInsideTryCatch` since it 217*795d594fSAndroid Build Coastguard Worker // is observable. 218*795d594fSAndroid Build Coastguard Worker 219*795d594fSAndroid Build Coastguard Worker // Consistency check to make sure the try/catch wasn't removed by an earlier pass. 220*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testKeepStoreInsideTry() load_store_elimination (after) 221*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: TryBoundary kind:entry 222*795d594fSAndroid Build Coastguard Worker 223*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testKeepStoreInsideTry() load_store_elimination (before) 224*795d594fSAndroid Build Coastguard Worker /// CHECK: InstanceFieldSet field_name:Main.sumForKeepStoreInsideTryCatch 225*795d594fSAndroid Build Coastguard Worker /// CHECK: InstanceFieldSet field_name:Main.sumForKeepStoreInsideTryCatch 226*795d594fSAndroid Build Coastguard Worker 227*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testKeepStoreInsideTry() load_store_elimination (after) 228*795d594fSAndroid Build Coastguard Worker /// CHECK: InstanceFieldSet field_name:Main.sumForKeepStoreInsideTryCatch 229*795d594fSAndroid Build Coastguard Worker /// CHECK: InstanceFieldSet field_name:Main.sumForKeepStoreInsideTryCatch $noinline$testKeepStoreInsideTry()230*795d594fSAndroid Build Coastguard Worker private static int $noinline$testKeepStoreInsideTry() { 231*795d594fSAndroid Build Coastguard Worker Main main = new Main(); 232*795d594fSAndroid Build Coastguard Worker main.sumForKeepStoreInsideTryCatch = 0; 233*795d594fSAndroid Build Coastguard Worker try { 234*795d594fSAndroid Build Coastguard Worker int[] array = {1}; 235*795d594fSAndroid Build Coastguard Worker main.sumForKeepStoreInsideTryCatch += array[0]; 236*795d594fSAndroid Build Coastguard Worker main.sumForKeepStoreInsideTryCatch += array[1]; 237*795d594fSAndroid Build Coastguard Worker throw new RuntimeException("Unreachable"); 238*795d594fSAndroid Build Coastguard Worker } catch (ArrayIndexOutOfBoundsException e) { 239*795d594fSAndroid Build Coastguard Worker return main.sumForKeepStoreInsideTryCatch; 240*795d594fSAndroid Build Coastguard Worker } 241*795d594fSAndroid Build Coastguard Worker } 242*795d594fSAndroid Build Coastguard Worker $noinline$returnValue(int value)243*795d594fSAndroid Build Coastguard Worker private static int $noinline$returnValue(int value) { 244*795d594fSAndroid Build Coastguard Worker return value; 245*795d594fSAndroid Build Coastguard Worker } 246*795d594fSAndroid Build Coastguard Worker 247*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testDontKeepStoreInsideCatch(int[]) load_store_elimination (before) 248*795d594fSAndroid Build Coastguard Worker /// CHECK: InstanceFieldSet field_name:Main.sumForKeepStoreInsideTryCatch 249*795d594fSAndroid Build Coastguard Worker /// CHECK: InstanceFieldSet field_name:Main.sumForKeepStoreInsideTryCatch 250*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: InstanceFieldSet field_name:Main.sumForKeepStoreInsideTryCatch 251*795d594fSAndroid Build Coastguard Worker 252*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testDontKeepStoreInsideCatch(int[]) load_store_elimination (after) 253*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: InstanceFieldSet field_name:Main.sumForKeepStoreInsideTryCatch $noinline$testDontKeepStoreInsideCatch(int[] array)254*795d594fSAndroid Build Coastguard Worker private static int $noinline$testDontKeepStoreInsideCatch(int[] array) { 255*795d594fSAndroid Build Coastguard Worker Main main = new Main(); 256*795d594fSAndroid Build Coastguard Worker int value = 0; 257*795d594fSAndroid Build Coastguard Worker try { 258*795d594fSAndroid Build Coastguard Worker value = array[0]; 259*795d594fSAndroid Build Coastguard Worker } catch (Exception e) { 260*795d594fSAndroid Build Coastguard Worker // These sets can be eliminated even though we have invokes since this catch is not part of an 261*795d594fSAndroid Build Coastguard Worker // outer try. 262*795d594fSAndroid Build Coastguard Worker main.sumForKeepStoreInsideTryCatch += $noinline$returnValue(10); 263*795d594fSAndroid Build Coastguard Worker main.sumForKeepStoreInsideTryCatch += $noinline$returnValue(20); 264*795d594fSAndroid Build Coastguard Worker } 265*795d594fSAndroid Build Coastguard Worker return main.sumForKeepStoreInsideTryCatch + value; 266*795d594fSAndroid Build Coastguard Worker } 267*795d594fSAndroid Build Coastguard Worker 268*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testKeepStoreInsideCatchWithOuterTry(int[]) load_store_elimination (before) 269*795d594fSAndroid Build Coastguard Worker /// CHECK: InstanceFieldSet field_name:Main.sumForKeepStoreInsideTryCatch 270*795d594fSAndroid Build Coastguard Worker /// CHECK: InstanceFieldSet field_name:Main.sumForKeepStoreInsideTryCatch 271*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: InstanceFieldSet field_name:Main.sumForKeepStoreInsideTryCatch 272*795d594fSAndroid Build Coastguard Worker 273*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testKeepStoreInsideCatchWithOuterTry(int[]) load_store_elimination (after) 274*795d594fSAndroid Build Coastguard Worker /// CHECK: InstanceFieldSet field_name:Main.sumForKeepStoreInsideTryCatch 275*795d594fSAndroid Build Coastguard Worker /// CHECK: InstanceFieldSet field_name:Main.sumForKeepStoreInsideTryCatch 276*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: InstanceFieldSet field_name:Main.sumForKeepStoreInsideTryCatch $noinline$testKeepStoreInsideCatchWithOuterTry(int[] array)277*795d594fSAndroid Build Coastguard Worker private static int $noinline$testKeepStoreInsideCatchWithOuterTry(int[] array) { 278*795d594fSAndroid Build Coastguard Worker Main main = new Main(); 279*795d594fSAndroid Build Coastguard Worker int value = 0; 280*795d594fSAndroid Build Coastguard Worker try { 281*795d594fSAndroid Build Coastguard Worker try { 282*795d594fSAndroid Build Coastguard Worker value = array[0]; 283*795d594fSAndroid Build Coastguard Worker } catch (Exception e) { 284*795d594fSAndroid Build Coastguard Worker // These sets can't be eliminated since this catch is part of a outer try. 285*795d594fSAndroid Build Coastguard Worker main.sumForKeepStoreInsideTryCatch += $noinline$returnValue(10); 286*795d594fSAndroid Build Coastguard Worker main.sumForKeepStoreInsideTryCatch += $noinline$returnValue(20); 287*795d594fSAndroid Build Coastguard Worker } 288*795d594fSAndroid Build Coastguard Worker } catch (Exception e) { 289*795d594fSAndroid Build Coastguard Worker value = 100000; 290*795d594fSAndroid Build Coastguard Worker } 291*795d594fSAndroid Build Coastguard Worker 292*795d594fSAndroid Build Coastguard Worker return main.sumForKeepStoreInsideTryCatch + value; 293*795d594fSAndroid Build Coastguard Worker } 294*795d594fSAndroid Build Coastguard Worker 295*795d594fSAndroid Build Coastguard Worker // Note that there are four `InstanceFieldSet` instead of two since we split the `finally` block 296*795d594fSAndroid Build Coastguard Worker // into the normal path, and the exceptional path. 297*795d594fSAndroid Build Coastguard Worker 298*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testDontKeepStoreInsideFinally(int[]) load_store_elimination (before) 299*795d594fSAndroid Build Coastguard Worker /// CHECK: InstanceFieldSet field_name:Main.sumForKeepStoreInsideTryCatch 300*795d594fSAndroid Build Coastguard Worker /// CHECK: InstanceFieldSet field_name:Main.sumForKeepStoreInsideTryCatch 301*795d594fSAndroid Build Coastguard Worker /// CHECK: InstanceFieldSet field_name:Main.sumForKeepStoreInsideTryCatch 302*795d594fSAndroid Build Coastguard Worker /// CHECK: InstanceFieldSet field_name:Main.sumForKeepStoreInsideTryCatch 303*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: InstanceFieldSet field_name:Main.sumForKeepStoreInsideTryCatch 304*795d594fSAndroid Build Coastguard Worker 305*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testDontKeepStoreInsideFinally(int[]) load_store_elimination (after) 306*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: InstanceFieldSet field_name:Main.sumForKeepStoreInsideTryCatch $noinline$testDontKeepStoreInsideFinally(int[] array)307*795d594fSAndroid Build Coastguard Worker private static int $noinline$testDontKeepStoreInsideFinally(int[] array) { 308*795d594fSAndroid Build Coastguard Worker Main main = new Main(); 309*795d594fSAndroid Build Coastguard Worker int value = 0; 310*795d594fSAndroid Build Coastguard Worker try { 311*795d594fSAndroid Build Coastguard Worker value = array[0]; 312*795d594fSAndroid Build Coastguard Worker } finally { 313*795d594fSAndroid Build Coastguard Worker // These sets can be eliminated even though we have invokes since this catch is not part of an 314*795d594fSAndroid Build Coastguard Worker // outer try. 315*795d594fSAndroid Build Coastguard Worker main.sumForKeepStoreInsideTryCatch += $noinline$returnValue(10); 316*795d594fSAndroid Build Coastguard Worker main.sumForKeepStoreInsideTryCatch += $noinline$returnValue(20); 317*795d594fSAndroid Build Coastguard Worker } 318*795d594fSAndroid Build Coastguard Worker return main.sumForKeepStoreInsideTryCatch + value; 319*795d594fSAndroid Build Coastguard Worker } 320*795d594fSAndroid Build Coastguard Worker 321*795d594fSAndroid Build Coastguard Worker // Checks that we are able to do LSE inside of catches which are outside of try blocks. 322*795d594fSAndroid Build Coastguard Worker 323*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testDontKeepStoreInsideOuterCatch(int[]) load_store_elimination (before) 324*795d594fSAndroid Build Coastguard Worker /// CHECK: InstanceFieldSet field_name:Main.sumForKeepStoreInsideTryCatch 325*795d594fSAndroid Build Coastguard Worker /// CHECK: InstanceFieldSet field_name:Main.sumForKeepStoreInsideTryCatch 326*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: InstanceFieldSet field_name:Main.sumForKeepStoreInsideTryCatch 327*795d594fSAndroid Build Coastguard Worker 328*795d594fSAndroid Build Coastguard Worker // This store potentially can be eliminated too, but our phi creation logic doesn't realize it can 329*795d594fSAndroid Build Coastguard Worker // create a Phi for `main.sumForKeepStoreInsideTryCatch` and skip a store+load. 330*795d594fSAndroid Build Coastguard Worker 331*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testDontKeepStoreInsideOuterCatch(int[]) load_store_elimination (after) 332*795d594fSAndroid Build Coastguard Worker /// CHECK: InstanceFieldSet field_name:Main.sumForKeepStoreInsideTryCatch 333*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: InstanceFieldSet field_name:Main.sumForKeepStoreInsideTryCatch 334*795d594fSAndroid Build Coastguard Worker $noinline$testDontKeepStoreInsideOuterCatch(int[] array)335*795d594fSAndroid Build Coastguard Worker private static int $noinline$testDontKeepStoreInsideOuterCatch(int[] array) { 336*795d594fSAndroid Build Coastguard Worker Main main = new Main(); 337*795d594fSAndroid Build Coastguard Worker int value = 0; 338*795d594fSAndroid Build Coastguard Worker try { 339*795d594fSAndroid Build Coastguard Worker value = array[0]; 340*795d594fSAndroid Build Coastguard Worker } catch (ArrayIndexOutOfBoundsException expected) { 341*795d594fSAndroid Build Coastguard Worker // These sets and gets are not considered to be part of a try so they are free to be 342*795d594fSAndroid Build Coastguard Worker // eliminated. 343*795d594fSAndroid Build Coastguard Worker main.sumForKeepStoreInsideTryCatch += $noinline$returnValue(10); 344*795d594fSAndroid Build Coastguard Worker main.sumForKeepStoreInsideTryCatch += $noinline$returnValue(20); 345*795d594fSAndroid Build Coastguard Worker try { 346*795d594fSAndroid Build Coastguard Worker value = array[0]; 347*795d594fSAndroid Build Coastguard Worker } catch (ArrayIndexOutOfBoundsException expectedToo) { 348*795d594fSAndroid Build Coastguard Worker value = 100000; 349*795d594fSAndroid Build Coastguard Worker } 350*795d594fSAndroid Build Coastguard Worker } 351*795d594fSAndroid Build Coastguard Worker 352*795d594fSAndroid Build Coastguard Worker return main.sumForKeepStoreInsideTryCatch + value; 353*795d594fSAndroid Build Coastguard Worker } 354*795d594fSAndroid Build Coastguard Worker 355*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$test40() load_store_elimination (before) 356*795d594fSAndroid Build Coastguard Worker /// CHECK: ArraySet 357*795d594fSAndroid Build Coastguard Worker /// CHECK: DivZeroCheck 358*795d594fSAndroid Build Coastguard Worker /// CHECK: ArraySet 359*795d594fSAndroid Build Coastguard Worker /// CHECK: ArraySet 360*795d594fSAndroid Build Coastguard Worker // 361*795d594fSAndroid Build Coastguard Worker /// CHECK: ArraySet 362*795d594fSAndroid Build Coastguard Worker /// CHECK: ArraySet 363*795d594fSAndroid Build Coastguard Worker /// CHECK: DivZeroCheck 364*795d594fSAndroid Build Coastguard Worker /// CHECK: ArraySet 365*795d594fSAndroid Build Coastguard Worker // 366*795d594fSAndroid Build Coastguard Worker /// CHECK: ArraySet 367*795d594fSAndroid Build Coastguard Worker /// CHECK: ArraySet 368*795d594fSAndroid Build Coastguard Worker /// CHECK: ArraySet 369*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: ArraySet 370*795d594fSAndroid Build Coastguard Worker 371*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$test40() load_store_elimination (after) 372*795d594fSAndroid Build Coastguard Worker /// CHECK: ArraySet 373*795d594fSAndroid Build Coastguard Worker /// CHECK: DivZeroCheck 374*795d594fSAndroid Build Coastguard Worker /// CHECK: ArraySet 375*795d594fSAndroid Build Coastguard Worker // 376*795d594fSAndroid Build Coastguard Worker /// CHECK: ArraySet 377*795d594fSAndroid Build Coastguard Worker /// CHECK: DivZeroCheck 378*795d594fSAndroid Build Coastguard Worker /// CHECK: ArraySet 379*795d594fSAndroid Build Coastguard Worker // 380*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: ArraySet 381*795d594fSAndroid Build Coastguard Worker 382*795d594fSAndroid Build Coastguard Worker // Like `test40` from 530-checker-lse but with $inline$ for the inner method so we check that we 383*795d594fSAndroid Build Coastguard Worker // have the array set inside try catches too. 384*795d594fSAndroid Build Coastguard Worker // Since we are inlining, we know the parameters and are able to elimnate (some) of the 385*795d594fSAndroid Build Coastguard Worker // `ArraySet`s. $noinline$test40()386*795d594fSAndroid Build Coastguard Worker private static int $noinline$test40() { 387*795d594fSAndroid Build Coastguard Worker int[] array = new int[1]; 388*795d594fSAndroid Build Coastguard Worker try { 389*795d594fSAndroid Build Coastguard Worker $inline$fillArrayTest40(array, 100, 0); 390*795d594fSAndroid Build Coastguard Worker System.out.println("UNREACHABLE"); 391*795d594fSAndroid Build Coastguard Worker } catch (Throwable expected) { 392*795d594fSAndroid Build Coastguard Worker } 393*795d594fSAndroid Build Coastguard Worker assertEquals(1, array[0]); 394*795d594fSAndroid Build Coastguard Worker try { 395*795d594fSAndroid Build Coastguard Worker $inline$fillArrayTest40(array, 100, 1); 396*795d594fSAndroid Build Coastguard Worker System.out.println("UNREACHABLE"); 397*795d594fSAndroid Build Coastguard Worker } catch (Throwable expected) { 398*795d594fSAndroid Build Coastguard Worker } 399*795d594fSAndroid Build Coastguard Worker assertEquals(2, array[0]); 400*795d594fSAndroid Build Coastguard Worker $inline$fillArrayTest40(array, 100, 2); 401*795d594fSAndroid Build Coastguard Worker assertEquals(150, array[0]); 402*795d594fSAndroid Build Coastguard Worker return array[0]; 403*795d594fSAndroid Build Coastguard Worker } 404*795d594fSAndroid Build Coastguard Worker 405*795d594fSAndroid Build Coastguard Worker /// CHECK-START: void Main.$inline$fillArrayTest40(int[], int, int) load_store_elimination (before) 406*795d594fSAndroid Build Coastguard Worker /// CHECK: ArraySet 407*795d594fSAndroid Build Coastguard Worker /// CHECK: DivZeroCheck 408*795d594fSAndroid Build Coastguard Worker /// CHECK: ArraySet 409*795d594fSAndroid Build Coastguard Worker /// CHECK: DivZeroCheck 410*795d594fSAndroid Build Coastguard Worker /// CHECK: ArraySet 411*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: ArraySet 412*795d594fSAndroid Build Coastguard Worker 413*795d594fSAndroid Build Coastguard Worker /// CHECK-START: void Main.$inline$fillArrayTest40(int[], int, int) load_store_elimination (after) 414*795d594fSAndroid Build Coastguard Worker /// CHECK: ArraySet 415*795d594fSAndroid Build Coastguard Worker /// CHECK: DivZeroCheck 416*795d594fSAndroid Build Coastguard Worker /// CHECK: ArraySet 417*795d594fSAndroid Build Coastguard Worker /// CHECK: DivZeroCheck 418*795d594fSAndroid Build Coastguard Worker /// CHECK: ArraySet 419*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: ArraySet 420*795d594fSAndroid Build Coastguard Worker 421*795d594fSAndroid Build Coastguard Worker // Check that the stores to array[0] are not eliminated since we can throw in between the stores. $inline$fillArrayTest40(int[] array, int a, int b)422*795d594fSAndroid Build Coastguard Worker private static void $inline$fillArrayTest40(int[] array, int a, int b) { 423*795d594fSAndroid Build Coastguard Worker array[0] = 1; 424*795d594fSAndroid Build Coastguard Worker int x = a / b; 425*795d594fSAndroid Build Coastguard Worker array[0] = 2; 426*795d594fSAndroid Build Coastguard Worker int y = a / (b - 1); 427*795d594fSAndroid Build Coastguard Worker array[0] = x + y; 428*795d594fSAndroid Build Coastguard Worker } 429*795d594fSAndroid Build Coastguard Worker assertEquals(int expected, int actual)430*795d594fSAndroid Build Coastguard Worker private static void assertEquals(int expected, int actual) { 431*795d594fSAndroid Build Coastguard Worker if (expected != actual) { 432*795d594fSAndroid Build Coastguard Worker throw new AssertionError("Expected: " + expected + ", Actual: " + actual); 433*795d594fSAndroid Build Coastguard Worker } 434*795d594fSAndroid Build Coastguard Worker } 435*795d594fSAndroid Build Coastguard Worker 436*795d594fSAndroid Build Coastguard Worker int sumForKeepStoreInsideTryCatch; 437*795d594fSAndroid Build Coastguard Worker } 438