--- a/hotspot/src/cpu/aarch64/vm/aarch64.ad Tue Jul 05 17:57:20 2016 -0700
+++ b/hotspot/src/cpu/aarch64/vm/aarch64.ad Thu Jul 07 15:07:13 2016 +0100
@@ -1942,11 +1942,34 @@
bool is_CAS(int opcode)
{
- return (opcode == Op_CompareAndSwapI ||
- opcode == Op_CompareAndSwapL ||
- opcode == Op_CompareAndSwapN ||
- opcode == Op_CompareAndSwapP);
- }
+ switch(opcode) {
+ // We handle these
+ case Op_CompareAndSwapI:
+ case Op_CompareAndSwapL:
+ case Op_CompareAndSwapP:
+ case Op_CompareAndSwapN:
+ // case Op_CompareAndSwapB:
+ // case Op_CompareAndSwapS:
+ return true;
+ // These are TBD
+ case Op_WeakCompareAndSwapB:
+ case Op_WeakCompareAndSwapS:
+ case Op_WeakCompareAndSwapI:
+ case Op_WeakCompareAndSwapL:
+ case Op_WeakCompareAndSwapP:
+ case Op_WeakCompareAndSwapN:
+ case Op_CompareAndExchangeB:
+ case Op_CompareAndExchangeS:
+ case Op_CompareAndExchangeI:
+ case Op_CompareAndExchangeL:
+ case Op_CompareAndExchangeP:
+ case Op_CompareAndExchangeN:
+ return false;
+ default:
+ return false;
+ }
+ }
+
// leading_to_trailing
//
@@ -4238,14 +4261,16 @@
MacroAssembler _masm(&cbuf);
guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
__ cmpxchg($mem$$base$$Register, $oldval$$Register, $newval$$Register,
- Assembler::xword, /*acquire*/ false, /*release*/ true);
+ Assembler::xword, /*acquire*/ false, /*release*/ true,
+ /*weak*/ false, noreg);
%}
enc_class aarch64_enc_cmpxchgw(memory mem, iRegINoSp oldval, iRegINoSp newval) %{
MacroAssembler _masm(&cbuf);
guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
__ cmpxchg($mem$$base$$Register, $oldval$$Register, $newval$$Register,
- Assembler::word, /*acquire*/ false, /*release*/ true);
+ Assembler::word, /*acquire*/ false, /*release*/ true,
+ /*weak*/ false, noreg);
%}
@@ -4257,14 +4282,16 @@
MacroAssembler _masm(&cbuf);
guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
__ cmpxchg($mem$$base$$Register, $oldval$$Register, $newval$$Register,
- Assembler::xword, /*acquire*/ true, /*release*/ true);
+ Assembler::xword, /*acquire*/ true, /*release*/ true,
+ /*weak*/ false, noreg);
%}
enc_class aarch64_enc_cmpxchgw_acq(memory mem, iRegINoSp oldval, iRegINoSp newval) %{
MacroAssembler _masm(&cbuf);
guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding");
__ cmpxchg($mem$$base$$Register, $oldval$$Register, $newval$$Register,
- Assembler::word, /*acquire*/ true, /*release*/ true);
+ Assembler::word, /*acquire*/ true, /*release*/ true,
+ /*weak*/ false, noreg);
%}
@@ -5803,6 +5830,7 @@
%{
constraint(ALLOC_IN_RC(no_special_reg));
match(RegL);
+ match(iRegL_R0);
format %{ %}
interface(REG_INTER);
%}
@@ -5924,6 +5952,39 @@
interface(REG_INTER);
%}
+// Long 64 bit Register R0 only
+operand iRegL_R0()
+%{
+ constraint(ALLOC_IN_RC(r0_reg));
+ match(RegL);
+ match(iRegLNoSp);
+ op_cost(0);
+ format %{ %}
+ interface(REG_INTER);
+%}
+
+// Long 64 bit Register R2 only
+operand iRegL_R2()
+%{
+ constraint(ALLOC_IN_RC(r2_reg));
+ match(RegL);
+ match(iRegLNoSp);
+ op_cost(0);
+ format %{ %}
+ interface(REG_INTER);
+%}
+
+// Long 64 bit Register R3 only
+operand iRegL_R3()
+%{
+ constraint(ALLOC_IN_RC(r3_reg));
+ match(RegL);
+ match(iRegLNoSp);
+ op_cost(0);
+ format %{ %}
+ interface(REG_INTER);
+%}
+
// Long 64 bit Register R11 only
operand iRegL_R11()
%{
@@ -5980,7 +6041,7 @@
%}
-// Register R2 only
+// Register R4 only
operand iRegI_R4()
%{
constraint(ALLOC_IN_RC(int_r4_reg));
@@ -6004,6 +6065,33 @@
interface(REG_INTER);
%}
+operand iRegN_R0()
+%{
+ constraint(ALLOC_IN_RC(r0_reg));
+ match(iRegN);
+ op_cost(0);
+ format %{ %}
+ interface(REG_INTER);
+%}
+
+operand iRegN_R2()
+%{
+ constraint(ALLOC_IN_RC(r2_reg));
+ match(iRegN);
+ op_cost(0);
+ format %{ %}
+ interface(REG_INTER);
+%}
+
+operand iRegN_R3()
+%{
+ constraint(ALLOC_IN_RC(r3_reg));
+ match(iRegN);
+ op_cost(0);
+ format %{ %}
+ interface(REG_INTER);
+%}
+
// Integer 64 bit Register not Special
operand iRegNNoSp()
%{
@@ -9390,12 +9478,12 @@
ins_pipe(pipe_slow);
%}
+// standard CompareAndSwapX when we are using barriers
+// these have higher priority than the rules selected by a predicate
+
// XXX No flag versions for CompareAndSwap{I,L,P,N} because matcher
// can't match them
-// standard CompareAndSwapX when we are using barriers
-// these have higher priority than the rules selected by a predicate
-
instruct compareAndSwapI(iRegINoSp res, indirect mem, iRegINoSp oldval, iRegINoSp newval, rFlagsReg cr) %{
match(Set res (CompareAndSwapI mem (Binary oldval newval)));
@@ -9547,6 +9635,216 @@
%}
+// ---------------------------------------------------------------------
+// Sundry CAS operations. Note that release is always true,
+// regardless of the memory ordering of the CAS. This is because we
+// need the volatile case to be sequentially consistent but there is
+// no trailing StoreLoad barrier emitted by C2. Unfortunately we
+// can't check the type of memory ordering here, so we always emit a
+// STLXR.
+
+// This section is generated from aarch64_ad_cas.m4
+
+
+instruct compareAndExchangeB(iRegI_R0 res, indirect mem, iRegI_R2 oldval, iRegI_R3 newval, rFlagsReg cr) %{
+ match(Set res (CompareAndExchangeB mem (Binary oldval newval)));
+ ins_cost(2 * VOLATILE_REF_COST);
+ effect(KILL cr);
+ format %{
+ "cmpxchg $res = $mem, $oldval, $newval\t# (byte, weak) if $mem == $oldval then $mem <-- $newval"
+ %}
+ ins_encode %{
+ __ uxtbw(rscratch2, $oldval$$Register);
+ __ cmpxchg($mem$$Register, rscratch2, $newval$$Register,
+ Assembler::byte, /*acquire*/ false, /*release*/ true,
+ /*weak*/ false, $res$$Register);
+ __ sxtbw($res$$Register, $res$$Register);
+ %}
+ ins_pipe(pipe_slow);
+%}
+
+instruct compareAndExchangeS(iRegI_R0 res, indirect mem, iRegI_R2 oldval, iRegI_R3 newval, rFlagsReg cr) %{
+ match(Set res (CompareAndExchangeS mem (Binary oldval newval)));
+ ins_cost(2 * VOLATILE_REF_COST);
+ effect(KILL cr);
+ format %{
+ "cmpxchg $res = $mem, $oldval, $newval\t# (short, weak) if $mem == $oldval then $mem <-- $newval"
+ %}
+ ins_encode %{
+ __ uxthw(rscratch2, $oldval$$Register);
+ __ cmpxchg($mem$$Register, rscratch2, $newval$$Register,
+ Assembler::halfword, /*acquire*/ false, /*release*/ true,
+ /*weak*/ false, $res$$Register);
+ __ sxthw($res$$Register, $res$$Register);
+ %}
+ ins_pipe(pipe_slow);
+%}
+
+instruct compareAndExchangeI(iRegI_R0 res, indirect mem, iRegI_R2 oldval, iRegI_R3 newval, rFlagsReg cr) %{
+ match(Set res (CompareAndExchangeI mem (Binary oldval newval)));
+ ins_cost(2 * VOLATILE_REF_COST);
+ effect(KILL cr);
+ format %{
+ "cmpxchg $res = $mem, $oldval, $newval\t# (int, weak) if $mem == $oldval then $mem <-- $newval"
+ %}
+ ins_encode %{
+ __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
+ Assembler::word, /*acquire*/ false, /*release*/ true,
+ /*weak*/ false, $res$$Register);
+ %}
+ ins_pipe(pipe_slow);
+%}
+
+instruct compareAndExchangeL(iRegL_R0 res, indirect mem, iRegL_R2 oldval, iRegL_R3 newval, rFlagsReg cr) %{
+ match(Set res (CompareAndExchangeL mem (Binary oldval newval)));
+ ins_cost(2 * VOLATILE_REF_COST);
+ effect(KILL cr);
+ format %{
+ "cmpxchg $res = $mem, $oldval, $newval\t# (long, weak) if $mem == $oldval then $mem <-- $newval"
+ %}
+ ins_encode %{
+ __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
+ Assembler::xword, /*acquire*/ false, /*release*/ true,
+ /*weak*/ false, $res$$Register);
+ %}
+ ins_pipe(pipe_slow);
+%}
+
+instruct compareAndExchangeN(iRegN_R0 res, indirect mem, iRegN_R2 oldval, iRegN_R3 newval, rFlagsReg cr) %{
+ match(Set res (CompareAndExchangeN mem (Binary oldval newval)));
+ ins_cost(2 * VOLATILE_REF_COST);
+ effect(KILL cr);
+ format %{
+ "cmpxchg $res = $mem, $oldval, $newval\t# (narrow oop, weak) if $mem == $oldval then $mem <-- $newval"
+ %}
+ ins_encode %{
+ __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
+ Assembler::word, /*acquire*/ false, /*release*/ true,
+ /*weak*/ false, $res$$Register);
+ %}
+ ins_pipe(pipe_slow);
+%}
+
+instruct compareAndExchangeP(iRegP_R0 res, indirect mem, iRegP_R2 oldval, iRegP_R3 newval, rFlagsReg cr) %{
+ match(Set res (CompareAndExchangeP mem (Binary oldval newval)));
+ ins_cost(2 * VOLATILE_REF_COST);
+ effect(KILL cr);
+ format %{
+ "cmpxchg $res = $mem, $oldval, $newval\t# (ptr, weak) if $mem == $oldval then $mem <-- $newval"
+ %}
+ ins_encode %{
+ __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
+ Assembler::xword, /*acquire*/ false, /*release*/ true,
+ /*weak*/ false, $res$$Register);
+ %}
+ ins_pipe(pipe_slow);
+%}
+
+instruct weakCompareAndSwapB(iRegINoSp res, indirect mem, iRegI oldval, iRegI newval, rFlagsReg cr) %{
+ match(Set res (WeakCompareAndSwapB mem (Binary oldval newval)));
+ ins_cost(2 * VOLATILE_REF_COST);
+ effect(KILL cr);
+ format %{
+ "cmpxchg $res = $mem, $oldval, $newval\t# (byte, weak) if $mem == $oldval then $mem <-- $newval"
+ "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
+ %}
+ ins_encode %{
+ __ uxtbw(rscratch2, $oldval$$Register);
+ __ cmpxchg($mem$$Register, rscratch2, $newval$$Register,
+ Assembler::byte, /*acquire*/ false, /*release*/ true,
+ /*weak*/ true, noreg);
+ __ csetw($res$$Register, Assembler::EQ);
+ %}
+ ins_pipe(pipe_slow);
+%}
+
+instruct weakCompareAndSwapS(iRegINoSp res, indirect mem, iRegI oldval, iRegI newval, rFlagsReg cr) %{
+ match(Set res (WeakCompareAndSwapS mem (Binary oldval newval)));
+ ins_cost(2 * VOLATILE_REF_COST);
+ effect(KILL cr);
+ format %{
+ "cmpxchg $res = $mem, $oldval, $newval\t# (short, weak) if $mem == $oldval then $mem <-- $newval"
+ "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
+ %}
+ ins_encode %{
+ __ uxthw(rscratch2, $oldval$$Register);
+ __ cmpxchg($mem$$Register, rscratch2, $newval$$Register,
+ Assembler::halfword, /*acquire*/ false, /*release*/ true,
+ /*weak*/ true, noreg);
+ __ csetw($res$$Register, Assembler::EQ);
+ %}
+ ins_pipe(pipe_slow);
+%}
+
+instruct weakCompareAndSwapI(iRegINoSp res, indirect mem, iRegI oldval, iRegI newval, rFlagsReg cr) %{
+ match(Set res (WeakCompareAndSwapI mem (Binary oldval newval)));
+ ins_cost(2 * VOLATILE_REF_COST);
+ effect(KILL cr);
+ format %{
+ "cmpxchg $res = $mem, $oldval, $newval\t# (int, weak) if $mem == $oldval then $mem <-- $newval"
+ "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
+ %}
+ ins_encode %{
+ __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
+ Assembler::word, /*acquire*/ false, /*release*/ true,
+ /*weak*/ true, noreg);
+ __ csetw($res$$Register, Assembler::EQ);
+ %}
+ ins_pipe(pipe_slow);
+%}
+
+instruct weakCompareAndSwapL(iRegINoSp res, indirect mem, iRegL oldval, iRegL newval, rFlagsReg cr) %{
+ match(Set res (WeakCompareAndSwapL mem (Binary oldval newval)));
+ ins_cost(2 * VOLATILE_REF_COST);
+ effect(KILL cr);
+ format %{
+ "cmpxchg $res = $mem, $oldval, $newval\t# (long, weak) if $mem == $oldval then $mem <-- $newval"
+ "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
+ %}
+ ins_encode %{
+ __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
+ Assembler::xword, /*acquire*/ false, /*release*/ true,
+ /*weak*/ true, noreg);
+ __ csetw($res$$Register, Assembler::EQ);
+ %}
+ ins_pipe(pipe_slow);
+%}
+
+instruct weakCompareAndSwapN(iRegINoSp res, indirect mem, iRegN oldval, iRegN newval, rFlagsReg cr) %{
+ match(Set res (WeakCompareAndSwapN mem (Binary oldval newval)));
+ ins_cost(2 * VOLATILE_REF_COST);
+ effect(KILL cr);
+ format %{
+ "cmpxchg $res = $mem, $oldval, $newval\t# (narrow oop, weak) if $mem == $oldval then $mem <-- $newval"
+ "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
+ %}
+ ins_encode %{
+ __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
+ Assembler::word, /*acquire*/ false, /*release*/ true,
+ /*weak*/ true, noreg);
+ __ csetw($res$$Register, Assembler::EQ);
+ %}
+ ins_pipe(pipe_slow);
+%}
+
+instruct weakCompareAndSwapP(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval, rFlagsReg cr) %{
+ match(Set res (WeakCompareAndSwapP mem (Binary oldval newval)));
+ ins_cost(2 * VOLATILE_REF_COST);
+ effect(KILL cr);
+ format %{
+ "cmpxchg $res = $mem, $oldval, $newval\t# (ptr, weak) if $mem == $oldval then $mem <-- $newval"
+ "csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
+ %}
+ ins_encode %{
+ __ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
+ Assembler::xword, /*acquire*/ false, /*release*/ true,
+ /*weak*/ true, noreg);
+ __ csetw($res$$Register, Assembler::EQ);
+ %}
+ ins_pipe(pipe_slow);
+%}
+// ---------------------------------------------------------------------
+
instruct get_and_setI(indirect mem, iRegINoSp newv, iRegI prev) %{
match(Set prev (GetAndSetI mem newv));
format %{ "atomic_xchgw $prev, $newv, [$mem]" %}