diff options
author | asaha <none@none> | 2017-06-20 14:52:27 -0700 |
---|---|---|
committer | asaha <none@none> | 2017-06-20 14:52:27 -0700 |
commit | 3424f46d86a71e05857328354f514c8d8a6d32df (patch) | |
tree | 58f8765edc749205f0004858f8157e2f69c40ad1 /src/cpu | |
parent | 8794c1a0cb3cdc310cf421ac25d46a8fba3e8392 (diff) | |
parent | 095ee276264e4ccab39ffd1386aa503d06b98535 (diff) | |
download | jdk8u_hotspot-3424f46d86a71e05857328354f514c8d8a6d32df.tar.gz |
Merge
Diffstat (limited to 'src/cpu')
-rw-r--r-- | src/cpu/ppc/vm/ppc.ad | 23 | ||||
-rw-r--r-- | src/cpu/sparc/vm/sparc.ad | 134 | ||||
-rw-r--r-- | src/cpu/x86/vm/x86_32.ad | 152 | ||||
-rw-r--r-- | src/cpu/x86/vm/x86_64.ad | 42 |
4 files changed, 350 insertions, 1 deletions
diff --git a/src/cpu/ppc/vm/ppc.ad b/src/cpu/ppc/vm/ppc.ad index 54c236101..c3a64d338 100644 --- a/src/cpu/ppc/vm/ppc.ad +++ b/src/cpu/ppc/vm/ppc.ad @@ -10230,6 +10230,29 @@ instruct cmpL_reg_imm16(flagsReg crx, iRegLsrc src1, immL16 src2) %{ ins_pipe(pipe_class_compare); %} +// Added CmpUL for LoopPredicate. +instruct cmpUL_reg_reg(flagsReg crx, iRegLsrc src1, iRegLsrc src2) %{ + match(Set crx (CmpUL src1 src2)); + format %{ "CMPLD $crx, $src1, $src2" %} + size(4); + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_cmpl); + __ cmpld($crx$$CondRegister, $src1$$Register, $src2$$Register); + %} + ins_pipe(pipe_class_compare); +%} + +instruct cmpUL_reg_imm16(flagsReg crx, iRegLsrc src1, uimmL16 src2) %{ + match(Set crx (CmpUL src1 src2)); + format %{ "CMPLDI $crx, $src1, $src2" %} + size(4); + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_cmpli); + __ cmpldi($crx$$CondRegister, $src1$$Register, $src2$$constant); + %} + ins_pipe(pipe_class_compare); +%} + instruct testL_reg_reg(flagsRegCR0 cr0, iRegLsrc src1, iRegLsrc src2, immL_0 zero) %{ match(Set cr0 (CmpL (AndL src1 src2) zero)); // r0 is killed diff --git a/src/cpu/sparc/vm/sparc.ad b/src/cpu/sparc/vm/sparc.ad index 0b46f32f5..112ffe62c 100644 --- a/src/cpu/sparc/vm/sparc.ad +++ b/src/cpu/sparc/vm/sparc.ad @@ -3458,6 +3458,16 @@ operand immI5() %{ interface(CONST_INTER); %} +// Unsigned Long Immediate: 12-bit (non-negative that fits in simm13) +operand immUL12() %{ + predicate((0 <= n->get_long()) && (n->get_long() == (int)n->get_long()) && Assembler::is_simm13((int)n->get_long())); + match(ConL); + op_cost(0); + + format %{ %} + interface(CONST_INTER); +%} + // Int Immediate non-negative operand immU31() %{ @@ -4083,6 +4093,15 @@ operand flagsRegL() %{ interface(REG_INTER); %} +// Condition Code Register, unsigned long comparisons. +operand flagsRegUL() %{ + constraint(ALLOC_IN_RC(int_flags)); + match(RegFlags); + + format %{ "xcc_UL" %} + interface(REG_INTER); +%} + // Condition Code Register, floating comparisons, unordered same as "less". operand flagsRegF() %{ constraint(ALLOC_IN_RC(float_flags)); @@ -8962,6 +8981,17 @@ instruct compU_iReg(flagsRegU icc, iRegI op1, iRegI op2) %{ ins_pipe(ialu_cconly_reg_reg); %} +instruct compUL_iReg(flagsRegUL xcc, iRegL op1, iRegL op2) %{ + match(Set xcc (CmpUL op1 op2)); + effect(DEF xcc, USE op1, USE op2); + + size(4); + format %{ "CMP $op1,$op2\t! unsigned long" %} + opcode(Assembler::subcc_op3, Assembler::arith_op); + ins_encode(form3_rs1_rs2_rd(op1, op2, R_G0)); + ins_pipe(ialu_cconly_reg_reg); +%} + instruct compI_iReg_imm13(flagsReg icc, iRegI op1, immI13 op2) %{ match(Set icc (CmpI op1 op2)); effect( DEF icc, USE op1 ); @@ -9048,6 +9078,17 @@ instruct compU_iReg_imm13(flagsRegU icc, iRegI op1, immU12 op2 ) %{ ins_pipe(ialu_cconly_reg_imm); %} +instruct compUL_iReg_imm13(flagsRegUL xcc, iRegL op1, immUL12 op2) %{ + match(Set xcc (CmpUL op1 op2)); + effect(DEF xcc, USE op1, USE op2); + + size(4); + format %{ "CMP $op1,$op2\t! unsigned long" %} + opcode(Assembler::subcc_op3, Assembler::arith_op); + ins_encode(form3_rs1_simm13_rd(op1, op2, R_G0)); + ins_pipe(ialu_cconly_reg_imm); +%} + // Compare Pointers instruct compP_iRegP(flagsRegP pcc, iRegP op1, iRegP op2 ) %{ match(Set pcc (CmpP op1 op2)); @@ -9421,6 +9462,44 @@ instruct cmpU_imm_branch(cmpOpU cmp, iRegI op1, immI5 op2, label labl, flagsRegU ins_pipe(cmp_br_reg_imm); %} +instruct cmpUL_reg_branch(cmpOpU cmp, iRegL op1, iRegL op2, label labl, flagsRegUL xcc) %{ + match(If cmp (CmpUL op1 op2)); + effect(USE labl, KILL xcc); + + size(12); + ins_cost(BRANCH_COST); + format %{ "CMP $op1,$op2\t! unsigned long\n\t" + "BP$cmp $labl" %} + ins_encode %{ + Label* L = $labl$$label; + Assembler::Predict predict_taken = + cbuf.is_backward_branch(*L) ? Assembler::pt : Assembler::pn; + __ cmp($op1$$Register, $op2$$Register); + __ bp((Assembler::Condition)($cmp$$cmpcode), false, Assembler::xcc, predict_taken, *L); + __ delayed()->nop(); + %} + ins_pipe(cmp_br_reg_reg); +%} + +instruct cmpUL_imm_branch(cmpOpU cmp, iRegL op1, immL5 op2, label labl, flagsRegUL xcc) %{ + match(If cmp (CmpUL op1 op2)); + effect(USE labl, KILL xcc); + + size(12); + ins_cost(BRANCH_COST); + format %{ "CMP $op1,$op2\t! unsigned long\n\t" + "BP$cmp $labl" %} + ins_encode %{ + Label* L = $labl$$label; + Assembler::Predict predict_taken = + cbuf.is_backward_branch(*L) ? Assembler::pt : Assembler::pn; + __ cmp($op1$$Register, $op2$$constant); + __ bp((Assembler::Condition)($cmp$$cmpcode), false, Assembler::xcc, predict_taken, *L); + __ delayed()->nop(); + %} + ins_pipe(cmp_br_reg_imm); +%} + instruct cmpL_reg_branch(cmpOp cmp, iRegL op1, iRegL op2, label labl, flagsRegL xcc) %{ match(If cmp (CmpL op1 op2)); effect(USE labl, KILL xcc); @@ -9649,6 +9728,42 @@ instruct cmpU_imm_branch_short(cmpOpU cmp, iRegI op1, immI5 op2, label labl, fla ins_pipe(cbcond_reg_imm); %} +instruct cmpUL_reg_branch_short(cmpOpU cmp, iRegL op1, iRegL op2, label labl, flagsRegUL xcc) %{ + match(If cmp (CmpUL op1 op2)); + predicate(UseCBCond); + effect(USE labl, KILL xcc); + + size(4); + ins_cost(BRANCH_COST); + format %{ "CXB$cmp $op1,$op2,$labl\t! unsigned long" %} + ins_encode %{ + Label* L = $labl$$label; + assert(__ use_cbcond(*L), "back to back cbcond"); + __ cbcond((Assembler::Condition)($cmp$$cmpcode), Assembler::xcc, $op1$$Register, $op2$$Register, *L); + %} + ins_short_branch(1); + ins_avoid_back_to_back(AVOID_BEFORE_AND_AFTER); + ins_pipe(cbcond_reg_reg); +%} + +instruct cmpUL_imm_branch_short(cmpOpU cmp, iRegL op1, immL5 op2, label labl, flagsRegUL xcc) %{ + match(If cmp (CmpUL op1 op2)); + predicate(UseCBCond); + effect(USE labl, KILL xcc); + + size(4); + ins_cost(BRANCH_COST); + format %{ "CXB$cmp $op1,$op2,$labl\t! unsigned long" %} + ins_encode %{ + Label* L = $labl$$label; + assert(__ use_cbcond(*L), "back to back cbcond"); + __ cbcond((Assembler::Condition)($cmp$$cmpcode), Assembler::xcc, $op1$$Register, $op2$$constant, *L); + %} + ins_short_branch(1); + ins_avoid_back_to_back(AVOID_BEFORE_AND_AFTER); + ins_pipe(cbcond_reg_imm); +%} + instruct cmpL_reg_branch_short(cmpOp cmp, iRegL op1, iRegL op2, label labl, flagsRegL xcc) %{ match(If cmp (CmpL op1 op2)); predicate(UseCBCond); @@ -9887,6 +10002,25 @@ instruct branchCon_long(cmpOp cmp, flagsRegL xcc, label labl) %{ ins_pipe(br_cc); %} +instruct branchConU_long(cmpOpU cmp, flagsRegUL xcc, label labl) %{ + match(If cmp xcc); + effect(USE labl); + + size(8); + ins_cost(BRANCH_COST); + format %{ "BP$cmp $xcc,$labl" %} + ins_encode %{ + Label* L = $labl$$label; + Assembler::Predict predict_taken = + cbuf.is_backward_branch(*L) ? Assembler::pt : Assembler::pn; + + __ bp((Assembler::Condition)($cmp$$cmpcode), false, Assembler::xcc, predict_taken, *L); + __ delayed()->nop(); + %} + ins_avoid_back_to_back(AVOID_BEFORE); + ins_pipe(br_cc); +%} + // Manifest a CmpL3 result in an integer register. Very painful. // This is the test to avoid. instruct cmpL3_reg_reg(iRegI dst, iRegL src1, iRegL src2, flagsReg ccr ) %{ diff --git a/src/cpu/x86/vm/x86_32.ad b/src/cpu/x86/vm/x86_32.ad index 512ec2029..f42d1a288 100644 --- a/src/cpu/x86/vm/x86_32.ad +++ b/src/cpu/x86/vm/x86_32.ad @@ -3948,6 +3948,26 @@ operand flagsReg_long_LEGT() %{ interface(REG_INTER); %} +// Condition Code Register used by unsigned long compare +operand flagsReg_ulong_LTGE() %{ + constraint(ALLOC_IN_RC(int_flags)); + match(RegFlags); + format %{ "FLAGS_U_LTGE" %} + interface(REG_INTER); +%} +operand flagsReg_ulong_EQNE() %{ + constraint(ALLOC_IN_RC(int_flags)); + match(RegFlags); + format %{ "FLAGS_U_EQNE" %} + interface(REG_INTER); +%} +operand flagsReg_ulong_LEGT() %{ + constraint(ALLOC_IN_RC(int_flags)); + match(RegFlags); + format %{ "FLAGS_U_LEGT" %} + interface(REG_INTER); +%} + // Float register operands operand regDPR() %{ predicate( UseSSE < 2 ); @@ -4473,7 +4493,7 @@ operand cmpOp_fcmov() %{ %} %} -// Comparision Code used in long compares +// Comparison Code used in long compares operand cmpOp_commute() %{ match(Bool); @@ -4490,6 +4510,23 @@ operand cmpOp_commute() %{ %} %} +// Comparison Code used in unsigned long compares +operand cmpOpU_commute() %{ + match(Bool); + + format %{ "" %} + interface(COND_INTER) %{ + equal(0x4, "e"); + not_equal(0x5, "ne"); + less(0x7, "nbe"); + greater_equal(0x6, "be"); + less_equal(0x3, "nb"); + greater(0x2, "b"); + overflow(0x0, "o"); + no_overflow(0x1, "no"); + %} +%} + //----------OPERAND CLASSES---------------------------------------------------- // Operand Classes are groups of operands that are used as to simplify // instruction definitions by not requiring the AD writer to specify separate @@ -12382,6 +12419,44 @@ instruct cmpL_LTGE(cmpOp cmp, flagsReg_long_LTGE flags, label labl) %{ %} %} +//====== +// Manifest a CmpUL result in the normal flags. Only good for LT or GE +// compares. Can be used for LE or GT compares by reversing arguments. +// NOT GOOD FOR EQ/NE tests. +instruct cmpUL_zero_flags_LTGE(flagsReg_ulong_LTGE flags, eRegL src, immL0 zero) %{ + match(Set flags (CmpUL src zero)); + ins_cost(100); + format %{ "TEST $src.hi,$src.hi" %} + opcode(0x85); + ins_encode(OpcP, RegReg_Hi2(src, src)); + ins_pipe(ialu_cr_reg_reg); +%} + +// Manifest a CmpUL result in the normal flags. Only good for LT or GE +// compares. Can be used for LE or GT compares by reversing arguments. +// NOT GOOD FOR EQ/NE tests. +instruct cmpUL_reg_flags_LTGE(flagsReg_ulong_LTGE flags, eRegL src1, eRegL src2, rRegI tmp) %{ + match(Set flags (CmpUL src1 src2)); + effect(TEMP tmp); + ins_cost(300); + format %{ "CMP $src1.lo,$src2.lo\t! Unsigned long compare; set flags for low bits\n\t" + "MOV $tmp,$src1.hi\n\t" + "SBB $tmp,$src2.hi\t! Compute flags for unsigned long compare" %} + ins_encode(long_cmp_flags2(src1, src2, tmp)); + ins_pipe(ialu_cr_reg_reg); +%} + +// Unsigned long compares reg < zero/req OR reg >= zero/req. +// Just a wrapper for a normal branch, plus the predicate test. +instruct cmpUL_LTGE(cmpOpU cmp, flagsReg_ulong_LTGE flags, label labl) %{ + match(If cmp flags); + effect(USE labl); + predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::lt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ge); + expand %{ + jmpCon(cmp, flags, labl); // JLT or JGE... + %} +%} + // Compare 2 longs and CMOVE longs. instruct cmovLL_reg_LTGE(cmpOp cmp, flagsReg_long_LTGE flags, eRegL dst, eRegL src) %{ match(Set dst (CMoveL (Binary cmp flags) (Binary dst src))); @@ -12510,6 +12585,41 @@ instruct cmpL_EQNE(cmpOp cmp, flagsReg_long_EQNE flags, label labl) %{ %} %} +//====== +// Manifest a CmpUL result in the normal flags. Only good for EQ/NE compares. +instruct cmpUL_zero_flags_EQNE(flagsReg_ulong_EQNE flags, eRegL src, immL0 zero, rRegI tmp) %{ + match(Set flags (CmpUL src zero)); + effect(TEMP tmp); + ins_cost(200); + format %{ "MOV $tmp,$src.lo\n\t" + "OR $tmp,$src.hi\t! Unsigned long is EQ/NE 0?" %} + ins_encode(long_cmp_flags0(src, tmp)); + ins_pipe(ialu_reg_reg_long); +%} + +// Manifest a CmpUL result in the normal flags. Only good for EQ/NE compares. +instruct cmpUL_reg_flags_EQNE(flagsReg_ulong_EQNE flags, eRegL src1, eRegL src2) %{ + match(Set flags (CmpUL src1 src2)); + ins_cost(200+300); + format %{ "CMP $src1.lo,$src2.lo\t! Unsigned long compare; set flags for low bits\n\t" + "JNE,s skip\n\t" + "CMP $src1.hi,$src2.hi\n\t" + "skip:\t" %} + ins_encode(long_cmp_flags1(src1, src2)); + ins_pipe(ialu_cr_reg_reg); +%} + +// Unsigned long compare reg == zero/reg OR reg != zero/reg +// Just a wrapper for a normal branch, plus the predicate test. +instruct cmpUL_EQNE(cmpOpU cmp, flagsReg_ulong_EQNE flags, label labl) %{ + match(If cmp flags); + effect(USE labl); + predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::eq || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne); + expand %{ + jmpCon(cmp, flags, labl); // JEQ or JNE... + %} +%} + // Compare 2 longs and CMOVE longs. instruct cmovLL_reg_EQNE(cmpOp cmp, flagsReg_long_EQNE flags, eRegL dst, eRegL src) %{ match(Set dst (CMoveL (Binary cmp flags) (Binary dst src))); @@ -12643,6 +12753,46 @@ instruct cmpL_LEGT(cmpOp_commute cmp, flagsReg_long_LEGT flags, label labl) %{ %} %} +//====== +// Manifest a CmpUL result in the normal flags. Only good for LE or GT compares. +// Same as cmpUL_reg_flags_LEGT except must negate src +instruct cmpUL_zero_flags_LEGT(flagsReg_ulong_LEGT flags, eRegL src, immL0 zero, rRegI tmp) %{ + match(Set flags (CmpUL src zero)); + effect(TEMP tmp); + ins_cost(300); + format %{ "XOR $tmp,$tmp\t# Unsigned long compare for -$src < 0, use commuted test\n\t" + "CMP $tmp,$src.lo\n\t" + "SBB $tmp,$src.hi\n\t" %} + ins_encode(long_cmp_flags3(src, tmp)); + ins_pipe(ialu_reg_reg_long); +%} + +// Manifest a CmpUL result in the normal flags. Only good for LE or GT compares. +// Same as cmpUL_reg_flags_LTGE except operands swapped. Swapping operands +// requires a commuted test to get the same result. +instruct cmpUL_reg_flags_LEGT(flagsReg_ulong_LEGT flags, eRegL src1, eRegL src2, rRegI tmp) %{ + match(Set flags (CmpUL src1 src2)); + effect(TEMP tmp); + ins_cost(300); + format %{ "CMP $src2.lo,$src1.lo\t! Unsigned long compare, swapped operands, use with commuted test\n\t" + "MOV $tmp,$src2.hi\n\t" + "SBB $tmp,$src1.hi\t! Compute flags for unsigned long compare" %} + ins_encode(long_cmp_flags2( src2, src1, tmp)); + ins_pipe(ialu_cr_reg_reg); +%} + +// Unsigned long compares reg < zero/req OR reg >= zero/req. +// Just a wrapper for a normal branch, plus the predicate test +instruct cmpUL_LEGT(cmpOpU_commute cmp, flagsReg_ulong_LEGT flags, label labl) %{ + match(If cmp flags); + effect(USE labl); + predicate(_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::gt || _kids[0]->_leaf->as_Bool()->_test._test == BoolTest::le); + ins_cost(300); + expand %{ + jmpCon(cmp, flags, labl); // JGT or JLE... + %} +%} + // Compare 2 longs and CMOVE longs. instruct cmovLL_reg_LEGT(cmpOp_commute cmp, flagsReg_long_LEGT flags, eRegL dst, eRegL src) %{ match(Set dst (CMoveL (Binary cmp flags) (Binary dst src))); diff --git a/src/cpu/x86/vm/x86_64.ad b/src/cpu/x86/vm/x86_64.ad index ed304df26..e20b02d2b 100644 --- a/src/cpu/x86/vm/x86_64.ad +++ b/src/cpu/x86/vm/x86_64.ad @@ -11068,6 +11068,48 @@ instruct cmpL3_reg_reg(rRegI dst, rRegL src1, rRegL src2, rFlagsReg flags) ins_pipe(pipe_slow); %} +// Unsigned long compare Instructions; really, same as signed long except they +// produce an rFlagsRegU instead of rFlagsReg. +instruct compUL_rReg(rFlagsRegU cr, rRegL op1, rRegL op2) +%{ + match(Set cr (CmpUL op1 op2)); + + format %{ "cmpq $op1, $op2\t# unsigned" %} + opcode(0x3B); /* Opcode 3B /r */ + ins_encode(REX_reg_reg_wide(op1, op2), OpcP, reg_reg(op1, op2)); + ins_pipe(ialu_cr_reg_reg); +%} + +instruct compUL_rReg_imm(rFlagsRegU cr, rRegL op1, immL32 op2) +%{ + match(Set cr (CmpUL op1 op2)); + + format %{ "cmpq $op1, $op2\t# unsigned" %} + opcode(0x81, 0x07); /* Opcode 81 /7 */ + ins_encode(OpcSErm_wide(op1, op2), Con8or32(op2)); + ins_pipe(ialu_cr_reg_imm); +%} + +instruct compUL_rReg_mem(rFlagsRegU cr, rRegL op1, memory op2) +%{ + match(Set cr (CmpUL op1 (LoadL op2))); + + format %{ "cmpq $op1, $op2\t# unsigned" %} + opcode(0x3B); /* Opcode 3B /r */ + ins_encode(REX_reg_mem_wide(op1, op2), OpcP, reg_mem(op1, op2)); + ins_pipe(ialu_cr_reg_mem); +%} + +instruct testUL_reg(rFlagsRegU cr, rRegL src, immL0 zero) +%{ + match(Set cr (CmpUL src zero)); + + format %{ "testq $src, $src\t# unsigned" %} + opcode(0x85); + ins_encode(REX_reg_reg_wide(src, src), OpcP, reg_reg(src, src)); + ins_pipe(ialu_cr_reg_imm); +%} + //----------Max and Min-------------------------------------------------------- // Min Instructions |