Aart Bik | 40fbf74 | 2016-10-31 11:02:50 -0700 | [diff] [blame^] | 1 | /* |
| 2 | * Copyright (C) 2016 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 on bounds check elimination in loops that use intrinsics. |
| 19 | * All bounds checks below should be statically eliminated. |
| 20 | */ |
| 21 | public class Main { |
| 22 | |
| 23 | /// CHECK-START: int Main.oneArray(int[]) BCE (before) |
| 24 | /// CHECK-DAG: BoundsCheck loop:<<Loop:B\d+>> outer_loop:none |
| 25 | // |
| 26 | /// CHECK-START: int Main.oneArray(int[]) BCE (after) |
| 27 | /// CHECK-NOT: BoundsCheck |
| 28 | /// CHECK-NOT: Deoptimize |
| 29 | static int oneArray(int[] a) { |
| 30 | int x = 0; |
| 31 | for (int i = 0; i < a.length; i++) { |
| 32 | x += a[i]; |
| 33 | } |
| 34 | return x; |
| 35 | } |
| 36 | |
| 37 | /// CHECK-START: int Main.oneArrayAbs(int[], int) BCE (before) |
| 38 | /// CHECK-DAG: BoundsCheck loop:<<Loop:B\d+>> outer_loop:none |
| 39 | // |
| 40 | /// CHECK-START: int Main.oneArrayAbs(int[], int) BCE (after) |
| 41 | /// CHECK-NOT: BoundsCheck |
| 42 | /// CHECK-NOT: Deoptimize |
| 43 | static int oneArrayAbs(int[] a, int lo) { |
| 44 | int x = 0; |
| 45 | for (int i = Math.abs(lo); i < a.length; i++) { |
| 46 | x += a[i]; |
| 47 | } |
| 48 | return x; |
| 49 | } |
| 50 | |
| 51 | |
| 52 | /// CHECK-START: int Main.twoArrays(int[], int[]) BCE (before) |
| 53 | /// CHECK-DAG: BoundsCheck loop:<<Loop:B\d+>> outer_loop:none |
| 54 | /// CHECK-DAG: BoundsCheck loop:<<Loop>> outer_loop:none |
| 55 | // |
| 56 | /// CHECK-START: int Main.twoArrays(int[], int[]) BCE (after) |
| 57 | /// CHECK-NOT: BoundsCheck |
| 58 | /// CHECK-NOT: Deoptimize |
| 59 | static int twoArrays(int[] a, int[] b) { |
| 60 | int x = 0; |
| 61 | for (int i = 0; i < Math.min(a.length, b.length); i++) { |
| 62 | x += a[i] + b[i]; |
| 63 | } |
| 64 | return x; |
| 65 | } |
| 66 | |
| 67 | /// CHECK-START: int Main.threeArrays(int[], int[], int[]) BCE (before) |
| 68 | /// CHECK-DAG: BoundsCheck loop:<<Loop:B\d+>> outer_loop:none |
| 69 | /// CHECK-DAG: BoundsCheck loop:<<Loop>> outer_loop:none |
| 70 | /// CHECK-DAG: BoundsCheck loop:<<Loop>> outer_loop:none |
| 71 | // |
| 72 | /// CHECK-START: int Main.threeArrays(int[], int[], int[]) BCE (after) |
| 73 | /// CHECK-NOT: BoundsCheck |
| 74 | /// CHECK-NOT: Deoptimize |
| 75 | static int threeArrays(int[] a, int[] b, int[] c) { |
| 76 | int x = 0; |
| 77 | for (int i = 0; i < Math.min(Math.min(a.length, b.length), c.length); i++) { |
| 78 | x += a[i] + b[i] + c[i]; |
| 79 | } |
| 80 | return x; |
| 81 | } |
| 82 | |
| 83 | /// CHECK-START: int Main.fourArrays(int[], int[], int[], int[]) BCE (before) |
| 84 | /// CHECK-DAG: BoundsCheck loop:<<Loop:B\d+>> outer_loop:none |
| 85 | /// CHECK-DAG: BoundsCheck loop:<<Loop>> outer_loop:none |
| 86 | /// CHECK-DAG: BoundsCheck loop:<<Loop>> outer_loop:none |
| 87 | /// CHECK-DAG: BoundsCheck loop:<<Loop>> outer_loop:none |
| 88 | // |
| 89 | /// CHECK-START: int Main.fourArrays(int[], int[], int[], int[]) BCE (after) |
| 90 | /// CHECK-NOT: BoundsCheck |
| 91 | /// CHECK-NOT: Deoptimize |
| 92 | static int fourArrays(int[] a, int[] b, int[] c, int[] d) { |
| 93 | int x = 0; |
| 94 | for (int i = 0; i < Math.min(Math.min(a.length, b.length), Math.min(c.length, d.length)); i++) { |
| 95 | x += a[i] + b[i] + c[i] + d[i]; |
| 96 | } |
| 97 | return x; |
| 98 | } |
| 99 | |
| 100 | /// CHECK-START: int Main.oneArrayWithCleanup(int[]) BCE (before) |
| 101 | /// CHECK-DAG: BoundsCheck loop:<<Loop1:B\d+>> outer_loop:none |
| 102 | /// CHECK-DAG: BoundsCheck loop:<<Loop2:B\d+>> outer_loop:none |
| 103 | // |
| 104 | /// CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>" |
| 105 | // |
| 106 | /// CHECK-START: int Main.oneArrayWithCleanup(int[]) BCE (after) |
| 107 | /// CHECK-NOT: BoundsCheck |
| 108 | /// CHECK-NOT: Deoptimize |
| 109 | static int oneArrayWithCleanup(int[] a) { |
| 110 | int x = 0; |
| 111 | int n = Math.min(4, a.length); |
| 112 | for (int i = 0; i < n; i++) { |
| 113 | x += a[i]; |
| 114 | } |
| 115 | for (int i = n; i < a.length; i++) { |
| 116 | x += a[i] * 10; |
| 117 | } |
| 118 | return x; |
| 119 | } |
| 120 | |
| 121 | /// CHECK-START: int Main.twoArraysWithCleanup(int[], int[]) BCE (before) |
| 122 | /// CHECK-DAG: BoundsCheck loop:<<Loop1:B\d+>> outer_loop:none |
| 123 | /// CHECK-DAG: BoundsCheck loop:<<Loop1>> outer_loop:none |
| 124 | /// CHECK-DAG: BoundsCheck loop:<<Loop2:B\d+>> outer_loop:none |
| 125 | // |
| 126 | /// CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>" |
| 127 | // |
| 128 | /// CHECK-START: int Main.twoArraysWithCleanup(int[], int[]) BCE (after) |
| 129 | /// CHECK-NOT: BoundsCheck |
| 130 | /// CHECK-NOT: Deoptimize |
| 131 | static int twoArraysWithCleanup(int[] a, int[] b) { |
| 132 | int x = 0; |
| 133 | int n = Math.min(a.length, b.length); |
| 134 | for (int i = n - 1; i >= 0; i--) { |
| 135 | x += a[i] + b[i]; |
| 136 | } |
| 137 | for (int i = n; i < a.length; i++) { |
| 138 | x += a[i]; |
| 139 | } |
| 140 | return x; |
| 141 | } |
| 142 | |
| 143 | /// CHECK-START: int Main.threeArraysWithCleanup(int[], int[], int[]) BCE (before) |
| 144 | /// CHECK-DAG: BoundsCheck loop:<<Loop1:B\d+>> outer_loop:none |
| 145 | /// CHECK-DAG: BoundsCheck loop:<<Loop1>> outer_loop:none |
| 146 | /// CHECK-DAG: BoundsCheck loop:<<Loop1>> outer_loop:none |
| 147 | /// CHECK-DAG: BoundsCheck loop:<<Loop2:B\d+>> outer_loop:none |
| 148 | // |
| 149 | /// CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>" |
| 150 | // |
| 151 | /// CHECK-START: int Main.threeArraysWithCleanup(int[], int[], int[]) BCE (after) |
| 152 | /// CHECK-NOT: BoundsCheck |
| 153 | /// CHECK-NOT: Deoptimize |
| 154 | static int threeArraysWithCleanup(int[] a, int[] b, int[] c) { |
| 155 | int x = 0; |
| 156 | int n = Math.min(a.length, Math.min(b.length, c.length)); |
| 157 | for (int i = n - 1; i >= 0; i--) { |
| 158 | x += a[i] + b[i] + c[i]; |
| 159 | } |
| 160 | for (int i = n; i < a.length; i++) { |
| 161 | x += a[i]; |
| 162 | } |
| 163 | return x; |
| 164 | } |
| 165 | |
| 166 | /// CHECK-START: int Main.altLoopLogic(int[], int[]) BCE (before) |
| 167 | /// CHECK-DAG: BoundsCheck loop:<<Loop:B\d+>> outer_loop:none |
| 168 | /// CHECK-DAG: BoundsCheck loop:<<Loop>> outer_loop:none |
| 169 | // |
| 170 | /// CHECK-START: int Main.altLoopLogic(int[], int[]) BCE (after) |
| 171 | /// CHECK-NOT: BoundsCheck |
| 172 | /// CHECK-NOT: Deoptimize |
| 173 | static int altLoopLogic(int[] a, int[] b) { |
| 174 | int x = 0; |
| 175 | int n = Math.min(a.length, b.length); |
| 176 | for (int i = n; i-- > 0;) { |
| 177 | x += a[i] + b[i]; |
| 178 | } |
| 179 | return x; |
| 180 | } |
| 181 | |
| 182 | /// CHECK-START: int Main.hiddenMin(int[], int[]) BCE (before) |
| 183 | /// CHECK-DAG: BoundsCheck loop:<<Loop:B\d+>> outer_loop:none |
| 184 | /// CHECK-DAG: BoundsCheck loop:<<Loop>> outer_loop:none |
| 185 | // |
| 186 | /// CHECK-START: int Main.hiddenMin(int[], int[]) BCE (after) |
| 187 | // |
| 188 | // TODO: make this so |
| 189 | static int hiddenMin(int[] a, int[] b) { |
| 190 | int x = 0; |
| 191 | for (int i = 0; i < a.length && i < b.length; i++) { |
| 192 | x += a[i] + b[i]; |
| 193 | } |
| 194 | return x; |
| 195 | } |
| 196 | |
| 197 | /// CHECK-START: int Main.hiddenMinWithCleanup(int[], int[]) BCE (before) |
| 198 | /// CHECK-DAG: BoundsCheck loop:<<Loop1:B\d+>> outer_loop:none |
| 199 | /// CHECK-DAG: BoundsCheck loop:<<Loop1>> outer_loop:none |
| 200 | /// CHECK-DAG: BoundsCheck loop:<<Loop2:B\d+>> outer_loop:none |
| 201 | // |
| 202 | /// CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>" |
| 203 | // |
| 204 | /// CHECK-START: int Main.hiddenMinWithCleanup(int[], int[]) BCE (after) |
| 205 | // |
| 206 | // TODO: make this so |
| 207 | static int hiddenMinWithCleanup(int[] a, int[] b) { |
| 208 | int x = 0; |
| 209 | int i = 0; |
| 210 | for (; i < a.length && i < b.length; i++) { |
| 211 | x += a[i] + b[i]; |
| 212 | } |
| 213 | for (; i < a.length; i++) { |
| 214 | x += a[i]; |
| 215 | } |
| 216 | return x; |
| 217 | } |
| 218 | |
| 219 | public static void main(String[] args) { |
| 220 | int[] a = { 1, 2, 3, 4, 5 }; |
| 221 | int[] b = { 6, 7, 8, 9, 4, 2 }; |
| 222 | int[] c = { 1, 2, 3 }; |
| 223 | int[] d = { 8, 5, 3, 2 }; |
| 224 | |
| 225 | expectEquals(15, oneArray(a)); |
| 226 | expectEquals(36, oneArray(b)); |
| 227 | expectEquals(6, oneArray(c)); |
| 228 | expectEquals(18, oneArray(d)); |
| 229 | |
| 230 | expectEquals(5, oneArrayAbs(a, -4)); |
| 231 | expectEquals(15, oneArrayAbs(a, 0)); |
| 232 | expectEquals(5, oneArrayAbs(a, 4)); |
| 233 | |
| 234 | expectEquals(30, twoArrays(a, a)); |
| 235 | expectEquals(49, twoArrays(a, b)); |
| 236 | expectEquals(12, twoArrays(a, c)); |
| 237 | expectEquals(28, twoArrays(a, d)); |
| 238 | |
| 239 | expectEquals(45, threeArrays(a, a, a)); |
| 240 | expectEquals(33, threeArrays(a, b, c)); |
| 241 | expectEquals(58, threeArrays(a, b, d)); |
| 242 | expectEquals(28, threeArrays(a, c, d)); |
| 243 | |
| 244 | expectEquals(60, fourArrays(a, a, a, a)); |
| 245 | expectEquals(49, fourArrays(a, b, c, d)); |
| 246 | |
| 247 | expectEquals(60, oneArrayWithCleanup(a)); |
| 248 | expectEquals(90, oneArrayWithCleanup(b)); |
| 249 | expectEquals(6, oneArrayWithCleanup(c)); |
| 250 | expectEquals(18, oneArrayWithCleanup(d)); |
| 251 | |
| 252 | expectEquals(30, twoArraysWithCleanup(a, a)); |
| 253 | expectEquals(49, twoArraysWithCleanup(a, b)); |
| 254 | expectEquals(21, twoArraysWithCleanup(a, c)); |
| 255 | expectEquals(33, twoArraysWithCleanup(a, d)); |
| 256 | |
| 257 | expectEquals(45, threeArraysWithCleanup(a, a, a)); |
| 258 | expectEquals(42, threeArraysWithCleanup(a, b, c)); |
| 259 | expectEquals(63, threeArraysWithCleanup(a, b, d)); |
| 260 | expectEquals(37, threeArraysWithCleanup(a, c, d)); |
| 261 | |
| 262 | expectEquals(30, altLoopLogic(a, a)); |
| 263 | expectEquals(49, altLoopLogic(a, b)); |
| 264 | expectEquals(12, altLoopLogic(a, c)); |
| 265 | expectEquals(28, altLoopLogic(a, d)); |
| 266 | |
| 267 | expectEquals(30, hiddenMin(a, a)); |
| 268 | expectEquals(49, hiddenMin(a, b)); |
| 269 | expectEquals(12, hiddenMin(a, c)); |
| 270 | expectEquals(28, hiddenMin(a, d)); |
| 271 | |
| 272 | expectEquals(30, hiddenMinWithCleanup(a, a)); |
| 273 | expectEquals(49, hiddenMinWithCleanup(a, b)); |
| 274 | expectEquals(21, hiddenMinWithCleanup(a, c)); |
| 275 | expectEquals(33, hiddenMinWithCleanup(a, d)); |
| 276 | |
| 277 | System.out.println("passed"); |
| 278 | } |
| 279 | |
| 280 | private static void expectEquals(int expected, int result) { |
| 281 | if (expected != result) { |
| 282 | throw new Error("Expected: " + expected + ", found: " + result); |
| 283 | } |
| 284 | } |
| 285 | } |