< prev index next >

src/hotspot/cpu/ppc/gc/shenandoah/shenandoah_ppc.ad

Print this page
@@ -24,194 +24,424 @@
  //
  
  source_hpp %{
  #include "gc/shenandoah/shenandoahBarrierSet.hpp"
  #include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp"
- %}
  
- // Weak compareAndSwap operations are treated as strong compareAndSwap operations.
- // This is motivated by the retry logic of ShenandoahBarrierSetAssembler::cmpxchg_oop which is hard to realise
- // using weak CAS operations.
+ bool need_acquire_load(const Node* n);
+ bool need_acquire_load_store(const Node *load);
+ %}
  
- instruct compareAndSwapP_shenandoah(iRegIdst res, indirect mem, iRegPsrc oldval, iRegPsrc newval,
-                                     iRegPdst tmp1, iRegPdst tmp2, flagsRegCR0 cr) %{
-   match(Set res (ShenandoahCompareAndSwapP mem (Binary oldval newval)));
-   match(Set res (ShenandoahWeakCompareAndSwapP mem (Binary oldval newval)));
-   effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, KILL cr);
+ source %{
+ bool need_acquire_load(const Node* n) {
+   return !n->as_Load()->is_unordered() && !followed_by_acquire(n);
+ }
+ bool need_acquire_load_store(const Node* n) {
+   MemNode::MemOrd order = ((CompareAndSwapNode*)n->as_LoadStore())->order();
+   return (order == MemNode::acquire) || (order == MemNode::seqcst);
+ }
+ %}
  
-   predicate(((CompareAndSwapNode*)n)->order() != MemNode::acquire
-             && ((CompareAndSwapNode*)n)->order() != MemNode::seqcst);
+ // ---------------------------------- LOADS ---------------------------------------
+ //
  
