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 bool need_acquire_load(const Node* n);
 31 bool need_acquire_load_store(const Node *load);
 32 %}
 33 
 34 source %{
 35 bool need_acquire_load(const Node* n) {
 36   return !n->as_Load()->is_unordered() && !followed_by_acquire(n);
 37 }
 38 bool need_acquire_load_store(const Node* n) {
 39   MemNode::MemOrd order = ((CompareAndSwapNode*)n->as_LoadStore())->order();
 40   return (order == MemNode::acquire) || (order == MemNode::seqcst);
 41 }
 42 %}
 43 
 44 // ---------------------------------- LOADS ---------------------------------------
 45 //
 46 
 47 instruct loadN_shenandoah(iRegNdst dst, memory mem, iRegPdstNoScratch tmp1, iRegPdstNoScratch tmp2, flagsRegCR0 cr0) %{
 48   match(Set dst (LoadN mem));
 49   effect(TEMP_DEF dst, TEMP tmp1, TEMP tmp2, KILL cr0);
 50   predicate(UseShenandoahGC && (n->as_Load()->barrier_data() != 0) && !need_acquire_load(n));
 51   // The main load is a candidate to implement implicit null checks.
 52   ins_is_late_expanded_null_check_candidate(true);
 53   format %{ "shenandoah_load $dst, $mem\t# ptr" %}
 54   ins_encode %{
 55     ShenandoahBarrierSet::assembler()->load_c2(this, masm,
 56       $dst$$Register,
 57       $mem$$base$$Register,
 58       $mem$$disp,
 59       $tmp1$$Register,
 60       $tmp2$$Register,
 61       /* narrow = */ true,
 62       /* acquire = */ false
 63     );
 64   %}
 65   ins_cost(MEMORY_REF_COST);
 66   ins_pipe(pipe_class_memory);
 67 %}
 68 
 69 instruct loadN_acq_shenandoah(iRegNdst dst, memory mem, iRegPdstNoScratch tmp1, iRegPdstNoScratch tmp2, flagsRegCR0 cr0) %{
 70   match(Set dst (LoadN mem));
 71   effect(TEMP_DEF dst, TEMP tmp1, TEMP tmp2, KILL cr0);
 72   predicate(UseShenandoahGC && (n->as_Load()->barrier_data() != 0) && need_acquire_load(n));
 73   // The main load is a candidate to implement implicit null checks.
 74   ins_is_late_expanded_null_check_candidate(true);
 75   format %{ "shenandoah_load $dst, $mem\t# ptr (acquire)" %}
 76   ins_encode %{
 77     ShenandoahBarrierSet::assembler()->load_c2(this, masm,
 78       $dst$$Register,
 79       $mem$$base$$Register,
 80       $mem$$disp,
 81       $tmp1$$Register,
 82       $tmp2$$Register,
 83       /* narrow = */ true,
 84       /* acquire = */ true
 85     );
 86   %}
 87   ins_cost(3*MEMORY_REF_COST);
 88   ins_pipe(pipe_class_memory);
 89 %}
 90 
 91 instruct loadP_shenandoah(iRegPdst dst, memoryAlg4 mem, iRegPdstNoScratch tmp1, iRegPdstNoScratch tmp2, flagsRegCR0 cr0) %{
 92   match(Set dst (LoadP mem));
 93   effect(TEMP_DEF dst, TEMP tmp1, TEMP tmp2, KILL cr0);
 94   predicate(UseShenandoahGC && (n->as_Load()->barrier_data() != 0) && !need_acquire_load(n));
 95   // The main load is a candidate to implement implicit null checks.
 96   ins_is_late_expanded_null_check_candidate(true);
 97   format %{ "shenandoah_load $dst, $mem\t# ptr" %}
 98   ins_encode %{
 99     ShenandoahBarrierSet::assembler()->load_c2(this, masm,
100       $dst$$Register,
101       $mem$$base$$Register,
102       $mem$$disp,
103       $tmp1$$Register,
104       $tmp2$$Register,
105       /* narrow = */ false,
106       /* acquire = */ false
107     );
108   %}
109   ins_cost(MEMORY_REF_COST);
110   ins_pipe(pipe_class_memory);
111 %}
112 
113 instruct loadP_acq_shenandoah(iRegPdst dst, memoryAlg4 mem, iRegPdstNoScratch tmp1, iRegPdstNoScratch tmp2, flagsRegCR0 cr0) %{
114   match(Set dst (LoadP mem));
115   effect(TEMP_DEF dst, TEMP tmp1, TEMP tmp2, KILL cr0);
116   predicate(UseShenandoahGC && (n->as_Load()->barrier_data() != 0) && need_acquire_load(n));
117   // The main load is a candidate to implement implicit null checks.
118   ins_is_late_expanded_null_check_candidate(true);
119   format %{ "shenandoah_load $dst, $mem\t# ptr (acquire)" %}
120   ins_encode %{
121     ShenandoahBarrierSet::assembler()->load_c2(this, masm,
122       $dst$$Register,
123       $mem$$base$$Register,
124       $mem$$disp,
125       $tmp1$$Register,
126       $tmp2$$Register,
127       /* narrow = */ false,
128       /* acquire = */ true
129     );
130   %}
131   ins_cost(3*MEMORY_REF_COST);
132   ins_pipe(pipe_class_memory);
133 %}
134 
135 // ---------------------------------- STORES ---------------------------------------
136 //
137 
138 instruct storeN_shenandoah(memory dst, iRegN_P2N src, iRegPdstNoScratch tmp1, iRegPdstNoScratch tmp2, iRegPdstNoScratch tmp3, flagsRegCR0 cr0) %{
139   match(Set dst (StoreN dst src));
140   predicate(UseShenandoahGC && (n->as_Store()->barrier_data() != 0));
141   effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, KILL cr0);
142   format %{ "shenandoah_store $dst, $src\t# compressed ptr" %}
143   ins_encode %{
144     ShenandoahBarrierSet::assembler()->store_c2(this, masm,
145       $dst$$base$$Register,
146       $dst$$disp,
147       /* dst_narrow = */ true,
148       $src$$Register,
149       /* src_narrow = */ true,
150       $tmp1$$Register,
151       $tmp2$$Register,
152       $tmp3$$Register
153     );
154   %}
155   ins_cost(MEMORY_REF_COST);
156   ins_pipe(pipe_class_memory);
157 %}
158 
159 instruct storeP_shenandoah(memoryAlg4 dst, iRegPsrc src, iRegPdstNoScratch tmp1, iRegPdstNoScratch tmp2, iRegPdstNoScratch tmp3, flagsRegCR0 cr0) %{
160   match(Set dst (StoreP dst src));
161   predicate(UseShenandoahGC && (n->as_Store()->barrier_data() != 0));
162   effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, KILL cr0);
163   format %{ "shenandoah_store $dst, $src\t# ptr" %}
164   ins_encode %{
165     ShenandoahBarrierSet::assembler()->store_c2(this, masm,
166       $dst$$base$$Register,
167       $dst$$disp,
168       /* dst_narrow = */ false,
169       $src$$Register,
170       /* src_narrow = */ false,
171       $tmp1$$Register,
172       $tmp2$$Register,
173       $tmp3$$Register
174     );
175   %}
176   ins_cost(MEMORY_REF_COST);
177   ins_pipe(pipe_class_memory);
178 %}
179 
180 instruct encodePAndStoreN_shenandoah(memory dst, iRegPsrc src, iRegPdstNoScratch tmp1, iRegPdstNoScratch tmp2, iRegPdstNoScratch tmp3, flagsRegCR0 cr0) %{
181   match(Set dst (StoreN dst (EncodeP src)));
182   predicate(UseShenandoahGC && (n->as_Store()->barrier_data() != 0));
183   effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, KILL cr0);
184   format %{ "shenandoah_store $dst, $src\t# compressed ptr (with encoding)" %}
185   ins_encode %{
186     ShenandoahBarrierSet::assembler()->store_c2(this, masm,
187       $dst$$base$$Register,
188       $dst$$disp,
189       /* dst_narrow = */ true,
190       $src$$Register,
191       /* src_narrow = */ false,
192       $tmp1$$Register,
193       $tmp2$$Register,
194       $tmp3$$Register
195     );
196   %}
197   ins_cost(MEMORY_REF_COST);
198   ins_pipe(pipe_class_memory);
199 %}
200 
201 // ---------------------- LOAD-STORES -----------------------------------
202 //
203 
204 instruct compareAndSwapN_regP_regN_regN_shenandoah(iRegIdst res, iRegPdst mem_ptr, iRegNsrc src1, iRegNsrc src2, iRegPdstNoScratch tmp1, iRegPdstNoScratch tmp2, iRegPdstNoScratch tmp3, flagsRegCR0 cr0) %{
205   match(Set res (CompareAndSwapN mem_ptr (Binary src1 src2)));
206   predicate(UseShenandoahGC && (n->as_LoadStore()->barrier_data() != 0) && !need_acquire_load_store(n));
207   effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, TEMP tmp3, KILL cr0); // TEMP_DEF to avoid jump
208   format %{ "CMPXCHGW $res, $mem_ptr, $src1, $src2; as bool" %}
209   ins_encode %{
210     ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
211       $res$$Register,
212       $mem_ptr$$Register,
213       $src1$$Register,
214       $src2$$Register,
215       $tmp1$$Register,
216       $tmp2$$Register,
217       $tmp3$$Register,
218       /* exchange */ false,
219       /* is_narrow */ true,
220       /* weak */ false,
221       /* acquire */ false);
222   %}
223   ins_pipe(pipe_class_default);
224 %}
225 
226 instruct compareAndSwapN_acq_regP_regN_regN_shenandoah(iRegIdst res, iRegPdst mem_ptr, iRegNsrc src1, iRegNsrc src2, iRegPdstNoScratch tmp1, iRegPdstNoScratch tmp2, iRegPdstNoScratch tmp3, flagsRegCR0 cr0) %{
227   match(Set res (CompareAndSwapN mem_ptr (Binary src1 src2)));
228   predicate(UseShenandoahGC && (n->as_LoadStore()->barrier_data() != 0) && need_acquire_load_store(n));
229   effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, TEMP tmp3, KILL cr0); // TEMP_DEF to avoid jump
230   format %{ "CMPXCHGW $res, $mem_ptr, $src1, $src2; as bool" %}
231   ins_encode %{
232     ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
233       $res$$Register,
234       $mem_ptr$$Register,
235       $src1$$Register,
236       $src2$$Register,
237       $tmp1$$Register,
238       $tmp2$$Register,
239       $tmp3$$Register,
240       /* exchange */ false,
241       /* is_narrow */ true,
242       /* weak */ false,
243       /* acquire */ true);
244   %}
245   ins_pipe(pipe_class_default);
246 %}
247 
248 instruct compareAndSwapP_regP_regP_regP_shenandoah(iRegIdst res, iRegPdst mem_ptr, iRegPsrc src1, iRegPsrc src2, iRegPdstNoScratch tmp1, iRegPdstNoScratch tmp2, iRegPdstNoScratch tmp3, flagsRegCR0 cr0) %{
249   match(Set res (CompareAndSwapP mem_ptr (Binary src1 src2)));
250   effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, TEMP tmp3, KILL cr0); // TEMP_DEF to avoid jump
251   predicate(UseShenandoahGC && (n->as_LoadStore()->barrier_data() != 0) && !need_acquire_load_store(n));
252   format %{ "CMPXCHGD $res, $mem_ptr, $src1, $src2; as bool; ptr" %}
253   ins_encode %{
254     ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
255       $res$$Register,
256       $mem_ptr$$Register,
257       $src1$$Register,
258       $src2$$Register,
259       $tmp1$$Register,
260       $tmp2$$Register,
261       $tmp3$$Register,
262       /* exchange */ false,
263       /* is_narrow */ false,
264       /* weak */ false,
265       /* acquire */ false);
266   %}
267   ins_pipe(pipe_class_default);
268 %}
269 
270 instruct compareAndSwapP_acq_regP_regP_regP_shenandoah(iRegIdst res, iRegPdst mem_ptr, iRegPsrc src1, iRegPsrc src2, iRegPdstNoScratch tmp1, iRegPdstNoScratch tmp2, iRegPdstNoScratch tmp3, flagsRegCR0 cr0) %{
271   match(Set res (CompareAndSwapP mem_ptr (Binary src1 src2)));
272   effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, TEMP tmp3, KILL cr0); // TEMP_DEF to avoid jump
273   predicate(UseShenandoahGC && (n->as_LoadStore()->barrier_data() != 0) && need_acquire_load_store(n));
274   format %{ "CMPXCHGD $res, $mem_ptr, $src1, $src2; as bool; ptr" %}
275   ins_encode %{
276     ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
277       $res$$Register,
278       $mem_ptr$$Register,
279       $src1$$Register,
280       $src2$$Register,
281       $tmp1$$Register,
282       $tmp2$$Register,
283       $tmp3$$Register,
284       /* exchange */ false,
285       /* is_narrow */ false,
286       /* weak */ false,
287       /* acquire */ true);
288   %}
289   ins_pipe(pipe_class_default);
290 %}
291 
292 instruct weakCompareAndSwapN_regP_regN_regN_shenandoah(iRegIdst res, iRegPdst mem_ptr, iRegNsrc src1, iRegNsrc src2, iRegPdstNoScratch tmp1, iRegPdstNoScratch tmp2, iRegPdstNoScratch tmp3, flagsRegCR0 cr0) %{
293   match(Set res (WeakCompareAndSwapN mem_ptr (Binary src1 src2)));
294   predicate(UseShenandoahGC && (n->as_LoadStore()->barrier_data() != 0) && !need_acquire_load_store(n));
295   effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, TEMP tmp3, KILL cr0); // TEMP_DEF to avoid jump
296   format %{ "weak CMPXCHGW acq $res, $mem_ptr, $src1, $src2; as bool" %}
297   ins_encode %{
298     ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
299       $res$$Register,
300       $mem_ptr$$Register,
301       $src1$$Register,
302       $src2$$Register,
303       $tmp1$$Register,
304       $tmp2$$Register,
305       $tmp3$$Register,
306       /* exchange */ false,
307       /* is_narrow */ true,
308       /* weak */ true,
309       /* acquire */ false);
310   %}
311   ins_pipe(pipe_class_default);
312 %}
313 
314 instruct weakCompareAndSwapN_acq_regP_regN_regN_shenandoah(iRegIdst res, iRegPdst mem_ptr, iRegNsrc src1, iRegNsrc src2, iRegPdstNoScratch tmp1, iRegPdstNoScratch tmp2, iRegPdstNoScratch tmp3, flagsRegCR0 cr0) %{
315   match(Set res (WeakCompareAndSwapN mem_ptr (Binary src1 src2)));
316   predicate(UseShenandoahGC && (n->as_LoadStore()->barrier_data() != 0) && need_acquire_load_store(n));
317   effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, TEMP tmp3, KILL cr0); // TEMP_DEF to avoid jump
318   format %{ "weak CMPXCHGW acq $res, $mem_ptr, $src1, $src2; as bool" %}
319   ins_encode %{
320     ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
321       $res$$Register,
322       $mem_ptr$$Register,
323       $src1$$Register,
324       $src2$$Register,
325       $tmp1$$Register,
326       $tmp2$$Register,
327       $tmp3$$Register,
328       /* exchange */ false,
329       /* is_narrow */ true,
330       /* weak */ true,
331       /* acquire */ true);
332   %}
333   ins_pipe(pipe_class_default);
334 %}
335 
336 instruct weakCompareAndSwapP_regP_regP_regP_shenandoah(iRegIdst res, iRegPdst mem_ptr, iRegPsrc src1, iRegPsrc src2, iRegPdstNoScratch tmp1, iRegPdstNoScratch tmp2, iRegPdstNoScratch tmp3, flagsRegCR0 cr0) %{
337   match(Set res (WeakCompareAndSwapP mem_ptr (Binary src1 src2)));
338   predicate(UseShenandoahGC && (n->as_LoadStore()->barrier_data() != 0) && !need_acquire_load_store(n));
339   effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, TEMP tmp3, KILL cr0); // TEMP_DEF to avoid jump
340   format %{ "weak CMPXCHGD $res, $mem_ptr, $src1, $src2; as bool; ptr" %}
341   ins_encode %{
342     ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
343       $res$$Register,
344       $mem_ptr$$Register,
345       $src1$$Register,
346       $src2$$Register,
347       $tmp1$$Register,
348       $tmp2$$Register,
349       $tmp3$$Register,
350       /* exchange */ false,
351       /* is_narrow */ false,
352       /* weak */ true,
353       /* acquire */ false);
354   %}
355   ins_pipe(pipe_class_default);
356 %}
357 
358 instruct weakCompareAndSwapP_acq_regP_regP_regP_shenandoah(iRegIdst res, iRegPdst mem_ptr, iRegPsrc src1, iRegPsrc src2, iRegPdstNoScratch tmp1, iRegPdstNoScratch tmp2, iRegPdstNoScratch tmp3, flagsRegCR0 cr0) %{
359   match(Set res (WeakCompareAndSwapP mem_ptr (Binary src1 src2)));
360   predicate(UseShenandoahGC && (n->as_LoadStore()->barrier_data() != 0) && need_acquire_load_store(n));
361   effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, TEMP tmp3, KILL cr0); // TEMP_DEF to avoid jump
362   format %{ "weak CMPXCHGD $res, $mem_ptr, $src1, $src2; as bool; ptr" %}
363   ins_encode %{
364     ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
365       $res$$Register,
366       $mem_ptr$$Register,
367       $src1$$Register,
368       $src2$$Register,
369       $tmp1$$Register,
370       $tmp2$$Register,
371       $tmp3$$Register,
372       /* exchange */ false,
373       /* is_narrow */ false,
374       /* weak */ true,
375       /* acquire */ true);
376   %}
377   ins_pipe(pipe_class_default);
378 %}
379 
380 instruct compareAndExchangeN_regP_regN_regN_shenandoah(iRegNdst res, iRegPdst mem_ptr, iRegNsrc src1, iRegNsrc src2, iRegPdstNoScratch tmp1, iRegPdstNoScratch tmp2, iRegPdstNoScratch tmp3, flagsRegCR0 cr0) %{
381   match(Set res (CompareAndExchangeN mem_ptr (Binary src1 src2)));
382   predicate(UseShenandoahGC && (n->as_LoadStore()->barrier_data() != 0) && !need_acquire_load_store(n));
383   effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, TEMP tmp3, KILL cr0);
384   format %{ "CMPXCHGW $res, $mem_ptr, $src1, $src2; as narrow oop" %}
385   ins_encode %{
386     ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
387       $res$$Register,
388       $mem_ptr$$Register,
389       $src1$$Register,
390       $src2$$Register,
391       $tmp1$$Register,
392       $tmp2$$Register,
393       $tmp3$$Register,
394       /* exchange */ true,
395       /* is_narrow */ true,
396       /* weak */ false,
397       /* acquire */ false);
398   %}
399   ins_pipe(pipe_class_default);
400 %}
401 
402 instruct compareAndExchangeN_acq_regP_regN_regN_shenandoah(iRegNdst res, iRegPdst mem_ptr, iRegNsrc src1, iRegNsrc src2, iRegPdstNoScratch tmp1, iRegPdstNoScratch tmp2, iRegPdstNoScratch tmp3, flagsRegCR0 cr0) %{
403   match(Set res (CompareAndExchangeN mem_ptr (Binary src1 src2)));
404   predicate(UseShenandoahGC && (n->as_LoadStore()->barrier_data() != 0) && need_acquire_load_store(n));
405   effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, TEMP tmp3, KILL cr0);
406   format %{ "CMPXCHGW $res, $mem_ptr, $src1, $src2; as narrow oop" %}
407   ins_encode %{
408     ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
409       $res$$Register,
410       $mem_ptr$$Register,
411       $src1$$Register,
412       $src2$$Register,
413       $tmp1$$Register,
414       $tmp2$$Register,
415       $tmp3$$Register,
416       /* exchange */ true,
417       /* is_narrow */ true,
418       /* weak */ false,
419       /* acquire */ true);
420   %}
421   ins_pipe(pipe_class_default);
422 %}
423 
424 instruct compareAndExchangeP_regP_regP_regP_shenandoah(iRegPdst res, iRegPdst mem_ptr, iRegPsrc src1, iRegPsrc src2, iRegPdstNoScratch tmp1, iRegPdstNoScratch tmp2, iRegPdstNoScratch tmp3, flagsRegCR0 cr0) %{
425   match(Set res (CompareAndExchangeP mem_ptr (Binary src1 src2)));
426   predicate(UseShenandoahGC && (n->as_LoadStore()->barrier_data() != 0) && !need_acquire_load_store(n));
427   effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, TEMP tmp3, KILL cr0);
428   format %{ "CMPXCHGD $res, $mem_ptr, $src1, $src2; as ptr; ptr" %}
429   ins_encode %{
430     ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
431       $res$$Register,
432       $mem_ptr$$Register,
433       $src1$$Register,
434       $src2$$Register,
435       $tmp1$$Register,
436       $tmp2$$Register,
437       $tmp3$$Register,
438       /* exchange */ true,
439       /* is_narrow */ false,
440       /* weak */ false,
441       /* acquire */ false);
442   %}
443   ins_pipe(pipe_class_default);
444 %}
445 
446 instruct compareAndExchangeP_acq_regP_regP_regP_shenandoah(iRegPdst res, iRegPdst mem_ptr, iRegPsrc src1, iRegPsrc src2, iRegPdstNoScratch tmp1, iRegPdstNoScratch tmp2, iRegPdstNoScratch tmp3, flagsRegCR0 cr0) %{
447   match(Set res (CompareAndExchangeP mem_ptr (Binary src1 src2)));
448   predicate(UseShenandoahGC && (n->as_LoadStore()->barrier_data() != 0) && need_acquire_load_store(n));
449   effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, TEMP tmp3, KILL cr0);
450   format %{ "CMPXCHGD $res, $mem_ptr, $src1, $src2; as ptr; ptr" %}
451   ins_encode %{
452     ShenandoahBarrierSet::assembler()->compare_and_set_c2(this, masm,
453       $res$$Register,
454       $mem_ptr$$Register,
455       $src1$$Register,
456       $src2$$Register,
457       $tmp1$$Register,
458       $tmp2$$Register,
459       $tmp3$$Register,
460       /* exchange */ true,
461       /* is_narrow */ false,
462       /* weak */ false,
463       /* acquire */ true);
464   %}
465   ins_pipe(pipe_class_default);
466 %}
467 
468 instruct getAndSetP_shenandoah(iRegPdst res, iRegPdst mem_ptr, iRegPsrc src, iRegPdstNoScratch tmp1, iRegPdstNoScratch tmp2, iRegPdstNoScratch tmp3, flagsRegCR0 cr0) %{
469   match(Set res (GetAndSetP mem_ptr src));
470   predicate(UseShenandoahGC && (n->as_LoadStore()->barrier_data() != 0));
471   effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, TEMP tmp3, KILL cr0);
472   format %{ "GetAndSetP $res, $mem_ptr, $src" %}
473   ins_encode %{
474     ShenandoahBarrierSet::assembler()->get_and_set_c2(this, masm,
475       $res$$Register,
476       $src$$Register,
477       $mem_ptr$$Register,
478       $tmp1$$Register,
479       $tmp2$$Register,
480       $tmp3$$Register);
481   %}
482   ins_pipe(pipe_class_default);
483 %}
484 
485 instruct getAndSetN_shenandoah(iRegNdst res, iRegPdst mem_ptr, iRegNsrc src, iRegPdstNoScratch tmp1, iRegPdstNoScratch tmp2, iRegPdstNoScratch tmp3, flagsRegCR0 cr0) %{
486   match(Set res (GetAndSetN mem_ptr src));
487   predicate(UseShenandoahGC && (n->as_LoadStore()->barrier_data() != 0));
488   effect(TEMP_DEF res, TEMP tmp1, TEMP tmp2, TEMP tmp3, KILL cr0);
489   format %{ "GetAndSetN $res, $mem_ptr, $src" %}
490   ins_encode %{
491     ShenandoahBarrierSet::assembler()->get_and_set_c2(this, masm,
492       $res$$Register,
493       $src$$Register,
494       $mem_ptr$$Register,
495       $tmp1$$Register,
496       $tmp2$$Register,
497       $tmp3$$Register);
498   %}
499   ins_pipe(pipe_class_default);
500 %}
501