Thu, 30 Mar 2017 15:28:33 +0200
8173770: Image conversion improvements
Reviewed-by: kvn, vlivanov, dlong, rhalade, mschoene, iignatyev
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) \