1 /* 2 * Copyright (C) 2018 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 * Functional tests for detecting min/max. 19 */ 20 public class TestMinMax { 21 22 // 23 // Direct intrinsics. 24 // 25 26 /// CHECK-START: int TestMinMax.minI(int) builder (after) 27 /// CHECK-DAG: <<Par:i\d+>> ParameterValue 28 /// CHECK-DAG: <<Con:i\d+>> IntConstant 20 29 /// CHECK-DAG: <<Min:i\d+>> Min [<<Par>>,<<Con>>] 30 /// CHECK-DAG: Return [<<Min>>] 31 // 32 /// CHECK-START: int TestMinMax.minI(int) builder (after) 33 /// CHECK-NOT: InvokeStaticOrDirect 34 // 35 /// CHECK-START-ARM64: int TestMinMax.minI(int) disassembly (after) 36 /// CHECK-NOT: mov {{w\d+}}, #0x14 37 /// CHECK: cmp {{w\d+}}, #0x14 38 // Check that the constant generation was handled by VIXL. 39 /// CHECK: mov w16, #0x14 40 /// CHECK: csel {{w\d+}}, {{w\d+}}, w16, lt minI(int a)41 public static int minI(int a) { 42 return Math.min(a, 20); 43 } 44 45 /// CHECK-START: long TestMinMax.minL(long) builder (after) 46 /// CHECK-DAG: <<Par:j\d+>> ParameterValue 47 /// CHECK-DAG: <<Con:j\d+>> LongConstant 20 48 /// CHECK-DAG: <<Min:j\d+>> Min [<<Par>>,<<Con>>] 49 /// CHECK-DAG: Return [<<Min>>] 50 // 51 /// CHECK-START: long TestMinMax.minL(long) builder (after) 52 /// CHECK-NOT: InvokeStaticOrDirect 53 // 54 /// CHECK-START-ARM64: long TestMinMax.minL(long) disassembly (after) 55 /// CHECK-NOT: mov {{x\d+}}, #0x14 56 /// CHECK: cmp {{x\d+}}, #0x14 57 // Check that the constant generation was handled by VIXL. 58 /// CHECK: mov x16, #0x14 59 /// CHECK: csel {{x\d+}}, {{x\d+}}, x16, lt minL(long a)60 public static long minL(long a) { 61 return Math.min(a, 20L); 62 } 63 64 /// CHECK-START: int TestMinMax.maxI(int) builder (after) 65 /// CHECK-DAG: <<Par:i\d+>> ParameterValue 66 /// CHECK-DAG: <<Con:i\d+>> IntConstant 20 67 /// CHECK-DAG: <<Max:i\d+>> Max [<<Par>>,<<Con>>] 68 /// CHECK-DAG: Return [<<Max>>] 69 // 70 /// CHECK-START: int TestMinMax.maxI(int) builder (after) 71 /// CHECK-NOT: InvokeStaticOrDirect 72 // 73 /// CHECK-START-ARM64: int TestMinMax.maxI(int) disassembly (after) 74 /// CHECK-NOT: mov {{w\d+}}, #0x14 75 /// CHECK: cmp {{w\d+}}, #0x14 76 // Check that the constant generation was handled by VIXL. 77 /// CHECK: mov w16, #0x14 78 /// CHECK: csel {{w\d+}}, {{w\d+}}, w16, gt maxI(int a)79 public static int maxI(int a) { 80 return Math.max(a, 20); 81 } 82 83 /// CHECK-START: long TestMinMax.maxL(long) builder (after) 84 /// CHECK-DAG: <<Par:j\d+>> ParameterValue 85 /// CHECK-DAG: <<Con:j\d+>> LongConstant 20 86 /// CHECK-DAG: <<Max:j\d+>> Max [<<Par>>,<<Con>>] 87 /// CHECK-DAG: Return [<<Max>>] 88 // 89 /// CHECK-START: long TestMinMax.maxL(long) builder (after) 90 /// CHECK-NOT: InvokeStaticOrDirect 91 // 92 /// CHECK-START-ARM64: long TestMinMax.maxL(long) disassembly (after) 93 /// CHECK-NOT: mov {{x\d+}}, #0x14 94 /// CHECK: cmp {{x\d+}}, #0x14 95 // Check that the constant generation was handled by VIXL. 96 /// CHECK: mov x16, #0x14 97 /// CHECK: csel {{x\d+}}, {{x\d+}}, x16, gt maxL(long a)98 public static long maxL(long a) { 99 return Math.max(a, 20L); 100 } 101 102 // 103 // Special Cases 104 // 105 106 /// CHECK-START-ARM64: int TestMinMax.minIntConstantZero(int) disassembly (after) 107 /// CHECK-NOT: InvokeStaticOrDirect 108 /// CHECK-NOT: mov {{w\d+}}, #0x0 109 /// CHECK: cmp {{w\d+}}, #0x0 (0) 110 /// CHECK: csel {{w\d+}}, {{w\d+}}, wzr, lt 111 /// CHECK: ret minIntConstantZero(int a)112 public static int minIntConstantZero(int a) { 113 return Math.min(a, 0); 114 } 115 116 /// CHECK-START-ARM64: int TestMinMax.minIntConstantOne(int) disassembly (after) 117 /// CHECK-NOT: InvokeStaticOrDirect 118 /// CHECK-NOT: mov {{w\d+}}, #0x1 119 /// CHECK: cmp {{w\d+}}, #0x1 (1) 120 /// CHECK: csinc {{w\d+}}, {{w\d+}}, wzr, lt 121 /// CHECK: ret minIntConstantOne(int a)122 public static int minIntConstantOne(int a) { 123 return Math.min(a, 1); 124 } 125 126 /// CHECK-START-ARM64: int TestMinMax.minIntConstantMinusOne(int) disassembly (after) 127 /// CHECK-NOT: InvokeStaticOrDirect 128 /// CHECK-NOT: mov {{w\d+}}, #0xffffffff 129 /// CHECK: cmn {{w\d+}}, #0x1 (1) 130 /// CHECK: csinv {{w\d+}}, {{w\d+}}, wzr, lt 131 /// CHECK: ret minIntConstantMinusOne(int a)132 public static int minIntConstantMinusOne(int a) { 133 return Math.min(a, -1); 134 } 135 136 /// CHECK-START-ARM64: long TestMinMax.minLongConstantZero(long) disassembly (after) 137 /// CHECK-NOT: InvokeStaticOrDirect 138 /// CHECK-NOT: mov {{x\d+}}, #0x0 139 /// CHECK: cmp {{x\d+}}, #0x0 (0) 140 /// CHECK: csel {{x\d+}}, {{x\d+}}, xzr, lt 141 /// CHECK: ret minLongConstantZero(long a)142 public static long minLongConstantZero(long a) { 143 return Math.min(a, 0L); 144 } 145 146 /// CHECK-START-ARM64: long TestMinMax.minLongConstantOne(long) disassembly (after) 147 /// CHECK-NOT: InvokeStaticOrDirect 148 /// CHECK-NOT: mov {{x\d+}}, #0x1 149 /// CHECK: cmp {{x\d+}}, #0x1 (1) 150 /// CHECK: csinc {{x\d+}}, {{x\d+}}, xzr, lt 151 /// CHECK: ret minLongConstantOne(long a)152 public static long minLongConstantOne(long a) { 153 return Math.min(a, 1L); 154 } 155 156 /// CHECK-START-ARM64: long TestMinMax.minLongConstantMinusOne(long) disassembly (after) 157 /// CHECK-NOT: InvokeStaticOrDirect 158 /// CHECK-NOT: mov {{x\d+}}, #0xffffffffffffffff 159 /// CHECK: cmn {{x\d+}}, #0x1 (1) 160 /// CHECK: csinv {{x\d+}}, {{x\d+}}, xzr, lt 161 /// CHECK: ret minLongConstantMinusOne(long a)162 public static long minLongConstantMinusOne(long a) { 163 return Math.min(a, -1L); 164 } 165 166 /// CHECK-START-ARM64: int TestMinMax.maxIntConstantZero(int) disassembly (after) 167 /// CHECK-NOT: InvokeStaticOrDirect 168 /// CHECK-NOT: mov {{w\d+}}, #0x0 169 /// CHECK: cmp {{w\d+}}, #0x0 (0) 170 /// CHECK: csel {{w\d+}}, {{w\d+}}, wzr, gt 171 /// CHECK: ret maxIntConstantZero(int a)172 public static int maxIntConstantZero(int a) { 173 return Math.max(a, 0); 174 } 175 176 /// CHECK-START-ARM64: int TestMinMax.maxIntConstantOne(int) disassembly (after) 177 /// CHECK-NOT: InvokeStaticOrDirect 178 /// CHECK-NOT: mov {{w\d+}}, #0x1 179 /// CHECK: cmp {{w\d+}}, #0x1 (1) 180 /// CHECK: csinc {{w\d+}}, {{w\d+}}, wzr, gt 181 /// CHECK: ret maxIntConstantOne(int a)182 public static int maxIntConstantOne(int a) { 183 return Math.max(a, 1); 184 } 185 186 /// CHECK-START-ARM64: int TestMinMax.maxIntConstantMinusOne(int) disassembly (after) 187 /// CHECK-NOT: InvokeStaticOrDirect 188 /// CHECK-NOT: mov {{w\d+}}, #0xffffffff 189 /// CHECK: cmn {{w\d+}}, #0x1 (1) 190 /// CHECK: csinv {{w\d+}}, {{w\d+}}, wzr, gt 191 /// CHECK: ret maxIntConstantMinusOne(int a)192 public static int maxIntConstantMinusOne(int a) { 193 return Math.max(a, -1); 194 } 195 196 /// CHECK-START-ARM64: int TestMinMax.maxIntLargeConstant(int) disassembly (after) 197 /// CHECK-NOT: InvokeStaticOrDirect 198 /// CHECK: mov {{w\d+}}, #0x2001 199 /// CHECK: cmp {{w\d+}}, {{w\d+}} 200 // Check that constant generation was not handled by VIXL. 201 /// CHECK-NOT: mov {{w\d+}}, #0x2001 202 /// CHECK: csel {{w\d+}}, {{w\d+}}, {{w\d+}}, gt 203 /// CHECK: ret maxIntLargeConstant(int a)204 public static int maxIntLargeConstant(int a) { 205 return Math.max(a, 8193); 206 } 207 208 /// CHECK-START-ARM64: long TestMinMax.maxLongConstantZero(long) disassembly (after) 209 /// CHECK-NOT: InvokeStaticOrDirect 210 /// CHECK-NOT: mov {{x\d+}}, #0x0 211 /// CHECK: cmp {{x\d+}}, #0x0 (0) 212 /// CHECK: csel {{x\d+}}, {{x\d+}}, xzr, gt 213 /// CHECK: ret maxLongConstantZero(long a)214 public static long maxLongConstantZero(long a) { 215 return Math.max(a, 0L); 216 } 217 218 /// CHECK-START-ARM64: long TestMinMax.maxLongConstantOne(long) disassembly (after) 219 /// CHECK-NOT: InvokeStaticOrDirect 220 /// CHECK-NOT: mov {{x\d+}}, #0x1 221 /// CHECK: cmp {{x\d+}}, #0x1 (1) 222 /// CHECK: csinc {{x\d+}}, {{x\d+}}, xzr, gt 223 /// CHECK: ret maxLongConstantOne(long a)224 public static long maxLongConstantOne(long a) { 225 return Math.max(a, 1L); 226 } 227 228 /// CHECK-START-ARM64: long TestMinMax.maxLongConstantMinusOne(long) disassembly (after) 229 /// CHECK-NOT: InvokeStaticOrDirect 230 /// CHECK-NOT: mov {{x\d+}}, #0xffffffffffffffff 231 /// CHECK: cmn {{x\d+}}, #0x1 (1) 232 /// CHECK: csinv {{x\d+}}, {{x\d+}}, xzr, gt 233 /// CHECK: ret maxLongConstantMinusOne(long a)234 public static long maxLongConstantMinusOne(long a) { 235 return Math.max(a, -1L); 236 } 237 238 /// CHECK-START-ARM64: long TestMinMax.maxLongLargeConstant(long) disassembly (after) 239 /// CHECK-NOT: InvokeStaticOrDirect 240 /// CHECK: mov {{x\d+}}, #0x2001 241 /// CHECK: cmp {{x\d+}}, {{x\d+}} 242 // Check that constant generation was not handled by VIXL. 243 /// CHECK-NOT: mov {{x\d+}}, #0x2001 244 /// CHECK: csel {{x\d+}}, {{x\d+}}, {{x\d+}}, gt 245 /// CHECK: ret maxLongLargeConstant(long a)246 public static long maxLongLargeConstant(long a) { 247 return Math.max(a, 8193L); 248 } 249 250 // 251 // Different types. 252 // 253 254 /// CHECK-START: int TestMinMax.min1(int, int) instruction_simplifier$after_gvn (before) 255 /// CHECK-DAG: <<Cnd:z\d+>> GreaterThanOrEqual [<<Op1:i\d+>>,<<Op2:i\d+>>] 256 /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op1>>,<<Op2>>,<<Cnd>>] 257 /// CHECK-DAG: Return [<<Sel>>] 258 // 259 /// CHECK-START: int TestMinMax.min1(int, int) instruction_simplifier$after_gvn (after) 260 /// CHECK-DAG: <<Min:i\d+>> Min 261 /// CHECK-DAG: Return [<<Min>>] 262 // 263 /// CHECK-START: int TestMinMax.min1(int, int) instruction_simplifier$after_gvn (after) 264 /// CHECK-NOT: Select min1(int a, int b)265 public static int min1(int a, int b) { 266 return a < b ? a : b; 267 } 268 269 /// CHECK-START: int TestMinMax.min2(int, int) instruction_simplifier$after_gvn (before) 270 /// CHECK-DAG: <<Cnd:z\d+>> GreaterThan [<<Op1:i\d+>>,<<Op2:i\d+>>] 271 /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op1>>,<<Op2>>,<<Cnd>>] 272 /// CHECK-DAG: Return [<<Sel>>] 273 // 274 /// CHECK-START: int TestMinMax.min2(int, int) instruction_simplifier$after_gvn (after) 275 /// CHECK-DAG: <<Min:i\d+>> Min 276 /// CHECK-DAG: Return [<<Min>>] 277 // 278 /// CHECK-START: int TestMinMax.min2(int, int) instruction_simplifier$after_gvn (after) 279 /// CHECK-NOT: Select min2(int a, int b)280 public static int min2(int a, int b) { 281 return a <= b ? a : b; 282 } 283 284 /// CHECK-START: int TestMinMax.min3(int, int) instruction_simplifier$after_gvn (before) 285 /// CHECK-DAG: <<Cnd:z\d+>> LessThanOrEqual [<<Op1:i\d+>>,<<Op2:i\d+>>] 286 /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op2>>,<<Op1>>,<<Cnd>>] 287 /// CHECK-DAG: Return [<<Sel>>] 288 // 289 /// CHECK-START: int TestMinMax.min3(int, int) instruction_simplifier$after_gvn (after) 290 /// CHECK-DAG: <<Min:i\d+>> Min 291 /// CHECK-DAG: Return [<<Min>>] 292 // 293 /// CHECK-START: int TestMinMax.min3(int, int) instruction_simplifier$after_gvn (after) 294 /// CHECK-NOT: Select min3(int a, int b)295 public static int min3(int a, int b) { 296 return a > b ? b : a; 297 } 298 299 /// CHECK-START: int TestMinMax.min4(int, int) instruction_simplifier$after_gvn (before) 300 /// CHECK-DAG: <<Cnd:z\d+>> LessThan [<<Op1:i\d+>>,<<Op2:i\d+>>] 301 /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op2>>,<<Op1>>,<<Cnd>>] 302 /// CHECK-DAG: Return [<<Sel>>] 303 // 304 /// CHECK-START: int TestMinMax.min4(int, int) instruction_simplifier$after_gvn (after) 305 /// CHECK-DAG: <<Min:i\d+>> Min 306 /// CHECK-DAG: Return [<<Min>>] 307 // 308 /// CHECK-START: int TestMinMax.min4(int, int) instruction_simplifier$after_gvn (after) 309 /// CHECK-NOT: Select min4(int a, int b)310 public static int min4(int a, int b) { 311 return a >= b ? b : a; 312 } 313 314 /// CHECK-START: int TestMinMax.min5(short, short) instruction_simplifier$after_gvn (before) 315 /// CHECK-DAG: <<Cnd:z\d+>> LessThan [<<Op1:s\d+>>,<<Op2:s\d+>>] 316 /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op2>>,<<Op1>>,<<Cnd>>] 317 /// CHECK-DAG: Return [<<Sel>>] 318 // 319 /// CHECK-START: int TestMinMax.min5(short, short) instruction_simplifier$after_gvn (after) 320 /// CHECK-DAG: <<Min:i\d+>> Min 321 /// CHECK-DAG: Return [<<Min>>] 322 // 323 /// CHECK-START: int TestMinMax.min5(short, short) instruction_simplifier$after_gvn (after) 324 /// CHECK-NOT: Select min5(short a, short b)325 public static int min5(short a, short b) { 326 return a >= b ? b : a; 327 } 328 329 /// CHECK-START: int TestMinMax.min6(byte, byte) instruction_simplifier$after_gvn (before) 330 /// CHECK-DAG: <<Cnd:z\d+>> LessThan [<<Op1:b\d+>>,<<Op2:b\d+>>] 331 /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op2>>,<<Op1>>,<<Cnd>>] 332 /// CHECK-DAG: Return [<<Sel>>] 333 // 334 /// CHECK-START: int TestMinMax.min6(byte, byte) instruction_simplifier$after_gvn (after) 335 /// CHECK-DAG: <<Min:i\d+>> Min 336 /// CHECK-DAG: Return [<<Min>>] 337 // 338 /// CHECK-START: int TestMinMax.min6(byte, byte) instruction_simplifier$after_gvn (after) 339 /// CHECK-NOT: Select min6(byte a, byte b)340 public static int min6(byte a, byte b) { 341 return a >= b ? b : a; 342 } 343 344 /// CHECK-START: long TestMinMax.min7(long, long) instruction_simplifier$after_gvn (before) 345 /// CHECK-DAG: <<Cnd:z\d+>> LessThan [<<Op1:j\d+>>,<<Op2:j\d+>>] 346 /// CHECK-DAG: <<Sel:j\d+>> Select [<<Op2>>,<<Op1>>,<<Cnd>>] 347 /// CHECK-DAG: Return [<<Sel>>] 348 // 349 /// CHECK-START: long TestMinMax.min7(long, long) instruction_simplifier$after_gvn (after) 350 /// CHECK-DAG: <<Min:j\d+>> Min 351 /// CHECK-DAG: Return [<<Min>>] 352 // 353 /// CHECK-START: long TestMinMax.min7(long, long) instruction_simplifier$after_gvn (after) 354 /// CHECK-NOT: Select min7(long a, long b)355 public static long min7(long a, long b) { 356 return a >= b ? b : a; 357 } 358 359 /// CHECK-START: int TestMinMax.max1(int, int) instruction_simplifier$after_gvn (before) 360 /// CHECK-DAG: <<Cnd:z\d+>> GreaterThanOrEqual [<<Op1:i\d+>>,<<Op2:i\d+>>] 361 /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op2>>,<<Op1>>,<<Cnd>>] 362 /// CHECK-DAG: Return [<<Sel>>] 363 // 364 /// CHECK-START: int TestMinMax.max1(int, int) instruction_simplifier$after_gvn (after) 365 /// CHECK-DAG: <<Max:i\d+>> Max 366 /// CHECK-DAG: Return [<<Max>>] 367 // 368 /// CHECK-START: int TestMinMax.max1(int, int) instruction_simplifier$after_gvn (after) 369 /// CHECK-NOT: Select max1(int a, int b)370 public static int max1(int a, int b) { 371 return a < b ? b : a; 372 } 373 374 /// CHECK-START: int TestMinMax.max2(int, int) instruction_simplifier$after_gvn (before) 375 /// CHECK-DAG: <<Cnd:z\d+>> GreaterThan [<<Op1:i\d+>>,<<Op2:i\d+>>] 376 /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op2>>,<<Op1>>,<<Cnd>>] 377 /// CHECK-DAG: Return [<<Sel>>] 378 // 379 /// CHECK-START: int TestMinMax.max2(int, int) instruction_simplifier$after_gvn (after) 380 /// CHECK-DAG: <<Max:i\d+>> Max 381 /// CHECK-DAG: Return [<<Max>>] 382 // 383 /// CHECK-START: int TestMinMax.max2(int, int) instruction_simplifier$after_gvn (after) 384 /// CHECK-NOT: Select max2(int a, int b)385 public static int max2(int a, int b) { 386 return a <= b ? b : a; 387 } 388 389 /// CHECK-START: int TestMinMax.max3(int, int) instruction_simplifier$after_gvn (before) 390 /// CHECK-DAG: <<Cnd:z\d+>> LessThanOrEqual [<<Op1:i\d+>>,<<Op2:i\d+>>] 391 /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op1>>,<<Op2>>,<<Cnd>>] 392 /// CHECK-DAG: Return [<<Sel>>] 393 // 394 /// CHECK-START: int TestMinMax.max3(int, int) instruction_simplifier$after_gvn (after) 395 /// CHECK-DAG: <<Max:i\d+>> Max 396 /// CHECK-DAG: Return [<<Max>>] 397 // 398 /// CHECK-START: int TestMinMax.max3(int, int) instruction_simplifier$after_gvn (after) 399 /// CHECK-NOT: Select max3(int a, int b)400 public static int max3(int a, int b) { 401 return a > b ? a : b; 402 } 403 404 /// CHECK-START: int TestMinMax.max4(int, int) instruction_simplifier$after_gvn (before) 405 /// CHECK-DAG: <<Cnd:z\d+>> LessThan [<<Op1:i\d+>>,<<Op2:i\d+>>] 406 /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op1>>,<<Op2>>,<<Cnd>>] 407 /// CHECK-DAG: Return [<<Sel>>] 408 // 409 /// CHECK-START: int TestMinMax.max4(int, int) instruction_simplifier$after_gvn (after) 410 /// CHECK-DAG: <<Max:i\d+>> Max 411 /// CHECK-DAG: Return [<<Max>>] 412 // 413 /// CHECK-START: int TestMinMax.max4(int, int) instruction_simplifier$after_gvn (after) 414 /// CHECK-NOT: Select max4(int a, int b)415 public static int max4(int a, int b) { 416 return a >= b ? a : b; 417 } 418 419 /// CHECK-START: int TestMinMax.max5(short, short) instruction_simplifier$after_gvn (before) 420 /// CHECK-DAG: <<Cnd:z\d+>> LessThan [<<Op1:s\d+>>,<<Op2:s\d+>>] 421 /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op1>>,<<Op2>>,<<Cnd>>] 422 /// CHECK-DAG: Return [<<Sel>>] 423 // 424 /// CHECK-START: int TestMinMax.max5(short, short) instruction_simplifier$after_gvn (after) 425 /// CHECK-DAG: <<Max:i\d+>> Max 426 /// CHECK-DAG: Return [<<Max>>] 427 // 428 /// CHECK-START: int TestMinMax.max5(short, short) instruction_simplifier$after_gvn (after) 429 /// CHECK-NOT: Select max5(short a, short b)430 public static int max5(short a, short b) { 431 return a >= b ? a : b; 432 } 433 434 /// CHECK-START: int TestMinMax.max6(byte, byte) instruction_simplifier$after_gvn (before) 435 /// CHECK-DAG: <<Cnd:z\d+>> LessThan [<<Op1:b\d+>>,<<Op2:b\d+>>] 436 /// CHECK-DAG: <<Sel:i\d+>> Select [<<Op1>>,<<Op2>>,<<Cnd>>] 437 /// CHECK-DAG: Return [<<Sel>>] 438 // 439 /// CHECK-START: int TestMinMax.max6(byte, byte) instruction_simplifier$after_gvn (after) 440 /// CHECK-DAG: <<Max:i\d+>> Max 441 /// CHECK-DAG: Return [<<Max>>] 442 // 443 /// CHECK-START: int TestMinMax.max6(byte, byte) instruction_simplifier$after_gvn (after) 444 /// CHECK-NOT: Select max6(byte a, byte b)445 public static int max6(byte a, byte b) { 446 return a >= b ? a : b; 447 } 448 449 /// CHECK-START: long TestMinMax.max7(long, long) instruction_simplifier$after_gvn (before) 450 /// CHECK-DAG: <<Cnd:z\d+>> LessThan [<<Op1:j\d+>>,<<Op2:j\d+>>] 451 /// CHECK-DAG: <<Sel:j\d+>> Select [<<Op1>>,<<Op2>>,<<Cnd>>] 452 /// CHECK-DAG: Return [<<Sel>>] 453 // 454 /// CHECK-START: long TestMinMax.max7(long, long) instruction_simplifier$after_gvn (after) 455 /// CHECK-DAG: <<Max:j\d+>> Max 456 /// CHECK-DAG: Return [<<Max>>] 457 // 458 /// CHECK-START: long TestMinMax.max7(long, long) instruction_simplifier$after_gvn (after) 459 /// CHECK-NOT: Select max7(long a, long b)460 public static long max7(long a, long b) { 461 return a >= b ? a : b; 462 } 463 464 // 465 // Complications. 466 // 467 468 /// CHECK-START: int TestMinMax.min0(int[], int[]) instruction_simplifier$after_gvn (before) 469 /// CHECK-DAG: <<Ar1:i\d+>> ArrayGet [{{l\d+}},{{i\d+}}] 470 /// CHECK-DAG: <<Ar2:i\d+>> ArrayGet [{{l\d+}},{{i\d+}}] 471 /// CHECK-DAG: <<Cnd:z\d+>> GreaterThan [<<Ar1>>,<<Ar2>>] 472 /// CHECK-DAG: <<Sel:i\d+>> Select [<<Ar1>>,<<Ar2>>,<<Cnd>>] 473 /// CHECK-DAG: Return [<<Sel>>] 474 // 475 /// CHECK-START: int TestMinMax.min0(int[], int[]) instruction_simplifier$after_gvn (after) 476 /// CHECK-DAG: <<Min:i\d+>> Min 477 /// CHECK-DAG: Return [<<Min>>] 478 // 479 /// CHECK-START: int TestMinMax.min0(int[], int[]) instruction_simplifier$after_gvn (after) 480 /// CHECK-NOT: Select min0(int[] a, int[] b)481 public static int min0(int[] a, int[] b) { 482 // Repeat of array references needs finding the common subexpressions 483 // prior to doing the select and min/max recognition. 484 return a[0] <= b[0] ? a[0] : b[0]; 485 } 486 487 /// CHECK-START: int TestMinMax.max0(int[], int[]) instruction_simplifier$after_gvn (before) 488 /// CHECK-DAG: <<Ar1:i\d+>> ArrayGet [{{l\d+}},{{i\d+}}] 489 /// CHECK-DAG: <<Ar2:i\d+>> ArrayGet [{{l\d+}},{{i\d+}}] 490 /// CHECK-DAG: <<Cnd:z\d+>> LessThan [<<Ar1>>,<<Ar2>>] 491 /// CHECK-DAG: <<Sel:i\d+>> Select [<<Ar1>>,<<Ar2>>,<<Cnd>>] 492 /// CHECK-DAG: Return [<<Sel>>] 493 // 494 /// CHECK-START: int TestMinMax.max0(int[], int[]) instruction_simplifier$after_gvn (after) 495 /// CHECK-DAG: <<Max:i\d+>> Max 496 /// CHECK-DAG: Return [<<Max>>] 497 // 498 /// CHECK-START: int TestMinMax.max0(int[], int[]) instruction_simplifier$after_gvn (after) 499 /// CHECK-NOT: Select max0(int[] a, int[] b)500 public static int max0(int[] a, int[] b) { 501 // Repeat of array references needs finding the common subexpressions 502 // prior to doing the select and min/max recognition. 503 return a[0] >= b[0] ? a[0] : b[0]; 504 } 505 506 /// CHECK-START: int TestMinMax.minmax1(int) instruction_simplifier$after_gvn (before) 507 /// CHECK-DAG: <<Par:i\d+>> ParameterValue 508 /// CHECK-DAG: <<P100:i\d+>> IntConstant 100 509 /// CHECK-DAG: <<M100:i\d+>> IntConstant -100 510 /// CHECK-DAG: <<Cnd1:z\d+>> LessThanOrEqual [<<Par>>,<<P100>>] 511 /// CHECK-DAG: <<Sel1:i\d+>> Select [<<P100>>,<<Par>>,<<Cnd1>>] 512 /// CHECK-DAG: <<Cnd2:z\d+>> GreaterThanOrEqual [<<Sel1>>,<<M100>>] 513 /// CHECK-DAG: <<Sel2:i\d+>> Select [<<M100>>,<<Sel1>>,<<Cnd2>>] 514 /// CHECK-DAG: Return [<<Sel2>>] 515 // 516 /// CHECK-START: int TestMinMax.minmax1(int) instruction_simplifier$after_gvn (after) 517 /// CHECK-DAG: <<Par:i\d+>> ParameterValue 518 /// CHECK-DAG: <<P100:i\d+>> IntConstant 100 519 /// CHECK-DAG: <<M100:i\d+>> IntConstant -100 520 /// CHECK-DAG: <<Min:i\d+>> Min [<<Par>>,<<P100>>] 521 /// CHECK-DAG: <<Max:i\d+>> Max [<<Min>>,<<M100>>] 522 /// CHECK-DAG: Return [<<Max>>] 523 // 524 /// CHECK-START: int TestMinMax.minmax1(int) instruction_simplifier$after_gvn (after) 525 /// CHECK-NOT: Select minmax1(int x)526 public static int minmax1(int x) { 527 // Simple if-if gives clean select sequence. 528 if (x > 100) { 529 x = 100; 530 } 531 if (x < -100) { 532 x = -100; 533 } 534 return x; 535 } 536 537 /// CHECK-START: int TestMinMax.minmax2(int) instruction_simplifier$after_gvn (before) 538 /// CHECK-DAG: <<Par:i\d+>> ParameterValue 539 /// CHECK-DAG: <<P100:i\d+>> IntConstant 100 540 /// CHECK-DAG: <<M100:i\d+>> IntConstant -100 541 /// CHECK-DAG: <<Cnd1:z\d+>> LessThanOrEqual [<<Par>>,<<P100>>] 542 /// CHECK-DAG: <<Cnd2:z\d+>> GreaterThanOrEqual [<<Par>>,<<M100>>] 543 /// CHECK-DAG: <<Sel1:i\d+>> Select [<<M100>>,<<Par>>,<<Cnd2>>] 544 /// CHECK-DAG: <<Sel2:i\d+>> Select [<<P100>>,<<Sel1>>,<<Cnd1>>] 545 /// CHECK-DAG: Return [<<Sel2>>] 546 // 547 /// CHECK-START: int TestMinMax.minmax2(int) instruction_simplifier$after_gvn (after) 548 /// CHECK-DAG: <<Par:i\d+>> ParameterValue 549 /// CHECK-DAG: <<P100:i\d+>> IntConstant 100 550 /// CHECK-DAG: <<M100:i\d+>> IntConstant -100 551 /// CHECK-DAG: <<Max:i\d+>> Max [<<Par>>,<<M100>>] 552 /// CHECK-DAG: <<Min:i\d+>> Min [<<Max>>,<<P100>>] 553 /// CHECK-DAG: Return [<<Min>>] 554 // 555 /// CHECK-START: int TestMinMax.minmax2(int) instruction_simplifier$after_gvn (after) 556 /// CHECK-NOT: Select minmax2(int x)557 public static int minmax2(int x) { 558 // Simple if-else requires inspecting bounds of resulting selects. 559 if (x > 100) { 560 x = 100; 561 } else if (x < -100) { 562 x = -100; 563 } 564 return x; 565 } 566 567 /// CHECK-START: int TestMinMax.minmax3(int) instruction_simplifier$after_gvn (after) 568 /// CHECK-DAG: <<Par:i\d+>> ParameterValue 569 /// CHECK-DAG: <<P100:i\d+>> IntConstant 100 570 /// CHECK-DAG: <<M100:i\d+>> IntConstant -100 571 /// CHECK-DAG: <<Max:i\d+>> Max [<<Par>>,<<M100>>] 572 /// CHECK-DAG: <<Min:i\d+>> Min [<<Max>>,<<P100>>] 573 /// CHECK-DAG: Return [<<Min>>] 574 // 575 /// CHECK-START: int TestMinMax.minmax3(int) instruction_simplifier$after_gvn (after) 576 /// CHECK-NOT: Select minmax3(int x)577 public static int minmax3(int x) { 578 return (x > 100) ? 100 : ((x < -100) ? -100 : x); 579 } 580 581 /// CHECK-START: int TestMinMax.minmax4(int) instruction_simplifier$after_gvn (after) 582 /// CHECK-DAG: <<Par:i\d+>> ParameterValue 583 /// CHECK-DAG: <<P100:i\d+>> IntConstant 100 584 /// CHECK-DAG: <<M100:i\d+>> IntConstant -100 585 /// CHECK-DAG: <<Min:i\d+>> Min [<<Par>>,<<P100>>] 586 /// CHECK-DAG: <<Max:i\d+>> Max [<<Min>>,<<M100>>] 587 /// CHECK-DAG: Return [<<Max>>] 588 // 589 /// CHECK-START: int TestMinMax.minmax4(int) instruction_simplifier$after_gvn (after) 590 /// CHECK-NOT: Select minmax4(int x)591 public static int minmax4(int x) { 592 return (x < -100) ? -100 : ((x > 100) ? 100 : x); 593 } 594 595 /// CHECK-START: int TestMinMax.minmaxCSEScalar(int, int) select_generator (after) 596 /// CHECK-DAG: <<Par1:i\d+>> ParameterValue 597 /// CHECK-DAG: <<Par2:i\d+>> ParameterValue 598 /// CHECK-DAG: <<Cnd1:z\d+>> LessThanOrEqual [<<Par1>>,<<Par2>>] 599 /// CHECK-DAG: <<Sel1:i\d+>> Select [<<Par1>>,<<Par2>>,<<Cnd1>>] 600 /// CHECK-DAG: <<Cnd2:z\d+>> GreaterThanOrEqual [<<Par1>>,<<Par2>>] 601 /// CHECK-DAG: <<Sel2:i\d+>> Select [<<Par1>>,<<Par2>>,<<Cnd2>>] 602 /// CHECK-DAG: <<Add1:i\d+>> Add [<<Sel1>>,<<Sel2>>] 603 /// CHECK-DAG: <<Add2:i\d+>> Add [<<Sel1>>,<<Add1>>] 604 /// CHECK-DAG: <<Add3:i\d+>> Add [<<Sel2>>,<<Add2>>] 605 /// CHECK-DAG: <<Add4:i\d+>> Add [<<Sel1>>,<<Add3>>] 606 /// CHECK-DAG: <<Add5:i\d+>> Add [<<Sel2>>,<<Add4>>] 607 /// CHECK-DAG: Return [<<Add5>>] 608 // 609 /// CHECK-START: int TestMinMax.minmaxCSEScalar(int, int) instruction_simplifier$after_gvn (after) 610 /// CHECK-DAG: <<Par1:i\d+>> ParameterValue 611 /// CHECK-DAG: <<Par2:i\d+>> ParameterValue 612 /// CHECK-DAG: <<Max:i\d+>> Max [<<Par1>>,<<Par2>>] 613 /// CHECK-DAG: <<Min:i\d+>> Min [<<Par1>>,<<Par2>>] 614 /// CHECK-DAG: <<Add1:i\d+>> Add [<<Max>>,<<Min>>] 615 /// CHECK-DAG: <<Add2:i\d+>> Add [<<Max>>,<<Add1>>] 616 /// CHECK-DAG: <<Add3:i\d+>> Add [<<Min>>,<<Add2>>] 617 /// CHECK-DAG: <<Add4:i\d+>> Add [<<Max>>,<<Add3>>] 618 /// CHECK-DAG: <<Add5:i\d+>> Add [<<Min>>,<<Add4>>] 619 /// CHECK-DAG: Return [<<Add5>>] minmaxCSEScalar(int x, int y)620 public static int minmaxCSEScalar(int x, int y) { 621 int t1 = (x > y) ? x : y; 622 int t2 = (x < y) ? x : y; 623 int t3 = (x > y) ? x : y; 624 int t4 = (x < y) ? x : y; 625 int t5 = (x > y) ? x : y; 626 int t6 = (x < y) ? x : y; 627 // Make sure min/max is CSEed. 628 return t1 + t2 + t3 + t4 + t5 + t6; 629 } 630 631 /// CHECK-START: int TestMinMax.minmaxCSEArray(int[], int[]) select_generator (after) 632 /// CHECK-DAG: <<Arr1:i\d+>> ArrayGet 633 /// CHECK-DAG: <<Arr2:i\d+>> ArrayGet 634 /// CHECK-DAG: <<Cnd1:z\d+>> LessThanOrEqual [<<Arr1>>,<<Arr2>>] 635 /// CHECK-DAG: <<Sel1:i\d+>> Select [<<Arr1>>,<<Arr2>>,<<Cnd1>>] 636 /// CHECK-DAG: <<Cnd2:z\d+>> GreaterThanOrEqual [<<Arr1>>,<<Arr2>>] 637 /// CHECK-DAG: <<Sel2:i\d+>> Select [<<Arr1>>,<<Arr2>>,<<Cnd2>>] 638 /// CHECK-DAG: <<Add1:i\d+>> Add [<<Sel1>>,<<Sel2>>] 639 /// CHECK-DAG: <<Add2:i\d+>> Add [<<Sel1>>,<<Add1>>] 640 /// CHECK-DAG: <<Add3:i\d+>> Add [<<Sel2>>,<<Add2>>] 641 /// CHECK-DAG: <<Add4:i\d+>> Add [<<Sel1>>,<<Add3>>] 642 /// CHECK-DAG: <<Add5:i\d+>> Add [<<Sel2>>,<<Add4>>] 643 /// CHECK-DAG: Return [<<Add5>>] 644 // 645 /// CHECK-START: int TestMinMax.minmaxCSEArray(int[], int[]) instruction_simplifier$after_gvn (after) 646 /// CHECK-DAG: <<Arr1:i\d+>> ArrayGet 647 /// CHECK-DAG: <<Arr2:i\d+>> ArrayGet 648 /// CHECK-DAG: <<Max:i\d+>> Max [<<Arr1>>,<<Arr2>>] 649 /// CHECK-DAG: <<Min:i\d+>> Min [<<Arr1>>,<<Arr2>>] 650 /// CHECK-DAG: <<Add1:i\d+>> Add [<<Max>>,<<Min>>] 651 /// CHECK-DAG: <<Add2:i\d+>> Add [<<Max>>,<<Add1>>] 652 /// CHECK-DAG: <<Add3:i\d+>> Add [<<Min>>,<<Add2>>] 653 /// CHECK-DAG: <<Add4:i\d+>> Add [<<Max>>,<<Add3>>] 654 /// CHECK-DAG: <<Add5:i\d+>> Add [<<Min>>,<<Add4>>] 655 /// CHECK-DAG: Return [<<Add5>>] minmaxCSEArray(int[] x, int[] y)656 public static int minmaxCSEArray(int[] x, int[] y) { 657 int t1 = (x[0] > y[0]) ? x[0] : y[0]; 658 int t2 = (x[0] < y[0]) ? x[0] : y[0]; 659 int t3 = (x[0] > y[0]) ? x[0] : y[0]; 660 int t4 = (x[0] < y[0]) ? x[0] : y[0]; 661 int t5 = (x[0] > y[0]) ? x[0] : y[0]; 662 int t6 = (x[0] < y[0]) ? x[0] : y[0]; 663 // Make sure min/max is CSEed. 664 return t1 + t2 + t3 + t4 + t5 + t6; 665 } 666 667 /// CHECK-START: int TestMinMax.minmaxCSEScalarAndCond(int, int) instruction_simplifier$after_gvn (after) 668 /// CHECK-DAG: <<Par1:i\d+>> ParameterValue 669 /// CHECK-DAG: <<Par2:i\d+>> ParameterValue 670 /// CHECK-DAG: <<Max:i\d+>> Max [<<Par1>>,<<Par2>>] 671 /// CHECK-DAG: <<Min:i\d+>> Min [<<Par1>>,<<Par2>>] 672 /// CHECK-DAG: <<Add:i\d+>> Add [<<Max>>,<<Min>>] 673 /// CHECK-DAG: Return [<<Add>>] 674 /// CHECK-DAG: <<Add1:i\d+>> Add [<<Max>>,<<Min>>] 675 /// CHECK-DAG: <<Add2:i\d+>> Add [<<Max>>,<<Add1>>] 676 /// CHECK-DAG: <<Add3:i\d+>> Add [<<Min>>,<<Add2>>] 677 /// CHECK-DAG: Return [<<Add3>>] minmaxCSEScalarAndCond(int x, int y)678 public static int minmaxCSEScalarAndCond(int x, int y) { 679 int t1 = (x > y) ? x : y; 680 int t2 = (x < y) ? x : y; 681 if (x == y) 682 return t1 + t2; 683 int t3 = (x > y) ? x : y; 684 int t4 = (x < y) ? x : y; 685 // Make sure min/max is CSEed. 686 return t1 + t2 + t3 + t4; 687 } 688 main()689 public static void main() { 690 // Intrinsics. 691 expectEquals(10, minI(10)); 692 expectEquals(20, minI(25)); 693 expectEquals(-1, minIntConstantZero(-1)); 694 expectEquals(0, minIntConstantZero(1)); 695 expectEquals(0, minIntConstantOne(0)); 696 expectEquals(1, minIntConstantOne(2)); 697 expectEquals(-2, minIntConstantMinusOne(-2)); 698 expectEquals(-1, minIntConstantMinusOne(0)); 699 expectEquals(10L, minL(10L)); 700 expectEquals(20L, minL(25L)); 701 expectEquals(-1L, minLongConstantZero(-1L)); 702 expectEquals(0L, minLongConstantZero(1L)); 703 expectEquals(0L, minLongConstantOne(0L)); 704 expectEquals(1L, minLongConstantOne(2L)); 705 expectEquals(-2L, minLongConstantMinusOne(-2L)); 706 expectEquals(-1L, minLongConstantMinusOne(0L)); 707 expectEquals(20, maxI(10)); 708 expectEquals(25, maxI(25)); 709 expectEquals(0, maxIntConstantZero(-1)); 710 expectEquals(1, maxIntConstantZero(1)); 711 expectEquals(1, maxIntConstantOne(0)); 712 expectEquals(2, maxIntConstantOne(2)); 713 expectEquals(-1, maxIntConstantMinusOne(-2)); 714 expectEquals(0, maxIntConstantMinusOne(0)); 715 expectEquals(8193, maxIntLargeConstant(8192)); 716 expectEquals(9000, maxIntLargeConstant(9000)); 717 expectEquals(20L, maxL(10L)); 718 expectEquals(25L, maxL(25L)); 719 expectEquals(0L, maxLongConstantZero(-1L)); 720 expectEquals(1L, maxLongConstantZero(1L)); 721 expectEquals(1L, maxLongConstantOne(0L)); 722 expectEquals(2L, maxLongConstantOne(2L)); 723 expectEquals(-1L, maxLongConstantMinusOne(-2L)); 724 expectEquals(0L, maxLongConstantMinusOne(0L)); 725 expectEquals(8193L, maxLongLargeConstant(8192L)); 726 expectEquals(9000L, maxLongLargeConstant(9000L)); 727 // Types. 728 expectEquals(10, min1(10, 20)); 729 expectEquals(10, min2(10, 20)); 730 expectEquals(10, min3(10, 20)); 731 expectEquals(10, min4(10, 20)); 732 expectEquals(10, min5((short) 10, (short) 20)); 733 expectEquals(10, min6((byte) 10, (byte) 20)); 734 expectEquals(10L, min7(10L, 20L)); 735 expectEquals(20, max1(10, 20)); 736 expectEquals(20, max2(10, 20)); 737 expectEquals(20, max3(10, 20)); 738 expectEquals(20, max4(10, 20)); 739 expectEquals(20, max5((short) 10, (short) 20)); 740 expectEquals(20, max6((byte) 10, (byte) 20)); 741 expectEquals(20L, max7(10L, 20L)); 742 // Complications. 743 int[] a = { 10 }; 744 int[] b = { 20 }; 745 expectEquals(10, min0(a, b)); 746 expectEquals(20, max0(a, b)); 747 expectEquals(-100, minmax1(-200)); 748 expectEquals(10, minmax1(10)); 749 expectEquals(100, minmax1(200)); 750 expectEquals(-100, minmax2(-200)); 751 expectEquals(10, minmax2(10)); 752 expectEquals(100, minmax2(200)); 753 expectEquals(-100, minmax3(-200)); 754 expectEquals(10, minmax3(10)); 755 expectEquals(100, minmax3(200)); 756 expectEquals(-100, minmax4(-200)); 757 expectEquals(10, minmax4(10)); 758 expectEquals(100, minmax4(200)); 759 expectEquals(90, minmaxCSEScalar(10, 20)); 760 expectEquals(90, minmaxCSEArray(a, b)); 761 expectEquals(20, minmaxCSEScalarAndCond(10, 10)); 762 expectEquals(60, minmaxCSEScalarAndCond(10, 20)); 763 System.out.println("TestMinMax passed"); 764 } 765 expectEquals(int expected, int result)766 private static void expectEquals(int expected, int result) { 767 if (expected != result) { 768 throw new Error("Expected: " + expected + ", found: " + result); 769 } 770 } 771 expectEquals(long expected, long result)772 private static void expectEquals(long expected, long result) { 773 if (expected != result) { 774 throw new Error("Expected: " + expected + ", found: " + result); 775 } 776 } 777 } 778