8024924: Intrinsify java.lang.Math.addExact

Fri, 27 Sep 2013 08:39:19 +0200

author
rbackman
date
Fri, 27 Sep 2013 08:39:19 +0200
changeset 5791
c9ccd7b85f20
parent 5790
72b7e96c1922
child 5792
510fbd28919c
child 5793
a07c25e4f67e

8024924: Intrinsify java.lang.Math.addExact
Reviewed-by: kvn, twisti

src/cpu/sparc/vm/sparc.ad file | annotate | diff | comparison | revisions
src/cpu/x86/vm/x86_32.ad file | annotate | diff | comparison | revisions
src/cpu/x86/vm/x86_64.ad file | annotate | diff | comparison | revisions
src/share/vm/adlc/adlparse.cpp file | annotate | diff | comparison | revisions
src/share/vm/adlc/archDesc.cpp file | annotate | diff | comparison | revisions
src/share/vm/adlc/formssel.cpp file | annotate | diff | comparison | revisions
src/share/vm/adlc/formssel.hpp file | annotate | diff | comparison | revisions
src/share/vm/adlc/output_h.cpp file | annotate | diff | comparison | revisions
src/share/vm/classfile/vmSymbols.hpp file | annotate | diff | comparison | revisions
src/share/vm/opto/c2_globals.hpp file | annotate | diff | comparison | revisions
src/share/vm/opto/classes.cpp file | annotate | diff | comparison | revisions
src/share/vm/opto/classes.hpp file | annotate | diff | comparison | revisions
src/share/vm/opto/ifnode.cpp file | annotate | diff | comparison | revisions
src/share/vm/opto/lcm.cpp file | annotate | diff | comparison | revisions
src/share/vm/opto/library_call.cpp file | annotate | diff | comparison | revisions
src/share/vm/opto/loopTransform.cpp file | annotate | diff | comparison | revisions
src/share/vm/opto/loopopts.cpp file | annotate | diff | comparison | revisions
src/share/vm/opto/matcher.cpp file | annotate | diff | comparison | revisions
src/share/vm/opto/matcher.hpp file | annotate | diff | comparison | revisions
src/share/vm/opto/mathexactnode.cpp file | annotate | diff | comparison | revisions
src/share/vm/opto/mathexactnode.hpp file | annotate | diff | comparison | revisions
src/share/vm/opto/multnode.cpp file | annotate | diff | comparison | revisions
src/share/vm/opto/node.hpp file | annotate | diff | comparison | revisions
src/share/vm/opto/subnode.cpp file | annotate | diff | comparison | revisions
src/share/vm/opto/subnode.hpp file | annotate | diff | comparison | revisions
src/share/vm/opto/type.cpp file | annotate | diff | comparison | revisions
src/share/vm/opto/type.hpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/vmStructs.cpp file | annotate | diff | comparison | revisions
test/compiler/intrinsics/mathexact/CondTest.java file | annotate | diff | comparison | revisions
test/compiler/intrinsics/mathexact/ConstantTest.java file | annotate | diff | comparison | revisions
test/compiler/intrinsics/mathexact/LoadTest.java file | annotate | diff | comparison | revisions
test/compiler/intrinsics/mathexact/LoopDependentTest.java file | annotate | diff | comparison | revisions
test/compiler/intrinsics/mathexact/NonConstantTest.java file | annotate | diff | comparison | revisions
test/compiler/intrinsics/mathexact/Verify.java file | annotate | diff | comparison | revisions
     1.1 --- a/src/cpu/sparc/vm/sparc.ad	Thu Sep 26 12:07:53 2013 -0700
     1.2 +++ b/src/cpu/sparc/vm/sparc.ad	Fri Sep 27 08:39:19 2013 +0200
     1.3 @@ -2018,6 +2018,15 @@
     1.4    return L7_REGP_mask();
     1.5  }
     1.6  
     1.7 +const RegMask Matcher::mathExactI_result_proj_mask() {
     1.8 +  return G1_REGI_mask();
     1.9 +}
    1.10 +
    1.11 +const RegMask Matcher::mathExactI_flags_proj_mask() {
    1.12 +  return INT_FLAGS_mask();
    1.13 +}
    1.14 +
    1.15 +
    1.16  %}
    1.17  
    1.18  
    1.19 @@ -4245,12 +4254,16 @@
    1.20      greater_equal(0xB);
    1.21      less_equal(0x2);
    1.22      greater(0xA);
    1.23 +    overflow(0x7);
    1.24 +    no_overflow(0xF);
    1.25    %}
    1.26  %}
    1.27  
    1.28  // Comparison Op, unsigned
    1.29  operand cmpOpU() %{
    1.30    match(Bool);
    1.31 +  predicate(n->as_Bool()->_test._test != BoolTest::overflow &&
    1.32 +            n->as_Bool()->_test._test != BoolTest::no_overflow);
    1.33  
    1.34    format %{ "u" %}
    1.35    interface(COND_INTER) %{
    1.36 @@ -4260,12 +4273,16 @@
    1.37      greater_equal(0xD);
    1.38      less_equal(0x4);
    1.39      greater(0xC);
    1.40 +    overflow(0x7);
    1.41 +    no_overflow(0xF);
    1.42    %}
    1.43  %}
    1.44  
    1.45  // Comparison Op, pointer (same as unsigned)
    1.46  operand cmpOpP() %{
    1.47    match(Bool);
    1.48 +  predicate(n->as_Bool()->_test._test != BoolTest::overflow &&
    1.49 +            n->as_Bool()->_test._test != BoolTest::no_overflow);
    1.50  
    1.51    format %{ "p" %}
    1.52    interface(COND_INTER) %{
    1.53 @@ -4275,12 +4292,16 @@
    1.54      greater_equal(0xD);
    1.55      less_equal(0x4);
    1.56      greater(0xC);
    1.57 +    overflow(0x7);
    1.58 +    no_overflow(0xF);
    1.59    %}
    1.60  %}
    1.61  
    1.62  // Comparison Op, branch-register encoding
    1.63  operand cmpOp_reg() %{
    1.64    match(Bool);
    1.65 +  predicate(n->as_Bool()->_test._test != BoolTest::overflow &&
    1.66 +            n->as_Bool()->_test._test != BoolTest::no_overflow);
    1.67  
    1.68    format %{ "" %}
    1.69    interface(COND_INTER) %{
    1.70 @@ -4290,12 +4311,16 @@
    1.71      greater_equal(0x7);
    1.72      less_equal   (0x2);
    1.73      greater      (0x6);
    1.74 +    overflow(0x7); // not supported
    1.75 +    no_overflow(0xF); // not supported
    1.76    %}
    1.77  %}
    1.78  
    1.79  // Comparison Code, floating, unordered same as less
    1.80  operand cmpOpF() %{
    1.81    match(Bool);
    1.82 +  predicate(n->as_Bool()->_test._test != BoolTest::overflow &&
    1.83 +            n->as_Bool()->_test._test != BoolTest::no_overflow);
    1.84  
    1.85    format %{ "fl" %}
    1.86    interface(COND_INTER) %{
    1.87 @@ -4305,12 +4330,17 @@
    1.88      greater_equal(0xB);
    1.89      less_equal(0xE);
    1.90      greater(0x6);
    1.91 +
    1.92 +    overflow(0x7); // not supported
    1.93 +    no_overflow(0xF); // not supported
    1.94    %}
    1.95  %}
    1.96  
    1.97  // Used by long compare
    1.98  operand cmpOp_commute() %{
    1.99    match(Bool);
   1.100 +  predicate(n->as_Bool()->_test._test != BoolTest::overflow &&
   1.101 +            n->as_Bool()->_test._test != BoolTest::no_overflow);
   1.102  
   1.103    format %{ "" %}
   1.104    interface(COND_INTER) %{
   1.105 @@ -4320,6 +4350,8 @@
   1.106      greater_equal(0x2);
   1.107      less_equal(0xB);
   1.108      greater(0x3);
   1.109 +    overflow(0x7);
   1.110 +    no_overflow(0xF);
   1.111    %}
   1.112  %}
   1.113  
     2.1 --- a/src/cpu/x86/vm/x86_32.ad	Thu Sep 26 12:07:53 2013 -0700
     2.2 +++ b/src/cpu/x86/vm/x86_32.ad	Fri Sep 27 08:39:19 2013 +0200
     2.3 @@ -1534,6 +1534,14 @@
     2.4    return EBP_REG_mask();
     2.5  }
     2.6  
     2.7 +const RegMask Matcher::mathExactI_result_proj_mask() {
     2.8 +  return EAX_REG_mask();
     2.9 +}
    2.10 +
    2.11 +const RegMask Matcher::mathExactI_flags_proj_mask() {
    2.12 +  return INT_FLAGS_mask();
    2.13 +}
    2.14 +
    2.15  // Returns true if the high 32 bits of the value is known to be zero.
    2.16  bool is_operand_hi32_zero(Node* n) {
    2.17    int opc = n->Opcode();
    2.18 @@ -4922,6 +4930,8 @@
    2.19      greater_equal(0xD, "ge");
    2.20      less_equal(0xE, "le");
    2.21      greater(0xF, "g");
    2.22 +    overflow(0x0, "o");
    2.23 +    no_overflow(0x1, "no");
    2.24    %}
    2.25  %}
    2.26  
    2.27 @@ -4939,6 +4949,8 @@
    2.28      greater_equal(0x3, "nb");
    2.29      less_equal(0x6, "be");
    2.30      greater(0x7, "nbe");
    2.31 +    overflow(0x0, "o");
    2.32 +    no_overflow(0x1, "no");
    2.33    %}
    2.34  %}
    2.35  
    2.36 @@ -4957,6 +4969,8 @@
    2.37      greater_equal(0x3, "nb");
    2.38      less_equal(0x6, "be");
    2.39      greater(0x7, "nbe");
    2.40 +    overflow(0x0, "o");
    2.41 +    no_overflow(0x1, "no");
    2.42    %}
    2.43  %}
    2.44  
    2.45 @@ -4974,6 +4988,8 @@
    2.46      greater_equal(0x3, "nb");
    2.47      less_equal(0x6, "be");
    2.48      greater(0x7, "nbe");
    2.49 +    overflow(0x0, "o");
    2.50 +    no_overflow(0x1, "no");
    2.51    %}
    2.52  %}
    2.53  
    2.54 @@ -4981,6 +4997,8 @@
    2.55  operand cmpOp_fcmov() %{
    2.56    match(Bool);
    2.57  
    2.58 +  predicate(n->as_Bool()->_test._test != BoolTest::overflow &&
    2.59 +            n->as_Bool()->_test._test != BoolTest::no_overflow);
    2.60    format %{ "" %}
    2.61    interface(COND_INTER) %{
    2.62      equal        (0x0C8);
    2.63 @@ -4989,6 +5007,8 @@
    2.64      greater_equal(0x1C0);
    2.65      less_equal   (0x0D0);
    2.66      greater      (0x1D0);
    2.67 +    overflow(0x0, "o"); // not really supported by the instruction
    2.68 +    no_overflow(0x1, "no"); // not really supported by the instruction
    2.69    %}
    2.70  %}
    2.71  
    2.72 @@ -5004,6 +5024,8 @@
    2.73      greater_equal(0xE, "le");
    2.74      less_equal(0xD, "ge");
    2.75      greater(0xC, "l");
    2.76 +    overflow(0x0, "o");
    2.77 +    no_overflow(0x1, "no");
    2.78    %}
    2.79  %}
    2.80  
    2.81 @@ -7496,6 +7518,31 @@
    2.82  
    2.83  //----------Arithmetic Instructions--------------------------------------------
    2.84  //----------Addition Instructions----------------------------------------------
    2.85 +
    2.86 +instruct addExactI_rReg(eAXRegI dst, rRegI src, eFlagsReg cr)
    2.87 +%{
    2.88 +  match(AddExactI dst src);
    2.89 +  effect(DEF cr);
    2.90 +
    2.91 +  format %{ "ADD    $dst, $src\t# addExact int" %}
    2.92 +  ins_encode %{
    2.93 +    __ addl($dst$$Register, $src$$Register);
    2.94 +  %}
    2.95 +  ins_pipe(ialu_reg_reg);
    2.96 +%}
    2.97 +
    2.98 +instruct addExactI_rReg_imm(eAXRegI dst, immI src, eFlagsReg cr)
    2.99 +%{
   2.100 +  match(AddExactI dst src);
   2.101 +  effect(DEF cr);
   2.102 +
   2.103 +  format %{ "ADD    $dst, $src\t# addExact int" %}
   2.104 +  ins_encode %{
   2.105 +    __ addl($dst$$Register, $src$$constant);
   2.106 +  %}
   2.107 +  ins_pipe(ialu_reg_reg);
   2.108 +%}
   2.109 +
   2.110  // Integer Addition Instructions
   2.111  instruct addI_eReg(rRegI dst, rRegI src, eFlagsReg cr) %{
   2.112    match(Set dst (AddI dst src));
     3.1 --- a/src/cpu/x86/vm/x86_64.ad	Thu Sep 26 12:07:53 2013 -0700
     3.2 +++ b/src/cpu/x86/vm/x86_64.ad	Fri Sep 27 08:39:19 2013 +0200
     3.3 @@ -1649,6 +1649,14 @@
     3.4    return PTR_RBP_REG_mask();
     3.5  }
     3.6  
     3.7 +const RegMask Matcher::mathExactI_result_proj_mask() {
     3.8 +  return INT_RAX_REG_mask();
     3.9 +}
    3.10 +
    3.11 +const RegMask Matcher::mathExactI_flags_proj_mask() {
    3.12 +  return INT_FLAGS_mask();
    3.13 +}
    3.14 +
    3.15  %}
    3.16  
    3.17  //----------ENCODING BLOCK-----------------------------------------------------
    3.18 @@ -4133,6 +4141,8 @@
    3.19      greater_equal(0xD, "ge");
    3.20      less_equal(0xE, "le");
    3.21      greater(0xF, "g");
    3.22 +    overflow(0x0, "o");
    3.23 +    no_overflow(0x1, "no");
    3.24    %}
    3.25  %}
    3.26  
    3.27 @@ -4151,6 +4161,8 @@
    3.28      greater_equal(0x3, "nb");
    3.29      less_equal(0x6, "be");
    3.30      greater(0x7, "nbe");
    3.31 +    overflow(0x0, "o");
    3.32 +    no_overflow(0x1, "no");
    3.33    %}
    3.34  %}
    3.35  
    3.36 @@ -4170,6 +4182,8 @@
    3.37      greater_equal(0x3, "nb");
    3.38      less_equal(0x6, "be");
    3.39      greater(0x7, "nbe");
    3.40 +    overflow(0x0, "o");
    3.41 +    no_overflow(0x1, "no");
    3.42    %}
    3.43  %}
    3.44  
    3.45 @@ -4187,6 +4201,8 @@
    3.46      greater_equal(0x3, "nb");
    3.47      less_equal(0x6, "be");
    3.48      greater(0x7, "nbe");
    3.49 +    overflow(0x0, "o");
    3.50 +    no_overflow(0x1, "no");
    3.51    %}
    3.52  %}
    3.53  
    3.54 @@ -6922,6 +6938,30 @@
    3.55  //----------Arithmetic Instructions--------------------------------------------
    3.56  //----------Addition Instructions----------------------------------------------
    3.57  
    3.58 +instruct addExactI_rReg(rax_RegI dst, rRegI src, rFlagsReg cr)
    3.59 +%{
    3.60 +  match(AddExactI dst src);
    3.61 +  effect(DEF cr);
    3.62 +
    3.63 +  format %{ "addl    $dst, $src\t# addExact int" %}
    3.64 +  ins_encode %{
    3.65 +    __ addl($dst$$Register, $src$$Register);
    3.66 +  %}
    3.67 +  ins_pipe(ialu_reg_reg);
    3.68 +%}
    3.69 +
    3.70 +instruct addExactI_rReg_imm(rax_RegI dst, immI src, rFlagsReg cr)
    3.71 +%{
    3.72 +  match(AddExactI dst src);
    3.73 +  effect(DEF cr);
    3.74 +
    3.75 +  format %{ "addl    $dst, $src\t# addExact int" %}
    3.76 +  ins_encode %{
    3.77 +    __ addl($dst$$Register, $src$$constant);
    3.78 +  %}
    3.79 +  ins_pipe(ialu_reg_reg);
    3.80 +%}
    3.81 +
    3.82  instruct addI_rReg(rRegI dst, rRegI src, rFlagsReg cr)
    3.83  %{
    3.84    match(Set dst (AddI dst src));
     4.1 --- a/src/share/vm/adlc/adlparse.cpp	Thu Sep 26 12:07:53 2013 -0700
     4.2 +++ b/src/share/vm/adlc/adlparse.cpp	Fri Sep 27 08:39:19 2013 +0200
     4.3 @@ -3395,12 +3395,16 @@
     4.4    char *greater_equal;
     4.5    char *less_equal;
     4.6    char *greater;
     4.7 +  char *overflow;
     4.8 +  char *no_overflow;
     4.9    const char *equal_format = "eq";
    4.10    const char *not_equal_format = "ne";
    4.11    const char *less_format = "lt";
    4.12    const char *greater_equal_format = "ge";
    4.13    const char *less_equal_format = "le";
    4.14    const char *greater_format = "gt";
    4.15 +  const char *overflow_format = "o";
    4.16 +  const char *no_overflow_format = "no";
    4.17  
    4.18    if (_curchar != '%') {
    4.19      parse_err(SYNERR, "Missing '%%{' for 'cond_interface' block.\n");
    4.20 @@ -3437,6 +3441,12 @@
    4.21      else if ( strcmp(field,"greater") == 0 ) {
    4.22        greater = interface_field_parse(&greater_format);
    4.23      }
    4.24 +    else if ( strcmp(field,"overflow") == 0 ) {
    4.25 +      overflow = interface_field_parse(&overflow_format);
    4.26 +    }
    4.27 +    else if ( strcmp(field,"no_overflow") == 0 ) {
    4.28 +      no_overflow = interface_field_parse(&no_overflow_format);
    4.29 +    }
    4.30      else {
    4.31        parse_err(SYNERR, "Expected keyword, base|index|scale|disp,  or '%%}' ending interface.\n");
    4.32        return NULL;
    4.33 @@ -3455,7 +3465,9 @@
    4.34                                         less,          less_format,
    4.35                                         greater_equal, greater_equal_format,
    4.36                                         less_equal,    less_equal_format,
    4.37 -                                       greater,       greater_format);
    4.38 +                                       greater,       greater_format,
    4.39 +                                       overflow,      overflow_format,
    4.40 +                                       no_overflow,   no_overflow_format);
    4.41    return inter;
    4.42  }
    4.43  
     5.1 --- a/src/share/vm/adlc/archDesc.cpp	Thu Sep 26 12:07:53 2013 -0700
     5.2 +++ b/src/share/vm/adlc/archDesc.cpp	Fri Sep 27 08:39:19 2013 +0200
     5.3 @@ -1192,6 +1192,8 @@
     5.4           || strcmp(idealName,"CmpF") == 0
     5.5           || strcmp(idealName,"FastLock") == 0
     5.6           || strcmp(idealName,"FastUnlock") == 0
     5.7 +         || strcmp(idealName,"AddExactI") == 0
     5.8 +         || strcmp(idealName,"FlagsProj") == 0
     5.9           || strcmp(idealName,"Bool") == 0
    5.10           || strcmp(idealName,"Binary") == 0 ) {
    5.11        // Removed ConI from the must_clone list.  CPUs that cannot use
     6.1 --- a/src/share/vm/adlc/formssel.cpp	Thu Sep 26 12:07:53 2013 -0700
     6.2 +++ b/src/share/vm/adlc/formssel.cpp	Fri Sep 27 08:39:19 2013 +0200
     6.3 @@ -2757,14 +2757,18 @@
     6.4                               const char* less,          const char* less_format,
     6.5                               const char* greater_equal, const char* greater_equal_format,
     6.6                               const char* less_equal,    const char* less_equal_format,
     6.7 -                             const char* greater,       const char* greater_format)
     6.8 +                             const char* greater,       const char* greater_format,
     6.9 +                             const char* overflow,      const char* overflow_format,
    6.10 +                             const char* no_overflow,   const char* no_overflow_format)
    6.11    : Interface("COND_INTER"),
    6.12      _equal(equal),                 _equal_format(equal_format),
    6.13      _not_equal(not_equal),         _not_equal_format(not_equal_format),
    6.14      _less(less),                   _less_format(less_format),
    6.15      _greater_equal(greater_equal), _greater_equal_format(greater_equal_format),
    6.16      _less_equal(less_equal),       _less_equal_format(less_equal_format),
    6.17 -    _greater(greater),             _greater_format(greater_format) {
    6.18 +    _greater(greater),             _greater_format(greater_format),
    6.19 +    _overflow(overflow),           _overflow_format(overflow_format),
    6.20 +    _no_overflow(no_overflow),     _no_overflow_format(no_overflow_format) {
    6.21  }
    6.22  CondInterface::~CondInterface() {
    6.23    // not owner of any character arrays
    6.24 @@ -2777,12 +2781,14 @@
    6.25  // Write info to output files
    6.26  void CondInterface::output(FILE *fp) {
    6.27    Interface::output(fp);
    6.28 -  if ( _equal  != NULL )     fprintf(fp," equal       == %s\n", _equal);
    6.29 -  if ( _not_equal  != NULL ) fprintf(fp," not_equal   == %s\n", _not_equal);
    6.30 -  if ( _less  != NULL )      fprintf(fp," less        == %s\n", _less);
    6.31 -  if ( _greater_equal  != NULL ) fprintf(fp," greater_equal   == %s\n", _greater_equal);
    6.32 -  if ( _less_equal  != NULL ) fprintf(fp," less_equal  == %s\n", _less_equal);
    6.33 -  if ( _greater  != NULL )    fprintf(fp," greater     == %s\n", _greater);
    6.34 +  if ( _equal  != NULL )     fprintf(fp," equal        == %s\n", _equal);
    6.35 +  if ( _not_equal  != NULL ) fprintf(fp," not_equal    == %s\n", _not_equal);
    6.36 +  if ( _less  != NULL )      fprintf(fp," less         == %s\n", _less);
    6.37 +  if ( _greater_equal  != NULL ) fprintf(fp," greater_equal    == %s\n", _greater_equal);
    6.38 +  if ( _less_equal  != NULL ) fprintf(fp," less_equal   == %s\n", _less_equal);
    6.39 +  if ( _greater  != NULL )    fprintf(fp," greater      == %s\n", _greater);
    6.40 +  if ( _overflow != NULL )    fprintf(fp," overflow     == %s\n", _overflow);
    6.41 +  if ( _no_overflow != NULL ) fprintf(fp," no_overflow  == %s\n", _no_overflow);
    6.42    // fprintf(fp,"\n");
    6.43  }
    6.44  
     7.1 --- a/src/share/vm/adlc/formssel.hpp	Thu Sep 26 12:07:53 2013 -0700
     7.2 +++ b/src/share/vm/adlc/formssel.hpp	Fri Sep 27 08:39:19 2013 +0200
     7.3 @@ -798,12 +798,16 @@
     7.4    const char *_greater_equal;
     7.5    const char *_less_equal;
     7.6    const char *_greater;
     7.7 +  const char *_overflow;
     7.8 +  const char *_no_overflow;
     7.9    const char *_equal_format;
    7.10    const char *_not_equal_format;
    7.11    const char *_less_format;
    7.12    const char *_greater_equal_format;
    7.13    const char *_less_equal_format;
    7.14    const char *_greater_format;
    7.15 +  const char *_overflow_format;
    7.16 +  const char *_no_overflow_format;
    7.17  
    7.18    // Public Methods
    7.19    CondInterface(const char* equal,         const char* equal_format,
    7.20 @@ -811,7 +815,9 @@
    7.21                  const char* less,          const char* less_format,
    7.22                  const char* greater_equal, const char* greater_equal_format,
    7.23                  const char* less_equal,    const char* less_equal_format,
    7.24 -                const char* greater,       const char* greater_format);
    7.25 +                const char* greater,       const char* greater_format,
    7.26 +                const char* overflow,      const char* overflow_format,
    7.27 +                const char* no_overflow,   const char* no_overflow_format);
    7.28    ~CondInterface();
    7.29  
    7.30    void dump();
     8.1 --- a/src/share/vm/adlc/output_h.cpp	Thu Sep 26 12:07:53 2013 -0700
     8.2 +++ b/src/share/vm/adlc/output_h.cpp	Fri Sep 27 08:39:19 2013 +0200
     8.3 @@ -388,6 +388,8 @@
     8.4    fprintf(fp, "  else if( _c%d == BoolTest::ge ) st->print(\"%s\");\n",i,cond->_greater_equal_format);
     8.5    fprintf(fp, "  else if( _c%d == BoolTest::lt ) st->print(\"%s\");\n",i,cond->_less_format);
     8.6    fprintf(fp, "  else if( _c%d == BoolTest::gt ) st->print(\"%s\");\n",i,cond->_greater_format);
     8.7 +  fprintf(fp, "  else if( _c%d == BoolTest::overflow ) st->print(\"%s\");\n",i,cond->_overflow_format);
     8.8 +  fprintf(fp, "  else if( _c%d == BoolTest::no_overflow ) st->print(\"%s\");\n",i,cond->_no_overflow_format);
     8.9  }
    8.10  
    8.11  // Output code that dumps constant values, increment "i" if type is constant
    8.12 @@ -1208,6 +1210,8 @@
    8.13        fprintf(fp,"    case  BoolTest::ne : return not_equal();\n");
    8.14        fprintf(fp,"    case  BoolTest::le : return less_equal();\n");
    8.15        fprintf(fp,"    case  BoolTest::ge : return greater_equal();\n");
    8.16 +      fprintf(fp,"    case  BoolTest::overflow : return overflow();\n");
    8.17 +      fprintf(fp,"    case  BoolTest::no_overflow: return no_overflow();\n");
    8.18        fprintf(fp,"    default : ShouldNotReachHere(); return 0;\n");
    8.19        fprintf(fp,"    }\n");
    8.20        fprintf(fp,"  };\n");
    8.21 @@ -1373,6 +1377,14 @@
    8.22          if( greater != NULL ) {
    8.23            define_oper_interface(fp, *oper, _globalNames, "greater", greater);
    8.24          }
    8.25 +        const char *overflow = cInterface->_overflow;
    8.26 +        if( overflow != NULL ) {
    8.27 +          define_oper_interface(fp, *oper, _globalNames, "overflow", overflow);
    8.28 +        }
    8.29 +        const char *no_overflow = cInterface->_no_overflow;
    8.30 +        if( no_overflow != NULL ) {
    8.31 +          define_oper_interface(fp, *oper, _globalNames, "no_overflow", no_overflow);
    8.32 +        }
    8.33        } // end Conditional Interface
    8.34        // Check if it is a Constant Interface
    8.35        else if (oper->_interface->is_ConstInterface() != NULL ) {
     9.1 --- a/src/share/vm/classfile/vmSymbols.hpp	Thu Sep 26 12:07:53 2013 -0700
     9.2 +++ b/src/share/vm/classfile/vmSymbols.hpp	Fri Sep 27 08:39:19 2013 +0200
     9.3 @@ -631,6 +631,10 @@
     9.4    do_name(log_name,"log")       do_name(log10_name,"log10")     do_name(pow_name,"pow")                                 \
     9.5    do_name(exp_name,"exp")       do_name(min_name,"min")         do_name(max_name,"max")                                 \
     9.6                                                                                                                          \
     9.7 +  do_name(addExact_name,"addExact")                                                                                     \
     9.8 +  do_name(subtractExact_name,"subtractExact")                                                                           \
     9.9 +  do_name(multiplyExact_name,"multiplyExact")                                                                           \
    9.10 +                                                                                                                        \
    9.11    do_intrinsic(_dabs,                     java_lang_Math,         abs_name,   double_double_signature,           F_S)   \
    9.12    do_intrinsic(_dsin,                     java_lang_Math,         sin_name,   double_double_signature,           F_S)   \
    9.13    do_intrinsic(_dcos,                     java_lang_Math,         cos_name,   double_double_signature,           F_S)   \
    9.14 @@ -643,6 +647,7 @@
    9.15    do_intrinsic(_dexp,                     java_lang_Math,         exp_name,   double_double_signature,           F_S)   \
    9.16    do_intrinsic(_min,                      java_lang_Math,         min_name,   int2_int_signature,                F_S)   \
    9.17    do_intrinsic(_max,                      java_lang_Math,         max_name,   int2_int_signature,                F_S)   \
    9.18 +  do_intrinsic(_addExact,                 java_lang_Math,         addExact_name, int2_int_signature,             F_S)   \
    9.19                                                                                                                          \
    9.20    do_intrinsic(_floatToRawIntBits,        java_lang_Float,        floatToRawIntBits_name,   float_int_signature, F_S)   \
    9.21     do_name(     floatToRawIntBits_name,                          "floatToRawIntBits")                                   \
    10.1 --- a/src/share/vm/opto/c2_globals.hpp	Thu Sep 26 12:07:53 2013 -0700
    10.2 +++ b/src/share/vm/opto/c2_globals.hpp	Fri Sep 27 08:39:19 2013 +0200
    10.3 @@ -636,7 +636,9 @@
    10.4                                                                              \
    10.5    diagnostic(bool, OptimizeExpensiveOps, true,                              \
    10.6            "Find best control for expensive operations")                     \
    10.7 -
    10.8 +                                                                            \
    10.9 +  product(bool, UseMathExactIntrinsics, true,                               \
   10.10 +          "Enables intrinsification of various java.lang.Math funcitons")
   10.11  
   10.12  C2_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_EXPERIMENTAL_FLAG, DECLARE_NOTPRODUCT_FLAG)
   10.13  
    11.1 --- a/src/share/vm/opto/classes.cpp	Thu Sep 26 12:07:53 2013 -0700
    11.2 +++ b/src/share/vm/opto/classes.cpp	Fri Sep 27 08:39:19 2013 +0200
    11.3 @@ -32,6 +32,7 @@
    11.4  #include "opto/loopnode.hpp"
    11.5  #include "opto/machnode.hpp"
    11.6  #include "opto/memnode.hpp"
    11.7 +#include "opto/mathexactnode.hpp"
    11.8  #include "opto/mulnode.hpp"
    11.9  #include "opto/multnode.hpp"
   11.10  #include "opto/node.hpp"
    12.1 --- a/src/share/vm/opto/classes.hpp	Thu Sep 26 12:07:53 2013 -0700
    12.2 +++ b/src/share/vm/opto/classes.hpp	Fri Sep 27 08:39:19 2013 +0200
    12.3 @@ -29,6 +29,7 @@
    12.4  macro(AbsF)
    12.5  macro(AbsI)
    12.6  macro(AddD)
    12.7 +macro(AddExactI)
    12.8  macro(AddF)
    12.9  macro(AddI)
   12.10  macro(AddL)
   12.11 @@ -133,6 +134,7 @@
   12.12  macro(ExpD)
   12.13  macro(FastLock)
   12.14  macro(FastUnlock)
   12.15 +macro(FlagsProj)
   12.16  macro(Goto)
   12.17  macro(Halt)
   12.18  macro(If)
   12.19 @@ -167,6 +169,7 @@
   12.20  macro(LoopLimit)
   12.21  macro(Mach)
   12.22  macro(MachProj)
   12.23 +macro(MathExact)
   12.24  macro(MaxI)
   12.25  macro(MemBarAcquire)
   12.26  macro(MemBarAcquireLock)
    13.1 --- a/src/share/vm/opto/ifnode.cpp	Thu Sep 26 12:07:53 2013 -0700
    13.2 +++ b/src/share/vm/opto/ifnode.cpp	Fri Sep 27 08:39:19 2013 +0200
    13.3 @@ -76,6 +76,7 @@
    13.4    if( !i1->is_Bool() ) return NULL;
    13.5    BoolNode *b = i1->as_Bool();
    13.6    Node *cmp = b->in(1);
    13.7 +  if( cmp->is_FlagsProj() ) return NULL;
    13.8    if( !cmp->is_Cmp() ) return NULL;
    13.9    i1 = cmp->in(1);
   13.10    if( i1 == NULL || !i1->is_Phi() ) return NULL;
    14.1 --- a/src/share/vm/opto/lcm.cpp	Thu Sep 26 12:07:53 2013 -0700
    14.2 +++ b/src/share/vm/opto/lcm.cpp	Fri Sep 27 08:39:19 2013 +0200
    14.3 @@ -472,6 +472,13 @@
    14.4            break;
    14.5          }
    14.6  
    14.7 +        // For nodes that produce a FlagsProj, make the node adjacent to the
    14.8 +        // use of the FlagsProj
    14.9 +        if (use->is_FlagsProj() && get_block_for_node(use) == block) {
   14.10 +          found_machif = true;
   14.11 +          break;
   14.12 +        }
   14.13 +
   14.14          // More than this instruction pending for successor to be ready,
   14.15          // don't choose this if other opportunities are ready
   14.16          if (ready_cnt.at(use->_idx) > 1)
    15.1 --- a/src/share/vm/opto/library_call.cpp	Thu Sep 26 12:07:53 2013 -0700
    15.2 +++ b/src/share/vm/opto/library_call.cpp	Fri Sep 27 08:39:19 2013 +0200
    15.3 @@ -32,6 +32,7 @@
    15.4  #include "opto/callGenerator.hpp"
    15.5  #include "opto/cfgnode.hpp"
    15.6  #include "opto/idealKit.hpp"
    15.7 +#include "opto/mathexactnode.hpp"
    15.8  #include "opto/mulnode.hpp"
    15.9  #include "opto/parse.hpp"
   15.10  #include "opto/runtime.hpp"
   15.11 @@ -199,6 +200,8 @@
   15.12    bool inline_math_native(vmIntrinsics::ID id);
   15.13    bool inline_trig(vmIntrinsics::ID id);
   15.14    bool inline_math(vmIntrinsics::ID id);
   15.15 +  bool inline_math_mathExact(Node* math);
   15.16 +  bool inline_math_addExact();
   15.17    bool inline_exp();
   15.18    bool inline_pow();
   15.19    void finish_pow_exp(Node* result, Node* x, Node* y, const TypeFunc* call_type, address funcAddr, const char* funcName);
   15.20 @@ -498,6 +501,15 @@
   15.21      if (!UseCRC32Intrinsics) return NULL;
   15.22      break;
   15.23  
   15.24 +  case vmIntrinsics::_addExact:
   15.25 +    if (!Matcher::match_rule_supported(Op_AddExactI)) {
   15.26 +      return NULL;
   15.27 +    }
   15.28 +    if (!UseMathExactIntrinsics) {
   15.29 +      return NULL;
   15.30 +    }
   15.31 +    break;
   15.32 +
   15.33   default:
   15.34      assert(id <= vmIntrinsics::LAST_COMPILER_INLINE, "caller responsibility");
   15.35      assert(id != vmIntrinsics::_Object_init && id != vmIntrinsics::_invoke, "enum out of order?");
   15.36 @@ -668,6 +680,8 @@
   15.37    case vmIntrinsics::_min:
   15.38    case vmIntrinsics::_max:                      return inline_min_max(intrinsic_id());
   15.39  
   15.40 +  case vmIntrinsics::_addExact:                 return inline_math_addExact();
   15.41 +
   15.42    case vmIntrinsics::_arraycopy:                return inline_arraycopy();
   15.43  
   15.44    case vmIntrinsics::_compareTo:                return inline_string_compareTo();
   15.45 @@ -1911,6 +1925,45 @@
   15.46    return true;
   15.47  }
   15.48  
   15.49 +bool LibraryCallKit::inline_math_mathExact(Node* math) {
   15.50 +  Node* result = _gvn.transform( new(C) ProjNode(math, MathExactNode::result_proj_node));
   15.51 +  Node* flags = _gvn.transform( new(C) FlagsProjNode(math, MathExactNode::flags_proj_node));
   15.52 +
   15.53 +  Node* bol = _gvn.transform( new (C) BoolNode(flags, BoolTest::overflow) );
   15.54 +  IfNode* check = create_and_map_if(control(), bol, PROB_UNLIKELY_MAG(3), COUNT_UNKNOWN);
   15.55 +  Node* fast_path = _gvn.transform( new (C) IfFalseNode(check));
   15.56 +  Node* slow_path = _gvn.transform( new (C) IfTrueNode(check) );
   15.57 +
   15.58 +  {
   15.59 +    PreserveJVMState pjvms(this);
   15.60 +    PreserveReexecuteState preexecs(this);
   15.61 +    jvms()->set_should_reexecute(true);
   15.62 +
   15.63 +    set_control(slow_path);
   15.64 +    set_i_o(i_o());
   15.65 +
   15.66 +    uncommon_trap(Deoptimization::Reason_intrinsic,
   15.67 +                  Deoptimization::Action_none);
   15.68 +  }
   15.69 +
   15.70 +  set_control(fast_path);
   15.71 +  set_result(result);
   15.72 +  return true;
   15.73 +}
   15.74 +
   15.75 +bool LibraryCallKit::inline_math_addExact() {
   15.76 +  Node* arg1 = argument(0);
   15.77 +  Node* arg2 = argument(1);
   15.78 +
   15.79 +  Node* add = _gvn.transform( new(C) AddExactINode(NULL, arg1, arg2) );
   15.80 +  if (add->Opcode() == Op_AddExactI) {
   15.81 +    return inline_math_mathExact(add);
   15.82 +  } else {
   15.83 +    set_result(add);
   15.84 +  }
   15.85 +  return true;
   15.86 +}
   15.87 +
   15.88  Node*
   15.89  LibraryCallKit::generate_min_max(vmIntrinsics::ID id, Node* x0, Node* y0) {
   15.90    // These are the candidate return value:
    16.1 --- a/src/share/vm/opto/loopTransform.cpp	Thu Sep 26 12:07:53 2013 -0700
    16.2 +++ b/src/share/vm/opto/loopTransform.cpp	Fri Sep 27 08:39:19 2013 +0200
    16.3 @@ -776,6 +776,9 @@
    16.4          continue; // not RC
    16.5  
    16.6        Node *cmp = bol->in(1);
    16.7 +      if (cmp->is_FlagsProj()) {
    16.8 +        continue;
    16.9 +      }
   16.10  
   16.11        Node *rc_exp = cmp->in(1);
   16.12        Node *limit = cmp->in(2);
    17.1 --- a/src/share/vm/opto/loopopts.cpp	Thu Sep 26 12:07:53 2013 -0700
    17.2 +++ b/src/share/vm/opto/loopopts.cpp	Fri Sep 27 08:39:19 2013 +0200
    17.3 @@ -2355,7 +2355,8 @@
    17.4          opc == Op_Catch     ||
    17.5          opc == Op_CatchProj ||
    17.6          opc == Op_Jump      ||
    17.7 -        opc == Op_JumpProj) {
    17.8 +        opc == Op_JumpProj  ||
    17.9 +        opc == Op_FlagsProj) {
   17.10  #if !defined(PRODUCT)
   17.11        if (TracePartialPeeling) {
   17.12          tty->print_cr("\nExit control too complex: lp: %d", head->_idx);
    18.1 --- a/src/share/vm/opto/matcher.cpp	Thu Sep 26 12:07:53 2013 -0700
    18.2 +++ b/src/share/vm/opto/matcher.cpp	Fri Sep 27 08:39:19 2013 +0200
    18.3 @@ -1964,6 +1964,7 @@
    18.4        case Op_Catch:
    18.5        case Op_CatchProj:
    18.6        case Op_CProj:
    18.7 +      case Op_FlagsProj:
    18.8        case Op_JumpProj:
    18.9        case Op_JProj:
   18.10        case Op_NeverBranch:
    19.1 --- a/src/share/vm/opto/matcher.hpp	Thu Sep 26 12:07:53 2013 -0700
    19.2 +++ b/src/share/vm/opto/matcher.hpp	Fri Sep 27 08:39:19 2013 +0200
    19.3 @@ -337,6 +337,9 @@
    19.4    // Register for MODL projection of divmodL
    19.5    static RegMask modL_proj_mask();
    19.6  
    19.7 +  static const RegMask mathExactI_result_proj_mask();
    19.8 +  static const RegMask mathExactI_flags_proj_mask();
    19.9 +
   19.10    // Use hardware DIV instruction when it is faster than
   19.11    // a code which use multiply for division by constant.
   19.12    static bool use_asm_for_ldiv_by_con( jlong divisor );
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/src/share/vm/opto/mathexactnode.cpp	Fri Sep 27 08:39:19 2013 +0200
    20.3 @@ -0,0 +1,143 @@
    20.4 +/*
    20.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
    20.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    20.7 + *
    20.8 + * This code is free software; you can redistribute it and/or modify it
    20.9 + * under the terms of the GNU General Public License version 2 only, as
   20.10 + * published by the Free Software Foundation.
   20.11 + *
   20.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   20.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   20.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   20.15 + * version 2 for more details (a copy is included in the LICENSE file that
   20.16 + * accompanied this code).
   20.17 + *
   20.18 + * You should have received a copy of the GNU General Public License version
   20.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   20.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20.21 + *
   20.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   20.23 + * or visit www.oracle.com if you need additional information or have any
   20.24 + * questions.
   20.25 + *
   20.26 + */
   20.27 +
   20.28 +#include "precompiled.hpp"
   20.29 +#include "memory/allocation.inline.hpp"
   20.30 +#include "opto/addnode.hpp"
   20.31 +#include "opto/machnode.hpp"
   20.32 +#include "opto/mathexactnode.hpp"
   20.33 +#include "opto/matcher.hpp"
   20.34 +#include "opto/subnode.hpp"
   20.35 +
   20.36 +MathExactNode::MathExactNode(Node* ctrl, Node* n1, Node* n2) : MultiNode(3) {
   20.37 +  init_req(0, ctrl);
   20.38 +  init_req(1, n1);
   20.39 +  init_req(2, n2);
   20.40 +}
   20.41 +
   20.42 +Node* AddExactINode::match(const ProjNode* proj, const Matcher* m) {
   20.43 +  uint ideal_reg = proj->ideal_reg();
   20.44 +  RegMask rm;
   20.45 +  if (proj->_con == result_proj_node) {
   20.46 +    rm = m->mathExactI_result_proj_mask();
   20.47 +  } else {
   20.48 +    assert(proj->_con == flags_proj_node, "must be result or flags");
   20.49 +    assert(ideal_reg == Op_RegFlags, "sanity");
   20.50 +    rm = m->mathExactI_flags_proj_mask();
   20.51 +  }
   20.52 +  return new (m->C) MachProjNode(this, proj->_con, rm, ideal_reg);
   20.53 +}
   20.54 +
   20.55 +// If the MathExactNode won't overflow we have to replace the
   20.56 +// FlagsProjNode and ProjNode that is generated by the MathExactNode
   20.57 +Node* MathExactNode::no_overflow(PhaseGVN *phase, Node* new_result) {
   20.58 +  PhaseIterGVN *igvn = phase->is_IterGVN();
   20.59 +  if (igvn) {
   20.60 +    ProjNode* result = result_node();
   20.61 +    ProjNode* flags = flags_node();
   20.62 +
   20.63 +    if (result != NULL) {
   20.64 +      igvn->replace_node(result, new_result);
   20.65 +    }
   20.66 +
   20.67 +    if (flags != NULL) {
   20.68 +      BoolNode* bolnode = (BoolNode *) flags->unique_out();
   20.69 +      switch (bolnode->_test._test) {
   20.70 +        case BoolTest::overflow:
   20.71 +          // if the check is for overflow - never taken
   20.72 +          igvn->replace_node(bolnode, phase->intcon(0));
   20.73 +          break;
   20.74 +        case BoolTest::no_overflow:
   20.75 +          // if the check is for no overflow - always taken
   20.76 +          igvn->replace_node(bolnode, phase->intcon(1));
   20.77 +          break;
   20.78 +        default:
   20.79 +          fatal("Unexpected value of BoolTest");
   20.80 +          break;
   20.81 +      }
   20.82 +      flags->del_req(0);
   20.83 +    }
   20.84 +  }
   20.85 +  return new_result;
   20.86 +}
   20.87 +
   20.88 +Node *AddExactINode::Ideal(PhaseGVN *phase, bool can_reshape) {
   20.89 +  Node *arg1 = in(1);
   20.90 +  Node *arg2 = in(2);
   20.91 +
   20.92 +  const Type* type1 = phase->type(arg1);
   20.93 +  const Type* type2 = phase->type(arg2);
   20.94 +
   20.95 +  if (type1 != Type::TOP && type1->singleton() &&
   20.96 +      type2 != Type::TOP && type2->singleton()) {
   20.97 +    jint val1 = arg1->get_int();
   20.98 +    jint val2 = arg2->get_int();
   20.99 +    jint result = val1 + val2;
  20.100 +    // Hacker's Delight 2-12 Overflow if both arguments have the opposite sign of the result
  20.101 +    if ( (((val1 ^ result) & (val2 ^ result)) >= 0)) {
  20.102 +      Node* con_result = ConINode::make(phase->C, result);
  20.103 +      return no_overflow(phase, con_result);
  20.104 +    }
  20.105 +    return NULL;
  20.106 +  }
  20.107 +
  20.108 +  if (type1 == TypeInt::ZERO) { // (Add 0 x) == x
  20.109 +    Node* add_result = new (phase->C) AddINode(arg1, arg2);
  20.110 +    return no_overflow(phase, add_result);
  20.111 +  }
  20.112 +
  20.113 +  if (type2 == TypeInt::ZERO) { // (Add x 0) == x
  20.114 +    Node* add_result = new (phase->C) AddINode(arg1, arg2);
  20.115 +    return no_overflow(phase, add_result);
  20.116 +  }
  20.117 +
  20.118 +  if (type2->singleton()) {
  20.119 +    return NULL; // no change - keep constant on the right
  20.120 +  }
  20.121 +
  20.122 +  if (type1->singleton()) {
  20.123 +    // Make it x + Constant - move constant to the right
  20.124 +    swap_edges(1, 2);
  20.125 +    return this;
  20.126 +  }
  20.127 +
  20.128 +  if (arg2->is_Load()) {
  20.129 +    return NULL; // no change - keep load on the right
  20.130 +  }
  20.131 +
  20.132 +  if (arg1->is_Load()) {
  20.133 +    // Make it x + Load - move load to the right
  20.134 +    swap_edges(1, 2);
  20.135 +    return this;
  20.136 +  }
  20.137 +
  20.138 +  if (arg1->_idx > arg2->_idx) {
  20.139 +    // Sort the edges
  20.140 +    swap_edges(1, 2);
  20.141 +    return this;
  20.142 +  }
  20.143 +
  20.144 +  return NULL;
  20.145 +}
  20.146 +
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/src/share/vm/opto/mathexactnode.hpp	Fri Sep 27 08:39:19 2013 +0200
    21.3 @@ -0,0 +1,81 @@
    21.4 +/*
    21.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
    21.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    21.7 + *
    21.8 + * This code is free software; you can redistribute it and/or modify it
    21.9 + * under the terms of the GNU General Public License version 2 only, as
   21.10 + * published by the Free Software Foundation.
   21.11 + *
   21.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   21.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   21.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   21.15 + * version 2 for more details (a copy is included in the LICENSE file that
   21.16 + * accompanied this code).
   21.17 + *
   21.18 + * You should have received a copy of the GNU General Public License version
   21.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   21.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   21.21 + *
   21.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   21.23 + * or visit www.oracle.com if you need additional information or have any
   21.24 + * questions.
   21.25 + *
   21.26 + */
   21.27 +
   21.28 +#ifndef SHARE_VM_OPTO_MATHEXACTNODE_HPP
   21.29 +#define SHARE_VM_OPTO_MATHEXACTNODE_HPP
   21.30 +
   21.31 +#include "opto/multnode.hpp"
   21.32 +#include "opto/node.hpp"
   21.33 +#include "opto/type.hpp"
   21.34 +
   21.35 +class Node;
   21.36 +
   21.37 +class PhaseGVN;
   21.38 +class PhaseTransform;
   21.39 +
   21.40 +class MathExactNode : public MultiNode {
   21.41 +public:
   21.42 +  MathExactNode(Node* ctrl, Node* in1, Node* in2);
   21.43 +  enum {
   21.44 +    result_proj_node = 0,
   21.45 +    flags_proj_node = 1
   21.46 +  };
   21.47 +  virtual int Opcode() const;
   21.48 +  virtual Node* Identity(PhaseTransform* phase) { return this; }
   21.49 +  virtual Node* Ideal(PhaseGVN* phase, bool can_reshape) { return NULL; }
   21.50 +  virtual const Type* Value(PhaseTransform* phase) const { return bottom_type(); }
   21.51 +  virtual uint hash() const { return Node::hash(); }
   21.52 +  virtual bool is_CFG() const { return false; }
   21.53 +  virtual uint ideal_reg() const { return NotAMachineReg; }
   21.54 +
   21.55 +  ProjNode* result_node() { return proj_out(result_proj_node); }
   21.56 +  ProjNode* flags_node() { return proj_out(flags_proj_node); }
   21.57 +protected:
   21.58 +  Node* no_overflow(PhaseGVN *phase, Node* new_result);
   21.59 +};
   21.60 +
   21.61 +class AddExactINode : public MathExactNode {
   21.62 +public:
   21.63 +  AddExactINode(Node* ctrl, Node* in1, Node* in2) : MathExactNode(ctrl, in1, in2) {}
   21.64 +  virtual int Opcode() const;
   21.65 +  virtual const Type* bottom_type() const { return TypeTuple::INT_CC_PAIR; }
   21.66 +  virtual Node* match(const ProjNode* proj, const Matcher* m);
   21.67 +  virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
   21.68 +};
   21.69 +
   21.70 +class FlagsProjNode : public ProjNode {
   21.71 +public:
   21.72 +  FlagsProjNode(Node* src, uint con) : ProjNode(src, con) {
   21.73 +    init_class_id(Class_FlagsProj);
   21.74 +  }
   21.75 +
   21.76 +  virtual int Opcode() const;
   21.77 +  virtual bool is_CFG() const { return false; }
   21.78 +  virtual const Type* bottom_type() const { return TypeInt::CC; }
   21.79 +  virtual uint ideal_reg() const { return Op_RegFlags; }
   21.80 +};
   21.81 +
   21.82 +
   21.83 +#endif
   21.84 +
    22.1 --- a/src/share/vm/opto/multnode.cpp	Thu Sep 26 12:07:53 2013 -0700
    22.2 +++ b/src/share/vm/opto/multnode.cpp	Fri Sep 27 08:39:19 2013 +0200
    22.3 @@ -25,6 +25,7 @@
    22.4  #include "precompiled.hpp"
    22.5  #include "opto/callnode.hpp"
    22.6  #include "opto/matcher.hpp"
    22.7 +#include "opto/mathexactnode.hpp"
    22.8  #include "opto/multnode.hpp"
    22.9  #include "opto/opcodes.hpp"
   22.10  #include "opto/phaseX.hpp"
   22.11 @@ -46,15 +47,21 @@
   22.12    assert(Opcode() != Op_If || outcnt() == 2, "bad if #1");
   22.13    for( DUIterator_Fast imax, i = fast_outs(imax); i < imax; i++ ) {
   22.14      Node *p = fast_out(i);
   22.15 -    if( !p->is_Proj() ) {
   22.16 +    if (p->is_Proj()) {
   22.17 +      ProjNode *proj = p->as_Proj();
   22.18 +      if (proj->_con == which_proj) {
   22.19 +        assert(Opcode() != Op_If || proj->Opcode() == (which_proj?Op_IfTrue:Op_IfFalse), "bad if #2");
   22.20 +        return proj;
   22.21 +      }
   22.22 +    } else if (p->is_FlagsProj()) {
   22.23 +      FlagsProjNode *proj = p->as_FlagsProj();
   22.24 +      if (proj->_con == which_proj) {
   22.25 +        return proj;
   22.26 +      }
   22.27 +    } else {
   22.28        assert(p == this && this->is_Start(), "else must be proj");
   22.29        continue;
   22.30      }
   22.31 -    ProjNode *proj = p->as_Proj();
   22.32 -    if( proj->_con == which_proj ) {
   22.33 -      assert(Opcode() != Op_If || proj->Opcode() == (which_proj?Op_IfTrue:Op_IfFalse), "bad if #2");
   22.34 -      return proj;
   22.35 -    }
   22.36    }
   22.37    return NULL;
   22.38  }
    23.1 --- a/src/share/vm/opto/node.hpp	Thu Sep 26 12:07:53 2013 -0700
    23.2 +++ b/src/share/vm/opto/node.hpp	Fri Sep 27 08:39:19 2013 +0200
    23.3 @@ -69,6 +69,7 @@
    23.4  class EncodePKlassNode;
    23.5  class FastLockNode;
    23.6  class FastUnlockNode;
    23.7 +class FlagsProjNode;
    23.8  class IfNode;
    23.9  class IfFalseNode;
   23.10  class IfTrueNode;
   23.11 @@ -623,6 +624,7 @@
   23.12        DEFINE_CLASS_ID(Cmp,   Sub, 0)
   23.13          DEFINE_CLASS_ID(FastLock,   Cmp, 0)
   23.14          DEFINE_CLASS_ID(FastUnlock, Cmp, 1)
   23.15 +        DEFINE_CLASS_ID(FlagsProj, Cmp, 2)
   23.16  
   23.17      DEFINE_CLASS_ID(MergeMem, Node, 7)
   23.18      DEFINE_CLASS_ID(Bool,     Node, 8)
   23.19 @@ -726,6 +728,7 @@
   23.20    DEFINE_CLASS_QUERY(EncodePKlass)
   23.21    DEFINE_CLASS_QUERY(FastLock)
   23.22    DEFINE_CLASS_QUERY(FastUnlock)
   23.23 +  DEFINE_CLASS_QUERY(FlagsProj)
   23.24    DEFINE_CLASS_QUERY(If)
   23.25    DEFINE_CLASS_QUERY(IfFalse)
   23.26    DEFINE_CLASS_QUERY(IfTrue)
    24.1 --- a/src/share/vm/opto/subnode.cpp	Thu Sep 26 12:07:53 2013 -0700
    24.2 +++ b/src/share/vm/opto/subnode.cpp	Fri Sep 27 08:39:19 2013 +0200
    24.3 @@ -1064,7 +1064,7 @@
    24.4  // Print special per-node info
    24.5  #ifndef PRODUCT
    24.6  void BoolTest::dump_on(outputStream *st) const {
    24.7 -  const char *msg[] = {"eq","gt","??","lt","ne","le","??","ge"};
    24.8 +  const char *msg[] = {"eq","gt","of","lt","ne","le","nof","ge"};
    24.9    st->print(msg[_test]);
   24.10  }
   24.11  #endif
   24.12 @@ -1126,7 +1126,7 @@
   24.13    Node *cmp = in(1);
   24.14    if( !cmp->is_Sub() ) return NULL;
   24.15    int cop = cmp->Opcode();
   24.16 -  if( cop == Op_FastLock || cop == Op_FastUnlock ) return NULL;
   24.17 +  if( cop == Op_FastLock || cop == Op_FastUnlock || cop == Op_FlagsProj) return NULL;
   24.18    Node *cmp1 = cmp->in(1);
   24.19    Node *cmp2 = cmp->in(2);
   24.20    if( !cmp1 ) return NULL;
    25.1 --- a/src/share/vm/opto/subnode.hpp	Thu Sep 26 12:07:53 2013 -0700
    25.2 +++ b/src/share/vm/opto/subnode.hpp	Fri Sep 27 08:39:19 2013 +0200
    25.3 @@ -263,16 +263,16 @@
    25.4  // We pick the values as 3 bits; the low order 2 bits we compare against the
    25.5  // condition codes, the high bit flips the sense of the result.
    25.6  struct BoolTest VALUE_OBJ_CLASS_SPEC {
    25.7 -  enum mask { eq = 0, ne = 4, le = 5, ge = 7, lt = 3, gt = 1, illegal = 8 };
    25.8 +  enum mask { eq = 0, ne = 4, le = 5, ge = 7, lt = 3, gt = 1, overflow = 2, no_overflow = 6, illegal = 8 };
    25.9    mask _test;
   25.10    BoolTest( mask btm ) : _test(btm) {}
   25.11    const Type *cc2logical( const Type *CC ) const;
   25.12    // Commute the test.  I use a small table lookup.  The table is created as
   25.13    // a simple char array where each element is the ASCII version of a 'mask'
   25.14    // enum from above.
   25.15 -  mask commute( ) const { return mask("038147858"[_test]-'0'); }
   25.16 +  mask commute( ) const { return mask("032147658"[_test]-'0'); }
   25.17    mask negate( ) const { return mask(_test^4); }
   25.18 -  bool is_canonical( ) const { return (_test == BoolTest::ne || _test == BoolTest::lt || _test == BoolTest::le); }
   25.19 +  bool is_canonical( ) const { return (_test == BoolTest::ne || _test == BoolTest::lt || _test == BoolTest::le || _test == BoolTest::overflow); }
   25.20  #ifndef PRODUCT
   25.21    void dump_on(outputStream *st) const;
   25.22  #endif
    26.1 --- a/src/share/vm/opto/type.cpp	Thu Sep 26 12:07:53 2013 -0700
    26.2 +++ b/src/share/vm/opto/type.cpp	Fri Sep 27 08:39:19 2013 +0200
    26.3 @@ -430,6 +430,11 @@
    26.4    longpair[1] = TypeLong::LONG;
    26.5    TypeTuple::LONG_PAIR = TypeTuple::make(2, longpair);
    26.6  
    26.7 +  const Type **intccpair = TypeTuple::fields(2);
    26.8 +  intccpair[0] = TypeInt::INT;
    26.9 +  intccpair[1] = TypeInt::CC;
   26.10 +  TypeTuple::INT_CC_PAIR = TypeTuple::make(2, intccpair);
   26.11 +
   26.12    _const_basic_type[T_NARROWOOP]   = TypeNarrowOop::BOTTOM;
   26.13    _const_basic_type[T_NARROWKLASS] = Type::BOTTOM;
   26.14    _const_basic_type[T_BOOLEAN]     = TypeInt::BOOL;
   26.15 @@ -1646,6 +1651,7 @@
   26.16  const TypeTuple *TypeTuple::START_I2C;
   26.17  const TypeTuple *TypeTuple::INT_PAIR;
   26.18  const TypeTuple *TypeTuple::LONG_PAIR;
   26.19 +const TypeTuple *TypeTuple::INT_CC_PAIR;
   26.20  
   26.21  
   26.22  //------------------------------make-------------------------------------------
    27.1 --- a/src/share/vm/opto/type.hpp	Thu Sep 26 12:07:53 2013 -0700
    27.2 +++ b/src/share/vm/opto/type.hpp	Fri Sep 27 08:39:19 2013 +0200
    27.3 @@ -584,6 +584,7 @@
    27.4    static const TypeTuple *START_I2C;
    27.5    static const TypeTuple *INT_PAIR;
    27.6    static const TypeTuple *LONG_PAIR;
    27.7 +  static const TypeTuple *INT_CC_PAIR;
    27.8  #ifndef PRODUCT
    27.9    virtual void dump2( Dict &d, uint, outputStream *st  ) const; // Specialized per-Type dumping
   27.10  #endif
    28.1 --- a/src/share/vm/runtime/vmStructs.cpp	Thu Sep 26 12:07:53 2013 -0700
    28.2 +++ b/src/share/vm/runtime/vmStructs.cpp	Fri Sep 27 08:39:19 2013 +0200
    28.3 @@ -176,6 +176,7 @@
    28.4  #include "opto/loopnode.hpp"
    28.5  #include "opto/machnode.hpp"
    28.6  #include "opto/matcher.hpp"
    28.7 +#include "opto/mathexactnode.hpp"
    28.8  #include "opto/mulnode.hpp"
    28.9  #include "opto/phaseX.hpp"
   28.10  #include "opto/parse.hpp"
   28.11 @@ -1927,6 +1928,9 @@
   28.12    declare_c2_type(CmpF3Node, CmpFNode)                                    \
   28.13    declare_c2_type(CmpDNode, CmpNode)                                      \
   28.14    declare_c2_type(CmpD3Node, CmpDNode)                                    \
   28.15 +  declare_c2_type(MathExactNode, MultiNode)                               \
   28.16 +  declare_c2_type(AddExactINode, MathExactNode)                           \
   28.17 +  declare_c2_type(FlagsProjNode, ProjNode)                                \
   28.18    declare_c2_type(BoolNode, Node)                                         \
   28.19    declare_c2_type(AbsNode, Node)                                          \
   28.20    declare_c2_type(AbsINode, AbsNode)                                      \
    29.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.2 +++ b/test/compiler/intrinsics/mathexact/CondTest.java	Fri Sep 27 08:39:19 2013 +0200
    29.3 @@ -0,0 +1,59 @@
    29.4 +/*
    29.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
    29.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    29.7 + *
    29.8 + * This code is free software; you can redistribute it and/or modify it
    29.9 + * under the terms of the GNU General Public License version 2 only, as
   29.10 + * published by the Free Software Foundation.
   29.11 + *
   29.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   29.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   29.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   29.15 + * version 2 for more details (a copy is included in the LICENSE file that
   29.16 + * accompanied this code).
   29.17 + *
   29.18 + * You should have received a copy of the GNU General Public License version
   29.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   29.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   29.21 + *
   29.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   29.23 + * or visit www.oracle.com if you need additional information or have any
   29.24 + * questions.
   29.25 + */
   29.26 +
   29.27 +/*
   29.28 + * @test
   29.29 + * @bug 8024924
   29.30 + * @summary Test non constant addExact
   29.31 + * @compile CondTest.java Verify.java
   29.32 + * @run main CondTest
   29.33 + *
   29.34 + */
   29.35 +
   29.36 +import java.lang.ArithmeticException;
   29.37 +
   29.38 +public class CondTest {
   29.39 +  public static int result = 0;
   29.40 +
   29.41 +  public static void main(String[] args) {
   29.42 +    for (int i = 0; i < 50000; ++i) {
   29.43 +      runTest();
   29.44 +    }
   29.45 +  }
   29.46 +
   29.47 +  public static void runTest() {
   29.48 +    int i = 7;
   29.49 +    while (java.lang.Math.addExact(i, result) < 89361) {
   29.50 +        if ((java.lang.Math.addExact(i, i) & 1) == 1) {
   29.51 +            i += 3;
   29.52 +        } else if ((i & 5) == 4) {
   29.53 +            i += 7;
   29.54 +        } else if ((i & 0xf) == 6) {
   29.55 +            i += 2;
   29.56 +        } else {
   29.57 +            i += 1;
   29.58 +        }
   29.59 +        result += 2;
   29.60 +    }
   29.61 +  }
   29.62 +}
    30.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    30.2 +++ b/test/compiler/intrinsics/mathexact/ConstantTest.java	Fri Sep 27 08:39:19 2013 +0200
    30.3 @@ -0,0 +1,47 @@
    30.4 +/*
    30.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
    30.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    30.7 + *
    30.8 + * This code is free software; you can redistribute it and/or modify it
    30.9 + * under the terms of the GNU General Public License version 2 only, as
   30.10 + * published by the Free Software Foundation.
   30.11 + *
   30.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   30.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   30.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   30.15 + * version 2 for more details (a copy is included in the LICENSE file that
   30.16 + * accompanied this code).
   30.17 + *
   30.18 + * You should have received a copy of the GNU General Public License version
   30.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   30.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   30.21 + *
   30.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   30.23 + * or visit www.oracle.com if you need additional information or have any
   30.24 + * questions.
   30.25 + */
   30.26 +
   30.27 +/*
   30.28 + * @test
   30.29 + * @bug 8024924
   30.30 + * @summary Test constant addExact
   30.31 + * @compile ConstantTest.java Verify.java
   30.32 + * @run main ConstantTest
   30.33 + *
   30.34 + */
   30.35 +
   30.36 +import java.lang.ArithmeticException;
   30.37 +
   30.38 +public class ConstantTest {
   30.39 +  public static void main(String[] args) {
   30.40 +    for (int i = 0; i < 50000; ++i) {
   30.41 +      Verify.verify(5, 7);
   30.42 +      Verify.verify(Integer.MAX_VALUE, 1);
   30.43 +      Verify.verify(Integer.MIN_VALUE, -1);
   30.44 +      Verify.verify(Integer.MAX_VALUE, -1);
   30.45 +      Verify.verify(Integer.MIN_VALUE, 1);
   30.46 +      Verify.verify(Integer.MAX_VALUE / 2, Integer.MAX_VALUE / 2);
   30.47 +      Verify.verify(Integer.MAX_VALUE / 2, (Integer.MAX_VALUE / 2) + 3);
   30.48 +    }
   30.49 +  }
   30.50 +}
    31.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    31.2 +++ b/test/compiler/intrinsics/mathexact/LoadTest.java	Fri Sep 27 08:39:19 2013 +0200
    31.3 @@ -0,0 +1,55 @@
    31.4 +/*
    31.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
    31.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    31.7 + *
    31.8 + * This code is free software; you can redistribute it and/or modify it
    31.9 + * under the terms of the GNU General Public License version 2 only, as
   31.10 + * published by the Free Software Foundation.
   31.11 + *
   31.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   31.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   31.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   31.15 + * version 2 for more details (a copy is included in the LICENSE file that
   31.16 + * accompanied this code).
   31.17 + *
   31.18 + * You should have received a copy of the GNU General Public License version
   31.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   31.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   31.21 + *
   31.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   31.23 + * or visit www.oracle.com if you need additional information or have any
   31.24 + * questions.
   31.25 + */
   31.26 +
   31.27 +/*
   31.28 + * @test
   31.29 + * @bug 8024924
   31.30 + * @summary Test non constant addExact
   31.31 + * @compile LoadTest.java Verify.java
   31.32 + * @run main LoadTest
   31.33 + *
   31.34 + */
   31.35 +
   31.36 +import java.lang.ArithmeticException;
   31.37 +
   31.38 +public class LoadTest {
   31.39 +  public static java.util.Random rnd = new java.util.Random();
   31.40 +  public static int[] values = new int[256];
   31.41 +
   31.42 +  public static void main(String[] args) {
   31.43 +    for (int i = 0; i < values.length; ++i) {
   31.44 +        values[i] = rnd.nextInt();
   31.45 +    }
   31.46 +
   31.47 +    for (int i = 0; i < 50000; ++i) {
   31.48 +      Verify.verify(values[i & 255], values[i & 255] - i);
   31.49 +      Verify.verify(values[i & 255] + i, values[i & 255] - i);
   31.50 +      Verify.verify(values[i & 255], values[i & 255]);
   31.51 +      if ((i & 1) == 1 && i > 5) {
   31.52 +          Verify.verify(values[i & 255] + i, values[i & 255] - i);
   31.53 +      } else {
   31.54 +          Verify.verify(values[i & 255] - i, values[i & 255] + i);
   31.55 +      }
   31.56 +    }
   31.57 +  }
   31.58 +}
    32.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    32.2 +++ b/test/compiler/intrinsics/mathexact/LoopDependentTest.java	Fri Sep 27 08:39:19 2013 +0200
    32.3 @@ -0,0 +1,48 @@
    32.4 +/*
    32.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
    32.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    32.7 + *
    32.8 + * This code is free software; you can redistribute it and/or modify it
    32.9 + * under the terms of the GNU General Public License version 2 only, as
   32.10 + * published by the Free Software Foundation.
   32.11 + *
   32.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   32.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   32.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   32.15 + * version 2 for more details (a copy is included in the LICENSE file that
   32.16 + * accompanied this code).
   32.17 + *
   32.18 + * You should have received a copy of the GNU General Public License version
   32.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   32.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   32.21 + *
   32.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   32.23 + * or visit www.oracle.com if you need additional information or have any
   32.24 + * questions.
   32.25 + */
   32.26 +
   32.27 +/*
   32.28 + * @test
   32.29 + * @bug 8024924
   32.30 + * @summary Test non constant addExact
   32.31 + * @compile LoopDependentTest.java Verify.java
   32.32 + * @run main LoopDependentTest
   32.33 + *
   32.34 + */
   32.35 +
   32.36 +import java.lang.ArithmeticException;
   32.37 +
   32.38 +public class LoopDependentTest {
   32.39 +  public static java.util.Random rnd = new java.util.Random();
   32.40 +
   32.41 +  public static void main(String[] args) {
   32.42 +    int rnd1 = rnd.nextInt(), rnd2 = rnd.nextInt();
   32.43 +    for (int i = 0; i < 50000; ++i) {
   32.44 +      Verify.verify(rnd1 + i, rnd2 + i);
   32.45 +      Verify.verify(rnd1 + i, rnd2 + (i & 0xff));
   32.46 +      Verify.verify(rnd1 - i, rnd2 - (i & 0xff));
   32.47 +      Verify.verify(rnd1 + i + 1, rnd2 + i + 2);
   32.48 +      Verify.verify(rnd1 + i * 2, rnd2 + i);
   32.49 +    }
   32.50 +  }
   32.51 +}
    33.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    33.2 +++ b/test/compiler/intrinsics/mathexact/NonConstantTest.java	Fri Sep 27 08:39:19 2013 +0200
    33.3 @@ -0,0 +1,48 @@
    33.4 +/*
    33.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
    33.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    33.7 + *
    33.8 + * This code is free software; you can redistribute it and/or modify it
    33.9 + * under the terms of the GNU General Public License version 2 only, as
   33.10 + * published by the Free Software Foundation.
   33.11 + *
   33.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   33.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   33.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   33.15 + * version 2 for more details (a copy is included in the LICENSE file that
   33.16 + * accompanied this code).
   33.17 + *
   33.18 + * You should have received a copy of the GNU General Public License version
   33.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   33.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   33.21 + *
   33.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   33.23 + * or visit www.oracle.com if you need additional information or have any
   33.24 + * questions.
   33.25 + */
   33.26 +
   33.27 +/*
   33.28 + * @test
   33.29 + * @bug 8024924
   33.30 + * @summary Test non constant addExact
   33.31 + * @compile NonConstantTest.java Verify.java
   33.32 + * @run main NonConstantTest
   33.33 + *
   33.34 + */
   33.35 +
   33.36 +import java.lang.ArithmeticException;
   33.37 +
   33.38 +public class NonConstantTest {
   33.39 +  public static java.util.Random rnd = new java.util.Random();
   33.40 +
   33.41 +  public static void main(String[] args) {
   33.42 +    for (int i = 0; i < 50000; ++i) {
   33.43 +      int rnd1 = rnd.nextInt(), rnd2 = rnd.nextInt();
   33.44 +      Verify.verify(rnd1, rnd2);
   33.45 +      Verify.verify(rnd1, rnd2 + 1);
   33.46 +      Verify.verify(rnd1 + 1, rnd2);
   33.47 +      Verify.verify(rnd1 - 1, rnd2);
   33.48 +      Verify.verify(rnd1, rnd2 - 1);
   33.49 +    }
   33.50 +  }
   33.51 +}
    34.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.2 +++ b/test/compiler/intrinsics/mathexact/Verify.java	Fri Sep 27 08:39:19 2013 +0200
    34.3 @@ -0,0 +1,68 @@
    34.4 +/*
    34.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
    34.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    34.7 + *
    34.8 + * This code is free software; you can redistribute it and/or modify it
    34.9 + * under the terms of the GNU General Public License version 2 only, as
   34.10 + * published by the Free Software Foundation.
   34.11 + *
   34.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   34.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   34.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   34.15 + * version 2 for more details (a copy is included in the LICENSE file that
   34.16 + * accompanied this code).
   34.17 + *
   34.18 + * You should have received a copy of the GNU General Public License version
   34.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   34.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   34.21 + *
   34.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   34.23 + * or visit www.oracle.com if you need additional information or have any
   34.24 + * questions.
   34.25 + */
   34.26 +
   34.27 +public class Verify {
   34.28 +  public static String throwWord(boolean threw) {
   34.29 +    return (threw ? "threw" : "didn't throw");
   34.30 +  }
   34.31 +
   34.32 +  public static void verify(int a, int b) {
   34.33 +    boolean exception1 = false, exception2 = false;
   34.34 +    int result1 = 0, result2 = 0;
   34.35 +    try {
   34.36 +      result1 = testIntrinsic(a, b);
   34.37 +    } catch (ArithmeticException e) {
   34.38 +      exception1 = true;
   34.39 +    }
   34.40 +    try {
   34.41 +      result2 = testNonIntrinsic(a, b);
   34.42 +    } catch (ArithmeticException e) {
   34.43 +      exception2 = true;
   34.44 +    }
   34.45 +
   34.46 +    if (exception1 != exception2) {
   34.47 +      throw new RuntimeException("Intrinsic version " + throwWord(exception1) + " exception, NonIntrinsic version " + throwWord(exception2) + " for: " + a + " + " + b);
   34.48 +    }
   34.49 +    if (result1 != result2) {
   34.50 +      throw new RuntimeException("Intrinsic version returned: " + a + " while NonIntrinsic version returned: " + b);
   34.51 +    }
   34.52 +  }
   34.53 +
   34.54 +  public static int testIntrinsic(int a, int b) {
   34.55 +    return java.lang.Math.addExact(a, b);
   34.56 +  }
   34.57 +
   34.58 +  public static int testNonIntrinsic(int a, int b) {
   34.59 +    return safeAddExact(a, b);
   34.60 +  }
   34.61 +
   34.62 +  // Copied java.lang.Math.addExact to avoid intrinsification
   34.63 +  public static int safeAddExact(int x, int y) {
   34.64 +    int r = x + y;
   34.65 +    // HD 2-12 Overflow iff both arguments have the opposite sign of the result
   34.66 +    if (((x ^ r) & (y ^ r)) < 0) {
   34.67 +      throw new ArithmeticException("integer overflow");
   34.68 +    }
   34.69 +    return r;
   34.70 +  }
   34.71 +}

mercurial