-   format %{ "CMPXCHG $res, $mem, $oldval, $newval; as bool; ptr" %}
+ instruct loadN_shenandoah(iRegNdst dst, memory mem) %{
+   match(Set dst (LoadN mem));
+   predicate(UseShenandoahGC && (n->as_Load()->barrier_data() != 0) &&
+             !need_acquire_load(n));
+   // The main load is a candidate to implement implicit null checks.
+   ins_is_late_expanded_null_check_candidate(true);
+   format %{ "shenandoah_load $dst, $mem\t# ptr" %}
    ins_encode %{
-     ShenandoahBarrierSet::assembler()->cmpxchg_oop(
-         masm,
-         $mem$$Register, $oldval$$Register, $newval$$Register,
-         $tmp1$$Register, $tmp2$$Register,
-         false, $res$$Register
+     ShenandoahBarrierSet::assembler()->load_c2(this, masm,
+       $dst$$Register,
+       $mem$$base$$Register,
+       $mem$$disp,
+       /* narrow = */ true,
+       /* acquire = */ false
      );
    %}
-   ins_pipe(pipe_class_default);
+   ins_cost(MEMORY_REF_COST);
+   ins_pipe(pipe_class_memory);
  %}
  
- instruct compareAndSwapN_shenandoah(iRegIdst res, indirect mem, iRegNsrc oldval, iRegNsrc newval,
-                                     iRegNdst tmp1, iRegNdst tmp2, flagsRegCR0 cr) %{
-   match(Set res (ShenandoahCompareAndSwapN mem (Binary oldval newval)));
-   match(Set res (ShenandoahWeakCompareAndSwapN mem (Binary oldval newval)));
-   effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, KILL cr);
+ instruct loadN_acq_shenandoah(iRegNdst dst, memory mem) %{
+   match(Set dst (LoadN mem));
+   predicate(UseShenandoahGC && (n->as_Load()->barrier_data() != 0) &&
+             need_acquire_load(n));
+   // The main load is a candidate to implement implicit null checks.
+   ins_is_late_expanded_null_check_candidate(true);
+   format %{ "shenandoah_load $dst, $mem\t# ptr (acquire)" %}
+   ins_encode %{
+     ShenandoahBarrierSet::assembler()->load_c2(this, masm,
+       $dst$$Register,
+       $mem$$base$$Register,
+       $mem$$disp,
+       /* narrow = */ true,
+       /* acquire = */ true
+     );
+   %}
+   ins_cost(3*MEMORY_REF_COST);
+   ins_pipe(pipe_class_memory);
+ %}
  
-   predicate(((CompareAndSwapNode*)n)->order() != MemNode::acquire
-             && ((CompareAndSwapNode*)n)->order() != MemNode::seqcst);
+ instruct loadP_shenandoah(iRegPdst dst, memoryAlg4 mem) %{
+   match(Set dst (LoadP mem));
+   predicate(UseShenandoahGC && (n->as_Load()->barrier_data() != 0) &&
+             !need_acquire_load(n));
+   // The main load is a candidate to implement implicit null checks.
+   ins_is_late_expanded_null_check_candidate(true);
+   format %{ "shenandoah_load $dst, $mem\t# ptr (acquire)" %}
+   ins_encode %{
+     ShenandoahBarrierSet::assembler()->load_c2(this, masm,
+       $dst$$Register,
+       $mem$$base$$Register,
+       $mem$$disp,
+       /* narrow = */ false,
+       /* acquire = */ false
+     );
+   %}
+   ins_cost(MEMORY_REF_COST);
+   ins_pipe(pipe_class_memory);
+ %}
  
-   format %{ "CMPXCHG $res, $mem, $oldval, $newval; as bool; ptr" %}
+ instruct loadP_acq_shenandoah(iRegPdst dst, memoryAlg4 mem) %{
+   match(Set dst (LoadP mem));
+   predicate(UseShenandoahGC && (n->as_Load()->barrier_data() != 0) &&
+             need_acquire_load(n));
+   // The main load is a candidate to implement implicit null checks.
+   ins_is_late_expanded_null_check_candidate(true);
+   format %{ "shenandoah_load $dst, $mem\t# ptr (acquire)" %}
    ins_encode %{
-     ShenandoahBarrierSet::assembler()->cmpxchg_oop(
-         masm,
-         $mem$$Register, $oldval$$Register, $newval$$Register,
-         $tmp1$$Register, $tmp2$$Register,
-         false, $res$$Register
+     ShenandoahBarrierSet::assembler()->load_c2(this, masm,
+       $dst$$Register,
+       $mem$$base$$Register,
+       $mem$$disp,
+       /* narrow = */ false,
+       /* acquire = */ true
      );
    %}
-   ins_pipe(pipe_class_default);
+   ins_cost(3*MEMORY_REF_COST);
+   ins_pipe(pipe_class_memory);
  %}
  
- instruct compareAndSwapP_acq_shenandoah(iRegIdst res, indirect mem, iRegPsrc oldval, iRegPsrc newval,
-                                        iRegPdst tmp1, iRegPdst tmp2, flagsRegCR0 cr) %{
-   match(Set res (ShenandoahCompareAndSwapP mem (Binary oldval newval)));
-   match(Set res (ShenandoahWeakCompareAndSwapP mem (Binary oldval newval)));
-   effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, KILL cr);
+ // ---------------------------------- STORES ---------------------------------------
+ //
  
-   predicate(((CompareAndSwapNode*)n)->order() == MemNode::acquire
-             || ((CompareAndSwapNode*)n)->order() == MemNode::seqcst);
+ instruct storeN_shenandoah(memory dst, iRegN_P2N src, iRegPdst tmp) %{
+   match(Set dst (StoreN dst src));
+   predicate(UseShenandoahGC && (n->as_Store()->barrier_data() != 0));
+   effect(TEMP tmp);
+   format %{ "shenandoah_store $dst, $src\t# compressed ptr" %}
+   ins_encode %{
+     ShenandoahBarrierSet::assembler()->store_c2(this, masm,
+       $dst$$base$$Register,
+       $dst$$disp,
+       /* dst_narrow = */ true,
+       $src$$Register,
+       /* src_narrow = */ true,
+       $tmp$$Register
+     );
+   %}
+   ins_cost(MEMORY_REF_COST);
+   ins_pipe(pipe_class_memory);
+ %}
+ 
+ instruct storeP_shenandoah(memoryAlg4 dst, iRegPsrc src, iRegPdst tmp) %{
+   match(Set dst (StoreP dst src));
+   predicate(UseShenandoahGC && (n->as_Store()->barrier_data() != 0));
+   effect(TEMP tmp);
+   format %{ "shenandoah_store $dst, $src\t# ptr" %}
+   ins_encode %{
+     ShenandoahBarrierSet::assembler()->store_c2(this, masm,
+       $dst$$base$$Register,
+       $dst$$disp,
+       /* dst_narrow = */ false,
+       $src$$Register,
+       /* src_narrow = */ false,
+       $tmp$$Register
+     );
+   %}
+   ins_cost(MEMORY_REF_COST);
+   ins_pipe(pipe_class_memory);
+ %}
  
-   format %{ "CMPXCHGD acq $res, $mem, $oldval, $newval; as bool; ptr" %}
+ instruct encodePAndStoreN_shenandoah(memory dst, iRegPsrc src, iRegPdst tmp) %{
+   match(Set dst (StoreN dst (EncodeP src)));
+   predicate(UseShenandoahGC && (n->as_Store()->barrier_data() != 0));
+   effect(TEMP tmp);
+   format %{ "shenandoah_store $dst, $src\t# compressed ptr (with encoding)" %}
    ins_encode %{
-     ShenandoahBarrierSet::assembler()->cmpxchg_oop(
-         masm,
-         $mem$$Register, $oldval$$Register, $newval$$Register,
-         $tmp1$$Register, $tmp2$$Register,
-         false, $res$$Register
+     ShenandoahBarrierSet::assembler()->store_c2(this, masm,
+       $dst$$base$$Register,
+       $dst$$disp,
+       /* dst_narrow = */ true,
+       $src$$Register,
+       /* src_narrow = */ false,
+       $tmp$$Register
      );
+   %}
+   ins_cost(MEMORY_REF_COST);
+   ins_pipe(pipe_class_memory);
+ %}
+ 
+ // ---------------------- LOAD-STORES -----------------------------------
+ //
+ 
+ instruct compareAndSwapN_regP_regN_regN_shenandoah(iRegIdst res, iRegPdst mem_ptr, iRegNsrc src1, iRegNsrc src2, flagsRegCR0 cr0) %{
+   match(Set res (CompareAndSwapN mem_ptr (Binary src1 src2)));
+   predicate(UseShenandoahGC && (n->as_LoadStore()->barrier_data() != 0) &&
+             !need_acquire_load_store(n));
+   effect(TEMP_DEF res, TEMP cr0); // TEMP_DEF to avoid jump
+   format %{ "CMPXCHGW $res, $mem_ptr, $src1, $src2; as bool" %}
+   ins_encode %{
+     // CmpxchgX sets CR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
+     __ cmpxchgw(CR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register,
+                 MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(),
+                 $res$$Register, nullptr, true);
      if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
        __ isync();
      } else {
        __ sync();
      }
    %}
    ins_pipe(pipe_class_default);
  %}
  
- instruct compareAndSwapN_acq_shenandoah(iRegIdst res, indirect mem, iRegNsrc oldval, iRegNsrc newval,
-                                         iRegNdst tmp1, iRegNdst tmp2, flagsRegCR0 cr) %{
-   match(Set res (ShenandoahCompareAndSwapN mem (Binary oldval newval)));
-   match(Set res (ShenandoahWeakCompareAndSwapN mem (Binary oldval newval)));
-   effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, KILL cr);
+ instruct compareAndSwapN_acq_regP_regN_regN_shenandoah(iRegIdst res, iRegPdst mem_ptr, iRegNsrc src1, iRegNsrc src2, flagsRegCR0 cr0) %{
+   match(Set res (CompareAndSwapN mem_ptr (Binary src1 src2)));
+   predicate(UseShenandoahGC && (n->as_LoadStore()->barrier_data() != 0) &&
+             need_acquire_load_store(n));
+   effect(TEMP_DEF res, TEMP cr0); // TEMP_DEF to avoid jump
+   format %{ "CMPXCHGW $res, $mem_ptr, $src1, $src2; as bool" %}
+   ins_encode %{
+     // CmpxchgX sets CR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
+     __ cmpxchgw(CR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register,
+                 MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(),
+                 $res$$Register, nullptr, true);
+     if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
+       __ isync();
+     } else {
+       __ sync();
+     }
+   %}
+   ins_pipe(pipe_class_default);
+ %}
  
-   predicate(((CompareAndSwapNode*)n)->order() == MemNode::acquire
-             || ((CompareAndSwapNode*)n)->order() == MemNode::seqcst);
+ instruct compareAndSwapP_regP_regP_regP_shenandoah(iRegIdst res, iRegPdst mem_ptr, iRegPsrc src1, iRegPsrc src2, flagsRegCR0 cr0) %{
+   match(Set res (CompareAndSwapP mem_ptr (Binary src1 src2)));
+   effect(TEMP_DEF res, TEMP cr0); // TEMP_DEF to avoid jump
+   predicate(UseShenandoahGC && (n->as_LoadStore()->barrier_data() != 0) &&
+             !need_acquire_load_store(n));
+   format %{ "CMPXCHGD $res, $mem_ptr, $src1, $src2; as bool; ptr" %}
+   ins_encode %{
+     // CmpxchgX sets CR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
+     __ cmpxchgd(CR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register,
+                 MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(),
+                 $res$$Register, nullptr, true);
+     if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
+       __ isync();
+     } else {
+       __ sync();
+     }
+   %}
+   ins_pipe(pipe_class_default);
+ %}
  
