1 //
  2 // Copyright (c) 2018, 2021, Red Hat, Inc. All rights reserved.
  3 // Copyright (c) 2012, 2021 SAP SE. All rights reserved.
  4 // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  5 //
  6 // This code is free software; you can redistribute it and/or modify it
  7 // under the terms of the GNU General Public License version 2 only, as
  8 // published by the Free Software Foundation.
  9 //
 10 // This code is distributed in the hope that it will be useful, but WITHOUT
 11 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 12 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 13 // version 2 for more details (a copy is included in the LICENSE file that
 14 // accompanied this code).
 15 //
 16 // You should have received a copy of the GNU General Public License version
 17 // 2 along with this work; if not, write to the Free Software Foundation,
 18 // Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 19 //
 20 // Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 21 // or visit www.oracle.com if you need additional information or have any
 22 // questions.
 23 //
 24 //
 25 
 26 source_hpp %{
 27 #include "gc/shenandoah/shenandoahBarrierSet.hpp"
 28 #include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp"
 29 %}
 30 
 31 // Weak compareAndSwap operations are treated as strong compareAndSwap operations.
 32 // This is motivated by the retry logic of ShenandoahBarrierSetAssembler::cmpxchg_oop which is hard to realise
 33 // using weak CAS operations.
 34 
 35 instruct compareAndSwapP_shenandoah(iRegIdst res, indirect mem, iRegPsrc oldval, iRegPsrc newval,
 36                                     iRegPdst tmp1, iRegPdst tmp2, flagsRegCR0 cr) %{
 37   match(Set res (ShenandoahCompareAndSwapP mem (Binary oldval newval)));
 38   match(Set res (ShenandoahWeakCompareAndSwapP mem (Binary oldval newval)));
 39   effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, KILL cr);
 40 
 41   predicate(((CompareAndSwapNode*)n)->order() != MemNode::acquire
 42             && ((CompareAndSwapNode*)n)->order() != MemNode::seqcst);
 43 
 44   format %{ "CMPXCHG $res, $mem, $oldval, $newval; as bool; ptr" %}
 45   ins_encode %{
 46     ShenandoahBarrierSet::assembler()->cmpxchg_oop(
 47         masm,
 48         $mem$$Register, $oldval$$Register, $newval$$Register,
 49         $tmp1$$Register, $tmp2$$Register,
 50         false, $res$$Register
 51     );
 52   %}
 53   ins_pipe(pipe_class_default);
 54 %}
 55 
 56 instruct compareAndSwapN_shenandoah(iRegIdst res, indirect mem, iRegNsrc oldval, iRegNsrc newval,
 57                                     iRegNdst tmp1, iRegNdst tmp2, flagsRegCR0 cr) %{
 58   match(Set res (ShenandoahCompareAndSwapN mem (Binary oldval newval)));
 59   match(Set res (ShenandoahWeakCompareAndSwapN mem (Binary oldval newval)));
 60   effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, KILL cr);
 61 
 62   predicate(((CompareAndSwapNode*)n)->order() != MemNode::acquire
 63             && ((CompareAndSwapNode*)n)->order() != MemNode::seqcst);
 64 
 65   format %{ "CMPXCHG $res, $mem, $oldval, $newval; as bool; ptr" %}
 66   ins_encode %{
 67     ShenandoahBarrierSet::assembler()->cmpxchg_oop(
 68         masm,
 69         $mem$$Register, $oldval$$Register, $newval$$Register,
 70         $tmp1$$Register, $tmp2$$Register,
 71         false, $res$$Register
 72     );
 73   %}
 74   ins_pipe(pipe_class_default);
 75 %}
 76 
 77 instruct compareAndSwapP_acq_shenandoah(iRegIdst res, indirect mem, iRegPsrc oldval, iRegPsrc newval,
 78                                        iRegPdst tmp1, iRegPdst tmp2, flagsRegCR0 cr) %{
 79   match(Set res (ShenandoahCompareAndSwapP mem (Binary oldval newval)));
 80   match(Set res (ShenandoahWeakCompareAndSwapP mem (Binary oldval newval)));
 81   effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, KILL cr);
 82 
 83   predicate(((CompareAndSwapNode*)n)->order() == MemNode::acquire
 84             || ((CompareAndSwapNode*)n)->order() == MemNode::seqcst);
 85 
 86   format %{ "CMPXCHGD acq $res, $mem, $oldval, $newval; as bool; ptr" %}
 87   ins_encode %{
 88     ShenandoahBarrierSet::assembler()->cmpxchg_oop(
 89         masm,
 90         $mem$$Register, $oldval$$Register, $newval$$Register,
 91         $tmp1$$Register, $tmp2$$Register,
 92         false, $res$$Register
 93     );
 94     if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
 95       __ isync();
 96     } else {
 97       __ sync();
 98     }
 99   %}
