aboutsummaryrefslogtreecommitdiff
path: root/src/cpu
diff options
context:
space:
mode:
authorasaha <none@none>2017-06-20 14:52:27 -0700
committerasaha <none@none>2017-06-20 14:52:27 -0700
commit3424f46d86a71e05857328354f514c8d8a6d32df (patch)
tree58f8765edc749205f0004858f8157e2f69c40ad1 /src/cpu
parent8794c1a0cb3cdc310cf421ac25d46a8fba3e8392 (diff)
parent095ee276264e4ccab39ffd1386aa503d06b98535 (diff)
downloadjdk8u_hotspot-3424f46d86a71e05857328354f514c8d8a6d32df.tar.gz
Merge
Diffstat (limited to 'src/cpu')
-rw-r--r--src/cpu/ppc/vm/ppc.ad23
-rw-r--r--src/cpu/sparc/vm/sparc.ad134
-rw-r--r--src/cpu/x86/vm/x86_32.ad152
-rw-r--r--src/cpu/x86/vm/x86_64.ad42
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