-   format %{ "CMPXCHGD acq $res, $mem, $oldval, $newval; as bool; ptr" %}
+ instruct compareAndSwapP_acq_regP_regP_regP_shenandoah(iRegIdst res, iRegPdst mem_ptr, iRegPsrc src1, iRegPsrc src2, flagsRegCR0 cr0) %{
+   match(Set res (CompareAndSwapP mem_ptr (Binary src1 src2)));
+   effect(TEMP_DEF res, TEMP cr0); // TEMP_DEF to avoid jump
+   predicate(UseShenandoahGC && (n->as_LoadStore()->barrier_data() != 0) &&
+             need_acquire_load_store(n));
+   format %{ "CMPXCHGD $res, $mem_ptr, $src1, $src2; as bool; ptr" %}
    ins_encode %{
-     ShenandoahBarrierSet::assembler()->cmpxchg_oop(
-         masm,
-         $mem$$Register, $oldval$$Register, $newval$$Register,
-         $tmp1$$Register, $tmp2$$Register,
-         false, $res$$Register
-     );
+     // CmpxchgX sets CR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
+     __ cmpxchgd(CR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register,
+                 MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(),
+                 $res$$Register, nullptr, true);
      if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
        __ isync();
      } else {
        __ sync();
      }
    %}
    ins_pipe(pipe_class_default);
  %}
  