100   ins_pipe(pipe_class_default);
101 %}
102 
103 instruct compareAndSwapN_acq_shenandoah(iRegIdst res, indirect mem, iRegNsrc oldval, iRegNsrc newval,
104                                         iRegNdst tmp1, iRegNdst tmp2, flagsRegCR0 cr) %{
105   match(Set res (ShenandoahCompareAndSwapN mem (Binary oldval newval)));
106   match(Set res (ShenandoahWeakCompareAndSwapN mem (Binary oldval newval)));
107   effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, KILL cr);
108 
109   predicate(((CompareAndSwapNode*)n)->order() == MemNode::acquire
110             || ((CompareAndSwapNode*)n)->order() == MemNode::seqcst);
111 
112   format %{ "CMPXCHGD acq $res, $mem, $oldval, $newval; as bool; ptr" %}
113   ins_encode %{
114     ShenandoahBarrierSet::assembler()->cmpxchg_oop(
115         masm,
116         $mem$$Register, $oldval$$Register, $newval$$Register,
117         $tmp1$$Register, $tmp2$$Register,
118         false, $res$$Register
119     );
120     if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
121       __ isync();
122     } else {
123       __ sync();
124     }
125   %}
126   ins_pipe(pipe_class_default);
127 %}
128 
129 instruct compareAndExchangeP_shenandoah(iRegPdst res, indirect mem, iRegPsrc oldval, iRegPsrc newval,
130                                         iRegPdst tmp1, iRegPdst tmp2, flagsRegCR0 cr) %{
131   match(Set res (ShenandoahCompareAndExchangeP mem (Binary oldval newval)));
132   effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, KILL cr);
133 
134   predicate(((CompareAndSwapNode*)n)->order() != MemNode::acquire
135             && ((CompareAndSwapNode*)n)->order() != MemNode::seqcst);
136 
137   format %{ "CMPXCHGD $res, $mem, $oldval, $newval; as ptr; ptr" %}
138   ins_encode %{
139     ShenandoahBarrierSet::assembler()->cmpxchg_oop(
140         masm,
141         $mem$$Register, $oldval$$Register, $newval$$Register,
142         $tmp1$$Register, $tmp2$$Register,
143         true, $res$$Register
144     );
145   %}
146   ins_pipe(pipe_class_default);
147 %}
148 
149 instruct compareAndExchangeN_shenandoah(iRegNdst res, indirect mem, iRegNsrc oldval, iRegNsrc newval,
150                                         iRegNdst tmp1, iRegNdst tmp2, flagsRegCR0 cr) %{
151   match(Set res (ShenandoahCompareAndExchangeN mem (Binary oldval newval)));
152   effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, KILL cr);
153 
154   predicate(((CompareAndSwapNode*)n)->order() != MemNode::acquire
155             && ((CompareAndSwapNode*)n)->order() != MemNode::seqcst);
156 
157   format %{ "CMPXCHGD $res, $mem, $oldval, $newval; as ptr; ptr" %}
158   ins_encode %{
159     ShenandoahBarrierSet::assembler()->cmpxchg_oop(
160         masm,
161         $mem$$Register, $oldval$$Register, $newval$$Register,
162         $tmp1$$Register, $tmp2$$Register,
163         true, $res$$Register
164     );
165   %}
166   ins_pipe(pipe_class_default);
167 %}
168 
169 instruct compareAndExchangePAcq_shenandoah(iRegPdst res, indirect mem, iRegPsrc oldval, iRegPsrc newval,
170                                            iRegPdst tmp1, iRegPdst tmp2, flagsRegCR0 cr) %{
171   match(Set res (ShenandoahCompareAndExchangeP mem (Binary oldval newval)));
172   effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, KILL cr);
173 
174   predicate(((CompareAndSwapNode*)n)->order() == MemNode::acquire
175             || ((CompareAndSwapNode*)n)->order() == MemNode::seqcst);
176 
177   format %{ "CMPXCHGD acq $res, $mem, $oldval, $newval; as ptr; ptr" %}
178   ins_encode %{
179     ShenandoahBarrierSet::assembler()->cmpxchg_oop(
180         masm,
181         $mem$$Register, $oldval$$Register, $newval$$Register,
182         $tmp1$$Register, $tmp2$$Register,
183         true, $res$$Register
184     );
185     if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
186       __ isync();
187     } else {
188       __ sync();
189     }
190   %}
191   ins_pipe(pipe_class_default);
192 %}
193 
194 instruct compareAndExchangeNAcq_shenandoah(iRegNdst res, indirect mem, iRegNsrc oldval, iRegNsrc newval,
195                                            iRegNdst tmp1, iRegNdst tmp2, flagsRegCR0 cr) %{
196   match(Set res (ShenandoahCompareAndExchangeN mem (Binary oldval newval)));
197   effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, KILL cr);
198 
199   predicate(((CompareAndSwapNode*)n)->order() == MemNode::acquire
200             || ((CompareAndSwapNode*)n)->order() == MemNode::seqcst);
201 
202   format %{ "CMPXCHGD acq $res, $mem, $oldval, $newval; as ptr; ptr" %}
203   ins_encode %{
204     ShenandoahBarrierSet::assembler()->cmpxchg_oop(
205         masm,
206         $mem$$Register, $oldval$$Register, $newval$$Register,
207         $tmp1$$Register, $tmp2$$Register,
208         true, $res$$Register
209     );
210     if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
211       __ isync();
212     } else {
213       __ sync();
214     }
215   %}
216   ins_pipe(pipe_class_default);
217 %}