1 From f797260adaf52bee0ec0e16190bbefbe1bfc3692 Mon Sep 17 00:00:00 2001
2 From: Patrick O'Neill <patrick@rivosinc.com>
3 Date: Tue, 18 Apr 2023 14:33:13 -0700
4 Subject: [PATCH] RISCV: Inline subword atomic ops
6 RISC-V has no support for subword atomic operations; code currently
7 generates libatomic library calls.
9 This patch changes the default behavior to inline subword atomic calls
10 (using the same logic as the existing library call).
11 Behavior can be specified using the -minline-atomics and
12 -mno-inline-atomics command line flags.
14 gcc/libgcc/config/riscv/atomic.c has the same logic implemented in asm.
15 This will need to stay for backwards compatibility and the
16 -mno-inline-atomics flag.
18 2023-04-18 Patrick O'Neill <patrick@rivosinc.com>
22 * config/riscv/riscv-protos.h: Add helper function stubs.
23 * config/riscv/riscv.cc: Add helper functions for subword masking.
24 * config/riscv/riscv.opt: Add command-line flag.
25 * config/riscv/sync.md: Add masking logic and inline asm for fetch_and_op,
26 fetch_and_nand, CAS, and exchange ops.
27 * doc/invoke.texi: Add blurb regarding command-line flag.
31 * config/riscv/atomic.c: Add reference to duplicate logic.
33 gcc/testsuite/ChangeLog:
35 * gcc.target/riscv/inline-atomics-1.c: New test.
36 * gcc.target/riscv/inline-atomics-2.c: New test.
37 * gcc.target/riscv/inline-atomics-3.c: New test.
38 * gcc.target/riscv/inline-atomics-4.c: New test.
39 * gcc.target/riscv/inline-atomics-5.c: New test.
40 * gcc.target/riscv/inline-atomics-6.c: New test.
41 * gcc.target/riscv/inline-atomics-7.c: New test.
42 * gcc.target/riscv/inline-atomics-8.c: New test.
44 Signed-off-by: Patrick O'Neill <patrick@rivosinc.com>
45 Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
47 gcc/config/riscv/riscv-protos.h | 2 +
48 gcc/config/riscv/riscv.cc | 49 ++
49 gcc/config/riscv/riscv.opt | 4 +
50 gcc/config/riscv/sync.md | 301 +++++++++
51 gcc/doc/invoke.texi | 10 +-
52 .../gcc.target/riscv/inline-atomics-1.c | 18 +
53 .../gcc.target/riscv/inline-atomics-2.c | 9 +
54 .../gcc.target/riscv/inline-atomics-3.c | 569 ++++++++++++++++++
55 .../gcc.target/riscv/inline-atomics-4.c | 566 +++++++++++++++++
56 .../gcc.target/riscv/inline-atomics-5.c | 87 +++
57 .../gcc.target/riscv/inline-atomics-6.c | 87 +++
58 .../gcc.target/riscv/inline-atomics-7.c | 69 +++
59 .../gcc.target/riscv/inline-atomics-8.c | 69 +++
60 libgcc/config/riscv/atomic.c | 2 +
61 14 files changed, 1841 insertions(+), 1 deletion(-)
62 create mode 100644 gcc/testsuite/gcc.target/riscv/inline-atomics-1.c
63 create mode 100644 gcc/testsuite/gcc.target/riscv/inline-atomics-2.c
64 create mode 100644 gcc/testsuite/gcc.target/riscv/inline-atomics-3.c
65 create mode 100644 gcc/testsuite/gcc.target/riscv/inline-atomics-4.c
66 create mode 100644 gcc/testsuite/gcc.target/riscv/inline-atomics-5.c
67 create mode 100644 gcc/testsuite/gcc.target/riscv/inline-atomics-6.c
68 create mode 100644 gcc/testsuite/gcc.target/riscv/inline-atomics-7.c
69 create mode 100644 gcc/testsuite/gcc.target/riscv/inline-atomics-8.c
71 --- a/gcc/config/riscv/riscv-protos.h
72 +++ b/gcc/config/riscv/riscv-protos.h
73 @@ -79,6 +79,8 @@ extern void riscv_reinit (void);
74 extern poly_uint64 riscv_regmode_natural_size (machine_mode);
75 extern bool riscv_v_ext_vector_mode_p (machine_mode);
76 extern bool riscv_shamt_matches_mask_p (int, HOST_WIDE_INT);
77 +extern void riscv_subword_address (rtx, rtx *, rtx *, rtx *, rtx *);
78 +extern void riscv_lshift_subword (machine_mode, rtx, rtx, rtx *);
80 /* Routines implemented in riscv-c.cc. */
81 void riscv_cpu_cpp_builtins (cpp_reader *);
82 --- a/gcc/config/riscv/riscv.cc
83 +++ b/gcc/config/riscv/riscv.cc
84 @@ -7143,6 +7143,55 @@ riscv_zero_call_used_regs (HARD_REG_SET
88 +/* Given memory reference MEM, expand code to compute the aligned
89 + memory address, shift and mask values and store them into
90 + *ALIGNED_MEM, *SHIFT, *MASK and *NOT_MASK. */
93 +riscv_subword_address (rtx mem, rtx *aligned_mem, rtx *shift, rtx *mask,
96 + /* Align the memory address to a word. */
97 + rtx addr = force_reg (Pmode, XEXP (mem, 0));
99 + rtx addr_mask = gen_int_mode (-4, Pmode);
101 + rtx aligned_addr = gen_reg_rtx (Pmode);
102 + emit_move_insn (aligned_addr, gen_rtx_AND (Pmode, addr, addr_mask));
104 + *aligned_mem = change_address (mem, SImode, aligned_addr);
106 + /* Calculate the shift amount. */
107 + emit_move_insn (*shift, gen_rtx_AND (SImode, gen_lowpart (SImode, addr),
108 + gen_int_mode (3, SImode)));
109 + emit_move_insn (*shift, gen_rtx_ASHIFT (SImode, *shift,
110 + gen_int_mode (3, SImode)));
112 + /* Calculate the mask. */
113 + int unshifted_mask = GET_MODE_MASK (GET_MODE (mem));
115 + emit_move_insn (*mask, gen_int_mode (unshifted_mask, SImode));
117 + emit_move_insn (*mask, gen_rtx_ASHIFT (SImode, *mask,
118 + gen_lowpart (QImode, *shift)));
120 + emit_move_insn (*not_mask, gen_rtx_NOT(SImode, *mask));
123 +/* Leftshift a subword within an SImode register. */
126 +riscv_lshift_subword (machine_mode mode, rtx value, rtx shift,
127 + rtx *shifted_value)
129 + rtx value_reg = gen_reg_rtx (SImode);
130 + emit_move_insn (value_reg, simplify_gen_subreg (SImode, value,
133 + emit_move_insn(*shifted_value, gen_rtx_ASHIFT (SImode, value_reg,
134 + gen_lowpart (QImode, shift)));
137 /* Initialize the GCC target structure. */
138 #undef TARGET_ASM_ALIGNED_HI_OP
139 #define TARGET_ASM_ALIGNED_HI_OP "\t.half\t"
140 --- a/gcc/config/riscv/riscv.opt
141 +++ b/gcc/config/riscv/riscv.opt
142 @@ -238,6 +238,10 @@ int riscv_sv_subext
144 int riscv_xthead_subext
147 +Target Var(TARGET_INLINE_SUBWORD_ATOMIC) Init(1)
148 +Always inline subword atomic operations.
151 Name(isa_spec_class) Type(enum riscv_isa_spec_class)
152 Supported ISA specs (for use with the -misa-spec= option):
153 --- a/gcc/config/riscv/sync.md
154 +++ b/gcc/config/riscv/sync.md
157 (define_c_enum "unspec" [
158 UNSPEC_COMPARE_AND_SWAP
159 + UNSPEC_COMPARE_AND_SWAP_SUBWORD
161 + UNSPEC_SYNC_OLD_OP_SUBWORD
163 + UNSPEC_SYNC_EXCHANGE_SUBWORD
165 UNSPEC_MEMORY_BARRIER
168 [(set_attr "type" "atomic")
169 (set (attr "length") (const_int 8))])
171 +(define_insn "subword_atomic_fetch_strong_<atomic_optab>"
172 + [(set (match_operand:SI 0 "register_operand" "=&r") ;; old value at mem
173 + (match_operand:SI 1 "memory_operand" "+A")) ;; mem location
175 + (unspec_volatile:SI
176 + [(any_atomic:SI (match_dup 1)
177 + (match_operand:SI 2 "register_operand" "rI")) ;; value for op
178 + (match_operand:SI 3 "register_operand" "rI")] ;; mask
179 + UNSPEC_SYNC_OLD_OP_SUBWORD))
180 + (match_operand:SI 4 "register_operand" "rI") ;; not_mask
181 + (clobber (match_scratch:SI 5 "=&r")) ;; tmp_1
182 + (clobber (match_scratch:SI 6 "=&r"))] ;; tmp_2
183 + "TARGET_ATOMIC && TARGET_INLINE_SUBWORD_ATOMIC"
186 + "lr.w.aq\t%0, %1\;"
187 + "<insn>\t%5, %0, %2\;"
188 + "and\t%5, %5, %3\;"
189 + "and\t%6, %0, %4\;"
191 + "sc.w.rl\t%5, %6, %1\;"
194 + [(set (attr "length") (const_int 28))])
196 +(define_expand "atomic_fetch_nand<mode>"
197 + [(match_operand:SHORT 0 "register_operand") ;; old value at mem
198 + (not:SHORT (and:SHORT (match_operand:SHORT 1 "memory_operand") ;; mem location
199 + (match_operand:SHORT 2 "reg_or_0_operand"))) ;; value for op
200 + (match_operand:SI 3 "const_int_operand")] ;; model
201 + "TARGET_ATOMIC && TARGET_INLINE_SUBWORD_ATOMIC"
203 + /* We have no QImode/HImode atomics, so form a mask, then use
204 + subword_atomic_fetch_strong_nand to implement a LR/SC version of the
207 + /* Logic duplicated in gcc/libgcc/config/riscv/atomic.c for use when inlining
210 + rtx old = gen_reg_rtx (SImode);
211 + rtx mem = operands[1];
212 + rtx value = operands[2];
213 + rtx aligned_mem = gen_reg_rtx (SImode);
214 + rtx shift = gen_reg_rtx (SImode);
215 + rtx mask = gen_reg_rtx (SImode);
216 + rtx not_mask = gen_reg_rtx (SImode);
218 + riscv_subword_address (mem, &aligned_mem, &shift, &mask, ¬_mask);
220 + rtx shifted_value = gen_reg_rtx (SImode);
221 + riscv_lshift_subword (<MODE>mode, value, shift, &shifted_value);
223 + emit_insn (gen_subword_atomic_fetch_strong_nand (old, aligned_mem,
227 + emit_move_insn (old, gen_rtx_ASHIFTRT (SImode, old,
228 + gen_lowpart (QImode, shift)));
230 + emit_move_insn (operands[0], gen_lowpart (<MODE>mode, old));
235 +(define_insn "subword_atomic_fetch_strong_nand"
236 + [(set (match_operand:SI 0 "register_operand" "=&r") ;; old value at mem
237 + (match_operand:SI 1 "memory_operand" "+A")) ;; mem location
239 + (unspec_volatile:SI
240 + [(not:SI (and:SI (match_dup 1)
241 + (match_operand:SI 2 "register_operand" "rI"))) ;; value for op
242 + (match_operand:SI 3 "register_operand" "rI")] ;; mask
243 + UNSPEC_SYNC_OLD_OP_SUBWORD))
244 + (match_operand:SI 4 "register_operand" "rI") ;; not_mask
245 + (clobber (match_scratch:SI 5 "=&r")) ;; tmp_1
246 + (clobber (match_scratch:SI 6 "=&r"))] ;; tmp_2
247 + "TARGET_ATOMIC && TARGET_INLINE_SUBWORD_ATOMIC"
250 + "lr.w.aq\t%0, %1\;"
251 + "and\t%5, %0, %2\;"
253 + "and\t%5, %5, %3\;"
254 + "and\t%6, %0, %4\;"
256 + "sc.w.rl\t%5, %6, %1\;"
259 + [(set (attr "length") (const_int 32))])
261 +(define_expand "atomic_fetch_<atomic_optab><mode>"
262 + [(match_operand:SHORT 0 "register_operand") ;; old value at mem
263 + (any_atomic:SHORT (match_operand:SHORT 1 "memory_operand") ;; mem location
264 + (match_operand:SHORT 2 "reg_or_0_operand")) ;; value for op
265 + (match_operand:SI 3 "const_int_operand")] ;; model
266 + "TARGET_ATOMIC && TARGET_INLINE_SUBWORD_ATOMIC"
268 + /* We have no QImode/HImode atomics, so form a mask, then use
269 + subword_atomic_fetch_strong_<mode> to implement a LR/SC version of the
272 + /* Logic duplicated in gcc/libgcc/config/riscv/atomic.c for use when inlining
275 + rtx old = gen_reg_rtx (SImode);
276 + rtx mem = operands[1];
277 + rtx value = operands[2];
278 + rtx aligned_mem = gen_reg_rtx (SImode);
279 + rtx shift = gen_reg_rtx (SImode);
280 + rtx mask = gen_reg_rtx (SImode);
281 + rtx not_mask = gen_reg_rtx (SImode);
283 + riscv_subword_address (mem, &aligned_mem, &shift, &mask, ¬_mask);
285 + rtx shifted_value = gen_reg_rtx (SImode);
286 + riscv_lshift_subword (<MODE>mode, value, shift, &shifted_value);
288 + emit_insn (gen_subword_atomic_fetch_strong_<atomic_optab> (old, aligned_mem,
292 + emit_move_insn (old, gen_rtx_ASHIFTRT (SImode, old,
293 + gen_lowpart (QImode, shift)));
295 + emit_move_insn (operands[0], gen_lowpart (<MODE>mode, old));
300 (define_insn "atomic_exchange<mode>"
301 [(set (match_operand:GPR 0 "register_operand" "=&r")
304 [(set_attr "type" "atomic")
305 (set (attr "length") (const_int 8))])
307 +(define_expand "atomic_exchange<mode>"
308 + [(match_operand:SHORT 0 "register_operand") ;; old value at mem
309 + (match_operand:SHORT 1 "memory_operand") ;; mem location
310 + (match_operand:SHORT 2 "register_operand") ;; value
311 + (match_operand:SI 3 "const_int_operand")] ;; model
312 + "TARGET_ATOMIC && TARGET_INLINE_SUBWORD_ATOMIC"
314 + rtx old = gen_reg_rtx (SImode);
315 + rtx mem = operands[1];
316 + rtx value = operands[2];
317 + rtx aligned_mem = gen_reg_rtx (SImode);
318 + rtx shift = gen_reg_rtx (SImode);
319 + rtx mask = gen_reg_rtx (SImode);
320 + rtx not_mask = gen_reg_rtx (SImode);
322 + riscv_subword_address (mem, &aligned_mem, &shift, &mask, ¬_mask);
324 + rtx shifted_value = gen_reg_rtx (SImode);
325 + riscv_lshift_subword (<MODE>mode, value, shift, &shifted_value);
327 + emit_insn (gen_subword_atomic_exchange_strong (old, aligned_mem,
328 + shifted_value, not_mask));
330 + emit_move_insn (old, gen_rtx_ASHIFTRT (SImode, old,
331 + gen_lowpart (QImode, shift)));
333 + emit_move_insn (operands[0], gen_lowpart (<MODE>mode, old));
337 +(define_insn "subword_atomic_exchange_strong"
338 + [(set (match_operand:SI 0 "register_operand" "=&r") ;; old value at mem
339 + (match_operand:SI 1 "memory_operand" "+A")) ;; mem location
341 + (unspec_volatile:SI
342 + [(match_operand:SI 2 "reg_or_0_operand" "rI") ;; value
343 + (match_operand:SI 3 "reg_or_0_operand" "rI")] ;; not_mask
344 + UNSPEC_SYNC_EXCHANGE_SUBWORD))
345 + (clobber (match_scratch:SI 4 "=&r"))] ;; tmp_1
346 + "TARGET_ATOMIC && TARGET_INLINE_SUBWORD_ATOMIC"
349 + "lr.w.aq\t%0, %1\;"
350 + "and\t%4, %0, %3\;"
352 + "sc.w.rl\t%4, %4, %1\;"
355 + [(set (attr "length") (const_int 20))])
357 (define_insn "atomic_cas_value_strong<mode>"
358 [(set (match_operand:GPR 0 "register_operand" "=&r")
359 (match_operand:GPR 1 "memory_operand" "+A"))
360 @@ -153,6 +335,125 @@
364 +(define_expand "atomic_compare_and_swap<mode>"
365 + [(match_operand:SI 0 "register_operand") ;; bool output
366 + (match_operand:SHORT 1 "register_operand") ;; val output
367 + (match_operand:SHORT 2 "memory_operand") ;; memory
368 + (match_operand:SHORT 3 "reg_or_0_operand") ;; expected value
369 + (match_operand:SHORT 4 "reg_or_0_operand") ;; desired value
370 + (match_operand:SI 5 "const_int_operand") ;; is_weak
371 + (match_operand:SI 6 "const_int_operand") ;; mod_s
372 + (match_operand:SI 7 "const_int_operand")] ;; mod_f
373 + "TARGET_ATOMIC && TARGET_INLINE_SUBWORD_ATOMIC"
375 + emit_insn (gen_atomic_cas_value_strong<mode> (operands[1], operands[2],
376 + operands[3], operands[4],
377 + operands[6], operands[7]));
379 + rtx val = gen_reg_rtx (SImode);
380 + if (operands[1] != const0_rtx)
381 + emit_move_insn (val, gen_rtx_SIGN_EXTEND (SImode, operands[1]));
383 + emit_move_insn (val, const0_rtx);
385 + rtx exp = gen_reg_rtx (SImode);
386 + if (operands[3] != const0_rtx)
387 + emit_move_insn (exp, gen_rtx_SIGN_EXTEND (SImode, operands[3]));
389 + emit_move_insn (exp, const0_rtx);
392 + if (exp != const0_rtx)
394 + rtx difference = gen_rtx_MINUS (SImode, val, exp);
395 + compare = gen_reg_rtx (SImode);
396 + emit_move_insn (compare, difference);
399 + if (word_mode != SImode)
401 + rtx reg = gen_reg_rtx (word_mode);
402 + emit_move_insn (reg, gen_rtx_SIGN_EXTEND (word_mode, compare));
406 + emit_move_insn (operands[0], gen_rtx_EQ (SImode, compare, const0_rtx));
410 +(define_expand "atomic_cas_value_strong<mode>"
411 + [(match_operand:SHORT 0 "register_operand") ;; val output
412 + (match_operand:SHORT 1 "memory_operand") ;; memory
413 + (match_operand:SHORT 2 "reg_or_0_operand") ;; expected value
414 + (match_operand:SHORT 3 "reg_or_0_operand") ;; desired value
415 + (match_operand:SI 4 "const_int_operand") ;; mod_s
416 + (match_operand:SI 5 "const_int_operand") ;; mod_f
417 + (match_scratch:SHORT 6)]
418 + "TARGET_ATOMIC && TARGET_INLINE_SUBWORD_ATOMIC"
420 + /* We have no QImode/HImode atomics, so form a mask, then use
421 + subword_atomic_cas_strong<mode> to implement a LR/SC version of the
424 + /* Logic duplicated in gcc/libgcc/config/riscv/atomic.c for use when inlining
427 + rtx old = gen_reg_rtx (SImode);
428 + rtx mem = operands[1];
429 + rtx aligned_mem = gen_reg_rtx (SImode);
430 + rtx shift = gen_reg_rtx (SImode);
431 + rtx mask = gen_reg_rtx (SImode);
432 + rtx not_mask = gen_reg_rtx (SImode);
434 + riscv_subword_address (mem, &aligned_mem, &shift, &mask, ¬_mask);
436 + rtx o = operands[2];
437 + rtx n = operands[3];
438 + rtx shifted_o = gen_reg_rtx (SImode);
439 + rtx shifted_n = gen_reg_rtx (SImode);
441 + riscv_lshift_subword (<MODE>mode, o, shift, &shifted_o);
442 + riscv_lshift_subword (<MODE>mode, n, shift, &shifted_n);
444 + emit_move_insn (shifted_o, gen_rtx_AND (SImode, shifted_o, mask));
445 + emit_move_insn (shifted_n, gen_rtx_AND (SImode, shifted_n, mask));
447 + emit_insn (gen_subword_atomic_cas_strong (old, aligned_mem,
448 + shifted_o, shifted_n,
451 + emit_move_insn (old, gen_rtx_ASHIFTRT (SImode, old,
452 + gen_lowpart (QImode, shift)));
454 + emit_move_insn (operands[0], gen_lowpart (<MODE>mode, old));
459 +(define_insn "subword_atomic_cas_strong"
460 + [(set (match_operand:SI 0 "register_operand" "=&r") ;; old value at mem
461 + (match_operand:SI 1 "memory_operand" "+A")) ;; mem location
463 + (unspec_volatile:SI [(match_operand:SI 2 "reg_or_0_operand" "rJ") ;; expected value
464 + (match_operand:SI 3 "reg_or_0_operand" "rJ")] ;; desired value
465 + UNSPEC_COMPARE_AND_SWAP_SUBWORD))
466 + (match_operand:SI 4 "register_operand" "rI") ;; mask
467 + (match_operand:SI 5 "register_operand" "rI") ;; not_mask
468 + (clobber (match_scratch:SI 6 "=&r"))] ;; tmp_1
469 + "TARGET_ATOMIC && TARGET_INLINE_SUBWORD_ATOMIC"
472 + "lr.w.aq\t%0, %1\;"
473 + "and\t%6, %0, %4\;"
474 + "bne\t%6, %z2, 1f\;"
475 + "and\t%6, %0, %5\;"
477 + "sc.w.rl\t%6, %6, %1\;"
481 + [(set (attr "length") (const_int 28))])
483 (define_expand "atomic_test_and_set"
484 [(match_operand:QI 0 "register_operand" "") ;; bool output
485 (match_operand:QI 1 "memory_operand" "+A") ;; memory
486 --- a/gcc/doc/invoke.texi
487 +++ b/gcc/doc/invoke.texi
488 @@ -1226,7 +1226,8 @@ See RS/6000 and PowerPC Options.
489 -mbig-endian -mlittle-endian
490 -mstack-protector-guard=@var{guard} -mstack-protector-guard-reg=@var{reg}
491 -mstack-protector-guard-offset=@var{offset}
492 --mcsr-check -mno-csr-check}
493 +-mcsr-check -mno-csr-check
494 +-minline-atomics -mno-inline-atomics}
497 @gccoptlist{-msim -mmul=none -mmul=g13 -mmul=g14 -mallregs
498 @@ -29006,6 +29007,13 @@ Do or don't use smaller but slower prolo
499 library function calls. The default is to use fast inline prologues and
502 +@opindex minline-atomics
503 +@item -minline-atomics
504 +@itemx -mno-inline-atomics
505 +Do or don't use smaller but slower subword atomic emulation code that uses
506 +libatomic function calls. The default is to use fast inline subword atomics
507 +that do not require libatomic.
509 @opindex mshorten-memrefs
510 @item -mshorten-memrefs
511 @itemx -mno-shorten-memrefs
513 +++ b/gcc/testsuite/gcc.target/riscv/inline-atomics-1.c
515 +/* { dg-do compile } */
516 +/* { dg-options "-mno-inline-atomics" } */
517 +/* { dg-message "note: '__sync_fetch_and_nand' changed semantics in GCC 4.4" "fetch_and_nand" { target *-*-* } 0 } */
518 +/* { dg-final { scan-assembler "\tcall\t__sync_fetch_and_add_1" } } */
519 +/* { dg-final { scan-assembler "\tcall\t__sync_fetch_and_nand_1" } } */
520 +/* { dg-final { scan-assembler "\tcall\t__sync_bool_compare_and_swap_1" } } */
529 + __sync_fetch_and_add(&foo, 1);
530 + __sync_fetch_and_nand(&bar, 1);
531 + __sync_bool_compare_and_swap (&baz, 1, 2);
534 +++ b/gcc/testsuite/gcc.target/riscv/inline-atomics-2.c
536 +/* { dg-do compile } */
537 +/* Verify that subword atomics do not generate calls. */
538 +/* { dg-options "-minline-atomics" } */
539 +/* { dg-message "note: '__sync_fetch_and_nand' changed semantics in GCC 4.4" "fetch_and_nand" { target *-*-* } 0 } */
540 +/* { dg-final { scan-assembler-not "\tcall\t__sync_fetch_and_add_1" } } */
541 +/* { dg-final { scan-assembler-not "\tcall\t__sync_fetch_and_nand_1" } } */
542 +/* { dg-final { scan-assembler-not "\tcall\t__sync_bool_compare_and_swap_1" } } */
544 +#include "inline-atomics-1.c"
545 \ No newline at end of file
547 +++ b/gcc/testsuite/gcc.target/riscv/inline-atomics-3.c
549 +/* Check all char alignments. */
550 +/* Duplicate logic as libatomic/testsuite/libatomic.c/atomic-op-1.c */
551 +/* Test __atomic routines for existence and proper execution on 1 byte
552 + values with each valid memory model. */
554 +/* { dg-options "-minline-atomics -Wno-address-of-packed-member" } */
556 +/* Test the execution of the __atomic_*OP builtin routines for a char. */
558 +extern void abort(void);
561 +const char init = ~0;
569 +} __attribute__ ((packed)) A;
571 +/* The fetch_op routines return the original value before the operation. */
574 +test_fetch_add (char* v)
579 + if (__atomic_fetch_add (v, count, __ATOMIC_RELAXED) != 0)
582 + if (__atomic_fetch_add (v, 1, __ATOMIC_CONSUME) != 1)
585 + if (__atomic_fetch_add (v, count, __ATOMIC_ACQUIRE) != 2)
588 + if (__atomic_fetch_add (v, 1, __ATOMIC_RELEASE) != 3)
591 + if (__atomic_fetch_add (v, count, __ATOMIC_ACQ_REL) != 4)
594 + if (__atomic_fetch_add (v, 1, __ATOMIC_SEQ_CST) != 5)
600 +test_fetch_sub (char* v)
605 + if (__atomic_fetch_sub (v, count + 1, __ATOMIC_RELAXED) != res--)
608 + if (__atomic_fetch_sub (v, 1, __ATOMIC_CONSUME) != res--)
611 + if (__atomic_fetch_sub (v, count + 1, __ATOMIC_ACQUIRE) != res--)
614 + if (__atomic_fetch_sub (v, 1, __ATOMIC_RELEASE) != res--)
617 + if (__atomic_fetch_sub (v, count + 1, __ATOMIC_ACQ_REL) != res--)
620 + if (__atomic_fetch_sub (v, 1, __ATOMIC_SEQ_CST) != res--)
625 +test_fetch_and (char* v)
629 + if (__atomic_fetch_and (v, 0, __ATOMIC_RELAXED) != init)
632 + if (__atomic_fetch_and (v, init, __ATOMIC_CONSUME) != 0)
635 + if (__atomic_fetch_and (v, 0, __ATOMIC_ACQUIRE) != 0)
639 + if (__atomic_fetch_and (v, init, __ATOMIC_RELEASE) != init)
642 + if (__atomic_fetch_and (v, 0, __ATOMIC_ACQ_REL) != init)
645 + if (__atomic_fetch_and (v, 0, __ATOMIC_SEQ_CST) != 0)
650 +test_fetch_nand (char* v)
654 + if (__atomic_fetch_nand (v, 0, __ATOMIC_RELAXED) != init)
657 + if (__atomic_fetch_nand (v, init, __ATOMIC_CONSUME) != init)
660 + if (__atomic_fetch_nand (v, 0, __ATOMIC_ACQUIRE) != 0 )
663 + if (__atomic_fetch_nand (v, init, __ATOMIC_RELEASE) != init)
666 + if (__atomic_fetch_nand (v, init, __ATOMIC_ACQ_REL) != 0)
669 + if (__atomic_fetch_nand (v, 0, __ATOMIC_SEQ_CST) != init)
674 +test_fetch_xor (char* v)
679 + if (__atomic_fetch_xor (v, count, __ATOMIC_RELAXED) != init)
682 + if (__atomic_fetch_xor (v, ~count, __ATOMIC_CONSUME) != init)
685 + if (__atomic_fetch_xor (v, 0, __ATOMIC_ACQUIRE) != 0)
688 + if (__atomic_fetch_xor (v, ~count, __ATOMIC_RELEASE) != 0)
691 + if (__atomic_fetch_xor (v, 0, __ATOMIC_ACQ_REL) != init)
694 + if (__atomic_fetch_xor (v, ~count, __ATOMIC_SEQ_CST) != init)
699 +test_fetch_or (char* v)
704 + if (__atomic_fetch_or (v, count, __ATOMIC_RELAXED) != 0)
708 + if (__atomic_fetch_or (v, 2, __ATOMIC_CONSUME) != 1)
712 + if (__atomic_fetch_or (v, count, __ATOMIC_ACQUIRE) != 3)
716 + if (__atomic_fetch_or (v, 8, __ATOMIC_RELEASE) != 7)
720 + if (__atomic_fetch_or (v, count, __ATOMIC_ACQ_REL) != 15)
724 + if (__atomic_fetch_or (v, count, __ATOMIC_SEQ_CST) != 31)
728 +/* The OP_fetch routines return the new value after the operation. */
731 +test_add_fetch (char* v)
736 + if (__atomic_add_fetch (v, count, __ATOMIC_RELAXED) != 1)
739 + if (__atomic_add_fetch (v, 1, __ATOMIC_CONSUME) != 2)
742 + if (__atomic_add_fetch (v, count, __ATOMIC_ACQUIRE) != 3)
745 + if (__atomic_add_fetch (v, 1, __ATOMIC_RELEASE) != 4)
748 + if (__atomic_add_fetch (v, count, __ATOMIC_ACQ_REL) != 5)
751 + if (__atomic_add_fetch (v, count, __ATOMIC_SEQ_CST) != 6)
757 +test_sub_fetch (char* v)
762 + if (__atomic_sub_fetch (v, count + 1, __ATOMIC_RELAXED) != --res)
765 + if (__atomic_sub_fetch (v, 1, __ATOMIC_CONSUME) != --res)
768 + if (__atomic_sub_fetch (v, count + 1, __ATOMIC_ACQUIRE) != --res)
771 + if (__atomic_sub_fetch (v, 1, __ATOMIC_RELEASE) != --res)
774 + if (__atomic_sub_fetch (v, count + 1, __ATOMIC_ACQ_REL) != --res)
777 + if (__atomic_sub_fetch (v, count + 1, __ATOMIC_SEQ_CST) != --res)
782 +test_and_fetch (char* v)
786 + if (__atomic_and_fetch (v, 0, __ATOMIC_RELAXED) != 0)
790 + if (__atomic_and_fetch (v, init, __ATOMIC_CONSUME) != init)
793 + if (__atomic_and_fetch (v, 0, __ATOMIC_ACQUIRE) != 0)
797 + if (__atomic_and_fetch (v, init, __ATOMIC_RELEASE) != init)
800 + if (__atomic_and_fetch (v, 0, __ATOMIC_ACQ_REL) != 0)
804 + if (__atomic_and_fetch (v, 0, __ATOMIC_SEQ_CST) != 0)
809 +test_nand_fetch (char* v)
813 + if (__atomic_nand_fetch (v, 0, __ATOMIC_RELAXED) != init)
816 + if (__atomic_nand_fetch (v, init, __ATOMIC_CONSUME) != 0)
819 + if (__atomic_nand_fetch (v, 0, __ATOMIC_ACQUIRE) != init)
822 + if (__atomic_nand_fetch (v, init, __ATOMIC_RELEASE) != 0)
825 + if (__atomic_nand_fetch (v, init, __ATOMIC_ACQ_REL) != init)
828 + if (__atomic_nand_fetch (v, 0, __ATOMIC_SEQ_CST) != init)
835 +test_xor_fetch (char* v)
840 + if (__atomic_xor_fetch (v, count, __ATOMIC_RELAXED) != init)
843 + if (__atomic_xor_fetch (v, ~count, __ATOMIC_CONSUME) != 0)
846 + if (__atomic_xor_fetch (v, 0, __ATOMIC_ACQUIRE) != 0)
849 + if (__atomic_xor_fetch (v, ~count, __ATOMIC_RELEASE) != init)
852 + if (__atomic_xor_fetch (v, 0, __ATOMIC_ACQ_REL) != init)
855 + if (__atomic_xor_fetch (v, ~count, __ATOMIC_SEQ_CST) != 0)
860 +test_or_fetch (char* v)
865 + if (__atomic_or_fetch (v, count, __ATOMIC_RELAXED) != 1)
869 + if (__atomic_or_fetch (v, 2, __ATOMIC_CONSUME) != 3)
873 + if (__atomic_or_fetch (v, count, __ATOMIC_ACQUIRE) != 7)
877 + if (__atomic_or_fetch (v, 8, __ATOMIC_RELEASE) != 15)
881 + if (__atomic_or_fetch (v, count, __ATOMIC_ACQ_REL) != 31)
885 + if (__atomic_or_fetch (v, count, __ATOMIC_SEQ_CST) != 63)
890 +/* Test the OP routines with a result which isn't used. Use both variations
891 + within each function. */
899 + __atomic_add_fetch (v, count, __ATOMIC_RELAXED);
903 + __atomic_fetch_add (v, count, __ATOMIC_CONSUME);
907 + __atomic_add_fetch (v, 1 , __ATOMIC_ACQUIRE);
911 + __atomic_fetch_add (v, 1, __ATOMIC_RELEASE);
915 + __atomic_add_fetch (v, count, __ATOMIC_ACQ_REL);
919 + __atomic_fetch_add (v, count, __ATOMIC_SEQ_CST);
931 + __atomic_sub_fetch (v, count + 1, __ATOMIC_RELAXED);
935 + __atomic_fetch_sub (v, count + 1, __ATOMIC_CONSUME);
939 + __atomic_sub_fetch (v, 1, __ATOMIC_ACQUIRE);
943 + __atomic_fetch_sub (v, 1, __ATOMIC_RELEASE);
947 + __atomic_sub_fetch (v, count + 1, __ATOMIC_ACQ_REL);
951 + __atomic_fetch_sub (v, count + 1, __ATOMIC_SEQ_CST);
961 + __atomic_and_fetch (v, 0, __ATOMIC_RELAXED);
966 + __atomic_fetch_and (v, init, __ATOMIC_CONSUME);
970 + __atomic_and_fetch (v, 0, __ATOMIC_ACQUIRE);
975 + __atomic_fetch_and (v, init, __ATOMIC_RELEASE);
979 + __atomic_and_fetch (v, 0, __ATOMIC_ACQ_REL);
984 + __atomic_fetch_and (v, 0, __ATOMIC_SEQ_CST);
994 + __atomic_fetch_nand (v, 0, __ATOMIC_RELAXED);
998 + __atomic_fetch_nand (v, init, __ATOMIC_CONSUME);
1002 + __atomic_nand_fetch (v, 0, __ATOMIC_ACQUIRE);
1006 + __atomic_nand_fetch (v, init, __ATOMIC_RELEASE);
1010 + __atomic_fetch_nand (v, init, __ATOMIC_ACQ_REL);
1014 + __atomic_nand_fetch (v, 0, __ATOMIC_SEQ_CST);
1027 + __atomic_xor_fetch (v, count, __ATOMIC_RELAXED);
1031 + __atomic_fetch_xor (v, ~count, __ATOMIC_CONSUME);
1035 + __atomic_xor_fetch (v, 0, __ATOMIC_ACQUIRE);
1039 + __atomic_fetch_xor (v, ~count, __ATOMIC_RELEASE);
1043 + __atomic_fetch_xor (v, 0, __ATOMIC_ACQ_REL);
1047 + __atomic_xor_fetch (v, ~count, __ATOMIC_SEQ_CST);
1058 + __atomic_or_fetch (v, count, __ATOMIC_RELAXED);
1063 + __atomic_fetch_or (v, count, __ATOMIC_CONSUME);
1068 + __atomic_or_fetch (v, 4, __ATOMIC_ACQUIRE);
1073 + __atomic_fetch_or (v, 8, __ATOMIC_RELEASE);
1078 + __atomic_or_fetch (v, count, __ATOMIC_ACQ_REL);
1083 + __atomic_fetch_or (v, count, __ATOMIC_SEQ_CST);
1091 + char* V[] = {&A.a, &A.b, &A.c, &A.d};
1093 + for (int i = 0; i < 4; i++) {
1094 + test_fetch_add (V[i]);
1095 + test_fetch_sub (V[i]);
1096 + test_fetch_and (V[i]);
1097 + test_fetch_nand (V[i]);
1098 + test_fetch_xor (V[i]);
1099 + test_fetch_or (V[i]);
1101 + test_add_fetch (V[i]);
1102 + test_sub_fetch (V[i]);
1103 + test_and_fetch (V[i]);
1104 + test_nand_fetch (V[i]);
1105 + test_xor_fetch (V[i]);
1106 + test_or_fetch (V[i]);
1119 +++ b/gcc/testsuite/gcc.target/riscv/inline-atomics-4.c
1121 +/* Check all short alignments. */
1122 +/* Duplicate logic as libatomic/testsuite/libatomic.c/atomic-op-2.c */
1123 +/* Test __atomic routines for existence and proper execution on 2 byte
1124 + values with each valid memory model. */
1125 +/* { dg-do run } */
1126 +/* { dg-options "-minline-atomics -Wno-address-of-packed-member" } */
1128 +/* Test the execution of the __atomic_*OP builtin routines for a short. */
1130 +extern void abort(void);
1133 +const short init = ~0;
1139 +} __attribute__ ((packed)) A;
1141 +/* The fetch_op routines return the original value before the operation. */
1144 +test_fetch_add (short* v)
1149 + if (__atomic_fetch_add (v, count, __ATOMIC_RELAXED) != 0)
1152 + if (__atomic_fetch_add (v, 1, __ATOMIC_CONSUME) != 1)
1155 + if (__atomic_fetch_add (v, count, __ATOMIC_ACQUIRE) != 2)
1158 + if (__atomic_fetch_add (v, 1, __ATOMIC_RELEASE) != 3)
1161 + if (__atomic_fetch_add (v, count, __ATOMIC_ACQ_REL) != 4)
1164 + if (__atomic_fetch_add (v, 1, __ATOMIC_SEQ_CST) != 5)
1170 +test_fetch_sub (short* v)
1175 + if (__atomic_fetch_sub (v, count + 1, __ATOMIC_RELAXED) != res--)
1178 + if (__atomic_fetch_sub (v, 1, __ATOMIC_CONSUME) != res--)
1181 + if (__atomic_fetch_sub (v, count + 1, __ATOMIC_ACQUIRE) != res--)
1184 + if (__atomic_fetch_sub (v, 1, __ATOMIC_RELEASE) != res--)
1187 + if (__atomic_fetch_sub (v, count + 1, __ATOMIC_ACQ_REL) != res--)
1190 + if (__atomic_fetch_sub (v, 1, __ATOMIC_SEQ_CST) != res--)
1195 +test_fetch_and (short* v)
1199 + if (__atomic_fetch_and (v, 0, __ATOMIC_RELAXED) != init)
1202 + if (__atomic_fetch_and (v, init, __ATOMIC_CONSUME) != 0)
1205 + if (__atomic_fetch_and (v, 0, __ATOMIC_ACQUIRE) != 0)
1209 + if (__atomic_fetch_and (v, init, __ATOMIC_RELEASE) != init)
1212 + if (__atomic_fetch_and (v, 0, __ATOMIC_ACQ_REL) != init)
1215 + if (__atomic_fetch_and (v, 0, __ATOMIC_SEQ_CST) != 0)
1220 +test_fetch_nand (short* v)
1224 + if (__atomic_fetch_nand (v, 0, __ATOMIC_RELAXED) != init)
1227 + if (__atomic_fetch_nand (v, init, __ATOMIC_CONSUME) != init)
1230 + if (__atomic_fetch_nand (v, 0, __ATOMIC_ACQUIRE) != 0 )
1233 + if (__atomic_fetch_nand (v, init, __ATOMIC_RELEASE) != init)
1236 + if (__atomic_fetch_nand (v, init, __ATOMIC_ACQ_REL) != 0)
1239 + if (__atomic_fetch_nand (v, 0, __ATOMIC_SEQ_CST) != init)
1244 +test_fetch_xor (short* v)
1249 + if (__atomic_fetch_xor (v, count, __ATOMIC_RELAXED) != init)
1252 + if (__atomic_fetch_xor (v, ~count, __ATOMIC_CONSUME) != init)
1255 + if (__atomic_fetch_xor (v, 0, __ATOMIC_ACQUIRE) != 0)
1258 + if (__atomic_fetch_xor (v, ~count, __ATOMIC_RELEASE) != 0)
1261 + if (__atomic_fetch_xor (v, 0, __ATOMIC_ACQ_REL) != init)
1264 + if (__atomic_fetch_xor (v, ~count, __ATOMIC_SEQ_CST) != init)
1269 +test_fetch_or (short* v)
1274 + if (__atomic_fetch_or (v, count, __ATOMIC_RELAXED) != 0)
1278 + if (__atomic_fetch_or (v, 2, __ATOMIC_CONSUME) != 1)
1282 + if (__atomic_fetch_or (v, count, __ATOMIC_ACQUIRE) != 3)
1286 + if (__atomic_fetch_or (v, 8, __ATOMIC_RELEASE) != 7)
1290 + if (__atomic_fetch_or (v, count, __ATOMIC_ACQ_REL) != 15)
1294 + if (__atomic_fetch_or (v, count, __ATOMIC_SEQ_CST) != 31)
1298 +/* The OP_fetch routines return the new value after the operation. */
1301 +test_add_fetch (short* v)
1306 + if (__atomic_add_fetch (v, count, __ATOMIC_RELAXED) != 1)
1309 + if (__atomic_add_fetch (v, 1, __ATOMIC_CONSUME) != 2)
1312 + if (__atomic_add_fetch (v, count, __ATOMIC_ACQUIRE) != 3)
1315 + if (__atomic_add_fetch (v, 1, __ATOMIC_RELEASE) != 4)
1318 + if (__atomic_add_fetch (v, count, __ATOMIC_ACQ_REL) != 5)
1321 + if (__atomic_add_fetch (v, count, __ATOMIC_SEQ_CST) != 6)
1327 +test_sub_fetch (short* v)
1332 + if (__atomic_sub_fetch (v, count + 1, __ATOMIC_RELAXED) != --res)
1335 + if (__atomic_sub_fetch (v, 1, __ATOMIC_CONSUME) != --res)
1338 + if (__atomic_sub_fetch (v, count + 1, __ATOMIC_ACQUIRE) != --res)
1341 + if (__atomic_sub_fetch (v, 1, __ATOMIC_RELEASE) != --res)
1344 + if (__atomic_sub_fetch (v, count + 1, __ATOMIC_ACQ_REL) != --res)
1347 + if (__atomic_sub_fetch (v, count + 1, __ATOMIC_SEQ_CST) != --res)
1352 +test_and_fetch (short* v)
1356 + if (__atomic_and_fetch (v, 0, __ATOMIC_RELAXED) != 0)
1360 + if (__atomic_and_fetch (v, init, __ATOMIC_CONSUME) != init)
1363 + if (__atomic_and_fetch (v, 0, __ATOMIC_ACQUIRE) != 0)
1367 + if (__atomic_and_fetch (v, init, __ATOMIC_RELEASE) != init)
1370 + if (__atomic_and_fetch (v, 0, __ATOMIC_ACQ_REL) != 0)
1374 + if (__atomic_and_fetch (v, 0, __ATOMIC_SEQ_CST) != 0)
1379 +test_nand_fetch (short* v)
1383 + if (__atomic_nand_fetch (v, 0, __ATOMIC_RELAXED) != init)
1386 + if (__atomic_nand_fetch (v, init, __ATOMIC_CONSUME) != 0)
1389 + if (__atomic_nand_fetch (v, 0, __ATOMIC_ACQUIRE) != init)
1392 + if (__atomic_nand_fetch (v, init, __ATOMIC_RELEASE) != 0)
1395 + if (__atomic_nand_fetch (v, init, __ATOMIC_ACQ_REL) != init)
1398 + if (__atomic_nand_fetch (v, 0, __ATOMIC_SEQ_CST) != init)
1405 +test_xor_fetch (short* v)
1410 + if (__atomic_xor_fetch (v, count, __ATOMIC_RELAXED) != init)
1413 + if (__atomic_xor_fetch (v, ~count, __ATOMIC_CONSUME) != 0)
1416 + if (__atomic_xor_fetch (v, 0, __ATOMIC_ACQUIRE) != 0)
1419 + if (__atomic_xor_fetch (v, ~count, __ATOMIC_RELEASE) != init)
1422 + if (__atomic_xor_fetch (v, 0, __ATOMIC_ACQ_REL) != init)
1425 + if (__atomic_xor_fetch (v, ~count, __ATOMIC_SEQ_CST) != 0)
1430 +test_or_fetch (short* v)
1435 + if (__atomic_or_fetch (v, count, __ATOMIC_RELAXED) != 1)
1439 + if (__atomic_or_fetch (v, 2, __ATOMIC_CONSUME) != 3)
1443 + if (__atomic_or_fetch (v, count, __ATOMIC_ACQUIRE) != 7)
1447 + if (__atomic_or_fetch (v, 8, __ATOMIC_RELEASE) != 15)
1451 + if (__atomic_or_fetch (v, count, __ATOMIC_ACQ_REL) != 31)
1455 + if (__atomic_or_fetch (v, count, __ATOMIC_SEQ_CST) != 63)
1460 +/* Test the OP routines with a result which isn't used. Use both variations
1461 + within each function. */
1464 +test_add (short* v)
1469 + __atomic_add_fetch (v, count, __ATOMIC_RELAXED);
1473 + __atomic_fetch_add (v, count, __ATOMIC_CONSUME);
1477 + __atomic_add_fetch (v, 1 , __ATOMIC_ACQUIRE);
1481 + __atomic_fetch_add (v, 1, __ATOMIC_RELEASE);
1485 + __atomic_add_fetch (v, count, __ATOMIC_ACQ_REL);
1489 + __atomic_fetch_add (v, count, __ATOMIC_SEQ_CST);
1496 +test_sub (short* v)
1501 + __atomic_sub_fetch (v, count + 1, __ATOMIC_RELAXED);
1505 + __atomic_fetch_sub (v, count + 1, __ATOMIC_CONSUME);
1509 + __atomic_sub_fetch (v, 1, __ATOMIC_ACQUIRE);
1513 + __atomic_fetch_sub (v, 1, __ATOMIC_RELEASE);
1517 + __atomic_sub_fetch (v, count + 1, __ATOMIC_ACQ_REL);
1521 + __atomic_fetch_sub (v, count + 1, __ATOMIC_SEQ_CST);
1527 +test_and (short* v)
1531 + __atomic_and_fetch (v, 0, __ATOMIC_RELAXED);
1536 + __atomic_fetch_and (v, init, __ATOMIC_CONSUME);
1540 + __atomic_and_fetch (v, 0, __ATOMIC_ACQUIRE);
1545 + __atomic_fetch_and (v, init, __ATOMIC_RELEASE);
1549 + __atomic_and_fetch (v, 0, __ATOMIC_ACQ_REL);
1554 + __atomic_fetch_and (v, 0, __ATOMIC_SEQ_CST);
1560 +test_nand (short* v)
1564 + __atomic_fetch_nand (v, 0, __ATOMIC_RELAXED);
1568 + __atomic_fetch_nand (v, init, __ATOMIC_CONSUME);
1572 + __atomic_nand_fetch (v, 0, __ATOMIC_ACQUIRE);
1576 + __atomic_nand_fetch (v, init, __ATOMIC_RELEASE);
1580 + __atomic_fetch_nand (v, init, __ATOMIC_ACQ_REL);
1584 + __atomic_nand_fetch (v, 0, __ATOMIC_SEQ_CST);
1592 +test_xor (short* v)
1597 + __atomic_xor_fetch (v, count, __ATOMIC_RELAXED);
1601 + __atomic_fetch_xor (v, ~count, __ATOMIC_CONSUME);
1605 + __atomic_xor_fetch (v, 0, __ATOMIC_ACQUIRE);
1609 + __atomic_fetch_xor (v, ~count, __ATOMIC_RELEASE);
1613 + __atomic_fetch_xor (v, 0, __ATOMIC_ACQ_REL);
1617 + __atomic_xor_fetch (v, ~count, __ATOMIC_SEQ_CST);
1628 + __atomic_or_fetch (v, count, __ATOMIC_RELAXED);
1633 + __atomic_fetch_or (v, count, __ATOMIC_CONSUME);
1638 + __atomic_or_fetch (v, 4, __ATOMIC_ACQUIRE);
1643 + __atomic_fetch_or (v, 8, __ATOMIC_RELEASE);
1648 + __atomic_or_fetch (v, count, __ATOMIC_ACQ_REL);
1653 + __atomic_fetch_or (v, count, __ATOMIC_SEQ_CST);
1660 + short* V[] = {&A.a, &A.b};
1662 + for (int i = 0; i < 2; i++) {
1663 + test_fetch_add (V[i]);
1664 + test_fetch_sub (V[i]);
1665 + test_fetch_and (V[i]);
1666 + test_fetch_nand (V[i]);
1667 + test_fetch_xor (V[i]);
1668 + test_fetch_or (V[i]);
1670 + test_add_fetch (V[i]);
1671 + test_sub_fetch (V[i]);
1672 + test_and_fetch (V[i]);
1673 + test_nand_fetch (V[i]);
1674 + test_xor_fetch (V[i]);
1675 + test_or_fetch (V[i]);
1688 +++ b/gcc/testsuite/gcc.target/riscv/inline-atomics-5.c
1690 +/* Test __atomic routines for existence and proper execution on 1 byte
1691 + values with each valid memory model. */
1692 +/* Duplicate logic as libatomic/testsuite/libatomic.c/atomic-compare-exchange-1.c */
1693 +/* { dg-do run } */
1694 +/* { dg-options "-minline-atomics" } */
1696 +/* Test the execution of the __atomic_compare_exchange_n builtin for a char. */
1698 +extern void abort(void);
1713 + if (!__atomic_compare_exchange_n (&v, &expected, max, STRONG , __ATOMIC_RELAXED, __ATOMIC_RELAXED))
1715 + if (expected != 0)
1718 + if (__atomic_compare_exchange_n (&v, &expected, 0, STRONG , __ATOMIC_ACQUIRE, __ATOMIC_RELAXED))
1720 + if (expected != max)
1723 + if (!__atomic_compare_exchange_n (&v, &expected, 0, STRONG , __ATOMIC_RELEASE, __ATOMIC_ACQUIRE))
1725 + if (expected != max)
1730 + if (__atomic_compare_exchange_n (&v, &expected, desired, WEAK, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE))
1732 + if (expected != 0)
1735 + if (!__atomic_compare_exchange_n (&v, &expected, desired, STRONG , __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST))
1737 + if (expected != 0)
1742 + /* Now test the generic version. */
1746 + if (!__atomic_compare_exchange (&v, &expected, &max, STRONG, __ATOMIC_RELAXED, __ATOMIC_RELAXED))
1748 + if (expected != 0)
1751 + if (__atomic_compare_exchange (&v, &expected, &zero, STRONG , __ATOMIC_ACQUIRE, __ATOMIC_RELAXED))
1753 + if (expected != max)
1756 + if (!__atomic_compare_exchange (&v, &expected, &zero, STRONG , __ATOMIC_RELEASE, __ATOMIC_ACQUIRE))
1758 + if (expected != max)
1763 + if (__atomic_compare_exchange (&v, &expected, &desired, WEAK, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE))
1765 + if (expected != 0)
1768 + if (!__atomic_compare_exchange (&v, &expected, &desired, STRONG , __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST))
1770 + if (expected != 0)
1778 +++ b/gcc/testsuite/gcc.target/riscv/inline-atomics-6.c
1780 +/* Test __atomic routines for existence and proper execution on 2 byte
1781 + values with each valid memory model. */
1782 +/* Duplicate logic as libatomic/testsuite/libatomic.c/atomic-compare-exchange-2.c */
1783 +/* { dg-do run } */
1784 +/* { dg-options "-minline-atomics" } */
1786 +/* Test the execution of the __atomic_compare_exchange_n builtin for a short. */
1788 +extern void abort(void);
1791 +short expected = 0;
1793 +short desired = ~0;
1803 + if (!__atomic_compare_exchange_n (&v, &expected, max, STRONG , __ATOMIC_RELAXED, __ATOMIC_RELAXED))
1805 + if (expected != 0)
1808 + if (__atomic_compare_exchange_n (&v, &expected, 0, STRONG , __ATOMIC_ACQUIRE, __ATOMIC_RELAXED))
1810 + if (expected != max)
1813 + if (!__atomic_compare_exchange_n (&v, &expected, 0, STRONG , __ATOMIC_RELEASE, __ATOMIC_ACQUIRE))
1815 + if (expected != max)
1820 + if (__atomic_compare_exchange_n (&v, &expected, desired, WEAK, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE))
1822 + if (expected != 0)
1825 + if (!__atomic_compare_exchange_n (&v, &expected, desired, STRONG , __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST))
1827 + if (expected != 0)
1832 + /* Now test the generic version. */
1836 + if (!__atomic_compare_exchange (&v, &expected, &max, STRONG, __ATOMIC_RELAXED, __ATOMIC_RELAXED))
1838 + if (expected != 0)
1841 + if (__atomic_compare_exchange (&v, &expected, &zero, STRONG , __ATOMIC_ACQUIRE, __ATOMIC_RELAXED))
1843 + if (expected != max)
1846 + if (!__atomic_compare_exchange (&v, &expected, &zero, STRONG , __ATOMIC_RELEASE, __ATOMIC_ACQUIRE))
1848 + if (expected != max)
1853 + if (__atomic_compare_exchange (&v, &expected, &desired, WEAK, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE))
1855 + if (expected != 0)
1858 + if (!__atomic_compare_exchange (&v, &expected, &desired, STRONG , __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST))
1860 + if (expected != 0)
1868 +++ b/gcc/testsuite/gcc.target/riscv/inline-atomics-7.c
1870 +/* Test __atomic routines for existence and proper execution on 1 byte
1871 + values with each valid memory model. */
1872 +/* Duplicate logic as libatomic/testsuite/libatomic.c/atomic-exchange-1.c */
1873 +/* { dg-do run } */
1874 +/* { dg-options "-minline-atomics" } */
1876 +/* Test the execution of the __atomic_exchange_n builtin for a char. */
1878 +extern void abort(void);
1880 +char v, count, ret;
1888 + if (__atomic_exchange_n (&v, count + 1, __ATOMIC_RELAXED) != count)
1892 + if (__atomic_exchange_n (&v, count + 1, __ATOMIC_ACQUIRE) != count)
1896 + if (__atomic_exchange_n (&v, count + 1, __ATOMIC_RELEASE) != count)
1900 + if (__atomic_exchange_n (&v, count + 1, __ATOMIC_ACQ_REL) != count)
1904 + if (__atomic_exchange_n (&v, count + 1, __ATOMIC_SEQ_CST) != count)
1908 + /* Now test the generic version. */
1912 + __atomic_exchange (&v, &count, &ret, __ATOMIC_RELAXED);
1913 + if (ret != count - 1 || v != count)
1917 + __atomic_exchange (&v, &count, &ret, __ATOMIC_ACQUIRE);
1918 + if (ret != count - 1 || v != count)
1922 + __atomic_exchange (&v, &count, &ret, __ATOMIC_RELEASE);
1923 + if (ret != count - 1 || v != count)
1927 + __atomic_exchange (&v, &count, &ret, __ATOMIC_ACQ_REL);
1928 + if (ret != count - 1 || v != count)
1932 + __atomic_exchange (&v, &count, &ret, __ATOMIC_SEQ_CST);
1933 + if (ret != count - 1 || v != count)
1940 +++ b/gcc/testsuite/gcc.target/riscv/inline-atomics-8.c
1942 +/* Test __atomic routines for existence and proper execution on 2 byte
1943 + values with each valid memory model. */
1944 +/* Duplicate logic as libatomic/testsuite/libatomic.c/atomic-exchange-2.c */
1945 +/* { dg-do run } */
1946 +/* { dg-options "-minline-atomics" } */
1948 +/* Test the execution of the __atomic_X builtin for a short. */
1950 +extern void abort(void);
1952 +short v, count, ret;
1960 + if (__atomic_exchange_n (&v, count + 1, __ATOMIC_RELAXED) != count)
1964 + if (__atomic_exchange_n (&v, count + 1, __ATOMIC_ACQUIRE) != count)
1968 + if (__atomic_exchange_n (&v, count + 1, __ATOMIC_RELEASE) != count)
1972 + if (__atomic_exchange_n (&v, count + 1, __ATOMIC_ACQ_REL) != count)
1976 + if (__atomic_exchange_n (&v, count + 1, __ATOMIC_SEQ_CST) != count)
1980 + /* Now test the generic version. */
1984 + __atomic_exchange (&v, &count, &ret, __ATOMIC_RELAXED);
1985 + if (ret != count - 1 || v != count)
1989 + __atomic_exchange (&v, &count, &ret, __ATOMIC_ACQUIRE);
1990 + if (ret != count - 1 || v != count)
1994 + __atomic_exchange (&v, &count, &ret, __ATOMIC_RELEASE);
1995 + if (ret != count - 1 || v != count)
1999 + __atomic_exchange (&v, &count, &ret, __ATOMIC_ACQ_REL);
2000 + if (ret != count - 1 || v != count)
2004 + __atomic_exchange (&v, &count, &ret, __ATOMIC_SEQ_CST);
2005 + if (ret != count - 1 || v != count)
2011 --- a/libgcc/config/riscv/atomic.c
2012 +++ b/libgcc/config/riscv/atomic.c
2013 @@ -30,6 +30,8 @@ see the files COPYING3 and COPYING.RUNTI
2014 #define INVERT "not %[tmp1], %[tmp1]\n\t"
2015 #define DONT_INVERT ""
2017 +/* Logic duplicated in gcc/gcc/config/riscv/sync.md for use when inlining is enabled */
2019 #define GENERATE_FETCH_AND_OP(type, size, opname, insn, invert, cop) \
2020 type __sync_fetch_and_ ## opname ## _ ## size (type *p, type v) \