- instruct compareAndExchangeP_shenandoah(iRegPdst res, indirect mem, iRegPsrc oldval, iRegPsrc newval,
-                                         iRegPdst tmp1, iRegPdst tmp2, flagsRegCR0 cr) %{
-   match(Set res (ShenandoahCompareAndExchangeP mem (Binary oldval newval)));
-   effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, KILL cr);
+ instruct weakCompareAndSwapN_regP_regN_regN_shenandoah(iRegIdst res, iRegPdst mem_ptr, iRegNsrc src1, iRegNsrc src2, flagsRegCR0 cr0) %{
+   match(Set res (WeakCompareAndSwapN mem_ptr (Binary src1 src2)));
+   predicate(UseShenandoahGC && (n->as_LoadStore()->barrier_data() != 0) &&
+             !need_acquire_load_store(n));
+   effect(TEMP_DEF res, TEMP cr0); // TEMP_DEF to avoid jump
+   format %{ "weak CMPXCHGW acq $res, $mem_ptr, $src1, $src2; as bool" %}
+   ins_encode %{
+     // CmpxchgX sets CR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
+     // Acquire only needed in successful case. Weak node is allowed to report unsuccessful in additional rare cases and
+     // value is never passed to caller.
+     __ cmpxchgw(CR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register,
+                 support_IRIW_for_not_multiple_copy_atomic_cpu ? MacroAssembler::MemBarAcq : MacroAssembler::MemBarFenceAfter,
+                 MacroAssembler::cmpxchgx_hint_atomic_update(), $res$$Register, nullptr, true, /*weak*/ true);
+   %}
+   ins_pipe(pipe_class_default);
+ %}
  
