8173770: Image conversion improvements jdk8u141-b08

Thu, 30 Mar 2017 15:28:33 +0200

author
thartmann
date
Thu, 30 Mar 2017 15:28:33 +0200
changeset 8797
37ba410ffd43
parent 8796
b1f3fbe39975
child 8798
b23c5879a33c

8173770: Image conversion improvements
Reviewed-by: kvn, vlivanov, dlong, rhalade, mschoene, iignatyev

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/archDesc.cpp file | annotate | diff | comparison | revisions
src/share/vm/opto/classes.hpp file | annotate | diff | comparison | revisions
src/share/vm/opto/loopPredicate.cpp file | annotate | diff | comparison | revisions
src/share/vm/opto/loopnode.hpp file | annotate | diff | comparison | revisions
src/share/vm/opto/output.cpp 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/runtime/vmStructs.cpp file | annotate | diff | comparison | revisions
     1.1 --- a/src/cpu/sparc/vm/sparc.ad	Thu Feb 16 15:14:44 2017 -0800
     1.2 +++ b/src/cpu/sparc/vm/sparc.ad	Thu Mar 30 15:28:33 2017 +0200
     1.3 @@ -3458,6 +3458,16 @@
     1.4    interface(CONST_INTER);
     1.5  %}
     1.6  
     1.7 +// Unsigned Long Immediate: 12-bit (non-negative that fits in simm13)
     1.8 +operand immUL12() %{
     1.9 +  predicate((0 <= n->get_long()) && (n->get_long() == (int)n->get_long()) && Assembler::is_simm13((int)n->get_long()));
    1.10 +  match(ConL);
    1.11 +  op_cost(0);
    1.12 +
    1.13 +  format %{ %}
    1.14 +  interface(CONST_INTER);
    1.15 +%}
    1.16 +
    1.17  // Int Immediate non-negative
    1.18  operand immU31()
    1.19  %{
    1.20 @@ -4083,6 +4093,15 @@
    1.21    interface(REG_INTER);
    1.22  %}
    1.23  
    1.24 +// Condition Code Register, unsigned long comparisons.
    1.25 +operand flagsRegUL() %{
    1.26 +  constraint(ALLOC_IN_RC(int_flags));
    1.27 +  match(RegFlags);
    1.28 +
    1.29 +  format %{ "xcc_UL" %}
    1.30 +  interface(REG_INTER);
    1.31 +%}
    1.32 +
    1.33  // Condition Code Register, floating comparisons, unordered same as "less".
    1.34  operand flagsRegF() %{
    1.35    constraint(ALLOC_IN_RC(float_flags));
    1.36 @@ -8962,6 +8981,17 @@
    1.37    ins_pipe(ialu_cconly_reg_reg);
    1.38  %}
    1.39  
    1.40 +instruct compUL_iReg(flagsRegUL xcc, iRegL op1, iRegL op2) %{
    1.41 +  match(Set xcc (CmpUL op1 op2));
    1.42 +  effect(DEF xcc, USE op1, USE op2);
    1.43 +
    1.44 +  size(4);
    1.45 +  format %{ "CMP    $op1,$op2\t! unsigned long" %}
    1.46 +  opcode(Assembler::subcc_op3, Assembler::arith_op);
    1.47 +  ins_encode(form3_rs1_rs2_rd(op1, op2, R_G0));
    1.48 +  ins_pipe(ialu_cconly_reg_reg);
    1.49 +%}
    1.50 +
    1.51  instruct compI_iReg_imm13(flagsReg icc, iRegI op1, immI13 op2) %{
    1.52    match(Set icc (CmpI op1 op2));
    1.53    effect( DEF icc, USE op1 );
    1.54 @@ -9048,6 +9078,17 @@
    1.55    ins_pipe(ialu_cconly_reg_imm);
    1.56  %}
    1.57  
    1.58 +instruct compUL_iReg_imm13(flagsRegUL xcc, iRegL op1, immUL12 op2) %{
    1.59 +  match(Set xcc (CmpUL op1 op2));
    1.60 +  effect(DEF xcc, USE op1, USE op2);
    1.61 +
    1.62 +  size(4);
    1.63 +  format %{ "CMP    $op1,$op2\t! unsigned long" %}
    1.64 +  opcode(Assembler::subcc_op3, Assembler::arith_op);
    1.65 +  ins_encode(form3_rs1_simm13_rd(op1, op2, R_G0));
    1.66 +  ins_pipe(ialu_cconly_reg_imm);
    1.67 +%}
    1.68 +
    1.69  // Compare Pointers
    1.70  instruct compP_iRegP(flagsRegP pcc, iRegP op1, iRegP op2 ) %{
    1.71    match(Set pcc (CmpP op1 op2));
    1.72 @@ -9421,6 +9462,44 @@
    1.73    ins_pipe(cmp_br_reg_imm);
    1.74  %}
    1.75  
    1.76 +instruct cmpUL_reg_branch(cmpOpU cmp, iRegL op1, iRegL op2, label labl, flagsRegUL xcc) %{
    1.77 +  match(If cmp (CmpUL op1 op2));
    1.78 +  effect(USE labl, KILL xcc);
    1.79 +
    1.80 +  size(12);
    1.81 +  ins_cost(BRANCH_COST);
    1.82 +  format %{ "CMP    $op1,$op2\t! unsigned long\n\t"
    1.83 +            "BP$cmp   $labl" %}
    1.84 +  ins_encode %{
    1.85 +    Label* L = $labl$$label;
    1.86 +    Assembler::Predict predict_taken =
    1.87 +      cbuf.is_backward_branch(*L) ? Assembler::pt : Assembler::pn;
    1.88 +    __ cmp($op1$$Register, $op2$$Register);
    1.89 +    __ bp((Assembler::Condition)($cmp$$cmpcode), false, Assembler::xcc, predict_taken, *L);
    1.90 +    __ delayed()->nop();
    1.91 +  %}
    1.92 +  ins_pipe(cmp_br_reg_reg);
    1.93 +%}
    1.94 +
    1.95 +instruct cmpUL_imm_branch(cmpOpU cmp, iRegL op1, immL5 op2, label labl, flagsRegUL xcc) %{
    1.96 +  match(If cmp (CmpUL op1 op2));
    1.97 +  effect(USE labl, KILL xcc);
    1.98 +
    1.99 +  size(12);
   1.100 +  ins_cost(BRANCH_COST);
   1.101 +  format %{ "CMP    $op1,$op2\t! unsigned long\n\t"
   1.102 +            "BP$cmp   $labl" %}
   1.103 +  ins_encode %{
   1.104 +    Label* L = $labl$$label;
   1.105 +    Assembler::Predict predict_taken =
   1.106 +      cbuf.is_backward_branch(*L) ? Assembler::pt : Assembler::pn;
   1.107 +    __ cmp($op1$$Register, $op2$$constant);
   1.108 +    __ bp((Assembler::Condition)($cmp$$cmpcode), false, Assembler::xcc, predict_taken, *L);
   1.109 +    __ delayed()->nop();
   1.110 +  %}
   1.111 +  ins_pipe(cmp_br_reg_imm);
   1.112 +%}
   1.113 +
   1.114  instruct cmpL_reg_branch(cmpOp cmp, iRegL op1, iRegL op2, label labl, flagsRegL xcc) %{
   1.115    match(If cmp (CmpL op1 op2));
   1.116    effect(USE labl, KILL xcc);
   1.117 @@ -9649,6 +9728,42 @@
   1.118    ins_pipe(cbcond_reg_imm);
   1.119  %}
   1.120  
   1.121 +instruct cmpUL_reg_branch_short(cmpOpU cmp, iRegL op1, iRegL op2, label labl, flagsRegUL xcc) %{
   1.122 +  match(If cmp (CmpUL op1 op2));
   1.123 +  predicate(UseCBCond);
   1.124 +  effect(USE labl, KILL xcc);
   1.125 +
   1.126 +  size(4);
   1.127 +  ins_cost(BRANCH_COST);
   1.128 +  format %{ "CXB$cmp  $op1,$op2,$labl\t! unsigned long" %}
   1.129 +  ins_encode %{
   1.130 +    Label* L = $labl$$label;
   1.131 +    assert(__ use_cbcond(*L), "back to back cbcond");
   1.132 +    __ cbcond((Assembler::Condition)($cmp$$cmpcode), Assembler::xcc, $op1$$Register, $op2$$Register, *L);
   1.133 +  %}
   1.134 +  ins_short_branch(1);
   1.135 +  ins_avoid_back_to_back(AVOID_BEFORE_AND_AFTER);
   1.136 +  ins_pipe(cbcond_reg_reg);
   1.137 +%}
   1.138 +
   1.139 +instruct cmpUL_imm_branch_short(cmpOpU cmp, iRegL op1, immL5 op2, label labl, flagsRegUL xcc) %{
   1.140 +  match(If cmp (CmpUL op1 op2));
   1.141 +  predicate(UseCBCond);
   1.142 +  effect(USE labl, KILL xcc);
   1.143 +
   1.144 +  size(4);
   1.145 +  ins_cost(BRANCH_COST);
   1.146 +  format %{ "CXB$cmp  $op1,$op2,$labl\t! unsigned long" %}
   1.147 +  ins_encode %{
   1.148 +    Label* L = $labl$$label;
   1.149 +    assert(__ use_cbcond(*L), "back to back cbcond");
   1.150 +    __ cbcond((Assembler::Condition)($cmp$$cmpcode), Assembler::xcc, $op1$$Register, $op2$$constant, *L);
   1.151 +  %}
   1.152 +  ins_short_branch(1);
   1.153 +  ins_avoid_back_to_back(AVOID_BEFORE_AND_AFTER);
   1.154 +  ins_pipe(cbcond_reg_imm);
   1.155 +%}
   1.156 +
   1.157  instruct cmpL_reg_branch_short(cmpOp cmp, iRegL op1, iRegL op2, label labl, flagsRegL xcc) %{
   1.158    match(If cmp (CmpL op1 op2));
   1.159    predicate(UseCBCond);
   1.160 @@ -9887,6 +10002,25 @@
   1.161    ins_pipe(br_cc);
   1.162  %}
   1.163  
   1.164 +instruct branchConU_long(cmpOpU cmp, flagsRegUL xcc, label labl) %{
   1.165 +  match(If cmp xcc);
   1.166 +  effect(USE labl);
   1.167 +
   1.168 +  size(8);
   1.169 +  ins_cost(BRANCH_COST);
   1.170 +  format %{ "BP$cmp   $xcc,$labl" %}
   1.171 +  ins_encode %{
   1.172 +    Label* L = $labl$$label;
   1.173 +    Assembler::Predict predict_taken =
   1.174 +      cbuf.is_backward_branch(*L) ? Assembler::pt : Assembler::pn;
   1.175 +
   1.176 +    __ bp((Assembler::Condition)($cmp$$cmpcode), false, Assembler::xcc, predict_taken, *L);
   1.177 +    __ delayed()->nop();
   1.178 +  %}
   1.179 +  ins_avoid_back_to_back(AVOID_BEFORE);
   1.180 +  ins_pipe(br_cc);
   1.181 +%}
   1.182 +
   1.183  // Manifest a CmpL3 result in an integer register.  Very painful.
   1.184  // This is the test to avoid.
   1.185  instruct cmpL3_reg_reg(iRegI dst, iRegL src1, iRegL src2, flagsReg ccr ) %{
     2.1 --- a/src/cpu/x86/vm/x86_32.ad	Thu Feb 16 15:14:44 2017 -0800
     2.2 +++ b/src/cpu/x86/vm/x86_32.ad	Thu Mar 30 15:28:33 2017 +0200
     2.3 @@ -3948,6 +3948,26 @@
     2.4    interface(REG_INTER);
     2.5  %}
     2.6  
     2.7 +// Condition Code Register used by unsigned long compare
     2.8 +operand flagsReg_ulong_LTGE() %{
     2.9 +  constraint(ALLOC_IN_RC(int_flags));
    2.10 +  match(RegFlags);
    2.11 +  format %{ "FLAGS_U_LTGE" %}
    2.12 +  interface(REG_INTER);
    2.13 +%}
    2.14 +operand flagsReg_ulong_EQNE() %{
    2.15 +  constraint(ALLOC_IN_RC(int_flags));
    2.16 +  match(RegFlags);
    2.17 +  format %{ "FLAGS_U_EQNE" %}
    2.18 +  interface(REG_INTER);
    2.19 +%}
    2.20 +operand flagsReg_ulong_LEGT() %{
    2.21 +  constraint(ALLOC_IN_RC(int_flags));
    2.22 +  match(RegFlags);
    2.23 +  format %{ "FLAGS_U_LEGT" %}
    2.24 +  interface(REG_INTER);
    2.25 +%}
    2.26 +
    2.27  // Float register operands
    2.28  operand regDPR() %{
    2.29    predicate( UseSSE < 2 );
    2.30 @@ -4473,7 +4493,7 @@
    2.31    %}
    2.32  %}
    2.33  
    2.34 -// Comparision Code used in long compares
    2.35 +// Comparison Code used in long compares
    2.36  operand cmpOp_commute() %{
    2.37    match(Bool);
    2.38  
    2.39 @@ -4490,6 +4510,23 @@
    2.40    %}
    2.41  %}
    2.42  
    2.43 +// Comparison Code used in unsigned long compares
    2.44 +operand cmpOpU_commute() %{
    2.45 +  match(Bool);
    2.46 +
    2.47 +  format %{ "" %}
    2.48 +  interface(COND_INTER) %{
    2.49 +    equal(0x4, "e");
    2.50 +    not_equal(0x5, "ne");
    2.51 +    less(0x7, "nbe");
    2.52 +    greater_equal(0x6, "be");
    2.53 +    less_equal(0x3, "nb");
    2.54 +    greater(0x2, "b");
    2.55 +    overflow(0x0, "o");
    2.56 +    no_overflow(0x1, "no");
    2.57 +  %}
    2.58 +%}
    2.59 +
    2.60  //----------OPERAND CLASSES----------------------------------------------------
    2.61  // Operand Classes are groups of operands that are used as to simplify
    2.62  // instruction definitions by not requiring the AD writer to specify separate
    2.63 @@ -12382,6 +12419,44 @@
    2.64    %}
    2.65  %}
    2.66  
    2.67 +//======
    2.68 +// Manifest a CmpUL result in the normal flags.  Only good for LT or GE
    2.69 +// compares.  Can be used for LE or GT compares by reversing arguments.
    2.70 +// NOT GOOD FOR EQ/NE tests.
    2.71 +instruct cmpUL_zero_flags_LTGE(flagsReg_ulong_LTGE flags, eRegL src, immL0 zero) %{
    2.72 +  match(Set flags (CmpUL src zero));
    2.73 +  ins_cost(100);
    2.74 +  format %{ "TEST   $src.hi,$src.hi" %}
    2.75 +  opcode(0x85);
    2.76 +  ins_encode(OpcP, RegReg_Hi2(src, src));
    2.77 +  ins_pipe(ialu_cr_reg_reg);
    2.78 +%}
    2.79 +
    2.80 +// Manifest a CmpUL result in the normal flags.  Only good for LT or GE
    2.81 +// compares.  Can be used for LE or GT compares by reversing arguments.
    2.82 +// NOT GOOD FOR EQ/NE tests.
    2.83 +instruct cmpUL_reg_flags_LTGE(flagsReg_ulong_LTGE flags, eRegL src1, eRegL src2, rRegI tmp) %{
    2.84 +  match(Set flags (CmpUL src1 src2));
    2.85 +  effect(TEMP tmp);
    2.86 +  ins_cost(300);
    2.87 +  format %{ "CMP    $src1.lo,$src2.lo\t! Unsigned long compare; set flags for low bits\n\t"
    2.88 +            "MOV    $tmp,$src1.hi\n\t"
    2.89 +            "SBB    $tmp,$src2.hi\t! Compute flags for unsigned long compare" %}
    2.90 +  ins_encode(long_cmp_flags2(src1, src2, tmp));
    2.91 +  ins_pipe(ialu_cr_reg_reg);
    2.92 +%}
    2.93 +
    2.94 +// Unsigned long compares reg < zero/req OR reg >= zero/req.
    2.95 +// Just a wrapper for a normal branch, plus the predicate test.
    2.96 +instruct cmpUL_LTGE(cmpOpU cmp, flagsReg_ulong_LTGE flags, label labl) %{
    2.97 +  match(If cmp flags);
    2.98 +  effect(USE labl);
    2.99 +  predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge);
   2.100 +  expand %{
   2.101 +    jmpCon(cmp, flags, labl);    // JLT or JGE...
   2.102 +  %}
   2.103 +%}
   2.104 +
   2.105  // Compare 2 longs and CMOVE longs.
   2.106  instruct cmovLL_reg_LTGE(cmpOp cmp, flagsReg_long_LTGE flags, eRegL dst, eRegL src) %{
   2.107    match(Set dst (CMoveL (Binary cmp flags) (Binary dst src)));
   2.108 @@ -12510,6 +12585,41 @@
   2.109    %}
   2.110  %}
   2.111  
   2.112 +//======
   2.113 +// Manifest a CmpUL result in the normal flags.  Only good for EQ/NE compares.
   2.114 +instruct cmpUL_zero_flags_EQNE(flagsReg_ulong_EQNE flags, eRegL src, immL0 zero, rRegI tmp) %{
   2.115 +  match(Set flags (CmpUL src zero));
   2.116 +  effect(TEMP tmp);
   2.117 +  ins_cost(200);
   2.118 +  format %{ "MOV    $tmp,$src.lo\n\t"
   2.119 +            "OR     $tmp,$src.hi\t! Unsigned long is EQ/NE 0?" %}
   2.120 +  ins_encode(long_cmp_flags0(src, tmp));
   2.121 +  ins_pipe(ialu_reg_reg_long);
   2.122 +%}
   2.123 +
   2.124 +// Manifest a CmpUL result in the normal flags.  Only good for EQ/NE compares.
   2.125 +instruct cmpUL_reg_flags_EQNE(flagsReg_ulong_EQNE flags, eRegL src1, eRegL src2) %{
   2.126 +  match(Set flags (CmpUL src1 src2));
   2.127 +  ins_cost(200+300);
   2.128 +  format %{ "CMP    $src1.lo,$src2.lo\t! Unsigned long compare; set flags for low bits\n\t"
   2.129 +            "JNE,s  skip\n\t"
   2.130 +            "CMP    $src1.hi,$src2.hi\n\t"
   2.131 +     "skip:\t" %}
   2.132 +  ins_encode(long_cmp_flags1(src1, src2));
   2.133 +  ins_pipe(ialu_cr_reg_reg);
   2.134 +%}
   2.135 +
   2.136 +// Unsigned long compare reg == zero/reg OR reg != zero/reg
   2.137 +// Just a wrapper for a normal branch, plus the predicate test.
   2.138 +instruct cmpUL_EQNE(cmpOpU cmp, flagsReg_ulong_EQNE flags, label labl) %{
   2.139 +  match(If cmp flags);
   2.140 +  effect(USE labl);
   2.141 +  predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne);
   2.142 +  expand %{
   2.143 +    jmpCon(cmp, flags, labl);    // JEQ or JNE...
   2.144 +  %}
   2.145 +%}
   2.146 +
   2.147  // Compare 2 longs and CMOVE longs.
   2.148  instruct cmovLL_reg_EQNE(cmpOp cmp, flagsReg_long_EQNE flags, eRegL dst, eRegL src) %{
   2.149    match(Set dst (CMoveL (Binary cmp flags) (Binary dst src)));
   2.150 @@ -12643,6 +12753,46 @@
   2.151    %}
   2.152  %}
   2.153  
   2.154 +//======
   2.155 +// Manifest a CmpUL result in the normal flags.  Only good for LE or GT compares.
   2.156 +// Same as cmpUL_reg_flags_LEGT except must negate src
   2.157 +instruct cmpUL_zero_flags_LEGT(flagsReg_ulong_LEGT flags, eRegL src, immL0 zero, rRegI tmp) %{
   2.158 +  match(Set flags (CmpUL src zero));
   2.159 +  effect(TEMP tmp);
   2.160 +  ins_cost(300);
   2.161 +  format %{ "XOR    $tmp,$tmp\t# Unsigned long compare for -$src < 0, use commuted test\n\t"
   2.162 +            "CMP    $tmp,$src.lo\n\t"
   2.163 +            "SBB    $tmp,$src.hi\n\t" %}
   2.164 +  ins_encode(long_cmp_flags3(src, tmp));
   2.165 +  ins_pipe(ialu_reg_reg_long);
   2.166 +%}
   2.167 +
   2.168 +// Manifest a CmpUL result in the normal flags.  Only good for LE or GT compares.
   2.169 +// Same as cmpUL_reg_flags_LTGE except operands swapped.  Swapping operands
   2.170 +// requires a commuted test to get the same result.
   2.171 +instruct cmpUL_reg_flags_LEGT(flagsReg_ulong_LEGT flags, eRegL src1, eRegL src2, rRegI tmp) %{
   2.172 +  match(Set flags (CmpUL src1 src2));
   2.173 +  effect(TEMP tmp);
   2.174 +  ins_cost(300);
   2.175 +  format %{ "CMP    $src2.lo,$src1.lo\t! Unsigned long compare, swapped operands, use with commuted test\n\t"
   2.176 +            "MOV    $tmp,$src2.hi\n\t"
   2.177 +            "SBB    $tmp,$src1.hi\t! Compute flags for unsigned long compare" %}
   2.178 +  ins_encode(long_cmp_flags2( src2, src1, tmp));
   2.179 +  ins_pipe(ialu_cr_reg_reg);
   2.180 +%}
   2.181 +
   2.182 +// Unsigned long compares reg < zero/req OR reg >= zero/req.
   2.183 +// Just a wrapper for a normal branch, plus the predicate test
   2.184 +instruct cmpUL_LEGT(cmpOpU_commute cmp, flagsReg_ulong_LEGT flags, label labl) %{
   2.185 +  match(If cmp flags);
   2.186 +  effect(USE labl);
   2.187 +  predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le);
   2.188 +  ins_cost(300);
   2.189 +  expand %{
   2.190 +    jmpCon(cmp, flags, labl);    // JGT or JLE...
   2.191 +  %}
   2.192 +%}
   2.193 +
   2.194  // Compare 2 longs and CMOVE longs.
   2.195  instruct cmovLL_reg_LEGT(cmpOp_commute cmp, flagsReg_long_LEGT flags, eRegL dst, eRegL src) %{
   2.196    match(Set dst (CMoveL (Binary cmp flags) (Binary dst src)));
     3.1 --- a/src/cpu/x86/vm/x86_64.ad	Thu Feb 16 15:14:44 2017 -0800
     3.2 +++ b/src/cpu/x86/vm/x86_64.ad	Thu Mar 30 15:28:33 2017 +0200
     3.3 @@ -11068,6 +11068,48 @@
     3.4    ins_pipe(pipe_slow);
     3.5  %}
     3.6  
     3.7 +// Unsigned long compare Instructions; really, same as signed long except they
     3.8 +// produce an rFlagsRegU instead of rFlagsReg.
     3.9 +instruct compUL_rReg(rFlagsRegU cr, rRegL op1, rRegL op2)
    3.10 +%{
    3.11 +  match(Set cr (CmpUL op1 op2));
    3.12 +
    3.13 +  format %{ "cmpq    $op1, $op2\t# unsigned" %}
    3.14 +  opcode(0x3B);  /* Opcode 3B /r */
    3.15 +  ins_encode(REX_reg_reg_wide(op1, op2), OpcP, reg_reg(op1, op2));
    3.16 +  ins_pipe(ialu_cr_reg_reg);
    3.17 +%}
    3.18 +
    3.19 +instruct compUL_rReg_imm(rFlagsRegU cr, rRegL op1, immL32 op2)
    3.20 +%{
    3.21 +  match(Set cr (CmpUL op1 op2));
    3.22 +
    3.23 +  format %{ "cmpq    $op1, $op2\t# unsigned" %}
    3.24 +  opcode(0x81, 0x07); /* Opcode 81 /7 */
    3.25 +  ins_encode(OpcSErm_wide(op1, op2), Con8or32(op2));
    3.26 +  ins_pipe(ialu_cr_reg_imm);
    3.27 +%}
    3.28 +
    3.29 +instruct compUL_rReg_mem(rFlagsRegU cr, rRegL op1, memory op2)
    3.30 +%{
    3.31 +  match(Set cr (CmpUL op1 (LoadL op2)));
    3.32 +
    3.33 +  format %{ "cmpq    $op1, $op2\t# unsigned" %}
    3.34 +  opcode(0x3B); /* Opcode 3B /r */
    3.35 +  ins_encode(REX_reg_mem_wide(op1, op2), OpcP, reg_mem(op1, op2));
    3.36 +  ins_pipe(ialu_cr_reg_mem);
    3.37 +%}
    3.38 +
    3.39 +instruct testUL_reg(rFlagsRegU cr, rRegL src, immL0 zero)
    3.40 +%{
    3.41 +  match(Set cr (CmpUL src zero));
    3.42 +
    3.43 +  format %{ "testq   $src, $src\t# unsigned" %}
    3.44 +  opcode(0x85);
    3.45 +  ins_encode(REX_reg_reg_wide(src, src), OpcP, reg_reg(src, src));
    3.46 +  ins_pipe(ialu_cr_reg_imm);
    3.47 +%}
    3.48 +
    3.49  //----------Max and Min--------------------------------------------------------
    3.50  // Min Instructions
    3.51  
     4.1 --- a/src/share/vm/adlc/archDesc.cpp	Thu Feb 16 15:14:44 2017 -0800
     4.2 +++ b/src/share/vm/adlc/archDesc.cpp	Thu Mar 30 15:28:33 2017 +0200
     4.3 @@ -1189,6 +1189,7 @@
     4.4           || strcmp(idealName,"CmpP") == 0
     4.5           || strcmp(idealName,"CmpN") == 0
     4.6           || strcmp(idealName,"CmpL") == 0
     4.7 +         || strcmp(idealName,"CmpUL") == 0
     4.8           || strcmp(idealName,"CmpD") == 0
     4.9           || strcmp(idealName,"CmpF") == 0
    4.10           || strcmp(idealName,"FastLock") == 0
     5.1 --- a/src/share/vm/opto/classes.hpp	Thu Feb 16 15:14:44 2017 -0800
     5.2 +++ b/src/share/vm/opto/classes.hpp	Thu Mar 30 15:28:33 2017 +0200
     5.3 @@ -79,6 +79,7 @@
     5.4  macro(CmpLTMask)
     5.5  macro(CmpP)
     5.6  macro(CmpU)
     5.7 +macro(CmpUL)
     5.8  macro(CompareAndSwapI)
     5.9  macro(CompareAndSwapL)
    5.10  macro(CompareAndSwapP)
     6.1 --- a/src/share/vm/opto/loopPredicate.cpp	Thu Feb 16 15:14:44 2017 -0800
     6.2 +++ b/src/share/vm/opto/loopPredicate.cpp	Thu Mar 30 15:28:33 2017 +0200
     6.3 @@ -28,6 +28,7 @@
     6.4  #include "opto/callnode.hpp"
     6.5  #include "opto/connode.hpp"
     6.6  #include "opto/loopnode.hpp"
     6.7 +#include "opto/matcher.hpp"
     6.8  #include "opto/mulnode.hpp"
     6.9  #include "opto/rootnode.hpp"
    6.10  #include "opto/subnode.hpp"
    6.11 @@ -593,50 +594,140 @@
    6.12  //   max(scale*i + offset) = scale*init + offset
    6.13  BoolNode* PhaseIdealLoop::rc_predicate(IdealLoopTree *loop, Node* ctrl,
    6.14                                         int scale, Node* offset,
    6.15 -                                       Node* init, Node* limit, Node* stride,
    6.16 -                                       Node* range, bool upper) {
    6.17 +                                       Node* init, Node* limit, jint stride,
    6.18 +                                       Node* range, bool upper, bool &overflow) {
    6.19 +  jint con_limit  = limit->is_Con()  ? limit->get_int()  : 0;
    6.20 +  jint con_init   = init->is_Con()   ? init->get_int()   : 0;
    6.21 +  jint con_offset = offset->is_Con() ? offset->get_int() : 0;
    6.22 +
    6.23    stringStream* predString = NULL;
    6.24    if (TraceLoopPredicate) {
    6.25      predString = new stringStream();
    6.26      predString->print("rc_predicate ");
    6.27    }
    6.28  
    6.29 -  Node* max_idx_expr  = init;
    6.30 -  int stride_con = stride->get_int();
    6.31 -  if ((stride_con > 0) == (scale > 0) == upper) {
    6.32 -    if (LoopLimitCheck) {
    6.33 -      // With LoopLimitCheck limit is not exact.
    6.34 -      // Calculate exact limit here.
    6.35 -      // Note, counted loop's test is '<' or '>'.
    6.36 -      limit = exact_limit(loop);
    6.37 -      max_idx_expr = new (C) SubINode(limit, stride);
    6.38 -      register_new_node(max_idx_expr, ctrl);
    6.39 -      if (TraceLoopPredicate) predString->print("(limit - stride) ");
    6.40 +  overflow = false;
    6.41 +  Node* max_idx_expr = NULL;
    6.42 +  const TypeInt* idx_type = TypeInt::INT;
    6.43 +  if ((stride > 0) == (scale > 0) == upper) {
    6.44 +    if (TraceLoopPredicate) {
    6.45 +      predString->print(limit->is_Con() ? "(%d " : "(limit ", con_limit);
    6.46 +      predString->print("- %d) ", stride);
    6.47 +    }
    6.48 +    // Check if (limit - stride) may overflow
    6.49 +    const TypeInt* limit_type = _igvn.type(limit)->isa_int();
    6.50 +    jint limit_lo = limit_type->_lo;
    6.51 +    jint limit_hi = limit_type->_hi;
    6.52 +    jint res_lo = limit_lo - stride;
    6.53 +    jint res_hi = limit_hi - stride;
    6.54 +    if ((stride > 0 && (res_lo < limit_lo)) ||
    6.55 +        (stride < 0 && (res_hi > limit_hi))) {
    6.56 +      // No overflow possible
    6.57 +      ConINode* con_stride = _igvn.intcon(stride);
    6.58 +      set_ctrl(con_stride, C->root());
    6.59 +      max_idx_expr = new (C) SubINode(limit, con_stride);
    6.60 +      idx_type = TypeInt::make(limit_lo - stride, limit_hi - stride, limit_type->_widen);
    6.61      } else {
    6.62 -      max_idx_expr = new (C) SubINode(limit, stride);
    6.63 -      register_new_node(max_idx_expr, ctrl);
    6.64 -      if (TraceLoopPredicate) predString->print("(limit - stride) ");
    6.65 +      // May overflow
    6.66 +      overflow = true;
    6.67 +      limit = new (C) ConvI2LNode(limit);
    6.68 +      register_new_node(limit, ctrl);
    6.69 +      ConLNode* con_stride = _igvn.longcon(stride);
    6.70 +      set_ctrl(con_stride, C->root());
    6.71 +      max_idx_expr = new (C) SubLNode(limit, con_stride);
    6.72      }
    6.73 +    register_new_node(max_idx_expr, ctrl);
    6.74    } else {
    6.75 -    if (TraceLoopPredicate) predString->print("init ");
    6.76 +    if (TraceLoopPredicate) {
    6.77 +      predString->print(init->is_Con() ? "%d " : "init ", con_init);
    6.78 +    }
    6.79 +    idx_type = _igvn.type(init)->isa_int();
    6.80 +    max_idx_expr = init;
    6.81    }
    6.82  
    6.83    if (scale != 1) {
    6.84      ConNode* con_scale = _igvn.intcon(scale);
    6.85 -    max_idx_expr = new (C) MulINode(max_idx_expr, con_scale);
    6.86 +    set_ctrl(con_scale, C->root());
    6.87 +    if (TraceLoopPredicate) {
    6.88 +      predString->print("* %d ", scale);
    6.89 +    }
    6.90 +    // Check if (scale * max_idx_expr) may overflow
    6.91 +    const TypeInt* scale_type = TypeInt::make(scale);
    6.92 +    MulINode* mul = new (C) MulINode(max_idx_expr, con_scale);
    6.93 +    idx_type = (TypeInt*)mul->mul_ring(idx_type, scale_type);
    6.94 +    if (overflow || TypeInt::INT->higher_equal(idx_type)) {
    6.95 +      // May overflow
    6.96 +      mul->destruct();
    6.97 +      if (!overflow) {
    6.98 +        max_idx_expr = new (C) ConvI2LNode(max_idx_expr);
    6.99 +        register_new_node(max_idx_expr, ctrl);
   6.100 +      }
   6.101 +      overflow = true;
   6.102 +      con_scale = _igvn.longcon(scale);
   6.103 +      set_ctrl(con_scale, C->root());
   6.104 +      max_idx_expr = new (C) MulLNode(max_idx_expr, con_scale);
   6.105 +    } else {
   6.106 +      // No overflow possible
   6.107 +      max_idx_expr = mul;
   6.108 +    }
   6.109      register_new_node(max_idx_expr, ctrl);
   6.110 -    if (TraceLoopPredicate) predString->print("* %d ", scale);
   6.111    }
   6.112  
   6.113 -  if (offset && (!offset->is_Con() || offset->get_int() != 0)){
   6.114 -    max_idx_expr = new (C) AddINode(max_idx_expr, offset);
   6.115 +  if (offset && (!offset->is_Con() || con_offset != 0)){
   6.116 +    if (TraceLoopPredicate) {
   6.117 +      predString->print(offset->is_Con() ? "+ %d " : "+ offset", con_offset);
   6.118 +    }
   6.119 +    // Check if (max_idx_expr + offset) may overflow
   6.120 +    const TypeInt* offset_type = _igvn.type(offset)->isa_int();
   6.121 +    jint lo = idx_type->_lo + offset_type->_lo;
   6.122 +    jint hi = idx_type->_hi + offset_type->_hi;
   6.123 +    if (overflow || (lo > hi) ||
   6.124 +        ((idx_type->_lo & offset_type->_lo) < 0 && lo >= 0) ||
   6.125 +        ((~(idx_type->_hi | offset_type->_hi)) < 0 && hi < 0)) {
   6.126 +      // May overflow
   6.127 +      if (!overflow) {
   6.128 +        max_idx_expr = new (C) ConvI2LNode(max_idx_expr);
   6.129 +        register_new_node(max_idx_expr, ctrl);
   6.130 +      }
   6.131 +      overflow = true;
   6.132 +      offset = new (C) ConvI2LNode(offset);
   6.133 +      register_new_node(offset, ctrl);
   6.134 +      max_idx_expr = new (C) AddLNode(max_idx_expr, offset);
   6.135 +    } else {
   6.136 +      // No overflow possible
   6.137 +      max_idx_expr = new (C) AddINode(max_idx_expr, offset);
   6.138 +    }
   6.139      register_new_node(max_idx_expr, ctrl);
   6.140 -    if (TraceLoopPredicate)
   6.141 -      if (offset->is_Con()) predString->print("+ %d ", offset->get_int());
   6.142 -      else predString->print("+ offset ");
   6.143    }
   6.144  
   6.145 -  CmpUNode* cmp = new (C) CmpUNode(max_idx_expr, range);
   6.146 +  CmpNode* cmp = NULL;
   6.147 +  if (overflow) {
   6.148 +    // Integer expressions may overflow, do long comparison
   6.149 +    range = new (C) ConvI2LNode(range);
   6.150 +    register_new_node(range, ctrl);
   6.151 +    if (!Matcher::has_match_rule(Op_CmpUL)) {
   6.152 +      // We don't support unsigned long comparisons. Set 'max_idx_expr'
   6.153 +      // to max_julong if < 0 to make the signed comparison fail.
   6.154 +      ConINode* sign_pos = _igvn.intcon(BitsPerLong - 1);
   6.155 +      set_ctrl(sign_pos, C->root());
   6.156 +      Node* sign_bit_mask = new (C) RShiftLNode(max_idx_expr, sign_pos);
   6.157 +      register_new_node(sign_bit_mask, ctrl);
   6.158 +      // OR with sign bit to set all bits to 1 if negative (otherwise no change)
   6.159 +      max_idx_expr = new (C) OrLNode(max_idx_expr, sign_bit_mask);
   6.160 +      register_new_node(max_idx_expr, ctrl);
   6.161 +      // AND with 0x7ff... to unset the sign bit
   6.162 +      ConLNode* remove_sign_mask = _igvn.longcon(max_jlong);
   6.163 +      set_ctrl(remove_sign_mask, C->root());
   6.164 +      max_idx_expr = new (C) AndLNode(max_idx_expr, remove_sign_mask);
   6.165 +      register_new_node(max_idx_expr, ctrl);
   6.166 +
   6.167 +      cmp = new (C) CmpLNode(max_idx_expr, range);
   6.168 +    } else {
   6.169 +      cmp = new (C) CmpULNode(max_idx_expr, range);
   6.170 +    }
   6.171 +  } else {
   6.172 +    cmp = new (C) CmpUNode(max_idx_expr, range);
   6.173 +  }
   6.174    register_new_node(cmp, ctrl);
   6.175    BoolNode* bol = new (C) BoolNode(cmp, BoolTest::lt);
   6.176    register_new_node(bol, ctrl);
   6.177 @@ -786,8 +877,11 @@
   6.178        assert(ok, "must be index expression");
   6.179  
   6.180        Node* init    = cl->init_trip();
   6.181 -      Node* limit   = cl->limit();
   6.182 -      Node* stride  = cl->stride();
   6.183 +      // Limit is not exact.
   6.184 +      // Calculate exact limit here.
   6.185 +      // Note, counted loop's test is '<' or '>'.
   6.186 +      Node* limit   = exact_limit(loop);
   6.187 +      int  stride   = cl->stride()->get_int();
   6.188  
   6.189        // Build if's for the upper and lower bound tests.  The
   6.190        // lower_bound test will dominate the upper bound test and all
   6.191 @@ -805,16 +899,18 @@
   6.192          assert(invar.is_invariant(offset), "offset must be loop invariant");
   6.193          offset = invar.clone(offset, ctrl);
   6.194        }
   6.195 +      // If predicate expressions may overflow in the integer range, longs are used.
   6.196 +      bool overflow = false;
   6.197  
   6.198        // Test the lower bound
   6.199 -      Node*  lower_bound_bol = rc_predicate(loop, ctrl, scale, offset, init, limit, stride, rng, false);
   6.200 +      Node*  lower_bound_bol = rc_predicate(loop, ctrl, scale, offset, init, limit, stride, rng, false, overflow);
   6.201        IfNode* lower_bound_iff = lower_bound_proj->in(0)->as_If();
   6.202        _igvn.hash_delete(lower_bound_iff);
   6.203        lower_bound_iff->set_req(1, lower_bound_bol);
   6.204        if (TraceLoopPredicate) tty->print_cr("lower bound check if: %d", lower_bound_iff->_idx);
   6.205  
   6.206        // Test the upper bound
   6.207 -      Node* upper_bound_bol = rc_predicate(loop, lower_bound_proj, scale, offset, init, limit, stride, rng, true);
   6.208 +      Node* upper_bound_bol = rc_predicate(loop, lower_bound_proj, scale, offset, init, limit, stride, rng, true, overflow);
   6.209        IfNode* upper_bound_iff = upper_bound_proj->in(0)->as_If();
   6.210        _igvn.hash_delete(upper_bound_iff);
   6.211        upper_bound_iff->set_req(1, upper_bound_bol);
     7.1 --- a/src/share/vm/opto/loopnode.hpp	Thu Feb 16 15:14:44 2017 -0800
     7.2 +++ b/src/share/vm/opto/loopnode.hpp	Thu Mar 30 15:28:33 2017 +0200
     7.3 @@ -905,8 +905,8 @@
     7.4    // Construct a range check for a predicate if
     7.5    BoolNode* rc_predicate(IdealLoopTree *loop, Node* ctrl,
     7.6                           int scale, Node* offset,
     7.7 -                         Node* init, Node* limit, Node* stride,
     7.8 -                         Node* range, bool upper);
     7.9 +                         Node* init, Node* limit, jint stride,
    7.10 +                         Node* range, bool upper, bool &overflow);
    7.11  
    7.12    // Implementation of the loop predication to promote checks outside the loop
    7.13    bool loop_predication_impl(IdealLoopTree *loop);
     8.1 --- a/src/share/vm/opto/output.cpp	Thu Feb 16 15:14:44 2017 -0800
     8.2 +++ b/src/share/vm/opto/output.cpp	Thu Mar 30 15:28:33 2017 +0200
     8.3 @@ -2095,6 +2095,7 @@
     8.4      if( last->is_MachIf() && last->in(1) == n &&
     8.5          ( op == Op_CmpI ||
     8.6            op == Op_CmpU ||
     8.7 +          op == Op_CmpUL ||
     8.8            op == Op_CmpP ||
     8.9            op == Op_CmpF ||
    8.10            op == Op_CmpD ||
     9.1 --- a/src/share/vm/opto/subnode.cpp	Thu Feb 16 15:14:44 2017 -0800
     9.2 +++ b/src/share/vm/opto/subnode.cpp	Thu Mar 30 15:28:33 2017 +0200
     9.3 @@ -707,6 +707,60 @@
     9.4    return TypeInt::CC;           // else use worst case results
     9.5  }
     9.6  
     9.7 +
     9.8 +// Simplify a CmpUL (compare 2 unsigned longs) node, based on local information.
     9.9 +// If both inputs are constants, compare them.
    9.10 +const Type* CmpULNode::sub(const Type* t1, const Type* t2) const {
    9.11 +  assert(!t1->isa_ptr(), "obsolete usage of CmpUL");
    9.12 +
    9.13 +  // comparing two unsigned longs
    9.14 +  const TypeLong* r0 = t1->is_long();   // Handy access
    9.15 +  const TypeLong* r1 = t2->is_long();
    9.16 +
    9.17 +  // Current installed version
    9.18 +  // Compare ranges for non-overlap
    9.19 +  julong lo0 = r0->_lo;
    9.20 +  julong hi0 = r0->_hi;
    9.21 +  julong lo1 = r1->_lo;
    9.22 +  julong hi1 = r1->_hi;
    9.23 +
    9.24 +  // If either one has both negative and positive values,
    9.25 +  // it therefore contains both 0 and -1, and since [0..-1] is the
    9.26 +  // full unsigned range, the type must act as an unsigned bottom.
    9.27 +  bool bot0 = ((jlong)(lo0 ^ hi0) < 0);
    9.28 +  bool bot1 = ((jlong)(lo1 ^ hi1) < 0);
    9.29 +
    9.30 +  if (bot0 || bot1) {
    9.31 +    // All unsigned values are LE -1 and GE 0.
    9.32 +    if (lo0 == 0 && hi0 == 0) {
    9.33 +      return TypeInt::CC_LE;            //   0 <= bot
    9.34 +    } else if ((jlong)lo0 == -1 && (jlong)hi0 == -1) {
    9.35 +      return TypeInt::CC_GE;            // -1 >= bot
    9.36 +    } else if (lo1 == 0 && hi1 == 0) {
    9.37 +      return TypeInt::CC_GE;            // bot >= 0
    9.38 +    } else if ((jlong)lo1 == -1 && (jlong)hi1 == -1) {
    9.39 +      return TypeInt::CC_LE;            // bot <= -1
    9.40 +    }
    9.41 +  } else {
    9.42 +    // We can use ranges of the form [lo..hi] if signs are the same.
    9.43 +    assert(lo0 <= hi0 && lo1 <= hi1, "unsigned ranges are valid");
    9.44 +    // results are reversed, '-' > '+' for unsigned compare
    9.45 +    if (hi0 < lo1) {
    9.46 +      return TypeInt::CC_LT;            // smaller
    9.47 +    } else if (lo0 > hi1) {
    9.48 +      return TypeInt::CC_GT;            // greater
    9.49 +    } else if (hi0 == lo1 && lo0 == hi1) {
    9.50 +      return TypeInt::CC_EQ;            // Equal results
    9.51 +    } else if (lo0 >= hi1) {
    9.52 +      return TypeInt::CC_GE;
    9.53 +    } else if (hi0 <= lo1) {
    9.54 +      return TypeInt::CC_LE;
    9.55 +    }
    9.56 +  }
    9.57 +
    9.58 +  return TypeInt::CC;                   // else use worst case results
    9.59 +}
    9.60 +
    9.61  //=============================================================================
    9.62  //------------------------------sub--------------------------------------------
    9.63  // Simplify an CmpP (compare 2 pointers) node, based on local information.
    10.1 --- a/src/share/vm/opto/subnode.hpp	Thu Feb 16 15:14:44 2017 -0800
    10.2 +++ b/src/share/vm/opto/subnode.hpp	Thu Mar 30 15:28:33 2017 +0200
    10.3 @@ -192,6 +192,15 @@
    10.4    virtual const Type *sub( const Type *, const Type * ) const;
    10.5  };
    10.6  
    10.7 +//------------------------------CmpULNode---------------------------------------
    10.8 +// Compare 2 unsigned long values, returning condition codes (-1, 0 or 1).
    10.9 +class CmpULNode : public CmpNode {
   10.10 +public:
   10.11 +  CmpULNode(Node* in1, Node* in2) : CmpNode(in1, in2) { }
   10.12 +  virtual int Opcode() const;
   10.13 +  virtual const Type* sub(const Type*, const Type*) const;
   10.14 +};
   10.15 +
   10.16  //------------------------------CmpL3Node--------------------------------------
   10.17  // Compare 2 long values, returning integer value (-1, 0 or 1).
   10.18  class CmpL3Node : public CmpLNode {
    11.1 --- a/src/share/vm/runtime/vmStructs.cpp	Thu Feb 16 15:14:44 2017 -0800
    11.2 +++ b/src/share/vm/runtime/vmStructs.cpp	Thu Mar 30 15:28:33 2017 +0200
    11.3 @@ -1942,6 +1942,7 @@
    11.4    declare_c2_type(CmpPNode, CmpNode)                                      \
    11.5    declare_c2_type(CmpNNode, CmpNode)                                      \
    11.6    declare_c2_type(CmpLNode, CmpNode)                                      \
    11.7 +  declare_c2_type(CmpULNode, CmpNode)                                     \
    11.8    declare_c2_type(CmpL3Node, CmpLNode)                                    \
    11.9    declare_c2_type(CmpFNode, CmpNode)                                      \
   11.10    declare_c2_type(CmpF3Node, CmpFNode)                                    \

mercurial