1*795d594fSAndroid Build Coastguard Worker /* 2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2017 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 /** 18*795d594fSAndroid Build Coastguard Worker * Tests for optimizations of break-loops, i.e. loops that break 19*795d594fSAndroid Build Coastguard Worker * out of a while-true loop when the end condition is satisfied. 20*795d594fSAndroid Build Coastguard Worker * In particular, the tests focus on break-loops that can be 21*795d594fSAndroid Build Coastguard Worker * rewritten into regular countable loops (this may improve certain 22*795d594fSAndroid Build Coastguard Worker * loops generated by the Kotlin compiler for inclusive ranges). 23*795d594fSAndroid Build Coastguard Worker */ 24*795d594fSAndroid Build Coastguard Worker public class Main { 25*795d594fSAndroid Build Coastguard Worker 26*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.breakLoop(int[]) induction_var_analysis (before) 27*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Par:l\d+>> ParameterValue loop:none 28*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Zero:i\d+>> IntConstant 0 loop:none 29*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<One:i\d+>> IntConstant 1 loop:none 30*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Nil:l\d+>> NullCheck [<<Par>>] loop:none 31*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Phi:i\d+>> Phi [<<Zero>>,<<AddI:i\d+>>] loop:<<Loop:B\d+>> outer_loop:none 32*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Bnd:i\d+>> BoundsCheck [<<Phi>>,{{i\d+}}] loop:<<Loop>> outer_loop:none 33*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: ArraySet [<<Nil>>,<<Bnd>>,<<One>>] loop:<<Loop>> outer_loop:none 34*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<NE:z\d+>> NotEqual [{{i\d+}},<<Phi>>] loop:<<Loop>> outer_loop:none 35*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: If [<<NE>>] loop:<<Loop>> outer_loop:none 36*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<AddI>> Add [<<Phi>>,<<One>>] loop:<<Loop>> outer_loop:none 37*795d594fSAndroid Build Coastguard Worker // 38*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.breakLoop(int[]) induction_var_analysis (after) 39*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Par:l\d+>> ParameterValue loop:none 40*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Zero:i\d+>> IntConstant 0 loop:none 41*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<One:i\d+>> IntConstant 1 loop:none 42*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Nil:l\d+>> NullCheck [<<Par>>] loop:none 43*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Phi:i\d+>> Phi [<<Zero>>,<<AddI:i\d+>>] loop:<<Loop:B\d+>> outer_loop:none 44*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<LE:z\d+>> LessThanOrEqual [<<Phi>>,{{i\d+}}] loop:<<Loop>> outer_loop:none 45*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: If [<<LE>>] loop:<<Loop>> outer_loop:none 46*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Bnd:i\d+>> BoundsCheck [<<Phi>>,{{i\d+}}] loop:<<Loop>> outer_loop:none 47*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: ArraySet [<<Nil>>,<<Bnd>>,<<One>>] loop:<<Loop>> outer_loop:none 48*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<AddI>> Add [<<Phi>>,<<One>>] loop:<<Loop>> outer_loop:none 49*795d594fSAndroid Build Coastguard Worker // 50*795d594fSAndroid Build Coastguard Worker /// CHECK-START-ARM64: int Main.breakLoop(int[]) loop_optimization (after) 51*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Par:l\d+>> ParameterValue loop:none 52*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<One:i\d+>> IntConstant 1 loop:none 53*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Nil:l\d+>> NullCheck [<<Par>>] loop:none 54*795d594fSAndroid Build Coastguard Worker /// CHECK-IF: hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true' 55*795d594fSAndroid Build Coastguard Worker // 56*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Rep:d\d+>> VecReplicateScalar [<<One>>,{{j\d+}}] loop:none 57*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<LoopP:j\d+>> VecPredWhile loop:<<Loop:B\d+>> outer_loop:none 58*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: VecStore [<<Nil>>,<<Phi:i\d+>>,<<Rep>>,<<LoopP>>] loop:<<Loop>> outer_loop:none 59*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: Add [<<Phi>>,{{i\d+}}] loop:<<Loop>> outer_loop:none 60*795d594fSAndroid Build Coastguard Worker // 61*795d594fSAndroid Build Coastguard Worker /// CHECK-ELSE: 62*795d594fSAndroid Build Coastguard Worker // 63*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Four:i\d+>> IntConstant 4 loop:none 64*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Rep:d\d+>> VecReplicateScalar [<<One>>] loop:none 65*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: VecStore [<<Nil>>,<<Phi:i\d+>>,<<Rep>>] loop:<<Loop:B\d+>> outer_loop:none 66*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: Add [<<Phi>>,<<Four>>] loop:<<Loop>> outer_loop:none 67*795d594fSAndroid Build Coastguard Worker // 68*795d594fSAndroid Build Coastguard Worker /// CHECK-FI: breakLoop(int[] a)69*795d594fSAndroid Build Coastguard Worker static int breakLoop(int[] a) { 70*795d594fSAndroid Build Coastguard Worker int l = 0; 71*795d594fSAndroid Build Coastguard Worker int u = a.length - 1; 72*795d594fSAndroid Build Coastguard Worker int i = l; 73*795d594fSAndroid Build Coastguard Worker if (l <= u) { 74*795d594fSAndroid Build Coastguard Worker while (true) { 75*795d594fSAndroid Build Coastguard Worker a[i] = 1; 76*795d594fSAndroid Build Coastguard Worker if (i == u) break; 77*795d594fSAndroid Build Coastguard Worker i++; 78*795d594fSAndroid Build Coastguard Worker } 79*795d594fSAndroid Build Coastguard Worker } 80*795d594fSAndroid Build Coastguard Worker return i; 81*795d594fSAndroid Build Coastguard Worker } 82*795d594fSAndroid Build Coastguard Worker 83*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.breakLoopDown(int[]) induction_var_analysis (before) 84*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Par:l\d+>> ParameterValue loop:none 85*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Zero:i\d+>> IntConstant 0 loop:none 86*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<MOne:i\d+>> IntConstant -1 loop:none 87*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Two:i\d+>> IntConstant 2 loop:none 88*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Nil:l\d+>> NullCheck [<<Par>>] loop:none 89*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Phi:i\d+>> Phi [{{i\d+}},<<AddI:i\d+>>] loop:<<Loop:B\d+>> outer_loop:none 90*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Bnd:i\d+>> BoundsCheck [<<Phi>>,{{i\d+}}] loop:<<Loop>> outer_loop:none 91*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: ArraySet [<<Nil>>,<<Bnd>>,<<Two>>] loop:<<Loop>> outer_loop:none 92*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<NE:z\d+>> NotEqual [<<Phi>>,<<Zero>>] loop:<<Loop>> outer_loop:none 93*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: If [<<NE>>] loop:<<Loop>> outer_loop:none 94*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<AddI>> Add [<<Phi>>,<<MOne>>] loop:<<Loop>> outer_loop:none 95*795d594fSAndroid Build Coastguard Worker // 96*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.breakLoopDown(int[]) induction_var_analysis (after) 97*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Par:l\d+>> ParameterValue loop:none 98*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Zero:i\d+>> IntConstant 0 loop:none 99*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<MOne:i\d+>> IntConstant -1 loop:none 100*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Two:i\d+>> IntConstant 2 loop:none 101*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Nil:l\d+>> NullCheck [<<Par>>] loop:none 102*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Phi:i\d+>> Phi [{{i\d+}},<<AddI:i\d+>>] loop:<<Loop:B\d+>> outer_loop:none 103*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<GE:z\d+>> GreaterThanOrEqual [<<Phi>>,<<Zero>>] loop:<<Loop>> outer_loop:none 104*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: If [<<GE>>] loop:<<Loop>> outer_loop:none 105*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Bnd:i\d+>> BoundsCheck [<<Phi>>,{{i\d+}}] loop:<<Loop>> outer_loop:none 106*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: ArraySet [<<Nil>>,<<Bnd>>,<<Two>>] loop:<<Loop>> outer_loop:none 107*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<AddI>> Add [<<Phi>>,<<MOne>>] loop:<<Loop>> outer_loop:none breakLoopDown(int[] a)108*795d594fSAndroid Build Coastguard Worker static int breakLoopDown(int[] a) { 109*795d594fSAndroid Build Coastguard Worker int l = 0; 110*795d594fSAndroid Build Coastguard Worker int u = a.length - 1; 111*795d594fSAndroid Build Coastguard Worker int i = u; 112*795d594fSAndroid Build Coastguard Worker if (u >= l) { 113*795d594fSAndroid Build Coastguard Worker while (true) { 114*795d594fSAndroid Build Coastguard Worker a[i] = 2; 115*795d594fSAndroid Build Coastguard Worker if (i == l) break; 116*795d594fSAndroid Build Coastguard Worker i--; 117*795d594fSAndroid Build Coastguard Worker } 118*795d594fSAndroid Build Coastguard Worker } 119*795d594fSAndroid Build Coastguard Worker return i; 120*795d594fSAndroid Build Coastguard Worker } 121*795d594fSAndroid Build Coastguard Worker 122*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.breakLoopSafeConst(int[]) induction_var_analysis (before) 123*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Par:l\d+>> ParameterValue loop:none 124*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<One:i\d+>> IntConstant 1 loop:none 125*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Three:i\d+>> IntConstant 3 loop:none 126*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<L1:i\d+>> IntConstant 2147483631 loop:none 127*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<L2:i\d+>> IntConstant 2147483646 loop:none 128*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Phi:i\d+>> Phi [<<L1>>,<<AddI:i\d+>>] loop:<<Loop:B\d+>> outer_loop:none 129*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Phi>>,<<L1>>] loop:<<Loop>> outer_loop:none 130*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Nil:l\d+>> NullCheck [<<Par>>] loop:<<Loop>> outer_loop:none 131*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Bnd:i\d+>> BoundsCheck [<<Sub>>,{{i\d+}}] loop:<<Loop>> outer_loop:none 132*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: ArraySet [<<Nil>>,<<Bnd>>,<<Three>>] loop:<<Loop>> outer_loop:none 133*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<NE:z\d+>> NotEqual [<<Phi>>,<<L2>>] loop:<<Loop>> outer_loop:none 134*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: If [<<NE>>] loop:<<Loop>> outer_loop:none 135*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<AddI>> Add [<<Phi>>,<<One>>] loop:<<Loop>> outer_loop:none 136*795d594fSAndroid Build Coastguard Worker // 137*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.breakLoopSafeConst(int[]) induction_var_analysis (after) 138*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Par:l\d+>> ParameterValue loop:none 139*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<One:i\d+>> IntConstant 1 loop:none 140*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Three:i\d+>> IntConstant 3 loop:none 141*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<L1:i\d+>> IntConstant 2147483631 loop:none 142*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<L2:i\d+>> IntConstant 2147483646 loop:none 143*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Phi:i\d+>> Phi [<<L1>>,<<AddI:i\d+>>] loop:<<Loop:B\d+>> outer_loop:none 144*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<LE:z\d+>> LessThanOrEqual [<<Phi>>,<<L2>>] loop:<<Loop>> outer_loop:none 145*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Phi>>,<<L1>>] loop:<<Loop>> outer_loop:none 146*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Nil:l\d+>> NullCheck [<<Par>>] loop:<<Loop>> outer_loop:none 147*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Bnd:i\d+>> BoundsCheck [<<Sub>>,{{i\d+}}] loop:<<Loop>> outer_loop:none 148*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: ArraySet [<<Nil>>,<<Bnd>>,<<Three>>] loop:<<Loop>> outer_loop:none 149*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<AddI>> Add [<<Phi>>,<<One>>] loop:<<Loop>> outer_loop:none 150*795d594fSAndroid Build Coastguard Worker // 151*795d594fSAndroid Build Coastguard Worker /// CHECK-START-ARM64: int Main.breakLoopSafeConst(int[]) loop_optimization (after) 152*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Par:l\d+>> ParameterValue loop:none 153*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<One:i\d+>> IntConstant 1 loop:none 154*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Three:i\d+>> IntConstant 3 loop:none 155*795d594fSAndroid Build Coastguard Worker /// CHECK-IF: hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true' 156*795d594fSAndroid Build Coastguard Worker // 157*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Rep:d\d+>> VecReplicateScalar [<<Three>>,{{j\d+}}] loop:none 158*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<LoopP:j\d+>> VecPredWhile loop:<<Loop:B\d+>> outer_loop:none 159*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: VecStore [<<Par>>,<<Phi:i\d+>>,<<Rep>>,<<LoopP>>] loop:<<Loop>> outer_loop:none 160*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: Add [<<Phi>>,{{i\d+}}] loop:<<Loop>> outer_loop:none 161*795d594fSAndroid Build Coastguard Worker // 162*795d594fSAndroid Build Coastguard Worker /// CHECK-ELSE: 163*795d594fSAndroid Build Coastguard Worker // 164*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Four:i\d+>> IntConstant 4 loop:none 165*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Rep:d\d+>> VecReplicateScalar [<<Three>>] loop:none 166*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: VecStore [<<Par>>,<<Phi:i\d+>>,<<Rep>>] loop:<<Loop:B\d+>> outer_loop:none 167*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: Add [<<Phi>>,<<Four>>] loop:<<Loop>> outer_loop:none 168*795d594fSAndroid Build Coastguard Worker // 169*795d594fSAndroid Build Coastguard Worker /// CHECK-FI: breakLoopSafeConst(int[] a)170*795d594fSAndroid Build Coastguard Worker static int breakLoopSafeConst(int[] a) { 171*795d594fSAndroid Build Coastguard Worker int l = Integer.MAX_VALUE - 16; 172*795d594fSAndroid Build Coastguard Worker int u = Integer.MAX_VALUE - 1; 173*795d594fSAndroid Build Coastguard Worker int i = l; 174*795d594fSAndroid Build Coastguard Worker if (l <= u) { // will be removed by simplifier 175*795d594fSAndroid Build Coastguard Worker while (true) { 176*795d594fSAndroid Build Coastguard Worker a[i - l] = 3; 177*795d594fSAndroid Build Coastguard Worker if (i == u) break; 178*795d594fSAndroid Build Coastguard Worker i++; 179*795d594fSAndroid Build Coastguard Worker } 180*795d594fSAndroid Build Coastguard Worker } 181*795d594fSAndroid Build Coastguard Worker return i; 182*795d594fSAndroid Build Coastguard Worker } 183*795d594fSAndroid Build Coastguard Worker 184*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.breakLoopUnsafeConst(int[]) induction_var_analysis (before) 185*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Par:l\d+>> ParameterValue loop:none 186*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<One:i\d+>> IntConstant 1 loop:none 187*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Four:i\d+>> IntConstant 4 loop:none 188*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<L1:i\d+>> IntConstant 2147483632 loop:none 189*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<L2:i\d+>> IntConstant 2147483647 loop:none 190*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Phi:i\d+>> Phi [<<L1>>,<<AddI:i\d+>>] loop:<<Loop:B\d+>> outer_loop:none 191*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Phi>>,<<L1>>] loop:<<Loop>> outer_loop:none 192*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Nil:l\d+>> NullCheck [<<Par>>] loop:<<Loop>> outer_loop:none 193*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Bnd:i\d+>> BoundsCheck [<<Sub>>,{{i\d+}}] loop:<<Loop>> outer_loop:none 194*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: ArraySet [<<Nil>>,<<Bnd>>,<<Four>>] loop:<<Loop>> outer_loop:none 195*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<NE:z\d+>> NotEqual [<<Phi>>,<<L2>>] loop:<<Loop>> outer_loop:none 196*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: If [<<NE>>] loop:<<Loop>> outer_loop:none 197*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<AddI>> Add [<<Phi>>,<<One>>] loop:<<Loop>> outer_loop:none 198*795d594fSAndroid Build Coastguard Worker // 199*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.breakLoopUnsafeConst(int[]) induction_var_analysis (after) 200*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: NotEqual 201*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: LessThanOrEqual breakLoopUnsafeConst(int[] a)202*795d594fSAndroid Build Coastguard Worker static int breakLoopUnsafeConst(int[] a) { 203*795d594fSAndroid Build Coastguard Worker int l = Integer.MAX_VALUE - 15; 204*795d594fSAndroid Build Coastguard Worker int u = Integer.MAX_VALUE; 205*795d594fSAndroid Build Coastguard Worker int i = l; 206*795d594fSAndroid Build Coastguard Worker if (l <= u) { // will be removed by simplifier 207*795d594fSAndroid Build Coastguard Worker while (true) { 208*795d594fSAndroid Build Coastguard Worker a[i - l] = 4; 209*795d594fSAndroid Build Coastguard Worker if (i == u) break; // rewriting exit not safe! 210*795d594fSAndroid Build Coastguard Worker i++; 211*795d594fSAndroid Build Coastguard Worker } 212*795d594fSAndroid Build Coastguard Worker } 213*795d594fSAndroid Build Coastguard Worker return i; 214*795d594fSAndroid Build Coastguard Worker } 215*795d594fSAndroid Build Coastguard Worker 216*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.breakLoopNastyPhi(int[]) induction_var_analysis (before) 217*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Par:l\d+>> ParameterValue loop:none 218*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Zero:i\d+>> IntConstant 0 loop:none 219*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<One:i\d+>> IntConstant 1 loop:none 220*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Five:i\d+>> IntConstant 5 loop:none 221*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<M123:i\d+>> IntConstant -123 loop:none 222*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Nil:l\d+>> NullCheck [<<Par>>] loop:none 223*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Phi:i\d+>> Phi [<<Zero>>,<<AddI:i\d+>>] loop:<<Loop:B\d+>> outer_loop:none 224*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Wrap:i\d+>> Phi [<<M123>>,<<Phi>>] loop:<<Loop>> outer_loop:none 225*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Bnd:i\d+>> BoundsCheck [<<Phi>>,{{i\d+}}] loop:<<Loop>> outer_loop:none 226*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: ArraySet [<<Nil>>,<<Bnd>>,<<Five>>] loop:<<Loop>> outer_loop:none 227*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<NE:z\d+>> NotEqual [{{i\d+}},<<Phi>>] loop:<<Loop>> outer_loop:none 228*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: If [<<NE>>] loop:<<Loop>> outer_loop:none 229*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<AddI>> Add [<<Phi>>,<<One>>] loop:<<Loop>> outer_loop:none 230*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Comb:i\d+>> Phi [<<M123>>,<<Wrap>>] loop:none 231*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: Return [<<Comb>>] loop:none 232*795d594fSAndroid Build Coastguard Worker // 233*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.breakLoopNastyPhi(int[]) induction_var_analysis (after) 234*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: NotEqual 235*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: LessThanOrEqual breakLoopNastyPhi(int[] a)236*795d594fSAndroid Build Coastguard Worker static int breakLoopNastyPhi(int[] a) { 237*795d594fSAndroid Build Coastguard Worker int l = 0; 238*795d594fSAndroid Build Coastguard Worker int u = a.length - 1; 239*795d594fSAndroid Build Coastguard Worker int x = -123; 240*795d594fSAndroid Build Coastguard Worker if (l <= u) { 241*795d594fSAndroid Build Coastguard Worker int i = l; 242*795d594fSAndroid Build Coastguard Worker while (true) { 243*795d594fSAndroid Build Coastguard Worker a[i] = 5; 244*795d594fSAndroid Build Coastguard Worker if (i == u) break; 245*795d594fSAndroid Build Coastguard Worker x = i; 246*795d594fSAndroid Build Coastguard Worker i++; 247*795d594fSAndroid Build Coastguard Worker } 248*795d594fSAndroid Build Coastguard Worker } 249*795d594fSAndroid Build Coastguard Worker return x; // keep another phi live 250*795d594fSAndroid Build Coastguard Worker } 251*795d594fSAndroid Build Coastguard Worker 252*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.breakLoopReduction(int[]) induction_var_analysis (before) 253*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Par:l\d+>> ParameterValue loop:none 254*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Zero:i\d+>> IntConstant 0 loop:none 255*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<One:i\d+>> IntConstant 1 loop:none 256*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Nil:l\d+>> NullCheck [<<Par>>] loop:none 257*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Red:i\d+>> Phi [<<Zero>>,<<RedI:i\d+>>] loop:<<Loop:B\d+>> outer_loop:none 258*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Phi:i\d+>> Phi [<<Zero>>,<<AddI:i\d+>>] loop:<<Loop>> outer_loop:none 259*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Bnd:i\d+>> BoundsCheck [<<Phi>>,{{i\d+}}] loop:<<Loop>> outer_loop:none 260*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Get:i\d+>> ArrayGet [<<Nil>>,<<Bnd>>] loop:<<Loop>> outer_loop:none 261*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<RedI>> Add [<<Red>>,<<Get>>] loop:<<Loop>> outer_loop:none 262*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<NE:z\d+>> NotEqual [{{i\d+}},<<Phi>>] loop:<<Loop>> outer_loop:none 263*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: If [<<NE>>] loop:<<Loop>> outer_loop:none 264*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<AddI>> Add [<<Phi>>,<<One>>] loop:<<Loop>> outer_loop:none 265*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Comb:i\d+>> Phi [<<Zero>>,<<RedI>>] loop:none 266*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: Return [<<Comb>>] loop:none 267*795d594fSAndroid Build Coastguard Worker // 268*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.breakLoopReduction(int[]) induction_var_analysis (after) 269*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Par:l\d+>> ParameterValue loop:none 270*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Zero:i\d+>> IntConstant 0 loop:none 271*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<One:i\d+>> IntConstant 1 loop:none 272*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Nil:l\d+>> NullCheck [<<Par>>] loop:none 273*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Red:i\d+>> Phi [<<Zero>>,<<RedI:i\d+>>] loop:<<Loop:B\d+>> outer_loop:none 274*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Phi:i\d+>> Phi [<<Zero>>,<<AddI:i\d+>>] loop:<<Loop>> outer_loop:none 275*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<LE:z\d+>> LessThanOrEqual [<<Phi>>,{{i\d+}}] loop:<<Loop>> outer_loop:none 276*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: If [<<LE>>] loop:<<Loop>> outer_loop:none 277*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Bnd:i\d+>> BoundsCheck [<<Phi>>,{{i\d+}}] loop:<<Loop>> outer_loop:none 278*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Get:i\d+>> ArrayGet [<<Nil>>,<<Bnd>>] loop:<<Loop>> outer_loop:none 279*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<RedI>> Add [<<Red>>,<<Get>>] loop:<<Loop>> outer_loop:none 280*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<AddI>> Add [<<Phi>>,<<One>>] loop:<<Loop>> outer_loop:none 281*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Comb:i\d+>> Phi [<<Zero>>,<<Red>>] loop:none 282*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: Return [<<Comb>>] loop:none 283*795d594fSAndroid Build Coastguard Worker // 284*795d594fSAndroid Build Coastguard Worker /// CHECK-START-ARM64: int Main.breakLoopReduction(int[]) loop_optimization (after) 285*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Par:l\d+>> ParameterValue loop:none 286*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Zero:i\d+>> IntConstant 0 loop:none 287*795d594fSAndroid Build Coastguard Worker /// CHECK-IF: hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true' 288*795d594fSAndroid Build Coastguard Worker // 289*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Exp:d\d+>> VecSetScalars [<<Zero>>,{{j\d+}}] loop:none 290*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<LoopP:j\d+>> VecPredWhile loop:<<Loop:B\d+>> outer_loop:none 291*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<VPhi:d\d+>> Phi [<<Exp>>,<<VAdd:d\d+>>] loop:<<Loop>> outer_loop:none 292*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<VLoad:d\d+>> VecLoad loop:<<Loop>> outer_loop:none 293*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<VAdd>> VecAdd [<<VPhi>>,<<VLoad>>,<<LoopP>>] loop:<<Loop>> outer_loop:none 294*795d594fSAndroid Build Coastguard Worker // 295*795d594fSAndroid Build Coastguard Worker /// CHECK-ELSE: 296*795d594fSAndroid Build Coastguard Worker // 297*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Exp:d\d+>> VecSetScalars [<<Zero>>] loop:none 298*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<VPhi:d\d+>> Phi [<<Exp>>,<<VAdd:d\d+>>] loop:<<Loop:B\d+>> outer_loop:none 299*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<VLoad:d\d+>> VecLoad loop:<<Loop>> outer_loop:none 300*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<VAdd>> VecAdd [<<VPhi>>,<<VLoad>>] loop:<<Loop>> outer_loop:none 301*795d594fSAndroid Build Coastguard Worker // 302*795d594fSAndroid Build Coastguard Worker /// CHECK-FI: breakLoopReduction(int[] a)303*795d594fSAndroid Build Coastguard Worker static int breakLoopReduction(int[] a) { 304*795d594fSAndroid Build Coastguard Worker int l = 0; 305*795d594fSAndroid Build Coastguard Worker int u = a.length - 1; 306*795d594fSAndroid Build Coastguard Worker int x = 0; 307*795d594fSAndroid Build Coastguard Worker if (l <= u) { 308*795d594fSAndroid Build Coastguard Worker int i = l; 309*795d594fSAndroid Build Coastguard Worker while (true) { 310*795d594fSAndroid Build Coastguard Worker x += a[i]; 311*795d594fSAndroid Build Coastguard Worker if (i == u) break; 312*795d594fSAndroid Build Coastguard Worker i++; 313*795d594fSAndroid Build Coastguard Worker } 314*795d594fSAndroid Build Coastguard Worker } 315*795d594fSAndroid Build Coastguard Worker return x; 316*795d594fSAndroid Build Coastguard Worker } 317*795d594fSAndroid Build Coastguard Worker 318*795d594fSAndroid Build Coastguard Worker // 319*795d594fSAndroid Build Coastguard Worker // Test driver. 320*795d594fSAndroid Build Coastguard Worker // 321*795d594fSAndroid Build Coastguard Worker main(String[] args)322*795d594fSAndroid Build Coastguard Worker public static void main(String[] args) { 323*795d594fSAndroid Build Coastguard Worker int[] a = new int[100]; 324*795d594fSAndroid Build Coastguard Worker 325*795d594fSAndroid Build Coastguard Worker expectEquals(99, breakLoop(a)); 326*795d594fSAndroid Build Coastguard Worker for (int i = 0; i < a.length; i++) { 327*795d594fSAndroid Build Coastguard Worker expectEquals(1, a[i]); 328*795d594fSAndroid Build Coastguard Worker } 329*795d594fSAndroid Build Coastguard Worker 330*795d594fSAndroid Build Coastguard Worker expectEquals(0, breakLoopDown(a)); 331*795d594fSAndroid Build Coastguard Worker for (int i = 0; i < a.length; i++) { 332*795d594fSAndroid Build Coastguard Worker expectEquals(2, a[i]); 333*795d594fSAndroid Build Coastguard Worker } 334*795d594fSAndroid Build Coastguard Worker 335*795d594fSAndroid Build Coastguard Worker expectEquals(Integer.MAX_VALUE - 1, breakLoopSafeConst(a)); 336*795d594fSAndroid Build Coastguard Worker for (int i = 0; i < a.length; i++) { 337*795d594fSAndroid Build Coastguard Worker int e = i < 16 ? 3 : 2; 338*795d594fSAndroid Build Coastguard Worker expectEquals(e, a[i]); 339*795d594fSAndroid Build Coastguard Worker } 340*795d594fSAndroid Build Coastguard Worker 341*795d594fSAndroid Build Coastguard Worker expectEquals(Integer.MAX_VALUE, breakLoopUnsafeConst(a)); 342*795d594fSAndroid Build Coastguard Worker for (int i = 0; i < a.length; i++) { 343*795d594fSAndroid Build Coastguard Worker int e = i < 16 ? 4 : 2; 344*795d594fSAndroid Build Coastguard Worker expectEquals(e, a[i]); 345*795d594fSAndroid Build Coastguard Worker } 346*795d594fSAndroid Build Coastguard Worker 347*795d594fSAndroid Build Coastguard Worker expectEquals(98, breakLoopNastyPhi(a)); 348*795d594fSAndroid Build Coastguard Worker for (int i = 0; i < a.length; i++) { 349*795d594fSAndroid Build Coastguard Worker expectEquals(5, a[i]); 350*795d594fSAndroid Build Coastguard Worker } 351*795d594fSAndroid Build Coastguard Worker 352*795d594fSAndroid Build Coastguard Worker expectEquals(500, breakLoopReduction(a)); 353*795d594fSAndroid Build Coastguard Worker 354*795d594fSAndroid Build Coastguard Worker System.out.println("passed"); 355*795d594fSAndroid Build Coastguard Worker } 356*795d594fSAndroid Build Coastguard Worker 357*795d594fSAndroid Build Coastguard Worker private static void expectEquals(int expected, int result) { 358*795d594fSAndroid Build Coastguard Worker if (expected != result) { 359*795d594fSAndroid Build Coastguard Worker throw new Error("Expected: " + expected + ", found: " + result); 360*795d594fSAndroid Build Coastguard Worker } 361*795d594fSAndroid Build Coastguard Worker } 362*795d594fSAndroid Build Coastguard Worker } 363