-   predicate(((CompareAndSwapNode*)n)->order() != MemNode::acquire
-             && ((CompareAndSwapNode*)n)->order() != MemNode::seqcst);
+ instruct weakCompareAndSwapN_acq_regP_regN_regN_shenandoah(iRegIdst res, iRegPdst mem_ptr, iRegNsrc src1, iRegNsrc src2, flagsRegCR0 cr0) %{
+   match(Set res (WeakCompareAndSwapN mem_ptr (Binary src1 src2)));
+   predicate(UseShenandoahGC && (n->as_LoadStore()->barrier_data() != 0) &&
+             need_acquire_load_store(n));
+   effect(TEMP_DEF res, TEMP cr0); // TEMP_DEF to avoid jump
+   format %{ "weak CMPXCHGW acq $res, $mem_ptr, $src1, $src2; as bool" %}
+   ins_encode %{
+     // CmpxchgX sets CR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
+     // Acquire only needed in successful case. Weak node is allowed to report unsuccessful in additional rare cases and
+     // value is never passed to caller.
+     __ cmpxchgw(CR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register,
+                 support_IRIW_for_not_multiple_copy_atomic_cpu ? MacroAssembler::MemBarAcq : MacroAssembler::MemBarFenceAfter,
+                 MacroAssembler::cmpxchgx_hint_atomic_update(), $res$$Register, nullptr, true, /*weak*/ true);
+   %}
+   ins_pipe(pipe_class_default);
+ %}
  
-   format %{ "CMPXCHGD $res, $mem, $oldval, $newval; as ptr; ptr" %}
+ instruct weakCompareAndSwapP_regP_regP_regP_shenandoah(iRegIdst res, iRegPdst mem_ptr, iRegPsrc src1, iRegPsrc src2, flagsRegCR0 cr0) %{
+   match(Set res (WeakCompareAndSwapP mem_ptr (Binary src1 src2)));
+   predicate(UseShenandoahGC && (n->as_LoadStore()->barrier_data() != 0) &&
+             !need_acquire_load_store(n));
+   effect(TEMP_DEF res, TEMP cr0); // TEMP_DEF to avoid jump
+   format %{ "weak CMPXCHGD $res, $mem_ptr, $src1, $src2; as bool; ptr" %}
    ins_encode %{
-     ShenandoahBarrierSet::assembler()->cmpxchg_oop(
-         masm,
-         $mem$$Register, $oldval$$Register, $newval$$Register,
-         $tmp1$$Register, $tmp2$$Register,
-         true, $res$$Register
-     );
+     MemNode::MemOrd order = ((CompareAndSwapNode*)as_LoadStore())->order();
+     bool acquire = (order == MemNode::acquire) || (order == MemNode::seqcst);
+ 
+     // CmpxchgX sets CR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
+     __ cmpxchgd(CR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register,
+                 MacroAssembler::MemBarNone,
+                 MacroAssembler::cmpxchgx_hint_atomic_update(), $res$$Register, nullptr, true, /*weak*/ true);
    %}
    ins_pipe(pipe_class_default);
  %}
  
- instruct compareAndExchangeN_shenandoah(iRegNdst res, indirect mem, iRegNsrc oldval, iRegNsrc newval,
-                                         iRegNdst tmp1, iRegNdst tmp2, flagsRegCR0 cr) %{
-   match(Set res (ShenandoahCompareAndExchangeN mem (Binary oldval newval)));
-   effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, KILL cr);
+ instruct weakCompareAndSwapP_acq_regP_regP_regP_shenandoah(iRegIdst res, iRegPdst mem_ptr, iRegPsrc src1, iRegPsrc src2, flagsRegCR0 cr0) %{
+   match(Set res (WeakCompareAndSwapP mem_ptr (Binary src1 src2)));
+   predicate(UseShenandoahGC && (n->as_LoadStore()->barrier_data() != 0) &&
+             need_acquire_load_store(n));
+   effect(TEMP_DEF res, TEMP cr0); // TEMP_DEF to avoid jump
+   format %{ "weak CMPXCHGD $res, $mem_ptr, $src1, $src2; as bool; ptr" %}
+   ins_encode %{
+     // CmpxchgX sets CR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
+     __ cmpxchgd(CR0, R0, $src1$$Register, $src2$$Register, $mem_ptr$$Register,
+                 MacroAssembler::MemBarNone,
+                 MacroAssembler::cmpxchgx_hint_atomic_update(), $res$$Register, nullptr, true, /*weak*/ true);
+   %}
+   ins_pipe(pipe_class_default);
+ %}
  
