1 /* 2 * Copyright (C) 2015 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 public class Main { 18 19 // A dummy value to defeat inlining of these routines. 20 static boolean doThrow = false; 21 22 public static void assertByteEquals(byte expected, byte result) { 23 if (expected != result) { 24 throw new Error("Expected: " + expected + ", found: " + result); 25 } 26 } 27 28 public static void assertCharEquals(char expected, char result) { 29 if (expected != result) { 30 throw new Error("Expected: " + expected + ", found: " + result); 31 } 32 } 33 34 public static void assertShortEquals(short expected, short result) { 35 if (expected != result) { 36 throw new Error("Expected: " + expected + ", found: " + result); 37 } 38 } 39 40 public static void assertIntEquals(int expected, int result) { 41 if (expected != result) { 42 throw new Error("Expected: " + expected + ", found: " + result); 43 } 44 } 45 46 public static void assertLongEquals(long expected, long result) { 47 if (expected != result) { 48 throw new Error("Expected: " + expected + ", found: " + result); 49 } 50 } 51 52 // Non-inlinable type-casting helpers. 53 static char $noinline$byteToChar (byte v) { if (doThrow) throw new Error(); return (char)v; } 54 static short $noinline$byteToShort (byte v) { if (doThrow) throw new Error(); return (short)v; } 55 static int $noinline$byteToInt (byte v) { if (doThrow) throw new Error(); return (int)v; } 56 static long $noinline$byteToLong (byte v) { if (doThrow) throw new Error(); return (long)v; } 57 static byte $noinline$charToByte (char v) { if (doThrow) throw new Error(); return (byte)v; } 58 static short $noinline$charToShort (char v) { if (doThrow) throw new Error(); return (short)v; } 59 static int $noinline$charToInt (char v) { if (doThrow) throw new Error(); return (int)v; } 60 static long $noinline$charToLong (char v) { if (doThrow) throw new Error(); return (long)v; } 61 static byte $noinline$shortToByte (short v) { if (doThrow) throw new Error(); return (byte)v; } 62 static char $noinline$shortToChar (short v) { if (doThrow) throw new Error(); return (char)v; } 63 static int $noinline$shortToInt (short v) { if (doThrow) throw new Error(); return (int)v; } 64 static long $noinline$shortToLong (short v) { if (doThrow) throw new Error(); return (long)v; } 65 static byte $noinline$intToByte (int v) { if (doThrow) throw new Error(); return (byte)v; } 66 static char $noinline$intToChar (int v) { if (doThrow) throw new Error(); return (char)v; } 67 static short $noinline$intToShort (int v) { if (doThrow) throw new Error(); return (short)v; } 68 static long $noinline$intToLong (int v) { if (doThrow) throw new Error(); return (long)v; } 69 static byte $noinline$longToByte (long v) { if (doThrow) throw new Error(); return (byte)v; } 70 static char $noinline$longToChar (long v) { if (doThrow) throw new Error(); return (char)v; } 71 static short $noinline$longToShort (long v) { if (doThrow) throw new Error(); return (short)v; } 72 static int $noinline$longToInt (long v) { if (doThrow) throw new Error(); return (int)v; } 73 74 /** 75 * Basic test merging a bitfield move operation (here a type conversion) into 76 * the shifter operand. 77 */ 78 79 /// CHECK-START-ARM64: long Main.$opt$noinline$translate(long, byte) instruction_simplifier_arm64 (before) 80 /// CHECK-DAG: <<l:j\d+>> ParameterValue 81 /// CHECK-DAG: <<b:b\d+>> ParameterValue 82 /// CHECK: <<tmp:j\d+>> TypeConversion [<<b>>] 83 /// CHECK: Sub [<<l>>,<<tmp>>] 84 85 /// CHECK-START-ARM64: long Main.$opt$noinline$translate(long, byte) instruction_simplifier_arm64 (after) 86 /// CHECK-DAG: <<l:j\d+>> ParameterValue 87 /// CHECK-DAG: <<b:b\d+>> ParameterValue 88 /// CHECK: Arm64DataProcWithShifterOp [<<l>>,<<b>>] kind:Sub+SXTB 89 90 /// CHECK-START-ARM64: long Main.$opt$noinline$translate(long, byte) instruction_simplifier_arm64 (after) 91 /// CHECK-NOT: TypeConversion 92 /// CHECK-NOT: Sub 93 94 /// CHECK-START-ARM64: long Main.$opt$noinline$translate(long, byte) disassembly (after) 95 /// CHECK: sub x{{\d+}}, x{{\d+}}, w{{\d+}}, sxtb 96 97 public static long $opt$noinline$translate(long l, byte b) { 98 if (doThrow) throw new Error(); 99 long tmp = (long)b; 100 return l - tmp; 101 } 102 103 104 /** 105 * Test that we do not merge into the shifter operand when the left and right 106 * inputs are the the IR. 107 */ 108 109 /// CHECK-START-ARM64: int Main.$opt$noinline$sameInput(int) instruction_simplifier_arm64 (before) 110 /// CHECK: <<a:i\d+>> ParameterValue 111 /// CHECK: <<Const2:i\d+>> IntConstant 2 112 /// CHECK: <<tmp:i\d+>> Shl [<<a>>,<<Const2>>] 113 /// CHECK: Add [<<tmp>>,<<tmp>>] 114 115 /// CHECK-START-ARM64: int Main.$opt$noinline$sameInput(int) instruction_simplifier_arm64 (after) 116 /// CHECK-DAG: <<a:i\d+>> ParameterValue 117 /// CHECK-DAG: <<Const2:i\d+>> IntConstant 2 118 /// CHECK: <<Shl:i\d+>> Shl [<<a>>,<<Const2>>] 119 /// CHECK: Add [<<Shl>>,<<Shl>>] 120 121 /// CHECK-START-ARM64: int Main.$opt$noinline$sameInput(int) instruction_simplifier_arm64 (after) 122 /// CHECK-NOT: Arm64DataProcWithShifterOp 123 124 public static int $opt$noinline$sameInput(int a) { 125 if (doThrow) throw new Error(); 126 int tmp = a << 2; 127 return tmp + tmp; 128 } 129 130 /** 131 * Check that we perform the merge for multiple uses. 132 */ 133 134 /// CHECK-START-ARM64: int Main.$opt$noinline$multipleUses(int) instruction_simplifier_arm64 (before) 135 /// CHECK: <<arg:i\d+>> ParameterValue 136 /// CHECK: <<Const23:i\d+>> IntConstant 23 137 /// CHECK: <<tmp:i\d+>> Shl [<<arg>>,<<Const23>>] 138 /// CHECK: Add [<<tmp>>,{{i\d+}}] 139 /// CHECK: Add [<<tmp>>,{{i\d+}}] 140 /// CHECK: Add [<<tmp>>,{{i\d+}}] 141 /// CHECK: Add [<<tmp>>,{{i\d+}}] 142 /// CHECK: Add [<<tmp>>,{{i\d+}}] 143 144 /// CHECK-START-ARM64: int Main.$opt$noinline$multipleUses(int) instruction_simplifier_arm64 (after) 145 /// CHECK: <<arg:i\d+>> ParameterValue 146 /// CHECK: Arm64DataProcWithShifterOp [{{i\d+}},<<arg>>] kind:Add+LSL shift:23 147 /// CHECK: Arm64DataProcWithShifterOp [{{i\d+}},<<arg>>] kind:Add+LSL shift:23 148 /// CHECK: Arm64DataProcWithShifterOp [{{i\d+}},<<arg>>] kind:Add+LSL shift:23 149 /// CHECK: Arm64DataProcWithShifterOp [{{i\d+}},<<arg>>] kind:Add+LSL shift:23 150 /// CHECK: Arm64DataProcWithShifterOp [{{i\d+}},<<arg>>] kind:Add+LSL shift:23 151 152 /// CHECK-START-ARM64: int Main.$opt$noinline$multipleUses(int) instruction_simplifier_arm64 (after) 153 /// CHECK-NOT: Shl 154 /// CHECK-NOT: Add 155 156 public static int $opt$noinline$multipleUses(int arg) { 157 if (doThrow) throw new Error(); 158 int tmp = arg << 23; 159 switch (arg) { 160 case 1: return (arg | 1) + tmp; 161 case 2: return (arg | 2) + tmp; 162 case 3: return (arg | 3) + tmp; 163 case 4: return (arg | 4) + tmp; 164 case (1 << 20): return (arg | 5) + tmp; 165 default: return 0; 166 } 167 } 168 169 /** 170 * Logical instructions cannot take 'extend' operations into the shift 171 * operand, so test that only the shifts are merged. 172 */ 173 174 /// CHECK-START-ARM64: void Main.$opt$noinline$testAnd(long, long) instruction_simplifier_arm64 (after) 175 /// CHECK: Arm64DataProcWithShifterOp 176 /// CHECK-NOT: Arm64DataProcWithShifterOp 177 178 /// CHECK-START-ARM64: void Main.$opt$noinline$testAnd(long, long) disassembly (after) 179 /// CHECK: and lsl 180 /// CHECK: sxtb 181 /// CHECK: and 182 183 static void $opt$noinline$testAnd(long a, long b) { 184 if (doThrow) throw new Error(); 185 assertLongEquals((a & $noinline$LongShl(b, 5)) | (a & $noinline$longToByte(b)), 186 (a & (b << 5)) | (a & (byte)b)); 187 } 188 189 /// CHECK-START-ARM64: void Main.$opt$noinline$testOr(int, int) instruction_simplifier_arm64 (after) 190 /// CHECK: Arm64DataProcWithShifterOp 191 /// CHECK-NOT: Arm64DataProcWithShifterOp 192 193 /// CHECK-START-ARM64: void Main.$opt$noinline$testOr(int, int) disassembly (after) 194 /// CHECK: orr asr 195 /// CHECK: uxth 196 /// CHECK: orr 197 198 static void $opt$noinline$testOr(int a, int b) { 199 if (doThrow) throw new Error(); 200 assertIntEquals((a | $noinline$IntShr(b, 6)) | (a | $noinline$intToChar(b)), 201 (a | (b >> 6)) | (a | (char)b)); 202 } 203 204 /// CHECK-START-ARM64: void Main.$opt$noinline$testXor(long, long) instruction_simplifier_arm64 (after) 205 /// CHECK: Arm64DataProcWithShifterOp 206 /// CHECK-NOT: Arm64DataProcWithShifterOp 207 208 /// CHECK-START-ARM64: void Main.$opt$noinline$testXor(long, long) disassembly (after) 209 /// CHECK: eor lsr 210 /// CHECK: sxtw 211 /// CHECK: eor 212 213 static void $opt$noinline$testXor(long a, long b) { 214 if (doThrow) throw new Error(); 215 assertLongEquals((a ^ $noinline$LongUshr(b, 7)) | (a ^ $noinline$longToInt(b)), 216 (a ^ (b >>> 7)) | (a ^ (int)b)); 217 } 218 219 /// CHECK-START-ARM64: void Main.$opt$noinline$testNeg(int) instruction_simplifier_arm64 (after) 220 /// CHECK: Arm64DataProcWithShifterOp 221 /// CHECK-NOT: Arm64DataProcWithShifterOp 222 223 /// CHECK-START-ARM64: void Main.$opt$noinline$testNeg(int) disassembly (after) 224 /// CHECK: neg lsl 225 /// CHECK: sxth 226 /// CHECK: neg 227 228 static void $opt$noinline$testNeg(int a) { 229 if (doThrow) throw new Error(); 230 assertIntEquals(-$noinline$IntShl(a, 8) | -$noinline$intToShort(a), 231 (-(a << 8)) | (-(short)a)); 232 } 233 234 /** 235 * The functions below are used to compare the result of optimized operations 236 * to non-optimized operations. 237 * On the left-hand side we use a non-inlined function call to ensure the 238 * optimization does not occur. The checker tests ensure that the optimization 239 * does occur on the right-hand. 240 */ 241 242 /// CHECK-START-ARM64: void Main.$opt$validateExtendByteInt1(int, byte) instruction_simplifier_arm64 (after) 243 /// CHECK: Arm64DataProcWithShifterOp 244 /// CHECK-NOT: Arm64DataProcWithShifterOp 245 246 /// CHECK-START-ARM64: void Main.$opt$validateExtendByteInt1(int, byte) instruction_simplifier_arm64 (after) 247 /// CHECK-NOT: TypeConversion 248 249 public static void $opt$validateExtendByteInt1(int a, byte b) { 250 assertIntEquals(a + $noinline$byteToChar (b), a + (char)b); 251 // Conversions byte->short and short->int are implicit; nothing to merge. 252 assertIntEquals(a + $noinline$byteToShort(b), a + (short)b); 253 } 254 255 /// CHECK-START-ARM64: void Main.$opt$validateExtendByteInt2(int, byte) instruction_simplifier_arm64 (after) 256 /// CHECK-NOT: Arm64DataProcWithShifterOp 257 /// CHECK-NOT: Arm64DataProcWithShifterOp 258 259 public static void $opt$validateExtendByteInt2(int a, byte b) { 260 // The conversion to `int` has been optimized away, so there is nothing to merge. 261 assertIntEquals (a + $noinline$byteToInt (b), a + (int)b); 262 // There is an environment use for `(long)b`, preventing the merge. 263 assertLongEquals(a + $noinline$byteToLong(b), a + (long)b); 264 } 265 266 /// CHECK-START-ARM64: void Main.$opt$validateExtendByteLong(long, byte) instruction_simplifier_arm64 (after) 267 /// CHECK: Arm64DataProcWithShifterOp 268 /// CHECK: Arm64DataProcWithShifterOp 269 /// CHECK: Arm64DataProcWithShifterOp 270 /// CHECK: Arm64DataProcWithShifterOp 271 /// CHECK: Arm64DataProcWithShifterOp 272 /// CHECK-NOT: Arm64DataProcWithShifterOp 273 274 /// CHECK-START-ARM64: void Main.$opt$validateExtendByteLong(long, byte) instruction_simplifier_arm64 (after) 275 /// CHECK: TypeConversion 276 /// CHECK-NOT: TypeConversion 277 278 public static void $opt$validateExtendByteLong(long a, byte b) { 279 // In each of the following tests, there will be a merge on the LHS. 280 281 // The first test has an explicit byte->char conversion on RHS, 282 // followed by a conversion that is merged with the Add. 283 assertLongEquals(a + $noinline$byteToChar (b), a + (char)b); 284 // Since conversions byte->short and byte->int are implicit, the RHS 285 // for the two tests below is the same and one is eliminated by GVN. 286 // The other is then merged to a shifter operand instruction. 287 assertLongEquals(a + $noinline$byteToShort(b), a + (short)b); 288 assertLongEquals(a + $noinline$byteToInt (b), a + (int)b); 289 } 290 291 public static void $opt$validateExtendByte(long a, byte b) { 292 $opt$validateExtendByteInt1((int)a, b); 293 $opt$validateExtendByteInt2((int)a, b); 294 $opt$validateExtendByteLong(a, b); 295 } 296 297 /// CHECK-START-ARM64: void Main.$opt$validateExtendCharInt1(int, char) instruction_simplifier_arm64 (after) 298 /// CHECK: Arm64DataProcWithShifterOp 299 /// CHECK: Arm64DataProcWithShifterOp 300 301 /// CHECK-START-ARM64: void Main.$opt$validateExtendCharInt1(int, char) instruction_simplifier_arm64 (after) 302 /// CHECK-NOT: TypeConversion 303 304 public static void $opt$validateExtendCharInt1(int a, char b) { 305 assertIntEquals(a + $noinline$charToByte (b), a + (byte)b); 306 assertIntEquals(a + $noinline$charToShort(b), a + (short)b); 307 } 308 309 /// CHECK-START-ARM64: void Main.$opt$validateExtendCharInt2(int, char) instruction_simplifier_arm64 (after) 310 /// CHECK-NOT: Arm64DataProcWithShifterOp 311 /// CHECK-NOT: Arm64DataProcWithShifterOp 312 313 public static void $opt$validateExtendCharInt2(int a, char b) { 314 // The conversion to `int` has been optimized away, so there is nothing to merge. 315 assertIntEquals (a + $noinline$charToInt (b), a + (int)b); 316 // There is an environment use for `(long)b`, preventing the merge. 317 assertLongEquals(a + $noinline$charToLong(b), a + (long)b); 318 } 319 320 /// CHECK-START-ARM64: void Main.$opt$validateExtendCharLong(long, char) instruction_simplifier_arm64 (after) 321 /// CHECK: Arm64DataProcWithShifterOp 322 /// CHECK: Arm64DataProcWithShifterOp 323 /// CHECK: Arm64DataProcWithShifterOp 324 /// CHECK: Arm64DataProcWithShifterOp 325 326 /// CHECK-START-ARM64: void Main.$opt$validateExtendCharLong(long, char) instruction_simplifier_arm64 (after) 327 /// CHECK: TypeConversion 328 /// CHECK: TypeConversion 329 /// CHECK-NOT: TypeConversion 330 331 public static void $opt$validateExtendCharLong(long a, char b) { 332 // The first two tests have a type conversion. 333 assertLongEquals(a + $noinline$charToByte (b), a + (byte)b); 334 assertLongEquals(a + $noinline$charToShort(b), a + (short)b); 335 // This test does not because the conversion to `int` is optimized away. 336 assertLongEquals(a + $noinline$charToInt (b), a + (int)b); 337 } 338 339 public static void $opt$validateExtendChar(long a, char b) { 340 $opt$validateExtendCharInt1((int)a, b); 341 $opt$validateExtendCharInt2((int)a, b); 342 $opt$validateExtendCharLong(a, b); 343 } 344 345 /// CHECK-START-ARM64: void Main.$opt$validateExtendShortInt1(int, short) instruction_simplifier_arm64 (after) 346 /// CHECK: Arm64DataProcWithShifterOp 347 /// CHECK: Arm64DataProcWithShifterOp 348 349 /// CHECK-START-ARM64: void Main.$opt$validateExtendShortInt1(int, short) instruction_simplifier_arm64 (after) 350 /// CHECK-NOT: TypeConversion 351 352 public static void $opt$validateExtendShortInt1(int a, short b) { 353 assertIntEquals(a + $noinline$shortToByte (b), a + (byte)b); 354 assertIntEquals(a + $noinline$shortToChar (b), a + (char)b); 355 } 356 357 /// CHECK-START-ARM64: void Main.$opt$validateExtendShortInt2(int, short) instruction_simplifier_arm64 (after) 358 /// CHECK-NOT: Arm64DataProcWithShifterOp 359 /// CHECK-NOT: Arm64DataProcWithShifterOp 360 361 public static void $opt$validateExtendShortInt2(int a, short b) { 362 // The conversion to `int` has been optimized away, so there is nothing to merge. 363 assertIntEquals (a + $noinline$shortToInt (b), a + (int)b); 364 // There is an environment use for `(long)b`, preventing the merge. 365 assertLongEquals(a + $noinline$shortToLong (b), a + (long)b); 366 } 367 368 /// CHECK-START-ARM64: void Main.$opt$validateExtendShortLong(long, short) instruction_simplifier_arm64 (after) 369 /// CHECK: Arm64DataProcWithShifterOp 370 /// CHECK: Arm64DataProcWithShifterOp 371 /// CHECK: Arm64DataProcWithShifterOp 372 373 /// CHECK-START-ARM64: void Main.$opt$validateExtendShortLong(long, short) instruction_simplifier_arm64 (after) 374 /// CHECK: TypeConversion 375 /// CHECK: TypeConversion 376 /// CHECK-NOT: TypeConversion 377 378 public static void $opt$validateExtendShortLong(long a, short b) { 379 // The first two tests have a type conversion. 380 assertLongEquals(a + $noinline$shortToByte(b), a + (byte)b); 381 assertLongEquals(a + $noinline$shortToChar(b), a + (char)b); 382 // This test does not because the conversion to `int` is optimized away. 383 assertLongEquals(a + $noinline$shortToInt (b), a + (int)b); 384 } 385 386 public static void $opt$validateExtendShort(long a, short b) { 387 $opt$validateExtendShortInt1((int)a, b); 388 $opt$validateExtendShortInt2((int)a, b); 389 $opt$validateExtendShortLong(a, b); 390 } 391 392 /// CHECK-START-ARM64: void Main.$opt$validateExtendInt(long, int) instruction_simplifier_arm64 (after) 393 /// CHECK: Arm64DataProcWithShifterOp 394 /// CHECK: Arm64DataProcWithShifterOp 395 /// CHECK: Arm64DataProcWithShifterOp 396 /// CHECK: Arm64DataProcWithShifterOp 397 398 /// CHECK-START-ARM64: void Main.$opt$validateExtendInt(long, int) instruction_simplifier_arm64 (after) 399 /// CHECK: TypeConversion 400 /// CHECK: TypeConversion 401 /// CHECK: TypeConversion 402 /// CHECK-NOT: TypeConversion 403 404 public static void $opt$validateExtendInt(long a, int b) { 405 // All tests have a conversion to `long`. The first three tests also have a 406 // conversion from `int` to the specified type. For each test the conversion 407 // to `long` is merged into the shifter operand. 408 assertLongEquals(a + $noinline$intToByte (b), a + (byte)b); 409 assertLongEquals(a + $noinline$intToChar (b), a + (char)b); 410 assertLongEquals(a + $noinline$intToShort(b), a + (short)b); 411 assertLongEquals(a + $noinline$intToLong (b), a + (long)b); 412 } 413 414 /// CHECK-START-ARM64: void Main.$opt$validateExtendLong(long, long) instruction_simplifier_arm64 (after) 415 /// CHECK: Arm64DataProcWithShifterOp 416 /// CHECK: Arm64DataProcWithShifterOp 417 /// CHECK: Arm64DataProcWithShifterOp 418 /// CHECK: Arm64DataProcWithShifterOp 419 420 /// CHECK-START-ARM64: void Main.$opt$validateExtendLong(long, long) instruction_simplifier_arm64 (after) 421 /// CHECK: TypeConversion 422 /// CHECK: TypeConversion 423 /// CHECK: TypeConversion 424 /// CHECK: TypeConversion 425 /// CHECK-NOT: TypeConversion 426 427 public static void $opt$validateExtendLong(long a, long b) { 428 // Each test has two conversions, from `long` and then back to `long`. The 429 // conversions to `long` are merged. 430 assertLongEquals(a + $noinline$longToByte (b), a + (byte)b); 431 assertLongEquals(a + $noinline$longToChar (b), a + (char)b); 432 assertLongEquals(a + $noinline$longToShort(b), a + (short)b); 433 assertLongEquals(a + $noinline$longToInt (b), a + (int)b); 434 } 435 436 437 static int $noinline$IntShl(int b, int c) { 438 if (doThrow) throw new Error(); 439 return b << c; 440 } 441 static int $noinline$IntShr(int b, int c) { 442 if (doThrow) throw new Error(); 443 return b >> c; 444 } 445 static int $noinline$IntUshr(int b, int c) { 446 if (doThrow) throw new Error(); 447 return b >>> c; 448 } 449 450 451 // Each test line below should see one merge. 452 /// CHECK-START-ARM64: void Main.$opt$validateShiftInt(int, int) instruction_simplifier_arm64 (after) 453 /// CHECK: Arm64DataProcWithShifterOp 454 /// CHECK: Arm64DataProcWithShifterOp 455 /// CHECK: Arm64DataProcWithShifterOp 456 /// CHECK: Arm64DataProcWithShifterOp 457 /// CHECK: Arm64DataProcWithShifterOp 458 /// CHECK: Arm64DataProcWithShifterOp 459 /// CHECK: Arm64DataProcWithShifterOp 460 /// CHECK: Arm64DataProcWithShifterOp 461 /// CHECK: Arm64DataProcWithShifterOp 462 /// CHECK: Arm64DataProcWithShifterOp 463 /// CHECK: Arm64DataProcWithShifterOp 464 /// CHECK: Arm64DataProcWithShifterOp 465 /// CHECK: Arm64DataProcWithShifterOp 466 /// CHECK: Arm64DataProcWithShifterOp 467 /// CHECK: Arm64DataProcWithShifterOp 468 /// CHECK: Arm64DataProcWithShifterOp 469 /// CHECK: Arm64DataProcWithShifterOp 470 /// CHECK: Arm64DataProcWithShifterOp 471 /// CHECK: Arm64DataProcWithShifterOp 472 /// CHECK: Arm64DataProcWithShifterOp 473 /// CHECK: Arm64DataProcWithShifterOp 474 /// CHECK: Arm64DataProcWithShifterOp 475 /// CHECK: Arm64DataProcWithShifterOp 476 /// CHECK: Arm64DataProcWithShifterOp 477 /// CHECK: Arm64DataProcWithShifterOp 478 /// CHECK: Arm64DataProcWithShifterOp 479 /// CHECK: Arm64DataProcWithShifterOp 480 /// CHECK: Arm64DataProcWithShifterOp 481 /// CHECK: Arm64DataProcWithShifterOp 482 /// CHECK: Arm64DataProcWithShifterOp 483 /// CHECK: Arm64DataProcWithShifterOp 484 /// CHECK: Arm64DataProcWithShifterOp 485 /// CHECK: Arm64DataProcWithShifterOp 486 // Note: `b << 32`, `b >> 32` and `b >>> 32` are optimized away by generic simplifier. 487 488 /// CHECK-START-ARM64: void Main.$opt$validateShiftInt(int, int) instruction_simplifier_arm64 (after) 489 /// CHECK-NOT: Shl 490 /// CHECK-NOT: Shr 491 /// CHECK-NOT: UShr 492 493 public static void $opt$validateShiftInt(int a, int b) { 494 assertIntEquals(a + $noinline$IntShl(b, 1), a + (b << 1)); 495 assertIntEquals(a + $noinline$IntShl(b, 6), a + (b << 6)); 496 assertIntEquals(a + $noinline$IntShl(b, 7), a + (b << 7)); 497 assertIntEquals(a + $noinline$IntShl(b, 8), a + (b << 8)); 498 assertIntEquals(a + $noinline$IntShl(b, 14), a + (b << 14)); 499 assertIntEquals(a + $noinline$IntShl(b, 15), a + (b << 15)); 500 assertIntEquals(a + $noinline$IntShl(b, 16), a + (b << 16)); 501 assertIntEquals(a + $noinline$IntShl(b, 30), a + (b << 30)); 502 assertIntEquals(a + $noinline$IntShl(b, 31), a + (b << 31)); 503 assertIntEquals(a + $noinline$IntShl(b, 32), a + (b << $opt$inline$IntConstant32())); 504 assertIntEquals(a + $noinline$IntShl(b, 62), a + (b << $opt$inline$IntConstant62())); 505 assertIntEquals(a + $noinline$IntShl(b, 63), a + (b << $opt$inline$IntConstant63())); 506 507 assertIntEquals(a - $noinline$IntShr(b, 1), a - (b >> 1)); 508 assertIntEquals(a - $noinline$IntShr(b, 6), a - (b >> 6)); 509 assertIntEquals(a - $noinline$IntShr(b, 7), a - (b >> 7)); 510 assertIntEquals(a - $noinline$IntShr(b, 8), a - (b >> 8)); 511 assertIntEquals(a - $noinline$IntShr(b, 14), a - (b >> 14)); 512 assertIntEquals(a - $noinline$IntShr(b, 15), a - (b >> 15)); 513 assertIntEquals(a - $noinline$IntShr(b, 16), a - (b >> 16)); 514 assertIntEquals(a - $noinline$IntShr(b, 30), a - (b >> 30)); 515 assertIntEquals(a - $noinline$IntShr(b, 31), a - (b >> 31)); 516 assertIntEquals(a - $noinline$IntShr(b, 32), a - (b >> $opt$inline$IntConstant32())); 517 assertIntEquals(a - $noinline$IntShr(b, 62), a - (b >> $opt$inline$IntConstant62())); 518 assertIntEquals(a - $noinline$IntShr(b, 63), a - (b >> $opt$inline$IntConstant63())); 519 520 assertIntEquals(a ^ $noinline$IntUshr(b, 1), a ^ (b >>> 1)); 521 assertIntEquals(a ^ $noinline$IntUshr(b, 6), a ^ (b >>> 6)); 522 assertIntEquals(a ^ $noinline$IntUshr(b, 7), a ^ (b >>> 7)); 523 assertIntEquals(a ^ $noinline$IntUshr(b, 8), a ^ (b >>> 8)); 524 assertIntEquals(a ^ $noinline$IntUshr(b, 14), a ^ (b >>> 14)); 525 assertIntEquals(a ^ $noinline$IntUshr(b, 15), a ^ (b >>> 15)); 526 assertIntEquals(a ^ $noinline$IntUshr(b, 16), a ^ (b >>> 16)); 527 assertIntEquals(a ^ $noinline$IntUshr(b, 30), a ^ (b >>> 30)); 528 assertIntEquals(a ^ $noinline$IntUshr(b, 31), a ^ (b >>> 31)); 529 assertIntEquals(a ^ $noinline$IntUshr(b, 32), a ^ (b >>> $opt$inline$IntConstant32())); 530 assertIntEquals(a ^ $noinline$IntUshr(b, 62), a ^ (b >>> $opt$inline$IntConstant62())); 531 assertIntEquals(a ^ $noinline$IntUshr(b, 63), a ^ (b >>> $opt$inline$IntConstant63())); 532 } 533 534 // Hiding constants outside the range [0, 32) used for int shifts from Jack. 535 // (Jack extracts only the low 5 bits.) 536 public static int $opt$inline$IntConstant32() { return 32; } 537 public static int $opt$inline$IntConstant62() { return 62; } 538 public static int $opt$inline$IntConstant63() { return 63; } 539 540 541 static long $noinline$LongShl(long b, long c) { 542 if (doThrow) throw new Error(); 543 return b << c; 544 } 545 static long $noinline$LongShr(long b, long c) { 546 if (doThrow) throw new Error(); 547 return b >> c; 548 } 549 static long $noinline$LongUshr(long b, long c) { 550 if (doThrow) throw new Error(); 551 return b >>> c; 552 } 553 554 // Each test line below should see one merge. 555 /// CHECK-START-ARM64: void Main.$opt$validateShiftLong(long, long) instruction_simplifier_arm64 (after) 556 /// CHECK: Arm64DataProcWithShifterOp 557 /// CHECK: Arm64DataProcWithShifterOp 558 /// CHECK: Arm64DataProcWithShifterOp 559 /// CHECK: Arm64DataProcWithShifterOp 560 /// CHECK: Arm64DataProcWithShifterOp 561 /// CHECK: Arm64DataProcWithShifterOp 562 /// CHECK: Arm64DataProcWithShifterOp 563 /// CHECK: Arm64DataProcWithShifterOp 564 /// CHECK: Arm64DataProcWithShifterOp 565 /// CHECK: Arm64DataProcWithShifterOp 566 /// CHECK: Arm64DataProcWithShifterOp 567 /// CHECK: Arm64DataProcWithShifterOp 568 /// CHECK: Arm64DataProcWithShifterOp 569 /// CHECK: Arm64DataProcWithShifterOp 570 /// CHECK: Arm64DataProcWithShifterOp 571 /// CHECK: Arm64DataProcWithShifterOp 572 /// CHECK: Arm64DataProcWithShifterOp 573 /// CHECK: Arm64DataProcWithShifterOp 574 /// CHECK: Arm64DataProcWithShifterOp 575 /// CHECK: Arm64DataProcWithShifterOp 576 /// CHECK: Arm64DataProcWithShifterOp 577 /// CHECK: Arm64DataProcWithShifterOp 578 /// CHECK: Arm64DataProcWithShifterOp 579 /// CHECK: Arm64DataProcWithShifterOp 580 /// CHECK: Arm64DataProcWithShifterOp 581 /// CHECK: Arm64DataProcWithShifterOp 582 /// CHECK: Arm64DataProcWithShifterOp 583 /// CHECK: Arm64DataProcWithShifterOp 584 /// CHECK: Arm64DataProcWithShifterOp 585 /// CHECK: Arm64DataProcWithShifterOp 586 /// CHECK: Arm64DataProcWithShifterOp 587 /// CHECK: Arm64DataProcWithShifterOp 588 /// CHECK: Arm64DataProcWithShifterOp 589 /// CHECK: Arm64DataProcWithShifterOp 590 /// CHECK: Arm64DataProcWithShifterOp 591 /// CHECK: Arm64DataProcWithShifterOp 592 593 /// CHECK-START-ARM64: void Main.$opt$validateShiftLong(long, long) instruction_simplifier_arm64 (after) 594 /// CHECK-NOT: Shl 595 /// CHECK-NOT: Shr 596 /// CHECK-NOT: UShr 597 598 public static void $opt$validateShiftLong(long a, long b) { 599 assertLongEquals(a + $noinline$LongShl(b, 1), a + (b << 1)); 600 assertLongEquals(a + $noinline$LongShl(b, 6), a + (b << 6)); 601 assertLongEquals(a + $noinline$LongShl(b, 7), a + (b << 7)); 602 assertLongEquals(a + $noinline$LongShl(b, 8), a + (b << 8)); 603 assertLongEquals(a + $noinline$LongShl(b, 14), a + (b << 14)); 604 assertLongEquals(a + $noinline$LongShl(b, 15), a + (b << 15)); 605 assertLongEquals(a + $noinline$LongShl(b, 16), a + (b << 16)); 606 assertLongEquals(a + $noinline$LongShl(b, 30), a + (b << 30)); 607 assertLongEquals(a + $noinline$LongShl(b, 31), a + (b << 31)); 608 assertLongEquals(a + $noinline$LongShl(b, 32), a + (b << 32)); 609 assertLongEquals(a + $noinline$LongShl(b, 62), a + (b << 62)); 610 assertLongEquals(a + $noinline$LongShl(b, 63), a + (b << 63)); 611 612 assertLongEquals(a - $noinline$LongShr(b, 1), a - (b >> 1)); 613 assertLongEquals(a - $noinline$LongShr(b, 6), a - (b >> 6)); 614 assertLongEquals(a - $noinline$LongShr(b, 7), a - (b >> 7)); 615 assertLongEquals(a - $noinline$LongShr(b, 8), a - (b >> 8)); 616 assertLongEquals(a - $noinline$LongShr(b, 14), a - (b >> 14)); 617 assertLongEquals(a - $noinline$LongShr(b, 15), a - (b >> 15)); 618 assertLongEquals(a - $noinline$LongShr(b, 16), a - (b >> 16)); 619 assertLongEquals(a - $noinline$LongShr(b, 30), a - (b >> 30)); 620 assertLongEquals(a - $noinline$LongShr(b, 31), a - (b >> 31)); 621 assertLongEquals(a - $noinline$LongShr(b, 32), a - (b >> 32)); 622 assertLongEquals(a - $noinline$LongShr(b, 62), a - (b >> 62)); 623 assertLongEquals(a - $noinline$LongShr(b, 63), a - (b >> 63)); 624 625 assertLongEquals(a ^ $noinline$LongUshr(b, 1), a ^ (b >>> 1)); 626 assertLongEquals(a ^ $noinline$LongUshr(b, 6), a ^ (b >>> 6)); 627 assertLongEquals(a ^ $noinline$LongUshr(b, 7), a ^ (b >>> 7)); 628 assertLongEquals(a ^ $noinline$LongUshr(b, 8), a ^ (b >>> 8)); 629 assertLongEquals(a ^ $noinline$LongUshr(b, 14), a ^ (b >>> 14)); 630 assertLongEquals(a ^ $noinline$LongUshr(b, 15), a ^ (b >>> 15)); 631 assertLongEquals(a ^ $noinline$LongUshr(b, 16), a ^ (b >>> 16)); 632 assertLongEquals(a ^ $noinline$LongUshr(b, 30), a ^ (b >>> 30)); 633 assertLongEquals(a ^ $noinline$LongUshr(b, 31), a ^ (b >>> 31)); 634 assertLongEquals(a ^ $noinline$LongUshr(b, 32), a ^ (b >>> 32)); 635 assertLongEquals(a ^ $noinline$LongUshr(b, 62), a ^ (b >>> 62)); 636 assertLongEquals(a ^ $noinline$LongUshr(b, 63), a ^ (b >>> 63)); 637 } 638 639 640 public static void main(String[] args) { 641 assertLongEquals(10000L - 3L, $opt$noinline$translate(10000L, (byte)3)); 642 assertLongEquals(-10000L - -3L, $opt$noinline$translate(-10000L, (byte)-3)); 643 644 assertIntEquals(4096, $opt$noinline$sameInput(512)); 645 assertIntEquals(-8192, $opt$noinline$sameInput(-1024)); 646 647 assertIntEquals(((1 << 23) | 1), $opt$noinline$multipleUses(1)); 648 assertIntEquals(((1 << 20) | 5), $opt$noinline$multipleUses(1 << 20)); 649 650 long inputs[] = { 651 -((1L << 7) - 1L), -((1L << 7)), -((1L << 7) + 1L), 652 -((1L << 15) - 1L), -((1L << 15)), -((1L << 15) + 1L), 653 -((1L << 16) - 1L), -((1L << 16)), -((1L << 16) + 1L), 654 -((1L << 31) - 1L), -((1L << 31)), -((1L << 31) + 1L), 655 -((1L << 32) - 1L), -((1L << 32)), -((1L << 32) + 1L), 656 -((1L << 63) - 1L), -((1L << 63)), -((1L << 63) + 1L), 657 -42L, -314L, -2718281828L, -0x123456789L, -0x987654321L, 658 -1L, -20L, -300L, -4000L, -50000L, -600000L, -7000000L, -80000000L, 659 0L, 660 1L, 20L, 300L, 4000L, 50000L, 600000L, 7000000L, 80000000L, 661 42L, 314L, 2718281828L, 0x123456789L, 0x987654321L, 662 (1L << 7) - 1L, (1L << 7), (1L << 7) + 1L, 663 (1L << 8) - 1L, (1L << 8), (1L << 8) + 1L, 664 (1L << 15) - 1L, (1L << 15), (1L << 15) + 1L, 665 (1L << 16) - 1L, (1L << 16), (1L << 16) + 1L, 666 (1L << 31) - 1L, (1L << 31), (1L << 31) + 1L, 667 (1L << 32) - 1L, (1L << 32), (1L << 32) + 1L, 668 (1L << 63) - 1L, (1L << 63), (1L << 63) + 1L, 669 Long.MIN_VALUE, Long.MAX_VALUE 670 }; 671 for (int i = 0; i < inputs.length; i++) { 672 $opt$noinline$testNeg((int)inputs[i]); 673 for (int j = 0; j < inputs.length; j++) { 674 $opt$noinline$testAnd(inputs[i], inputs[j]); 675 $opt$noinline$testOr((int)inputs[i], (int)inputs[j]); 676 $opt$noinline$testXor(inputs[i], inputs[j]); 677 678 $opt$validateExtendByte(inputs[i], (byte)inputs[j]); 679 $opt$validateExtendChar(inputs[i], (char)inputs[j]); 680 $opt$validateExtendShort(inputs[i], (short)inputs[j]); 681 $opt$validateExtendInt(inputs[i], (int)inputs[j]); 682 $opt$validateExtendLong(inputs[i], inputs[j]); 683 684 $opt$validateShiftInt((int)inputs[i], (int)inputs[j]); 685 $opt$validateShiftLong(inputs[i], inputs[j]); 686 } 687 } 688 689 } 690 } 691