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 public class Main { main(String[] args)18*795d594fSAndroid Build Coastguard Worker public static void main(String[] args) throws Exception { 19*795d594fSAndroid Build Coastguard Worker assertEquals(2, $noinline$testDivideOverTen(20)); 20*795d594fSAndroid Build Coastguard Worker assertEquals(-2, $noinline$testDivideOverTen(-20)); 21*795d594fSAndroid Build Coastguard Worker assertEquals(0, $noinline$testSimpleDivisionInLoop(0)); 22*795d594fSAndroid Build Coastguard Worker assertEquals(1, $noinline$testSimpleDivisionInLoop(81)); 23*795d594fSAndroid Build Coastguard Worker assertEquals(10, $noinline$testOptimizeSeparateBranches(60, true)); 24*795d594fSAndroid Build Coastguard Worker assertEquals(10, $noinline$testOptimizeSeparateBranches(80, false)); 25*795d594fSAndroid Build Coastguard Worker assertEquals(1, $noinline$testDoNotOptimizeOneBranchThrows(81, false)); 26*795d594fSAndroid Build Coastguard Worker assertEquals(-1000, $noinline$testDoNotOptimizeOneBranchThrows(81, true)); 27*795d594fSAndroid Build Coastguard Worker assertEquals(1, $noinline$testOptimizeAfterOneBranchDisappears(81, false)); 28*795d594fSAndroid Build Coastguard Worker assertEquals(10, $noinline$testRemoveTryBoundaryNested(60)); 29*795d594fSAndroid Build Coastguard Worker assertEquals(-2000, $noinline$testRemoveTryBoundaryNestedButNotCatch(60, true)); 30*795d594fSAndroid Build Coastguard Worker assertEquals(30, $noinline$testRemoveTryBoundaryNestedButNotCatch(60, false)); 31*795d594fSAndroid Build Coastguard Worker assertEquals(30, $noinline$testNestedTryBoundariesWithLoopAndCatchOutsideOfLoop(60, false)); 32*795d594fSAndroid Build Coastguard Worker } 33*795d594fSAndroid Build Coastguard Worker assertEquals(int expected, int result)34*795d594fSAndroid Build Coastguard Worker public static void assertEquals(int expected, int result) { 35*795d594fSAndroid Build Coastguard Worker if (expected != result) { 36*795d594fSAndroid Build Coastguard Worker throw new Error("Expected: " + expected + ", found: " + result); 37*795d594fSAndroid Build Coastguard Worker } 38*795d594fSAndroid Build Coastguard Worker } 39*795d594fSAndroid Build Coastguard Worker 40*795d594fSAndroid Build Coastguard Worker // Check that this version cannot remove the TryBoundary instructions since we may throw. 41*795d594fSAndroid Build Coastguard Worker 42*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$inline$division(int, int) register (after) 43*795d594fSAndroid Build Coastguard Worker /// CHECK: TryBoundary 44*795d594fSAndroid Build Coastguard Worker /// CHECK: TryBoundary 45*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: TryBoundary 46*795d594fSAndroid Build Coastguard Worker 47*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$inline$division(int, int) register (after) 48*795d594fSAndroid Build Coastguard Worker /// CHECK: flags "catch_block" $inline$division(int a, int b)49*795d594fSAndroid Build Coastguard Worker private static int $inline$division(int a, int b) { 50*795d594fSAndroid Build Coastguard Worker try { 51*795d594fSAndroid Build Coastguard Worker return a / b; 52*795d594fSAndroid Build Coastguard Worker } catch (Error unexpected) { 53*795d594fSAndroid Build Coastguard Worker return -1000; 54*795d594fSAndroid Build Coastguard Worker } 55*795d594fSAndroid Build Coastguard Worker } 56*795d594fSAndroid Build Coastguard Worker 57*795d594fSAndroid Build Coastguard Worker // Check that we can remove the TryBoundary afer inlining since we know we can't throw. 58*795d594fSAndroid Build Coastguard Worker 59*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testDivideOverTen(int) inliner (after) 60*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: TryBoundary 61*795d594fSAndroid Build Coastguard Worker 62*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testDivideOverTen(int) inliner (after) 63*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: flags "catch_block" $noinline$testDivideOverTen(int a)64*795d594fSAndroid Build Coastguard Worker private static int $noinline$testDivideOverTen(int a) { 65*795d594fSAndroid Build Coastguard Worker return $inline$division(a, 10); 66*795d594fSAndroid Build Coastguard Worker } 67*795d594fSAndroid Build Coastguard Worker 68*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testSimpleDivisionInLoop(int) dead_code_elimination$initial (before) 69*795d594fSAndroid Build Coastguard Worker /// CHECK: TryBoundary 70*795d594fSAndroid Build Coastguard Worker /// CHECK: TryBoundary 71*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: TryBoundary 72*795d594fSAndroid Build Coastguard Worker 73*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testSimpleDivisionInLoop(int) dead_code_elimination$initial (before) 74*795d594fSAndroid Build Coastguard Worker /// CHECK: flags "catch_block" 75*795d594fSAndroid Build Coastguard Worker 76*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testSimpleDivisionInLoop(int) dead_code_elimination$initial (after) 77*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: TryBoundary 78*795d594fSAndroid Build Coastguard Worker 79*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testSimpleDivisionInLoop(int) dead_code_elimination$initial (after) 80*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: flags "catch_block" $noinline$testSimpleDivisionInLoop(int a)81*795d594fSAndroid Build Coastguard Worker private static int $noinline$testSimpleDivisionInLoop(int a) { 82*795d594fSAndroid Build Coastguard Worker try { 83*795d594fSAndroid Build Coastguard Worker for (int i = 0; i < 4; i++) { 84*795d594fSAndroid Build Coastguard Worker a /= 3; 85*795d594fSAndroid Build Coastguard Worker } 86*795d594fSAndroid Build Coastguard Worker } catch (Error unexpected) { 87*795d594fSAndroid Build Coastguard Worker return -1000; 88*795d594fSAndroid Build Coastguard Worker } 89*795d594fSAndroid Build Coastguard Worker return a; 90*795d594fSAndroid Build Coastguard Worker } 91*795d594fSAndroid Build Coastguard Worker 92*795d594fSAndroid Build Coastguard Worker // Even though the `TryBoundary`s are split, we can remove them as nothing in the try can throw. 93*795d594fSAndroid Build Coastguard Worker 94*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testOptimizeSeparateBranches(int, boolean) dead_code_elimination$initial (before) 95*795d594fSAndroid Build Coastguard Worker /// CHECK: TryBoundary 96*795d594fSAndroid Build Coastguard Worker /// CHECK: TryBoundary 97*795d594fSAndroid Build Coastguard Worker /// CHECK: TryBoundary 98*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: TryBoundary 99*795d594fSAndroid Build Coastguard Worker 100*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testOptimizeSeparateBranches(int, boolean) dead_code_elimination$initial (before) 101*795d594fSAndroid Build Coastguard Worker /// CHECK: flags "catch_block" 102*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: flags "catch_block" 103*795d594fSAndroid Build Coastguard Worker 104*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testOptimizeSeparateBranches(int, boolean) dead_code_elimination$initial (after) 105*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: TryBoundary 106*795d594fSAndroid Build Coastguard Worker 107*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testOptimizeSeparateBranches(int, boolean) dead_code_elimination$initial (after) 108*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: flags "catch_block" $noinline$testOptimizeSeparateBranches(int a, boolean val)109*795d594fSAndroid Build Coastguard Worker private static int $noinline$testOptimizeSeparateBranches(int a, boolean val) { 110*795d594fSAndroid Build Coastguard Worker try { 111*795d594fSAndroid Build Coastguard Worker if (val) { 112*795d594fSAndroid Build Coastguard Worker // TryBoundary kind:entry 113*795d594fSAndroid Build Coastguard Worker a /= 3; 114*795d594fSAndroid Build Coastguard Worker } else { 115*795d594fSAndroid Build Coastguard Worker // TryBoundary kind:entry 116*795d594fSAndroid Build Coastguard Worker a /= 4; 117*795d594fSAndroid Build Coastguard Worker } 118*795d594fSAndroid Build Coastguard Worker a /= 2; 119*795d594fSAndroid Build Coastguard Worker // TryBoundary kind:exit 120*795d594fSAndroid Build Coastguard Worker } catch (Error unexpected) { 121*795d594fSAndroid Build Coastguard Worker return -1000; 122*795d594fSAndroid Build Coastguard Worker } 123*795d594fSAndroid Build Coastguard Worker return a; 124*795d594fSAndroid Build Coastguard Worker } 125*795d594fSAndroid Build Coastguard Worker 126*795d594fSAndroid Build Coastguard Worker // Even though the `a /= 3;` can't throw, we don't eliminate any `TryBoundary` instructions. This 127*795d594fSAndroid Build Coastguard Worker // is because we have the `throw new Error();` in the try as well. We could potentially support 128*795d594fSAndroid Build Coastguard Worker // removing some `TryBoundary` instructions and not all in the try, but this would complicate the 129*795d594fSAndroid Build Coastguard Worker // code and wouldn't bring code size reductions since we would be unable to remove the catch 130*795d594fSAndroid Build Coastguard Worker // block. 131*795d594fSAndroid Build Coastguard Worker 132*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testDoNotOptimizeOneBranchThrows(int, boolean) register (after) 133*795d594fSAndroid Build Coastguard Worker /// CHECK: TryBoundary 134*795d594fSAndroid Build Coastguard Worker /// CHECK: TryBoundary 135*795d594fSAndroid Build Coastguard Worker /// CHECK: TryBoundary 136*795d594fSAndroid Build Coastguard Worker /// CHECK: TryBoundary 137*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: TryBoundary 138*795d594fSAndroid Build Coastguard Worker 139*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testDoNotOptimizeOneBranchThrows(int, boolean) register (after) 140*795d594fSAndroid Build Coastguard Worker /// CHECK: flags "catch_block" $noinline$testDoNotOptimizeOneBranchThrows(int a, boolean val)141*795d594fSAndroid Build Coastguard Worker public static int $noinline$testDoNotOptimizeOneBranchThrows(int a, boolean val) { 142*795d594fSAndroid Build Coastguard Worker try { 143*795d594fSAndroid Build Coastguard Worker for (int i = 0; i < 4; i++) { 144*795d594fSAndroid Build Coastguard Worker // TryBoundary kind:entry 145*795d594fSAndroid Build Coastguard Worker a /= 3; 146*795d594fSAndroid Build Coastguard Worker // TryBoundary kind:exit 147*795d594fSAndroid Build Coastguard Worker } 148*795d594fSAndroid Build Coastguard Worker 149*795d594fSAndroid Build Coastguard Worker if (val) { 150*795d594fSAndroid Build Coastguard Worker // TryBoundary kind:entry 151*795d594fSAndroid Build Coastguard Worker throw new Error(); 152*795d594fSAndroid Build Coastguard Worker // TryBoundary kind:exit 153*795d594fSAndroid Build Coastguard Worker } 154*795d594fSAndroid Build Coastguard Worker } catch (Error e) { 155*795d594fSAndroid Build Coastguard Worker return -1000; 156*795d594fSAndroid Build Coastguard Worker } 157*795d594fSAndroid Build Coastguard Worker return a; 158*795d594fSAndroid Build Coastguard Worker } 159*795d594fSAndroid Build Coastguard Worker 160*795d594fSAndroid Build Coastguard Worker // The throw gets eliminated by `SimplifyIfs` in DCE, so we can detect that nothing can throw in 161*795d594fSAndroid Build Coastguard Worker // the graph and eliminate the `TryBoundary` instructions. 162*795d594fSAndroid Build Coastguard Worker 163*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testOptimizeAfterOneBranchDisappears(int, boolean) dead_code_elimination$initial (before) 164*795d594fSAndroid Build Coastguard Worker /// CHECK: Throw 165*795d594fSAndroid Build Coastguard Worker 166*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testOptimizeAfterOneBranchDisappears(int, boolean) dead_code_elimination$initial (before) 167*795d594fSAndroid Build Coastguard Worker /// CHECK: TryBoundary 168*795d594fSAndroid Build Coastguard Worker /// CHECK: TryBoundary 169*795d594fSAndroid Build Coastguard Worker /// CHECK: TryBoundary 170*795d594fSAndroid Build Coastguard Worker /// CHECK: TryBoundary 171*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: TryBoundary 172*795d594fSAndroid Build Coastguard Worker 173*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testOptimizeAfterOneBranchDisappears(int, boolean) dead_code_elimination$initial (before) 174*795d594fSAndroid Build Coastguard Worker /// CHECK: flags "catch_block" 175*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: flags "catch_block" 176*795d594fSAndroid Build Coastguard Worker 177*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testOptimizeAfterOneBranchDisappears(int, boolean) dead_code_elimination$initial (after) 178*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: Throw 179*795d594fSAndroid Build Coastguard Worker 180*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testOptimizeAfterOneBranchDisappears(int, boolean) dead_code_elimination$initial (after) 181*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: TryBoundary 182*795d594fSAndroid Build Coastguard Worker 183*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testOptimizeAfterOneBranchDisappears(int, boolean) dead_code_elimination$initial (after) 184*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: flags "catch_block" $noinline$testOptimizeAfterOneBranchDisappears(int a, boolean val)185*795d594fSAndroid Build Coastguard Worker public static int $noinline$testOptimizeAfterOneBranchDisappears(int a, boolean val) { 186*795d594fSAndroid Build Coastguard Worker try { 187*795d594fSAndroid Build Coastguard Worker for (int i = 0; i < 4; i++) { 188*795d594fSAndroid Build Coastguard Worker // TryBoundary kind:entry 189*795d594fSAndroid Build Coastguard Worker a /= 3; 190*795d594fSAndroid Build Coastguard Worker // TryBoundary kind:exit 191*795d594fSAndroid Build Coastguard Worker } 192*795d594fSAndroid Build Coastguard Worker 193*795d594fSAndroid Build Coastguard Worker if (val && !val) { 194*795d594fSAndroid Build Coastguard Worker // TryBoundary kind:entry 195*795d594fSAndroid Build Coastguard Worker throw new Error(); 196*795d594fSAndroid Build Coastguard Worker // TryBoundary kind:exit 197*795d594fSAndroid Build Coastguard Worker } 198*795d594fSAndroid Build Coastguard Worker } catch (Error e) { 199*795d594fSAndroid Build Coastguard Worker return -1000; 200*795d594fSAndroid Build Coastguard Worker } 201*795d594fSAndroid Build Coastguard Worker return a; 202*795d594fSAndroid Build Coastguard Worker } 203*795d594fSAndroid Build Coastguard Worker 204*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testRemoveTryBoundaryNested(int) dead_code_elimination$initial (before) 205*795d594fSAndroid Build Coastguard Worker /// CHECK: TryBoundary 206*795d594fSAndroid Build Coastguard Worker /// CHECK: TryBoundary 207*795d594fSAndroid Build Coastguard Worker /// CHECK: TryBoundary 208*795d594fSAndroid Build Coastguard Worker /// CHECK: TryBoundary 209*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: TryBoundary 210*795d594fSAndroid Build Coastguard Worker 211*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testRemoveTryBoundaryNested(int) dead_code_elimination$initial (before) 212*795d594fSAndroid Build Coastguard Worker /// CHECK: flags "catch_block" 213*795d594fSAndroid Build Coastguard Worker /// CHECK: flags "catch_block" 214*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: flags "catch_block" 215*795d594fSAndroid Build Coastguard Worker 216*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testRemoveTryBoundaryNested(int) dead_code_elimination$initial (after) 217*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: TryBoundary 218*795d594fSAndroid Build Coastguard Worker 219*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testRemoveTryBoundaryNested(int) dead_code_elimination$initial (after) 220*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: flags "catch_block" $noinline$testRemoveTryBoundaryNested(int a)221*795d594fSAndroid Build Coastguard Worker public static int $noinline$testRemoveTryBoundaryNested(int a) { 222*795d594fSAndroid Build Coastguard Worker try { 223*795d594fSAndroid Build Coastguard Worker // TryBoundary kind:entry 224*795d594fSAndroid Build Coastguard Worker a /= 2; 225*795d594fSAndroid Build Coastguard Worker // TryBoundary kind:exit 226*795d594fSAndroid Build Coastguard Worker try { 227*795d594fSAndroid Build Coastguard Worker // TryBoundary kind:entry 228*795d594fSAndroid Build Coastguard Worker a /= 3; 229*795d594fSAndroid Build Coastguard Worker // TryBoundary kind:exit 230*795d594fSAndroid Build Coastguard Worker } catch (Error e) { 231*795d594fSAndroid Build Coastguard Worker return -2000; 232*795d594fSAndroid Build Coastguard Worker } 233*795d594fSAndroid Build Coastguard Worker } catch (Exception e) { 234*795d594fSAndroid Build Coastguard Worker return -1000; 235*795d594fSAndroid Build Coastguard Worker } 236*795d594fSAndroid Build Coastguard Worker return a; 237*795d594fSAndroid Build Coastguard Worker } 238*795d594fSAndroid Build Coastguard Worker 239*795d594fSAndroid Build Coastguard Worker // We can remove the `TryBoundary` instructions surrounding `a /= 2;` but since the inner try can 240*795d594fSAndroid Build Coastguard Worker // throw, we must keep both the inner and outer catches as they are catch handlers of the inner 241*795d594fSAndroid Build Coastguard Worker // try. 242*795d594fSAndroid Build Coastguard Worker 243*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testRemoveTryBoundaryNestedButNotCatch(int, boolean) dead_code_elimination$initial (before) 244*795d594fSAndroid Build Coastguard Worker /// CHECK: TryBoundary 245*795d594fSAndroid Build Coastguard Worker /// CHECK: TryBoundary 246*795d594fSAndroid Build Coastguard Worker /// CHECK: TryBoundary 247*795d594fSAndroid Build Coastguard Worker /// CHECK: TryBoundary 248*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: TryBoundary 249*795d594fSAndroid Build Coastguard Worker 250*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testRemoveTryBoundaryNestedButNotCatch(int, boolean) dead_code_elimination$initial (before) 251*795d594fSAndroid Build Coastguard Worker /// CHECK: flags "catch_block" 252*795d594fSAndroid Build Coastguard Worker /// CHECK: flags "catch_block" 253*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: flags "catch_block" 254*795d594fSAndroid Build Coastguard Worker 255*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testRemoveTryBoundaryNestedButNotCatch(int, boolean) dead_code_elimination$initial (after) 256*795d594fSAndroid Build Coastguard Worker /// CHECK: TryBoundary 257*795d594fSAndroid Build Coastguard Worker /// CHECK: TryBoundary 258*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: TryBoundary 259*795d594fSAndroid Build Coastguard Worker 260*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testRemoveTryBoundaryNestedButNotCatch(int, boolean) dead_code_elimination$initial (after) 261*795d594fSAndroid Build Coastguard Worker /// CHECK: flags "catch_block" 262*795d594fSAndroid Build Coastguard Worker /// CHECK: flags "catch_block" 263*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: flags "catch_block" $noinline$testRemoveTryBoundaryNestedButNotCatch(int a, boolean val)264*795d594fSAndroid Build Coastguard Worker public static int $noinline$testRemoveTryBoundaryNestedButNotCatch(int a, boolean val) { 265*795d594fSAndroid Build Coastguard Worker try { 266*795d594fSAndroid Build Coastguard Worker // TryBoundary kind:entry 267*795d594fSAndroid Build Coastguard Worker a /= 2; 268*795d594fSAndroid Build Coastguard Worker // TryBoundary kind:exit 269*795d594fSAndroid Build Coastguard Worker try { 270*795d594fSAndroid Build Coastguard Worker if (val) { 271*795d594fSAndroid Build Coastguard Worker // TryBoundary kind:entry 272*795d594fSAndroid Build Coastguard Worker throw new Error(); 273*795d594fSAndroid Build Coastguard Worker // TryBoundary kind:exit 274*795d594fSAndroid Build Coastguard Worker } 275*795d594fSAndroid Build Coastguard Worker // TryBoundary kind:exit 276*795d594fSAndroid Build Coastguard Worker } catch (Error e) { 277*795d594fSAndroid Build Coastguard Worker return -2000; 278*795d594fSAndroid Build Coastguard Worker } 279*795d594fSAndroid Build Coastguard Worker } catch (Exception e) { 280*795d594fSAndroid Build Coastguard Worker return -1000; 281*795d594fSAndroid Build Coastguard Worker } 282*795d594fSAndroid Build Coastguard Worker return a; 283*795d594fSAndroid Build Coastguard Worker } 284*795d594fSAndroid Build Coastguard Worker 285*795d594fSAndroid Build Coastguard Worker // We eliminate the return -1000 catch block which is outside of the loop in 286*795d594fSAndroid Build Coastguard Worker // dead_code_elimination$initial. We can do so since we eliminated the TryBoundary of `a /= 2;`. 287*795d594fSAndroid Build Coastguard Worker 288*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testNestedTryBoundariesWithLoopAndCatchOutsideOfLoop(int, boolean) dead_code_elimination$initial (before) 289*795d594fSAndroid Build Coastguard Worker /// CHECK: TryBoundary 290*795d594fSAndroid Build Coastguard Worker /// CHECK: TryBoundary 291*795d594fSAndroid Build Coastguard Worker /// CHECK: TryBoundary 292*795d594fSAndroid Build Coastguard Worker /// CHECK: TryBoundary 293*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: TryBoundary 294*795d594fSAndroid Build Coastguard Worker 295*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testNestedTryBoundariesWithLoopAndCatchOutsideOfLoop(int, boolean) dead_code_elimination$initial (before) 296*795d594fSAndroid Build Coastguard Worker /// CHECK: flags "catch_block" 297*795d594fSAndroid Build Coastguard Worker /// CHECK: flags "catch_block" 298*795d594fSAndroid Build Coastguard Worker /// CHECK: flags "catch_block" 299*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: flags "catch_block" 300*795d594fSAndroid Build Coastguard Worker 301*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testNestedTryBoundariesWithLoopAndCatchOutsideOfLoop(int, boolean) dead_code_elimination$initial (before) 302*795d594fSAndroid Build Coastguard Worker /// CHECK: IntConstant -1000 303*795d594fSAndroid Build Coastguard Worker 304*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testNestedTryBoundariesWithLoopAndCatchOutsideOfLoop(int, boolean) dead_code_elimination$initial (after) 305*795d594fSAndroid Build Coastguard Worker /// CHECK: TryBoundary 306*795d594fSAndroid Build Coastguard Worker /// CHECK: TryBoundary 307*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: TryBoundary 308*795d594fSAndroid Build Coastguard Worker 309*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testNestedTryBoundariesWithLoopAndCatchOutsideOfLoop(int, boolean) dead_code_elimination$initial (after) 310*795d594fSAndroid Build Coastguard Worker /// CHECK: flags "catch_block" 311*795d594fSAndroid Build Coastguard Worker /// CHECK: flags "catch_block" 312*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: flags "catch_block" 313*795d594fSAndroid Build Coastguard Worker 314*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testNestedTryBoundariesWithLoopAndCatchOutsideOfLoop(int, boolean) dead_code_elimination$initial (after) 315*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: IntConstant -1000 316*795d594fSAndroid Build Coastguard Worker 317*795d594fSAndroid Build Coastguard Worker // When removing that block, we are removing a block outside of a loop but we still need to update 318*795d594fSAndroid Build Coastguard Worker // the loop information in the graph since we removed TryBoundary instructions inside of a loop 319*795d594fSAndroid Build Coastguard Worker // and now `a /= 2;` is not considered part of a loop (Cannot throw so it will not `continue` and 320*795d594fSAndroid Build Coastguard Worker // will always return). 321*795d594fSAndroid Build Coastguard Worker 322*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testNestedTryBoundariesWithLoopAndCatchOutsideOfLoop(int, boolean) dead_code_elimination$initial (before) 323*795d594fSAndroid Build Coastguard Worker /// CHECK: Div loop:B2 324*795d594fSAndroid Build Coastguard Worker 325*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testNestedTryBoundariesWithLoopAndCatchOutsideOfLoop(int, boolean) dead_code_elimination$initial (after) 326*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: Div loop:B2 327*795d594fSAndroid Build Coastguard Worker 328*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.$noinline$testNestedTryBoundariesWithLoopAndCatchOutsideOfLoop(int, boolean) dead_code_elimination$initial (after) 329*795d594fSAndroid Build Coastguard Worker /// CHECK: Div 330*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: Div $noinline$testNestedTryBoundariesWithLoopAndCatchOutsideOfLoop( int a, boolean val)331*795d594fSAndroid Build Coastguard Worker public static int $noinline$testNestedTryBoundariesWithLoopAndCatchOutsideOfLoop( 332*795d594fSAndroid Build Coastguard Worker int a, boolean val) { 333*795d594fSAndroid Build Coastguard Worker try { 334*795d594fSAndroid Build Coastguard Worker for (int i = 0; i < 4; ++i) { 335*795d594fSAndroid Build Coastguard Worker try { 336*795d594fSAndroid Build Coastguard Worker try { 337*795d594fSAndroid Build Coastguard Worker if (val) { 338*795d594fSAndroid Build Coastguard Worker // TryBoundary kind:entry 339*795d594fSAndroid Build Coastguard Worker throw new Error(); 340*795d594fSAndroid Build Coastguard Worker // TryBoundary kind:exit 341*795d594fSAndroid Build Coastguard Worker } 342*795d594fSAndroid Build Coastguard Worker // TryBoundary kind:exit 343*795d594fSAndroid Build Coastguard Worker } catch (Exception e) { 344*795d594fSAndroid Build Coastguard Worker continue; 345*795d594fSAndroid Build Coastguard Worker } 346*795d594fSAndroid Build Coastguard Worker // TryBoundary kind:entry 347*795d594fSAndroid Build Coastguard Worker a /= 2; 348*795d594fSAndroid Build Coastguard Worker // TryBoundary kind:exit 349*795d594fSAndroid Build Coastguard Worker return a; 350*795d594fSAndroid Build Coastguard Worker } catch (Error e) { 351*795d594fSAndroid Build Coastguard Worker continue; 352*795d594fSAndroid Build Coastguard Worker } 353*795d594fSAndroid Build Coastguard Worker } 354*795d594fSAndroid Build Coastguard Worker } catch (Exception e) { 355*795d594fSAndroid Build Coastguard Worker return -1000; 356*795d594fSAndroid Build Coastguard Worker } 357*795d594fSAndroid Build Coastguard Worker return a; 358*795d594fSAndroid Build Coastguard Worker } 359*795d594fSAndroid Build Coastguard Worker } 360