-   predicate(((CompareAndSwapNode*)n)->order() != MemNode::acquire
-             && ((CompareAndSwapNode*)n)->order() != MemNode::seqcst);
+ instruct compareAndExchangeN_regP_regN_regN_shenandoah(iRegNdst res, iRegPdst mem_ptr, iRegNsrc src1, iRegNsrc src2, flagsRegCR0 cr0) %{
+   match(Set res (CompareAndExchangeN mem_ptr (Binary src1 src2)));
+   predicate(UseShenandoahGC && (n->as_LoadStore()->barrier_data() != 0) &&
+             !need_acquire_load_store(n));
+   effect(TEMP_DEF res, TEMP cr0);
+   format %{ "CMPXCHGW $res, $mem_ptr, $src1, $src2; as narrow oop" %}
+   ins_encode %{
+     // CmpxchgX sets CR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
+     __ cmpxchgw(CR0, $res$$Register, $src1$$Register, $src2$$Register, $mem_ptr$$Register,
+                 MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(),
+                 noreg, nullptr, true);
+   %}
+   ins_pipe(pipe_class_default);
+ %}
  
-   format %{ "CMPXCHGD $res, $mem, $oldval, $newval; as ptr; ptr" %}
+ instruct compareAndExchangeN_acq_regP_regN_regN_shenandoah(iRegNdst res, iRegPdst mem_ptr, iRegNsrc src1, iRegNsrc src2, flagsRegCR0 cr0) %{
+   match(Set res (CompareAndExchangeN mem_ptr (Binary src1 src2)));
+   predicate(UseShenandoahGC && (n->as_LoadStore()->barrier_data() != 0) &&
+             need_acquire_load_store(n));
+   effect(TEMP_DEF res, TEMP cr0);
+   format %{ "CMPXCHGW $res, $mem_ptr, $src1, $src2; as narrow oop" %}
    ins_encode %{
-     ShenandoahBarrierSet::assembler()->cmpxchg_oop(
-         masm,
-         $mem$$Register, $oldval$$Register, $newval$$Register,
-         $tmp1$$Register, $tmp2$$Register,
-         true, $res$$Register
-     );
+     // CmpxchgX sets CR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
+     __ cmpxchgw(CR0, $res$$Register, $src1$$Register, $src2$$Register, $mem_ptr$$Register,
+                 MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(),
+                 noreg, nullptr, true);
+ 
+     if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
+         __ isync();
+     } else {
+        // isync would be sufficient in case of CompareAndExchangeAcquire, but we currently don't optimize for that.
+        __ sync();
+     }
    %}
    ins_pipe(pipe_class_default);
  %}
  
- instruct compareAndExchangePAcq_shenandoah(iRegPdst res, indirect mem, iRegPsrc oldval, iRegPsrc newval,
-                                            iRegPdst tmp1, iRegPdst tmp2, flagsRegCR0 cr) %{
-   match(Set res (ShenandoahCompareAndExchangeP mem (Binary oldval newval)));
-   effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, KILL cr);
+ instruct compareAndExchangeP_regP_regP_regP_shenandoah(iRegPdst res, iRegPdst mem_ptr, iRegPsrc src1, iRegPsrc src2, flagsRegCR0 cr0) %{
+   match(Set res (CompareAndExchangeP mem_ptr (Binary src1 src2)));
+   predicate(UseShenandoahGC && (n->as_LoadStore()->barrier_data() != 0) &&
+             !need_acquire_load_store(n));
+   effect(TEMP_DEF res, TEMP cr0);
+   format %{ "CMPXCHGD $res, $mem_ptr, $src1, $src2; as ptr; ptr" %}
+   ins_encode %{
+     MemNode::MemOrd order = ((CompareAndSwapNode*)as_LoadStore())->order();
+     bool acquire = (order == MemNode::acquire) || (order == MemNode::seqcst);
  
-   predicate(((CompareAndSwapNode*)n)->order() == MemNode::acquire
-             || ((CompareAndSwapNode*)n)->order() == MemNode::seqcst);
+     // CmpxchgX sets CR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
+     __ cmpxchgd(CR0, $res$$Register, $src1$$Register, $src2$$Register, $mem_ptr$$Register,
+                 MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(),
+                 noreg, nullptr, true);
+   %}
+   ins_pipe(pipe_class_default);
+ %}
  
