rev 5902 : 8027754: Enable loop optimizations for loops with MathExact inside

   1 /*
   2  * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 public class Verify {
  25     public static String throwWord(boolean threw) {
  26         return (threw ? "threw" : "didn't throw");
  27     }
  28 
  29     public static void verifyResult(UnaryMethod method, int result1, int result2, boolean exception1, boolean exception2, int value) {
  30         if (exception1 != exception2) {
  31             throw new RuntimeException("Intrinsic version [" + method.name() + "]" + throwWord(exception1) + " exception, NonIntrinsic version" + throwWord(exception2) + " for: " + value);
  32         }
  33         if (result1 != result2) {
  34             throw new RuntimeException("Intrinsic version [" + method.name() + "] returned: " + result1 + " while NonIntrinsic version returned: " + result2);
  35         }
  36     }
  37 
  38     public static void verifyResult(UnaryLongMethod method, long result1, long result2, boolean exception1, boolean exception2, long value) {
  39         if (exception1 != exception2) {
  40             throw new RuntimeException("Intrinsic version [" + method.name() + "]" + throwWord(exception1) + " exception, NonIntrinsic version" + throwWord(exception2) + " for: " + value);
  41         }
  42         if (result1 != result2) {
  43             throw new RuntimeException("Intrinsic version [" + method.name() + "] returned: " + result1 + " while NonIntrinsic version returned: " + result2);
  44         }
  45     }
  46 
  47     private static void verifyResult(BinaryMethod method, int result1, int result2, boolean exception1, boolean exception2, int a, int b) {
  48         if (exception1 != exception2) {
  49             throw new RuntimeException("Intrinsic version [" + method.name() + "]" + throwWord(exception1) + " exception, NonIntrinsic version " + throwWord(exception2) + " for: " + a + " + " + b);
  50         }
  51         if (result1 != result2) {
  52             throw new RuntimeException("Intrinsic version [" + method.name() + "] returned: " + result1 + " while NonIntrinsic version returned: " + result2);
  53         }
  54     }
  55 
  56     private static void verifyResult(BinaryLongMethod method, long result1, long result2, boolean exception1, boolean exception2, long a, long b) {
  57         if (exception1 != exception2) {
  58             throw new RuntimeException("Intrinsic version [" + method.name() + "]" + throwWord(exception1) + " exception, NonIntrinsic version " + throwWord(exception2) + " for: " + a + " + " + b);
  59         }
  60         if (result1 != result2) {
  61             throw new RuntimeException("Intrinsic version [" + method.name() + "] returned: " + result1 + " while NonIntrinsic version returned: " + result2);
  62         }
  63     }
  64 
  65 
  66     public static void verifyUnary(int a, UnaryMethod method) {
  67         boolean exception1 = false, exception2 = false;
  68         int result1 = 0, result2 = 0;
  69         try {
  70             result1 = method.checkMethod(a);
  71         } catch (ArithmeticException e) {
  72             exception1 = true;
  73         }
  74         try {
  75             result2 = method.safeMethod(a);
  76         } catch (ArithmeticException e) {
  77             exception2 = true;
  78         }
  79 
  80         verifyResult(method, result1, result2, exception1, exception2, a);
  81     }
  82 
  83     public static void verifyUnary(long a, UnaryLongMethod method) {
  84         boolean exception1 = false, exception2 = false;
  85         long result1 = 0, result2 = 0;
  86         try {
  87             result1 = method.checkMethod(a);
  88         } catch (ArithmeticException e) {
  89             exception1 = true;
  90         }
  91         try {
  92             result2 = method.safeMethod(a);
  93         } catch (ArithmeticException e) {
  94             exception2 = true;
  95         }
  96 
  97         verifyResult(method, result1, result2, exception1, exception2, a);
  98     }
  99 
 100 
 101     public static void verifyBinary(int a, int b, BinaryMethod method) {
 102         boolean exception1 = false, exception2 = false;
 103         int result1 = 0, result2 = 0;
 104         try {
 105             result1 = method.checkMethod(a, b);
 106         } catch (ArithmeticException e) {
 107             exception1 = true;
 108         }
 109         try {
 110             result2 = method.safeMethod(a, b);
 111         } catch (ArithmeticException e) {
 112             exception2 = true;
 113         }
 114 
 115         verifyResult(method, result1, result2, exception1, exception2, a, b);
 116     }
 117 
 118     public static void verifyBinary(long a, long b, BinaryLongMethod method) {
 119         boolean exception1 = false, exception2 = false;
 120         long result1 = 0, result2 = 0;
 121         try {
 122             result1 = method.checkMethod(a, b);
 123         } catch (ArithmeticException e) {
 124             exception1 = true;
 125         }
 126         try {
 127             result2 = method.safeMethod(a, b);
 128         } catch (ArithmeticException e) {
 129             exception2 = true;
 130         }
 131 
 132         verifyResult(method, result1, result2, exception1, exception2, a, b);
 133     }
 134 
 135 
 136     public static class LoadTest {
 137         public static java.util.Random rnd = new java.util.Random();
 138         public static int[] values = new int[256];
 139 
 140         public static void init() {
 141             for (int i = 0; i < values.length; ++i) {
 142                 values[i] = rnd.nextInt();
 143             }
 144         }
 145 
 146         public static void verify(BinaryMethod method) {
 147             for (int i = 0; i < 50000; ++i) {
 148                 Verify.verifyBinary(values[i & 255], values[i & 255] - i, method);
 149                 Verify.verifyBinary(values[i & 255] + i, values[i & 255] - i, method);
 150                 Verify.verifyBinary(values[i & 255], values[i & 255], method);
 151                 if ((i & 1) == 1 && i > 5) {
 152                     Verify.verifyBinary(values[i & 255] + i, values[i & 255] - i, method);
 153                 } else {
 154                     Verify.verifyBinary(values[i & 255] - i, values[i & 255] + i, method);
 155                 }
 156                 Verify.verifyBinary(values[i & 255], values[(i + 1) & 255], method);
 157             }
 158         }
 159     }
 160 
 161     public static class NonConstantTest {
 162         public static java.util.Random rnd = new java.util.Random();

 163 
 164         public static void verify(BinaryMethod method) {
 165             for (int i = 0; i < 50000; ++i) {
 166                 int rnd1 = rnd.nextInt(), rnd2 = rnd.nextInt();
 167                 Verify.verifyBinary(rnd1, rnd2, method);
 168                 Verify.verifyBinary(rnd1, rnd2 + 1, method);
 169                 Verify.verifyBinary(rnd1 + 1, rnd2, method);
 170                 Verify.verifyBinary(rnd1 - 1, rnd2, method);
 171                 Verify.verifyBinary(rnd1, rnd2 - 1, method);




 172             }
 173         }
 174     }
 175 
 176     public static class NonConstantLongTest {
 177         public static long[] values = { Long.MIN_VALUE, Long.MAX_VALUE, 0, Long.MAX_VALUE - 1831 };
 178         public static java.util.Random rnd = new java.util.Random();
 179 
 180         public static void verify(BinaryLongMethod method) {
 181             for (int i = 0; i < 50000; ++i) {
 182                 long rnd1 = rnd.nextLong(), rnd2 = rnd.nextLong();
 183                 Verify.verifyBinary(rnd1, rnd2, method);
 184                 Verify.verifyBinary(rnd1, rnd2 + 1, method);
 185                 Verify.verifyBinary(rnd1 + 1, rnd2, method);
 186                 Verify.verifyBinary(rnd1 - 1, rnd2, method);
 187                 Verify.verifyBinary(rnd1, rnd2 - 1, method);
 188                 Verify.verifyBinary(rnd1 + Long.MAX_VALUE - rnd2, rnd2 + 1, method);
 189                 Verify.verifyBinary(values[0], values[2], method);
 190                 Verify.verifyBinary(values[1], values[2], method);
 191                 Verify.verifyBinary(values[3], 74L, method);
 192             }
 193         }
 194     }
 195 
 196     public static class LoopDependentTest {
 197         public static java.util.Random rnd = new java.util.Random();
 198 
 199         public static void verify(BinaryMethod method) {
 200             int rnd1 = rnd.nextInt(), rnd2 = rnd.nextInt();
 201             runTest(rnd1, rnd2, method);
 202         }
 203 
 204         private static void runTest(int rnd1, int rnd2, BinaryMethod method) {
 205             for (int i = 0; i < 50000; ++i) {
 206                 Verify.verifyBinary(rnd1 + i, rnd2 + i, method);
 207                 Verify.verifyBinary(rnd1 + i, rnd2 + (i & 0xff), method);
 208                 Verify.verifyBinary(rnd1 - i, rnd2 - (i & 0xff), method);
 209                 Verify.verifyBinary(rnd1 + i + 1, rnd2 + i + 2, method);
 210                 Verify.verifyBinary(rnd1 + i * 2, rnd2 + i, method);
 211             }
 212         }
 213     }
 214 
 215     public static class ConstantTest {
 216         public static void verify(BinaryMethod method) {
 217             for (int i = 0; i < 50000; ++i) {
 218                 Verify.verifyBinary(5, 7, method);
 219                 Verify.verifyBinary(Integer.MAX_VALUE, 1, method);
 220                 Verify.verifyBinary(Integer.MIN_VALUE, -1, method);
 221                 Verify.verifyBinary(Integer.MAX_VALUE, -1, method);
 222                 Verify.verifyBinary(Integer.MIN_VALUE, 1, method);
 223                 Verify.verifyBinary(Integer.MAX_VALUE / 2, Integer.MAX_VALUE / 2, method);
 224                 Verify.verifyBinary(Integer.MAX_VALUE / 2, (Integer.MAX_VALUE / 2) + 3, method);
 225                 Verify.verifyBinary(Integer.MAX_VALUE, Integer.MIN_VALUE, method);
 226             }
 227         }
 228     }
 229 
 230     public static class ConstantLongTest {
 231         public static void verify(BinaryLongMethod method) {
 232             for (int i = 0; i < 50000; ++i) {
 233                 Verify.verifyBinary(5, 7, method);
 234                 Verify.verifyBinary(Long.MAX_VALUE, 1, method);
 235                 Verify.verifyBinary(Long.MIN_VALUE, -1, method);
 236                 Verify.verifyBinary(Long.MAX_VALUE, -1, method);
 237                 Verify.verifyBinary(Long.MIN_VALUE, 1, method);
 238                 Verify.verifyBinary(Long.MAX_VALUE / 2, Long.MAX_VALUE / 2, method);
 239                 Verify.verifyBinary(Long.MAX_VALUE / 2, (Long.MAX_VALUE / 2) + 3, method);
 240                 Verify.verifyBinary(Long.MAX_VALUE, Long.MIN_VALUE, method);
 241             }
 242         }
 243     }
 244 
 245     public static interface BinaryMethod {
 246         int safeMethod(int a, int b);
 247         int checkMethod(int a, int b);
 248         int unchecked(int a, int b);
 249         String name();
 250     }
 251 
 252     public static interface UnaryMethod {
 253         int safeMethod(int value);
 254         int checkMethod(int value);
 255         int unchecked(int value);
 256         String name();
 257     }
 258 
 259     public static interface BinaryLongMethod {
 260         long safeMethod(long a, long b);
 261         long checkMethod(long a, long b);
 262         long unchecked(long a, long b);
 263         String name();
 264     }
 265 
 266     public static interface UnaryLongMethod {
 267         long safeMethod(long value);
 268         long checkMethod(long value);
 269         long unchecked(long value);
 270         String name();
 271     }
 272 
 273     public static class UnaryToBinary implements BinaryMethod {
 274         private final UnaryMethod method;
 275         public UnaryToBinary(UnaryMethod method) {
 276             this.method = method;
 277         }
 278 
 279         @Override
 280         public int safeMethod(int a, int b) {
 281             return method.safeMethod(a);
 282         }
 283 
 284         @Override
 285         public int checkMethod(int a, int b) {
 286             return method.checkMethod(a);
 287         }
 288 
 289         @Override
 290         public int unchecked(int a, int b) {
 291             return method.unchecked(a);
 292 
 293         }
 294 
 295         @Override
 296         public String name() {
 297             return method.name();
 298         }
 299     }
 300 
 301     public static class UnaryToBinaryLong implements BinaryLongMethod {
 302         private final UnaryLongMethod method;
 303         public UnaryToBinaryLong(UnaryLongMethod method) {
 304             this.method = method;
 305         }
 306 
 307         @Override
 308         public long safeMethod(long a, long b) {
 309             return method.safeMethod(a);
 310         }
 311 
 312         @Override
 313         public long checkMethod(long a, long b) {
 314             return method.checkMethod(a);
 315         }
 316 
 317         @Override
 318         public long unchecked(long a, long b) {
 319             return method.unchecked(a);
 320 
 321         }
 322 
 323         @Override
 324         public String name() {
 325             return method.name();
 326         }
 327     }
 328 
 329 
 330     public static class AddExactI implements BinaryMethod {
 331         @Override
 332         public int safeMethod(int x, int y) {
 333             int r = x + y;
 334             // HD 2-12 Overflow iff both arguments have the opposite sign of the result
 335             if (((x ^ r) & (y ^ r)) < 0) {
 336                 throw new ArithmeticException("integer overflow");
 337             }
 338             return r;
 339 
 340         }
 341 
 342         @Override
 343         public int checkMethod(int a, int b) {
 344             return Math.addExact(a, b);
 345         }
 346 
 347         @Override
 348         public String name() {
 349             return "addExact";
 350         }
 351 
 352         @Override
 353         public int unchecked(int a, int b) {
 354             return a + b;
 355         }
 356     }
 357 
 358     public static class AddExactL implements BinaryLongMethod {
 359         @Override
 360         public long safeMethod(long x, long y) {
 361             long r = x + y;
 362             // HD 2-12 Overflow iff both arguments have the opposite sign of the result
 363             if (((x ^ r) & (y ^ r)) < 0) {
 364                 throw new ArithmeticException("integer overflow");
 365             }
 366             return r;
 367 
 368         }
 369 
 370         @Override
 371         public long checkMethod(long a, long b) {
 372             return Math.addExact(a, b);
 373         }
 374 
 375         @Override
 376         public String name() {
 377             return "addExactLong";
 378         }
 379 
 380         @Override
 381         public long unchecked(long a, long b) {
 382             return a + b;
 383         }
 384     }
 385 
 386     public static class MulExactI implements BinaryMethod {
 387         @Override
 388         public int safeMethod(int x, int y) {
 389             long r = (long)x * (long)y;
 390             if ((int)r != r) {
 391                 throw new ArithmeticException("integer overflow");
 392             }
 393             return (int)r;
 394 
 395         }
 396 
 397         @Override
 398         public int checkMethod(int a, int b) {
 399             return Math.multiplyExact(a, b);
 400         }
 401 
 402         @Override
 403         public int unchecked(int a, int b) {
 404             return a * b;
 405         }
 406 
 407         @Override
 408         public String name() {
 409             return "multiplyExact";
 410         }
 411     }
 412 
 413     public static class MulExactL implements BinaryLongMethod {
 414         @Override
 415         public long safeMethod(long x, long y) {
 416             long r = x * y;
 417             long ax = Math.abs(x);
 418             long ay = Math.abs(y);
 419             if (((ax | ay) >>> 31 != 0)) {
 420                 // Some bits greater than 2^31 that might cause overflow
 421                 // Check the result using the divide operator
 422                 // and check for the special case of Long.MIN_VALUE * -1
 423                 if (((y != 0) && (r / y != x)) ||
 424                         (x == Long.MIN_VALUE && y == -1)) {
 425                     throw new ArithmeticException("long overflow");
 426                 }
 427             }
 428             return r;
 429         }
 430 
 431         @Override
 432         public long checkMethod(long a, long b) {
 433             return Math.multiplyExact(a, b);
 434         }
 435 
 436         @Override
 437         public long unchecked(long a, long b) {
 438             return a * b;
 439         }
 440 
 441         @Override
 442         public String name() {
 443             return "multiplyExact";
 444         }
 445     }
 446 
 447     public static class NegExactL implements UnaryLongMethod {
 448         @Override
 449         public long safeMethod(long a) {
 450             if (a == Long.MIN_VALUE) {
 451                 throw new ArithmeticException("long overflow");
 452             }
 453 
 454             return -a;
 455 
 456         }
 457 
 458         @Override
 459         public long checkMethod(long value) {
 460             return Math.negateExact(value);
 461         }
 462 
 463         @Override
 464         public long unchecked(long value) {
 465             return -value;
 466         }
 467 
 468         @Override
 469         public String name() {
 470             return "negateExactLong";
 471         }
 472     }
 473 
 474     public static class NegExactI implements UnaryMethod {
 475         @Override
 476         public int safeMethod(int a) {
 477             if (a == Integer.MIN_VALUE) {
 478                 throw new ArithmeticException("integer overflow");
 479             }
 480 
 481             return -a;
 482 
 483         }
 484 
 485         @Override
 486         public int checkMethod(int value) {
 487             return Math.negateExact(value);
 488         }
 489 
 490         @Override
 491         public int unchecked(int value) {
 492             return -value;
 493         }
 494 
 495         @Override
 496         public String name() {
 497             return "negateExact";
 498         }
 499     }
 500 
 501     public static class SubExactI implements BinaryMethod {
 502         @Override
 503         public int safeMethod(int x, int y) {
 504             int r = x - y;
 505             // HD 2-12 Overflow iff the arguments have different signs and
 506             // the sign of the result is different than the sign of x
 507             if (((x ^ y) & (x ^ r)) < 0) {
 508                 throw new ArithmeticException("integer overflow");
 509             }
 510             return r;
 511         }
 512 
 513         @Override
 514         public int checkMethod(int a, int b) {
 515             return Math.subtractExact(a, b);
 516         }
 517 
 518         @Override
 519         public int unchecked(int a, int b) {
 520             return a - b;
 521         }
 522 
 523         @Override
 524         public String name() {
 525             return "subtractExact";
 526         }
 527     }
 528 
 529     public static class SubExactL implements BinaryLongMethod {
 530         @Override
 531         public long safeMethod(long x, long y) {
 532             long r = x - y;
 533             // HD 2-12 Overflow iff the arguments have different signs and
 534             // the sign of the result is different than the sign of x
 535             if (((x ^ y) & (x ^ r)) < 0) {
 536                 throw new ArithmeticException("integer overflow");
 537             }
 538             return r;
 539         }
 540 
 541         @Override
 542         public long checkMethod(long a, long b) {
 543             return Math.subtractExact(a, b);
 544         }
 545 
 546         @Override
 547         public long unchecked(long a, long b) {
 548             return a - b;
 549         }
 550 
 551         @Override
 552         public String name() {
 553             return "subtractExactLong";
 554         }
 555     }
 556 
 557     static class IncExactL implements UnaryLongMethod {
 558         @Override
 559         public long safeMethod(long a) {
 560             if (a == Long.MAX_VALUE) {
 561                 throw new ArithmeticException("long overflow");
 562             }
 563 
 564             return a + 1L;
 565 
 566         }
 567 
 568         @Override
 569         public long checkMethod(long value) {
 570             return Math.incrementExact(value);
 571         }
 572 
 573         @Override
 574         public long unchecked(long value) {
 575             return value + 1;
 576         }
 577 
 578         @Override
 579         public String name() {
 580             return "incrementExactLong";
 581         }
 582     }
 583 
 584     static class IncExactI implements UnaryMethod {
 585         @Override
 586         public int safeMethod(int a) {
 587             if (a == Integer.MAX_VALUE) {
 588                 throw new ArithmeticException("integer overflow");
 589             }
 590 
 591             return a + 1;
 592         }
 593 
 594         @Override
 595         public int checkMethod(int value) {
 596             return Math.incrementExact(value);
 597         }
 598 
 599         @Override
 600         public int unchecked(int value) {
 601             return value + 1;
 602         }
 603 
 604         @Override
 605         public String name() {
 606             return "incrementExact";
 607         }
 608     }
 609 
 610     static class DecExactL implements UnaryLongMethod {
 611         @Override
 612         public long safeMethod(long a) {
 613             if (a == Long.MIN_VALUE) {
 614                 throw new ArithmeticException("long overflow");
 615             }
 616 
 617             return a - 1L;
 618         }
 619 
 620         @Override
 621         public long checkMethod(long value) {
 622             return Math.decrementExact(value);
 623         }
 624 
 625         @Override
 626         public long unchecked(long value) {
 627             return value - 1;
 628         }
 629 
 630         @Override
 631         public String name() {
 632             return "decExactLong";
 633         }
 634     }
 635 
 636     static class DecExactI implements UnaryMethod {
 637         @Override
 638         public int safeMethod(int a) {
 639             if (a == Integer.MIN_VALUE) {
 640                 throw new ArithmeticException("integer overflow");
 641             }
 642 
 643             return a - 1;
 644         }
 645 
 646         @Override
 647         public int checkMethod(int value) {
 648             return Math.decrementExact(value);
 649         }
 650 
 651         @Override
 652         public int unchecked(int value) {
 653             return value - 1;
 654         }
 655 
 656         @Override
 657         public String name() {
 658             return "decrementExact";
 659         }
 660     }
 661 
 662 }
--- EOF ---