--- a/hotspot/src/cpu/sparc/vm/sparc.ad Wed Aug 10 14:06:57 2011 -0700
+++ b/hotspot/src/cpu/sparc/vm/sparc.ad Thu Aug 11 12:08:11 2011 -0700
@@ -1834,8 +1834,10 @@
//
// NOTE: If the platform does not provide any short branch variants, then
// this method should return false for offset 0.
-bool Matcher::is_short_branch_offset(int rule, int offset) {
- return false;
+bool Matcher::is_short_branch_offset(int rule, int br_size, int offset) {
+ // The passed offset is relative to address of the branch.
+ // Don't need to adjust the offset.
+ return UseCBCond && Assembler::is_simm(offset, 12);
}
const bool Matcher::isSimpleConstant64(jlong value) {
@@ -3315,6 +3317,7 @@
//----------Instruction Attributes---------------------------------------------
ins_attrib ins_cost(DEFAULT_COST); // Required cost attribute
ins_attrib ins_size(32); // Required size attribute (in bits)
+ins_attrib ins_avoid_back_to_back(0); // instruction should not be generated back to back
ins_attrib ins_short_branch(0); // Required flag: is this instruction a
// non-matching short branch variant of some
// long branch?
@@ -3402,6 +3405,15 @@
interface(CONST_INTER);
%}
+// Integer Immediate: 5-bit
+operand immI5() %{
+ predicate(Assembler::is_simm(n->get_int(), 5));
+ match(ConI);
+ op_cost(0);
+ format %{ %}
+ interface(CONST_INTER);
+%}
+
// Integer Immediate: 0-bit
operand immI0() %{
predicate(n->get_int() == 0);
@@ -3625,6 +3637,15 @@
interface(CONST_INTER);
%}
+// Integer Immediate: 5-bit
+operand immL5() %{
+ predicate(n->get_long() == (int)n->get_long() && Assembler::is_simm((int)n->get_long(), 5));
+ match(ConL);
+ op_cost(0);
+ format %{ %}
+ interface(CONST_INTER);
+%}
+
// Long Immediate: 13-bit
operand immL13() %{
predicate((-4096L < n->get_long()) && (n->get_long() <= 4095L));
@@ -5157,6 +5178,42 @@
MS : R;
%}
+// Compare and branch
+pipe_class cmp_br_reg_reg(Universe br, cmpOp cmp, iRegI src1, iRegI src2, label labl, flagsReg cr) %{
+ instruction_count(2); has_delay_slot;
+ cr : E(write);
+ src1 : R(read);
+ src2 : R(read);
+ IALU : R;
+ BR : R;
+%}
+
+// Compare and branch
+pipe_class cmp_br_reg_imm(Universe br, cmpOp cmp, iRegI src1, immI13 src2, label labl, flagsReg cr) %{
+ instruction_count(2); has_delay_slot;
+ cr : E(write);
+ src1 : R(read);
+ IALU : R;
+ BR : R;
+%}
+
+// Compare and branch using cbcond
+pipe_class cbcond_reg_reg(Universe br, cmpOp cmp, iRegI src1, iRegI src2, label labl) %{
+ single_instruction;
+ src1 : E(read);
+ src2 : E(read);
+ IALU : R;
+ BR : R;
+%}
+
+// Compare and branch using cbcond
+pipe_class cbcond_reg_imm(Universe br, cmpOp cmp, iRegI src1, immI5 src2, label labl) %{
+ single_instruction;
+ src1 : E(read);
+ IALU : R;
+ BR : R;
+%}
+
pipe_class br_fcc(Universe br, cmpOpF cc, flagsReg cr, label labl) %{
single_instruction_with_delay_slot;
cr : E(read);
@@ -9198,6 +9255,25 @@
ins_pipe(br);
%}
+// Direct Branch, short with no delay slot
+instruct branch_short(label labl) %{
+ match(Goto);
+ predicate(UseCBCond);
+ effect(USE labl);
+
+ size(4);
+ ins_cost(BRANCH_COST);
+ format %{ "BA $labl\t! short branch" %}
+ ins_encode %{
+ Label* L = $labl$$label;
+ assert(__ use_cbcond(*L), "back to back cbcond");
+ __ ba_short(*L);
+ %}
+ ins_short_branch(1);
+ ins_avoid_back_to_back(1);
+ ins_pipe(cbcond_reg_imm);
+%}
+
// Conditional Direct Branch
instruct branchCon(cmpOp cmp, flagsReg icc, label labl) %{
match(If cmp icc);
@@ -9211,50 +9287,11 @@
ins_pipe(br_cc);
%}
-// Branch-on-register tests all 64 bits. We assume that values
-// in 64-bit registers always remains zero or sign extended
-// unless our code munges the high bits. Interrupts can chop
-// the high order bits to zero or sign at any time.
-instruct branchCon_regI(cmpOp_reg cmp, iRegI op1, immI0 zero, label labl) %{
- match(If cmp (CmpI op1 zero));
- predicate(can_branch_register(_kids[0]->_leaf, _kids[1]->_leaf));
- effect(USE labl);
-
- size(8);
- ins_cost(BRANCH_COST);
- format %{ "BR$cmp $op1,$labl" %}
- ins_encode( enc_bpr( labl, cmp, op1 ) );
- ins_pipe(br_reg);
-%}
-
-instruct branchCon_regP(cmpOp_reg cmp, iRegP op1, immP0 null, label labl) %{
- match(If cmp (CmpP op1 null));
- predicate(can_branch_register(_kids[0]->_leaf, _kids[1]->_leaf));
- effect(USE labl);
-
- size(8);
- ins_cost(BRANCH_COST);
- format %{ "BR$cmp $op1,$labl" %}
- ins_encode( enc_bpr( labl, cmp, op1 ) );
- ins_pipe(br_reg);
-%}
-
-instruct branchCon_regL(cmpOp_reg cmp, iRegL op1, immL0 zero, label labl) %{
- match(If cmp (CmpL op1 zero));
- predicate(can_branch_register(_kids[0]->_leaf, _kids[1]->_leaf));
- effect(USE labl);
-
- size(8);
- ins_cost(BRANCH_COST);
- format %{ "BR$cmp $op1,$labl" %}
- ins_encode( enc_bpr( labl, cmp, op1 ) );
- ins_pipe(br_reg);
-%}
-
instruct branchConU(cmpOpU cmp, flagsRegU icc, label labl) %{
match(If cmp icc);
effect(USE labl);
+ ins_cost(BRANCH_COST);
format %{ "BP$cmp $icc,$labl" %}
// Prim = bits 24-22, Secnd = bits 31-30
ins_encode( enc_bp( labl, cmp, icc ) );
@@ -9321,6 +9358,506 @@
ins_pipe(br_cc);
%}
+// Compare and branch instructions
+instruct cmpI_reg_branch(cmpOp cmp, iRegI op1, iRegI op2, label labl, flagsReg icc) %{
+ match(If cmp (CmpI op1 op2));
+ effect(USE labl, KILL icc);
+
+ size(12);
+ ins_cost(BRANCH_COST);
+ format %{ "CMP $op1,$op2\t! int\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::icc, predict_taken, *L);
+ __ delayed()->nop();
+ %}
+ ins_pipe(cmp_br_reg_reg);
+%}
+
+instruct cmpI_imm_branch(cmpOp cmp, iRegI op1, immI5 op2, label labl, flagsReg icc) %{
+ match(If cmp (CmpI op1 op2));
+ effect(USE labl, KILL icc);
+
+ size(12);
+ ins_cost(BRANCH_COST);
+ format %{ "CMP $op1,$op2\t! int\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::icc, predict_taken, *L);
+ __ delayed()->nop();
+ %}
+ ins_pipe(cmp_br_reg_imm);
+%}
+
+instruct cmpU_reg_branch(cmpOpU cmp, iRegI op1, iRegI op2, label labl, flagsRegU icc) %{
+ match(If cmp (CmpU op1 op2));
+ effect(USE labl, KILL icc);
+
+ size(12);
+ ins_cost(BRANCH_COST);
+ format %{ "CMP $op1,$op2\t! unsigned\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::icc, predict_taken, *L);
+ __ delayed()->nop();
+ %}
+ ins_pipe(cmp_br_reg_reg);
+%}
+
+instruct cmpU_imm_branch(cmpOpU cmp, iRegI op1, immI5 op2, label labl, flagsRegU icc) %{
+ match(If cmp (CmpU op1 op2));
+ effect(USE labl, KILL icc);
+
+ size(12);
+ ins_cost(BRANCH_COST);
+ format %{ "CMP $op1,$op2\t! unsigned\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::icc, 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);
+
+ size(12);
+ ins_cost(BRANCH_COST);
+ format %{ "CMP $op1,$op2\t! 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 cmpL_imm_branch(cmpOp cmp, iRegL op1, immL5 op2, label labl, flagsRegL xcc) %{
+ match(If cmp (CmpL op1 op2));
+ effect(USE labl, KILL xcc);
+
+ size(12);
+ ins_cost(BRANCH_COST);
+ format %{ "CMP $op1,$op2\t! 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);
+%}
+
+// Compare Pointers and branch
+instruct cmpP_reg_branch(cmpOpP cmp, iRegP op1, iRegP op2, label labl, flagsRegP pcc) %{
+ match(If cmp (CmpP op1 op2));
+ effect(USE labl, KILL pcc);
+
+ size(12);
+ ins_cost(BRANCH_COST);
+ format %{ "CMP $op1,$op2\t! ptr\n\t"
+ "B$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::ptr_cc, predict_taken, *L);
+ __ delayed()->nop();
+ %}
+ ins_pipe(cmp_br_reg_reg);
+%}
+
+instruct cmpP_null_branch(cmpOpP cmp, iRegP op1, immP0 null, label labl, flagsRegP pcc) %{
+ match(If cmp (CmpP op1 null));
+ effect(USE labl, KILL pcc);
+
+ size(12);
+ ins_cost(BRANCH_COST);
+ format %{ "CMP $op1,0\t! ptr\n\t"
+ "B$cmp $labl" %}
+ ins_encode %{
+ Label* L = $labl$$label;
+ Assembler::Predict predict_taken =
+ cbuf.is_backward_branch(*L) ? Assembler::pt : Assembler::pn;
+ __ cmp($op1$$Register, G0);
+ // bpr() is not used here since it has shorter distance.
+ __ bp((Assembler::Condition)($cmp$$cmpcode), false, Assembler::ptr_cc, predict_taken, *L);
+ __ delayed()->nop();
+ %}
+ ins_pipe(cmp_br_reg_reg);
+%}
+
+instruct cmpN_reg_branch(cmpOp cmp, iRegN op1, iRegN op2, label labl, flagsReg icc) %{
+ match(If cmp (CmpN op1 op2));
+ effect(USE labl, KILL icc);
+
+ size(12);
+ ins_cost(BRANCH_COST);
+ format %{ "CMP $op1,$op2\t! compressed ptr\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::icc, predict_taken, *L);
+ __ delayed()->nop();
+ %}
+ ins_pipe(cmp_br_reg_reg);
+%}
+
+instruct cmpN_null_branch(cmpOp cmp, iRegN op1, immN0 null, label labl, flagsReg icc) %{
+ match(If cmp (CmpN op1 null));
+ effect(USE labl, KILL icc);
+
+ size(12);
+ ins_cost(BRANCH_COST);
+ format %{ "CMP $op1,0\t! compressed ptr\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, G0);
+ __ bp((Assembler::Condition)($cmp$$cmpcode), false, Assembler::icc, predict_taken, *L);
+ __ delayed()->nop();
+ %}
+ ins_pipe(cmp_br_reg_reg);
+%}
+
+// Loop back branch
+instruct cmpI_reg_branchLoopEnd(cmpOp cmp, iRegI op1, iRegI op2, label labl, flagsReg icc) %{
+ match(CountedLoopEnd cmp (CmpI op1 op2));
+ effect(USE labl, KILL icc);
+
+ size(12);
+ ins_cost(BRANCH_COST);
+ format %{ "CMP $op1,$op2\t! int\n\t"
+ "BP$cmp $labl\t! Loop end" %}
+ 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::icc, predict_taken, *L);
+ __ delayed()->nop();
+ %}
+ ins_pipe(cmp_br_reg_reg);
+%}
+
+instruct cmpI_imm_branchLoopEnd(cmpOp cmp, iRegI op1, immI5 op2, label labl, flagsReg icc) %{
+ match(CountedLoopEnd cmp (CmpI op1 op2));
+ effect(USE labl, KILL icc);
+
+ size(12);
+ ins_cost(BRANCH_COST);
+ format %{ "CMP $op1,$op2\t! int\n\t"
+ "BP$cmp $labl\t! Loop end" %}
+ 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::icc, predict_taken, *L);
+ __ delayed()->nop();
+ %}
+ ins_pipe(cmp_br_reg_imm);
+%}
+
+// Short compare and branch instructions
+instruct cmpI_reg_branch_short(cmpOp cmp, iRegI op1, iRegI op2, label labl, flagsReg icc) %{
+ match(If cmp (CmpI op1 op2));
+ predicate(UseCBCond);
+ effect(USE labl, KILL icc);
+
+ size(4);
+ ins_cost(BRANCH_COST);
+ format %{ "CWB$cmp $op1,$op2,$labl\t! int" %}
+ ins_encode %{
+ Label* L = $labl$$label;
+ assert(__ use_cbcond(*L), "back to back cbcond");
+ __ cbcond((Assembler::Condition)($cmp$$cmpcode), Assembler::icc, $op1$$Register, $op2$$Register, *L);
+ %}
+ ins_short_branch(1);
+ ins_avoid_back_to_back(1);
+ ins_pipe(cbcond_reg_reg);
+%}
+
+instruct cmpI_imm_branch_short(cmpOp cmp, iRegI op1, immI5 op2, label labl, flagsReg icc) %{
+ match(If cmp (CmpI op1 op2));
+ predicate(UseCBCond);
+ effect(USE labl, KILL icc);
+
+ size(4);
+ ins_cost(BRANCH_COST);
+ format %{ "CWB$cmp $op1,$op2,$labl\t! int" %}
+ ins_encode %{
+ Label* L = $labl$$label;
+ assert(__ use_cbcond(*L), "back to back cbcond");
+ __ cbcond((Assembler::Condition)($cmp$$cmpcode), Assembler::icc, $op1$$Register, $op2$$constant, *L);
+ %}
+ ins_short_branch(1);
+ ins_avoid_back_to_back(1);
+ ins_pipe(cbcond_reg_imm);
+%}
+
+instruct cmpU_reg_branch_short(cmpOpU cmp, iRegI op1, iRegI op2, label labl, flagsRegU icc) %{
+ match(If cmp (CmpU op1 op2));
+ predicate(UseCBCond);
+ effect(USE labl, KILL icc);
+
+ size(4);
+ ins_cost(BRANCH_COST);
+ format %{ "CWB$cmp $op1,$op2,$labl\t! unsigned" %}
+ ins_encode %{
+ Label* L = $labl$$label;
+ assert(__ use_cbcond(*L), "back to back cbcond");
+ __ cbcond((Assembler::Condition)($cmp$$cmpcode), Assembler::icc, $op1$$Register, $op2$$Register, *L);
+ %}
+ ins_short_branch(1);
+ ins_avoid_back_to_back(1);
+ ins_pipe(cbcond_reg_reg);
+%}
+
+instruct cmpU_imm_branch_short(cmpOpU cmp, iRegI op1, immI5 op2, label labl, flagsRegU icc) %{
+ match(If cmp (CmpU op1 op2));
+ predicate(UseCBCond);
+ effect(USE labl, KILL icc);
+
+ size(4);
+ ins_cost(BRANCH_COST);
+ format %{ "CWB$cmp $op1,$op2,$labl\t! unsigned" %}
+ ins_encode %{
+ Label* L = $labl$$label;
+ assert(__ use_cbcond(*L), "back to back cbcond");
+ __ cbcond((Assembler::Condition)($cmp$$cmpcode), Assembler::icc, $op1$$Register, $op2$$constant, *L);
+ %}
+ ins_short_branch(1);
+ ins_avoid_back_to_back(1);
+ 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);
+ effect(USE labl, KILL xcc);
+
+ size(4);
+ ins_cost(BRANCH_COST);
+ format %{ "CXB$cmp $op1,$op2,$labl\t! 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(1);
+ ins_pipe(cbcond_reg_reg);
+%}
+
+instruct cmpL_imm_branch_short(cmpOp cmp, iRegL op1, immL5 op2, label labl, flagsRegL xcc) %{
+ match(If cmp (CmpL op1 op2));
+ predicate(UseCBCond);
+ effect(USE labl, KILL xcc);
+
+ size(4);
+ ins_cost(BRANCH_COST);
+ format %{ "CXB$cmp $op1,$op2,$labl\t! 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(1);
+ ins_pipe(cbcond_reg_imm);
+%}
+
+// Compare Pointers and branch
+instruct cmpP_reg_branch_short(cmpOpP cmp, iRegP op1, iRegP op2, label labl, flagsRegP pcc) %{
+ match(If cmp (CmpP op1 op2));
+ predicate(UseCBCond);
+ effect(USE labl, KILL pcc);
+
+ size(4);
+ ins_cost(BRANCH_COST);
+#ifdef _LP64
+ format %{ "CXB$cmp $op1,$op2,$labl\t! ptr" %}
+#else
+ format %{ "CWB$cmp $op1,$op2,$labl\t! ptr" %}
+#endif
+ ins_encode %{
+ Label* L = $labl$$label;
+ assert(__ use_cbcond(*L), "back to back cbcond");
+ __ cbcond((Assembler::Condition)($cmp$$cmpcode), Assembler::ptr_cc, $op1$$Register, $op2$$Register, *L);
+ %}
+ ins_short_branch(1);
+ ins_avoid_back_to_back(1);
+ ins_pipe(cbcond_reg_reg);
+%}
+
+instruct cmpP_null_branch_short(cmpOpP cmp, iRegP op1, immP0 null, label labl, flagsRegP pcc) %{
+ match(If cmp (CmpP op1 null));
+ predicate(UseCBCond);
+ effect(USE labl, KILL pcc);
+
+ size(4);
+ ins_cost(BRANCH_COST);
+#ifdef _LP64
+ format %{ "CXB$cmp $op1,0,$labl\t! ptr" %}
+#else
+ format %{ "CWB$cmp $op1,0,$labl\t! ptr" %}
+#endif
+ ins_encode %{
+ Label* L = $labl$$label;
+ assert(__ use_cbcond(*L), "back to back cbcond");
+ __ cbcond((Assembler::Condition)($cmp$$cmpcode), Assembler::ptr_cc, $op1$$Register, G0, *L);
+ %}
+ ins_short_branch(1);
+ ins_avoid_back_to_back(1);
+ ins_pipe(cbcond_reg_reg);
+%}
+
+instruct cmpN_reg_branch_short(cmpOp cmp, iRegN op1, iRegN op2, label labl, flagsReg icc) %{
+ match(If cmp (CmpN op1 op2));
+ predicate(UseCBCond);
+ effect(USE labl, KILL icc);
+
+ size(4);
+ ins_cost(BRANCH_COST);
+ format %{ "CWB$cmp $op1,op2,$labl\t! compressed ptr" %}
+ ins_encode %{
+ Label* L = $labl$$label;
+ assert(__ use_cbcond(*L), "back to back cbcond");
+ __ cbcond((Assembler::Condition)($cmp$$cmpcode), Assembler::icc, $op1$$Register, $op2$$Register, *L);
+ %}
+ ins_short_branch(1);
+ ins_avoid_back_to_back(1);
+ ins_pipe(cbcond_reg_reg);
+%}
+
+instruct cmpN_null_branch_short(cmpOp cmp, iRegN op1, immN0 null, label labl, flagsReg icc) %{
+ match(If cmp (CmpN op1 null));
+ predicate(UseCBCond);
+ effect(USE labl, KILL icc);
+
+ size(4);
+ ins_cost(BRANCH_COST);
+ format %{ "CWB$cmp $op1,0,$labl\t! compressed ptr" %}
+ ins_encode %{
+ Label* L = $labl$$label;
+ assert(__ use_cbcond(*L), "back to back cbcond");
+ __ cbcond((Assembler::Condition)($cmp$$cmpcode), Assembler::icc, $op1$$Register, G0, *L);
+ %}
+ ins_short_branch(1);
+ ins_avoid_back_to_back(1);
+ ins_pipe(cbcond_reg_reg);
+%}
+
+// Loop back branch
+instruct cmpI_reg_branchLoopEnd_short(cmpOp cmp, iRegI op1, iRegI op2, label labl, flagsReg icc) %{
+ match(CountedLoopEnd cmp (CmpI op1 op2));
+ predicate(UseCBCond);
+ effect(USE labl, KILL icc);
+
+ size(4);
+ ins_cost(BRANCH_COST);
+ format %{ "CWB$cmp $op1,$op2,$labl\t! Loop end" %}
+ ins_encode %{
+ Label* L = $labl$$label;
+ assert(__ use_cbcond(*L), "back to back cbcond");
+ __ cbcond((Assembler::Condition)($cmp$$cmpcode), Assembler::icc, $op1$$Register, $op2$$Register, *L);
+ %}
+ ins_short_branch(1);
+ ins_avoid_back_to_back(1);
+ ins_pipe(cbcond_reg_reg);
+%}
+
+instruct cmpI_imm_branchLoopEnd_short(cmpOp cmp, iRegI op1, immI5 op2, label labl, flagsReg icc) %{
+ match(CountedLoopEnd cmp (CmpI op1 op2));
+ predicate(UseCBCond);
+ effect(USE labl, KILL icc);
+
+ size(4);
+ ins_cost(BRANCH_COST);
+ format %{ "CWB$cmp $op1,$op2,$labl\t! Loop end" %}
+ ins_encode %{
+ Label* L = $labl$$label;
+ assert(__ use_cbcond(*L), "back to back cbcond");
+ __ cbcond((Assembler::Condition)($cmp$$cmpcode), Assembler::icc, $op1$$Register, $op2$$constant, *L);
+ %}
+ ins_short_branch(1);
+ ins_avoid_back_to_back(1);
+ ins_pipe(cbcond_reg_imm);
+%}
+
+// Branch-on-register tests all 64 bits. We assume that values
+// in 64-bit registers always remains zero or sign extended
+// unless our code munges the high bits. Interrupts can chop
+// the high order bits to zero or sign at any time.
+instruct branchCon_regI(cmpOp_reg cmp, iRegI op1, immI0 zero, label labl) %{
+ match(If cmp (CmpI op1 zero));
+ predicate(can_branch_register(_kids[0]->_leaf, _kids[1]->_leaf));
+ effect(USE labl);
+
+ size(8);
+ ins_cost(BRANCH_COST);
+ format %{ "BR$cmp $op1,$labl" %}
+ ins_encode( enc_bpr( labl, cmp, op1 ) );
+ ins_pipe(br_reg);
+%}
+
+instruct branchCon_regP(cmpOp_reg cmp, iRegP op1, immP0 null, label labl) %{
+ match(If cmp (CmpP op1 null));
+ predicate(can_branch_register(_kids[0]->_leaf, _kids[1]->_leaf));
+ effect(USE labl);
+
+ size(8);
+ ins_cost(BRANCH_COST);
+ format %{ "BR$cmp $op1,$labl" %}
+ ins_encode( enc_bpr( labl, cmp, op1 ) );
+ ins_pipe(br_reg);
+%}
+
+instruct branchCon_regL(cmpOp_reg cmp, iRegL op1, immL0 zero, label labl) %{
+ match(If cmp (CmpL op1 zero));
+ predicate(can_branch_register(_kids[0]->_leaf, _kids[1]->_leaf));
+ effect(USE labl);
+
+ size(8);
+ ins_cost(BRANCH_COST);
+ format %{ "BR$cmp $op1,$labl" %}
+ ins_encode( enc_bpr( labl, cmp, op1 ) );
+ ins_pipe(br_reg);
+%}
+
+
// ============================================================================
// Long Compare
//