-   format %{ "CMPXCHGD acq $res, $mem, $oldval, $newval; as ptr; ptr" %}
+ instruct compareAndExchangeP_acq_regP_regP_regP_shenandoah(iRegPdst res, iRegPdst mem_ptr, iRegPsrc src1, iRegPsrc src2, flagsRegCR0 cr0) %{
+   match(Set res (CompareAndExchangeP mem_ptr (Binary src1 src2)));
+   predicate(UseShenandoahGC && (n->as_LoadStore()->barrier_data() != 0) &&
+             need_acquire_load_store(n));
+   effect(TEMP_DEF res, TEMP cr0);
+   format %{ "CMPXCHGD $res, $mem_ptr, $src1, $src2; as ptr; ptr" %}
    ins_encode %{
-     ShenandoahBarrierSet::assembler()->cmpxchg_oop(
-         masm,
-         $mem$$Register, $oldval$$Register, $newval$$Register,
-         $tmp1$$Register, $tmp2$$Register,
-         true, $res$$Register
-     );
+     // CmpxchgX sets CR0 to cmpX(src1, src2) and Rres to 'true'/'false'.
+     __ cmpxchgd(CR0, $res$$Register, $src1$$Register, $src2$$Register, $mem_ptr$$Register,
+                 MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(),
+                 noreg, nullptr, true);
+ 
      if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
        __ isync();
      } else {
-       __ sync();
+       // isync would be sufficient in case of CompareAndExchangeAcquire, but we currently don't optimize for that.
+       __  sync();
      }
    %}
    ins_pipe(pipe_class_default);
  %}
  
- instruct compareAndExchangeNAcq_shenandoah(iRegNdst res, indirect mem, iRegNsrc oldval, iRegNsrc newval,
-                                            iRegNdst tmp1, iRegNdst tmp2, flagsRegCR0 cr) %{
-   match(Set res (ShenandoahCompareAndExchangeN mem (Binary oldval newval)));
-   effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, KILL cr);
- 
-   predicate(((CompareAndSwapNode*)n)->order() == MemNode::acquire
-             || ((CompareAndSwapNode*)n)->order() == MemNode::seqcst);
+ instruct getAndSetP_shenandoah(iRegPdst res, iRegPdst mem_ptr, iRegPsrc src, flagsRegCR0 cr0) %{
+   match(Set res (GetAndSetP mem_ptr src));
+   predicate(UseShenandoahGC && (n->as_LoadStore()->barrier_data() != 0));
+   effect(TEMP_DEF res, TEMP cr0);
+   format %{ "GetAndSetP $res, $mem_ptr, $src" %}
+   ins_encode %{
+     __ getandsetd($res$$Register, $src$$Register, $mem_ptr$$Register,
+                   MacroAssembler::cmpxchgx_hint_atomic_update());
+     if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
+       __ isync();
+     } else {
+       __ sync();
+     }
+   %}
+   ins_pipe(pipe_class_default);
+ %}
  
-   format %{ "CMPXCHGD acq $res, $mem, $oldval, $newval; as ptr; ptr" %}
+ instruct getAndSetN_shenandoah(iRegNdst res, iRegPdst mem_ptr, iRegNsrc src, flagsRegCR0 cr0) %{
+   match(Set res (GetAndSetN mem_ptr src));
+   predicate(UseShenandoahGC && (n->as_LoadStore()->barrier_data() != 0));
+   effect(TEMP_DEF res, TEMP cr0);
+   format %{ "GetAndSetN $res, $mem_ptr, $src" %}
    ins_encode %{
-     ShenandoahBarrierSet::assembler()->cmpxchg_oop(
-         masm,
-         $mem$$Register, $oldval$$Register, $newval$$Register,
-         $tmp1$$Register, $tmp2$$Register,
-         true, $res$$Register
-     );
+     __ getandsetw($res$$Register, $src$$Register, $mem_ptr$$Register,
+                   MacroAssembler::cmpxchgx_hint_atomic_update());
      if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
        __ isync();
      } else {
        __ sync();
      }
    %}
    ins_pipe(pipe_class_default);
  %}
+ 
< prev index next >