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