urngd: fix archived tar hash
[openwrt/staging/nbd.git] / toolchain / gcc / patches-13.x / 700-RISCV-Inline-subword-atomic-ops.patch
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
5
6 RISC-V has no support for subword atomic operations; code currently
7 generates libatomic library calls.
8
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.
13
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.
17
18 2023-04-18 Patrick O'Neill <patrick@rivosinc.com>
19
20 gcc/ChangeLog:
21 PR target/104338
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.
28
29 libgcc/ChangeLog:
30 PR target/104338
31 * config/riscv/atomic.c: Add reference to duplicate logic.
32
33 gcc/testsuite/ChangeLog:
34 PR target/104338
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.
43
44 Signed-off-by: Patrick O'Neill <patrick@rivosinc.com>
45 Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
46 ---
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
70
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 *);
79
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
85 & ~zeroed_hardregs);
86 }
87
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. */
91 +
92 +void
93 +riscv_subword_address (rtx mem, rtx *aligned_mem, rtx *shift, rtx *mask,
94 + rtx *not_mask)
95 +{
96 + /* Align the memory address to a word. */
97 + rtx addr = force_reg (Pmode, XEXP (mem, 0));
98 +
99 + rtx addr_mask = gen_int_mode (-4, Pmode);
100 +
101 + rtx aligned_addr = gen_reg_rtx (Pmode);
102 + emit_move_insn (aligned_addr, gen_rtx_AND (Pmode, addr, addr_mask));
103 +
104 + *aligned_mem = change_address (mem, SImode, aligned_addr);
105 +
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)));
111 +
112 + /* Calculate the mask. */
113 + int unshifted_mask = GET_MODE_MASK (GET_MODE (mem));
114 +
115 + emit_move_insn (*mask, gen_int_mode (unshifted_mask, SImode));
116 +
117 + emit_move_insn (*mask, gen_rtx_ASHIFT (SImode, *mask,
118 + gen_lowpart (QImode, *shift)));
119 +
120 + emit_move_insn (*not_mask, gen_rtx_NOT(SImode, *mask));
121 +}
122 +
123 +/* Leftshift a subword within an SImode register. */
124 +
125 +void
126 +riscv_lshift_subword (machine_mode mode, rtx value, rtx shift,
127 + rtx *shifted_value)
128 +{
129 + rtx value_reg = gen_reg_rtx (SImode);
130 + emit_move_insn (value_reg, simplify_gen_subreg (SImode, value,
131 + mode, 0));
132 +
133 + emit_move_insn(*shifted_value, gen_rtx_ASHIFT (SImode, value_reg,
134 + gen_lowpart (QImode, shift)));
135 +}
136 +
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
143 TargetVariable
144 int riscv_xthead_subext
145
146 +minline-atomics
147 +Target Var(TARGET_INLINE_SUBWORD_ATOMIC) Init(1)
148 +Always inline subword atomic operations.
149 +
150 Enum
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
155 @@ -21,8 +21,11 @@
156
157 (define_c_enum "unspec" [
158 UNSPEC_COMPARE_AND_SWAP
159 + UNSPEC_COMPARE_AND_SWAP_SUBWORD
160 UNSPEC_SYNC_OLD_OP
161 + UNSPEC_SYNC_OLD_OP_SUBWORD
162 UNSPEC_SYNC_EXCHANGE
163 + UNSPEC_SYNC_EXCHANGE_SUBWORD
164 UNSPEC_ATOMIC_STORE
165 UNSPEC_MEMORY_BARRIER
166 ])
167 @@ -91,6 +94,135 @@
168 [(set_attr "type" "atomic")
169 (set (attr "length") (const_int 8))])
170
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
174 + (set (match_dup 1)
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"
184 + {
185 + return "1:\;"
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\;"
190 + "or\t%6, %6, %5\;"
191 + "sc.w.rl\t%5, %6, %1\;"
192 + "bnez\t%5, 1b";
193 + }
194 + [(set (attr "length") (const_int 28))])
195 +
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"
202 +{
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
205 + operation. */
206 +
207 + /* Logic duplicated in gcc/libgcc/config/riscv/atomic.c for use when inlining
208 + is disabled */
209 +
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);
217 +
218 + riscv_subword_address (mem, &aligned_mem, &shift, &mask, &not_mask);
219 +
220 + rtx shifted_value = gen_reg_rtx (SImode);
221 + riscv_lshift_subword (<MODE>mode, value, shift, &shifted_value);
222 +
223 + emit_insn (gen_subword_atomic_fetch_strong_nand (old, aligned_mem,
224 + shifted_value,
225 + mask, not_mask));
226 +
227 + emit_move_insn (old, gen_rtx_ASHIFTRT (SImode, old,
228 + gen_lowpart (QImode, shift)));
229 +
230 + emit_move_insn (operands[0], gen_lowpart (<MODE>mode, old));
231 +
232 + DONE;
233 +})
234 +
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
238 + (set (match_dup 1)
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"
248 + {
249 + return "1:\;"
250 + "lr.w.aq\t%0, %1\;"
251 + "and\t%5, %0, %2\;"
252 + "not\t%5, %5\;"
253 + "and\t%5, %5, %3\;"
254 + "and\t%6, %0, %4\;"
255 + "or\t%6, %6, %5\;"
256 + "sc.w.rl\t%5, %6, %1\;"
257 + "bnez\t%5, 1b";
258 + }
259 + [(set (attr "length") (const_int 32))])
260 +
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"
267 +{
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
270 + operation. */
271 +
272 + /* Logic duplicated in gcc/libgcc/config/riscv/atomic.c for use when inlining
273 + is disabled */
274 +
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);
282 +
283 + riscv_subword_address (mem, &aligned_mem, &shift, &mask, &not_mask);
284 +
285 + rtx shifted_value = gen_reg_rtx (SImode);
286 + riscv_lshift_subword (<MODE>mode, value, shift, &shifted_value);
287 +
288 + emit_insn (gen_subword_atomic_fetch_strong_<atomic_optab> (old, aligned_mem,
289 + shifted_value,
290 + mask, not_mask));
291 +
292 + emit_move_insn (old, gen_rtx_ASHIFTRT (SImode, old,
293 + gen_lowpart (QImode, shift)));
294 +
295 + emit_move_insn (operands[0], gen_lowpart (<MODE>mode, old));
296 +
297 + DONE;
298 +})
299 +
300 (define_insn "atomic_exchange<mode>"
301 [(set (match_operand:GPR 0 "register_operand" "=&r")
302 (unspec_volatile:GPR
303 @@ -104,6 +236,56 @@
304 [(set_attr "type" "atomic")
305 (set (attr "length") (const_int 8))])
306
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"
313 +{
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);
321 +
322 + riscv_subword_address (mem, &aligned_mem, &shift, &mask, &not_mask);
323 +
324 + rtx shifted_value = gen_reg_rtx (SImode);
325 + riscv_lshift_subword (<MODE>mode, value, shift, &shifted_value);
326 +
327 + emit_insn (gen_subword_atomic_exchange_strong (old, aligned_mem,
328 + shifted_value, not_mask));
329 +
330 + emit_move_insn (old, gen_rtx_ASHIFTRT (SImode, old,
331 + gen_lowpart (QImode, shift)));
332 +
333 + emit_move_insn (operands[0], gen_lowpart (<MODE>mode, old));
334 + DONE;
335 +})
336 +
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
340 + (set (match_dup 1)
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"
347 + {
348 + return "1:\;"
349 + "lr.w.aq\t%0, %1\;"
350 + "and\t%4, %0, %3\;"
351 + "or\t%4, %4, %2\;"
352 + "sc.w.rl\t%4, %4, %1\;"
353 + "bnez\t%4, 1b";
354 + }
355 + [(set (attr "length") (const_int 20))])
356 +
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 @@
361 DONE;
362 })
363
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"
374 +{
375 + emit_insn (gen_atomic_cas_value_strong<mode> (operands[1], operands[2],
376 + operands[3], operands[4],
377 + operands[6], operands[7]));
378 +
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]));
382 + else
383 + emit_move_insn (val, const0_rtx);
384 +
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]));
388 + else
389 + emit_move_insn (exp, const0_rtx);
390 +
391 + rtx compare = val;
392 + if (exp != const0_rtx)
393 + {
394 + rtx difference = gen_rtx_MINUS (SImode, val, exp);
395 + compare = gen_reg_rtx (SImode);
396 + emit_move_insn (compare, difference);
397 + }
398 +
399 + if (word_mode != SImode)
400 + {
401 + rtx reg = gen_reg_rtx (word_mode);
402 + emit_move_insn (reg, gen_rtx_SIGN_EXTEND (word_mode, compare));
403 + compare = reg;
404 + }
405 +
406 + emit_move_insn (operands[0], gen_rtx_EQ (SImode, compare, const0_rtx));
407 + DONE;
408 +})
409 +
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"
419 +{
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
422 + operation. */
423 +
424 + /* Logic duplicated in gcc/libgcc/config/riscv/atomic.c for use when inlining
425 + is disabled */
426 +
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);
433 +
434 + riscv_subword_address (mem, &aligned_mem, &shift, &mask, &not_mask);
435 +
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);
440 +
441 + riscv_lshift_subword (<MODE>mode, o, shift, &shifted_o);
442 + riscv_lshift_subword (<MODE>mode, n, shift, &shifted_n);
443 +
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));
446 +
447 + emit_insn (gen_subword_atomic_cas_strong (old, aligned_mem,
448 + shifted_o, shifted_n,
449 + mask, not_mask));
450 +
451 + emit_move_insn (old, gen_rtx_ASHIFTRT (SImode, old,
452 + gen_lowpart (QImode, shift)));
453 +
454 + emit_move_insn (operands[0], gen_lowpart (<MODE>mode, old));
455 +
456 + DONE;
457 +})
458 +
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
462 + (set (match_dup 1)
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"
470 + {
471 + return "1:\;"
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\;"
476 + "or\t%6, %6, %3\;"
477 + "sc.w.rl\t%6, %6, %1\;"
478 + "bnez\t%6, 1b\;"
479 + "1:";
480 + }
481 + [(set (attr "length") (const_int 28))])
482 +
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}
495
496 @emph{RL78 Options}
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
500 epilogues.
501
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.
508 +
509 @opindex mshorten-memrefs
510 @item -mshorten-memrefs
511 @itemx -mno-shorten-memrefs
512 --- /dev/null
513 +++ b/gcc/testsuite/gcc.target/riscv/inline-atomics-1.c
514 @@ -0,0 +1,18 @@
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" } } */
521 +
522 +char foo;
523 +char bar;
524 +char baz;
525 +
526 +int
527 +main ()
528 +{
529 + __sync_fetch_and_add(&foo, 1);
530 + __sync_fetch_and_nand(&bar, 1);
531 + __sync_bool_compare_and_swap (&baz, 1, 2);
532 +}
533 --- /dev/null
534 +++ b/gcc/testsuite/gcc.target/riscv/inline-atomics-2.c
535 @@ -0,0 +1,9 @@
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" } } */
543 +
544 +#include "inline-atomics-1.c"
545 \ No newline at end of file
546 --- /dev/null
547 +++ b/gcc/testsuite/gcc.target/riscv/inline-atomics-3.c
548 @@ -0,0 +1,569 @@
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. */
553 +/* { dg-do run } */
554 +/* { dg-options "-minline-atomics -Wno-address-of-packed-member" } */
555 +
556 +/* Test the execution of the __atomic_*OP builtin routines for a char. */
557 +
558 +extern void abort(void);
559 +
560 +char count, res;
561 +const char init = ~0;
562 +
563 +struct A
564 +{
565 + char a;
566 + char b;
567 + char c;
568 + char d;
569 +} __attribute__ ((packed)) A;
570 +
571 +/* The fetch_op routines return the original value before the operation. */
572 +
573 +void
574 +test_fetch_add (char* v)
575 +{
576 + *v = 0;
577 + count = 1;
578 +
579 + if (__atomic_fetch_add (v, count, __ATOMIC_RELAXED) != 0)
580 + abort ();
581 +
582 + if (__atomic_fetch_add (v, 1, __ATOMIC_CONSUME) != 1)
583 + abort ();
584 +
585 + if (__atomic_fetch_add (v, count, __ATOMIC_ACQUIRE) != 2)
586 + abort ();
587 +
588 + if (__atomic_fetch_add (v, 1, __ATOMIC_RELEASE) != 3)
589 + abort ();
590 +
591 + if (__atomic_fetch_add (v, count, __ATOMIC_ACQ_REL) != 4)
592 + abort ();
593 +
594 + if (__atomic_fetch_add (v, 1, __ATOMIC_SEQ_CST) != 5)
595 + abort ();
596 +}
597 +
598 +
599 +void
600 +test_fetch_sub (char* v)
601 +{
602 + *v = res = 20;
603 + count = 0;
604 +
605 + if (__atomic_fetch_sub (v, count + 1, __ATOMIC_RELAXED) != res--)
606 + abort ();
607 +
608 + if (__atomic_fetch_sub (v, 1, __ATOMIC_CONSUME) != res--)
609 + abort ();
610 +
611 + if (__atomic_fetch_sub (v, count + 1, __ATOMIC_ACQUIRE) != res--)
612 + abort ();
613 +
614 + if (__atomic_fetch_sub (v, 1, __ATOMIC_RELEASE) != res--)
615 + abort ();
616 +
617 + if (__atomic_fetch_sub (v, count + 1, __ATOMIC_ACQ_REL) != res--)
618 + abort ();
619 +
620 + if (__atomic_fetch_sub (v, 1, __ATOMIC_SEQ_CST) != res--)
621 + abort ();
622 +}
623 +
624 +void
625 +test_fetch_and (char* v)
626 +{
627 + *v = init;
628 +
629 + if (__atomic_fetch_and (v, 0, __ATOMIC_RELAXED) != init)
630 + abort ();
631 +
632 + if (__atomic_fetch_and (v, init, __ATOMIC_CONSUME) != 0)
633 + abort ();
634 +
635 + if (__atomic_fetch_and (v, 0, __ATOMIC_ACQUIRE) != 0)
636 + abort ();
637 +
638 + *v = ~*v;
639 + if (__atomic_fetch_and (v, init, __ATOMIC_RELEASE) != init)
640 + abort ();
641 +
642 + if (__atomic_fetch_and (v, 0, __ATOMIC_ACQ_REL) != init)
643 + abort ();
644 +
645 + if (__atomic_fetch_and (v, 0, __ATOMIC_SEQ_CST) != 0)
646 + abort ();
647 +}
648 +
649 +void
650 +test_fetch_nand (char* v)
651 +{
652 + *v = init;
653 +
654 + if (__atomic_fetch_nand (v, 0, __ATOMIC_RELAXED) != init)
655 + abort ();
656 +
657 + if (__atomic_fetch_nand (v, init, __ATOMIC_CONSUME) != init)
658 + abort ();
659 +
660 + if (__atomic_fetch_nand (v, 0, __ATOMIC_ACQUIRE) != 0 )
661 + abort ();
662 +
663 + if (__atomic_fetch_nand (v, init, __ATOMIC_RELEASE) != init)
664 + abort ();
665 +
666 + if (__atomic_fetch_nand (v, init, __ATOMIC_ACQ_REL) != 0)
667 + abort ();
668 +
669 + if (__atomic_fetch_nand (v, 0, __ATOMIC_SEQ_CST) != init)
670 + abort ();
671 +}
672 +
673 +void
674 +test_fetch_xor (char* v)
675 +{
676 + *v = init;
677 + count = 0;
678 +
679 + if (__atomic_fetch_xor (v, count, __ATOMIC_RELAXED) != init)
680 + abort ();
681 +
682 + if (__atomic_fetch_xor (v, ~count, __ATOMIC_CONSUME) != init)
683 + abort ();
684 +
685 + if (__atomic_fetch_xor (v, 0, __ATOMIC_ACQUIRE) != 0)
686 + abort ();
687 +
688 + if (__atomic_fetch_xor (v, ~count, __ATOMIC_RELEASE) != 0)
689 + abort ();
690 +
691 + if (__atomic_fetch_xor (v, 0, __ATOMIC_ACQ_REL) != init)
692 + abort ();
693 +
694 + if (__atomic_fetch_xor (v, ~count, __ATOMIC_SEQ_CST) != init)
695 + abort ();
696 +}
697 +
698 +void
699 +test_fetch_or (char* v)
700 +{
701 + *v = 0;
702 + count = 1;
703 +
704 + if (__atomic_fetch_or (v, count, __ATOMIC_RELAXED) != 0)
705 + abort ();
706 +
707 + count *= 2;
708 + if (__atomic_fetch_or (v, 2, __ATOMIC_CONSUME) != 1)
709 + abort ();
710 +
711 + count *= 2;
712 + if (__atomic_fetch_or (v, count, __ATOMIC_ACQUIRE) != 3)
713 + abort ();
714 +
715 + count *= 2;
716 + if (__atomic_fetch_or (v, 8, __ATOMIC_RELEASE) != 7)
717 + abort ();
718 +
719 + count *= 2;
720 + if (__atomic_fetch_or (v, count, __ATOMIC_ACQ_REL) != 15)
721 + abort ();
722 +
723 + count *= 2;
724 + if (__atomic_fetch_or (v, count, __ATOMIC_SEQ_CST) != 31)
725 + abort ();
726 +}
727 +
728 +/* The OP_fetch routines return the new value after the operation. */
729 +
730 +void
731 +test_add_fetch (char* v)
732 +{
733 + *v = 0;
734 + count = 1;
735 +
736 + if (__atomic_add_fetch (v, count, __ATOMIC_RELAXED) != 1)
737 + abort ();
738 +
739 + if (__atomic_add_fetch (v, 1, __ATOMIC_CONSUME) != 2)
740 + abort ();
741 +
742 + if (__atomic_add_fetch (v, count, __ATOMIC_ACQUIRE) != 3)
743 + abort ();
744 +
745 + if (__atomic_add_fetch (v, 1, __ATOMIC_RELEASE) != 4)
746 + abort ();
747 +
748 + if (__atomic_add_fetch (v, count, __ATOMIC_ACQ_REL) != 5)
749 + abort ();
750 +
751 + if (__atomic_add_fetch (v, count, __ATOMIC_SEQ_CST) != 6)
752 + abort ();
753 +}
754 +
755 +
756 +void
757 +test_sub_fetch (char* v)
758 +{
759 + *v = res = 20;
760 + count = 0;
761 +
762 + if (__atomic_sub_fetch (v, count + 1, __ATOMIC_RELAXED) != --res)
763 + abort ();
764 +
765 + if (__atomic_sub_fetch (v, 1, __ATOMIC_CONSUME) != --res)
766 + abort ();
767 +
768 + if (__atomic_sub_fetch (v, count + 1, __ATOMIC_ACQUIRE) != --res)
769 + abort ();
770 +
771 + if (__atomic_sub_fetch (v, 1, __ATOMIC_RELEASE) != --res)
772 + abort ();
773 +
774 + if (__atomic_sub_fetch (v, count + 1, __ATOMIC_ACQ_REL) != --res)
775 + abort ();
776 +
777 + if (__atomic_sub_fetch (v, count + 1, __ATOMIC_SEQ_CST) != --res)
778 + abort ();
779 +}
780 +
781 +void
782 +test_and_fetch (char* v)
783 +{
784 + *v = init;
785 +
786 + if (__atomic_and_fetch (v, 0, __ATOMIC_RELAXED) != 0)
787 + abort ();
788 +
789 + *v = init;
790 + if (__atomic_and_fetch (v, init, __ATOMIC_CONSUME) != init)
791 + abort ();
792 +
793 + if (__atomic_and_fetch (v, 0, __ATOMIC_ACQUIRE) != 0)
794 + abort ();
795 +
796 + *v = ~*v;
797 + if (__atomic_and_fetch (v, init, __ATOMIC_RELEASE) != init)
798 + abort ();
799 +
800 + if (__atomic_and_fetch (v, 0, __ATOMIC_ACQ_REL) != 0)
801 + abort ();
802 +
803 + *v = ~*v;
804 + if (__atomic_and_fetch (v, 0, __ATOMIC_SEQ_CST) != 0)
805 + abort ();
806 +}
807 +
808 +void
809 +test_nand_fetch (char* v)
810 +{
811 + *v = init;
812 +
813 + if (__atomic_nand_fetch (v, 0, __ATOMIC_RELAXED) != init)
814 + abort ();
815 +
816 + if (__atomic_nand_fetch (v, init, __ATOMIC_CONSUME) != 0)
817 + abort ();
818 +
819 + if (__atomic_nand_fetch (v, 0, __ATOMIC_ACQUIRE) != init)
820 + abort ();
821 +
822 + if (__atomic_nand_fetch (v, init, __ATOMIC_RELEASE) != 0)
823 + abort ();
824 +
825 + if (__atomic_nand_fetch (v, init, __ATOMIC_ACQ_REL) != init)
826 + abort ();
827 +
828 + if (__atomic_nand_fetch (v, 0, __ATOMIC_SEQ_CST) != init)
829 + abort ();
830 +}
831 +
832 +
833 +
834 +void
835 +test_xor_fetch (char* v)
836 +{
837 + *v = init;
838 + count = 0;
839 +
840 + if (__atomic_xor_fetch (v, count, __ATOMIC_RELAXED) != init)
841 + abort ();
842 +
843 + if (__atomic_xor_fetch (v, ~count, __ATOMIC_CONSUME) != 0)
844 + abort ();
845 +
846 + if (__atomic_xor_fetch (v, 0, __ATOMIC_ACQUIRE) != 0)
847 + abort ();
848 +
849 + if (__atomic_xor_fetch (v, ~count, __ATOMIC_RELEASE) != init)
850 + abort ();
851 +
852 + if (__atomic_xor_fetch (v, 0, __ATOMIC_ACQ_REL) != init)
853 + abort ();
854 +
855 + if (__atomic_xor_fetch (v, ~count, __ATOMIC_SEQ_CST) != 0)
856 + abort ();
857 +}
858 +
859 +void
860 +test_or_fetch (char* v)
861 +{
862 + *v = 0;
863 + count = 1;
864 +
865 + if (__atomic_or_fetch (v, count, __ATOMIC_RELAXED) != 1)
866 + abort ();
867 +
868 + count *= 2;
869 + if (__atomic_or_fetch (v, 2, __ATOMIC_CONSUME) != 3)
870 + abort ();
871 +
872 + count *= 2;
873 + if (__atomic_or_fetch (v, count, __ATOMIC_ACQUIRE) != 7)
874 + abort ();
875 +
876 + count *= 2;
877 + if (__atomic_or_fetch (v, 8, __ATOMIC_RELEASE) != 15)
878 + abort ();
879 +
880 + count *= 2;
881 + if (__atomic_or_fetch (v, count, __ATOMIC_ACQ_REL) != 31)
882 + abort ();
883 +
884 + count *= 2;
885 + if (__atomic_or_fetch (v, count, __ATOMIC_SEQ_CST) != 63)
886 + abort ();
887 +}
888 +
889 +
890 +/* Test the OP routines with a result which isn't used. Use both variations
891 + within each function. */
892 +
893 +void
894 +test_add (char* v)
895 +{
896 + *v = 0;
897 + count = 1;
898 +
899 + __atomic_add_fetch (v, count, __ATOMIC_RELAXED);
900 + if (*v != 1)
901 + abort ();
902 +
903 + __atomic_fetch_add (v, count, __ATOMIC_CONSUME);
904 + if (*v != 2)
905 + abort ();
906 +
907 + __atomic_add_fetch (v, 1 , __ATOMIC_ACQUIRE);
908 + if (*v != 3)
909 + abort ();
910 +
911 + __atomic_fetch_add (v, 1, __ATOMIC_RELEASE);
912 + if (*v != 4)
913 + abort ();
914 +
915 + __atomic_add_fetch (v, count, __ATOMIC_ACQ_REL);
916 + if (*v != 5)
917 + abort ();
918 +
919 + __atomic_fetch_add (v, count, __ATOMIC_SEQ_CST);
920 + if (*v != 6)
921 + abort ();
922 +}
923 +
924 +
925 +void
926 +test_sub (char* v)
927 +{
928 + *v = res = 20;
929 + count = 0;
930 +
931 + __atomic_sub_fetch (v, count + 1, __ATOMIC_RELAXED);
932 + if (*v != --res)
933 + abort ();
934 +
935 + __atomic_fetch_sub (v, count + 1, __ATOMIC_CONSUME);
936 + if (*v != --res)
937 + abort ();
938 +
939 + __atomic_sub_fetch (v, 1, __ATOMIC_ACQUIRE);
940 + if (*v != --res)
941 + abort ();
942 +
943 + __atomic_fetch_sub (v, 1, __ATOMIC_RELEASE);
944 + if (*v != --res)
945 + abort ();
946 +
947 + __atomic_sub_fetch (v, count + 1, __ATOMIC_ACQ_REL);
948 + if (*v != --res)
949 + abort ();
950 +
951 + __atomic_fetch_sub (v, count + 1, __ATOMIC_SEQ_CST);
952 + if (*v != --res)
953 + abort ();
954 +}
955 +
956 +void
957 +test_and (char* v)
958 +{
959 + *v = init;
960 +
961 + __atomic_and_fetch (v, 0, __ATOMIC_RELAXED);
962 + if (*v != 0)
963 + abort ();
964 +
965 + *v = init;
966 + __atomic_fetch_and (v, init, __ATOMIC_CONSUME);
967 + if (*v != init)
968 + abort ();
969 +
970 + __atomic_and_fetch (v, 0, __ATOMIC_ACQUIRE);
971 + if (*v != 0)
972 + abort ();
973 +
974 + *v = ~*v;
975 + __atomic_fetch_and (v, init, __ATOMIC_RELEASE);
976 + if (*v != init)
977 + abort ();
978 +
979 + __atomic_and_fetch (v, 0, __ATOMIC_ACQ_REL);
980 + if (*v != 0)
981 + abort ();
982 +
983 + *v = ~*v;
984 + __atomic_fetch_and (v, 0, __ATOMIC_SEQ_CST);
985 + if (*v != 0)
986 + abort ();
987 +}
988 +
989 +void
990 +test_nand (char* v)
991 +{
992 + *v = init;
993 +
994 + __atomic_fetch_nand (v, 0, __ATOMIC_RELAXED);
995 + if (*v != init)
996 + abort ();
997 +
998 + __atomic_fetch_nand (v, init, __ATOMIC_CONSUME);
999 + if (*v != 0)
1000 + abort ();
1001 +
1002 + __atomic_nand_fetch (v, 0, __ATOMIC_ACQUIRE);
1003 + if (*v != init)
1004 + abort ();
1005 +
1006 + __atomic_nand_fetch (v, init, __ATOMIC_RELEASE);
1007 + if (*v != 0)
1008 + abort ();
1009 +
1010 + __atomic_fetch_nand (v, init, __ATOMIC_ACQ_REL);
1011 + if (*v != init)
1012 + abort ();
1013 +
1014 + __atomic_nand_fetch (v, 0, __ATOMIC_SEQ_CST);
1015 + if (*v != init)
1016 + abort ();
1017 +}
1018 +
1019 +
1020 +
1021 +void
1022 +test_xor (char* v)
1023 +{
1024 + *v = init;
1025 + count = 0;
1026 +
1027 + __atomic_xor_fetch (v, count, __ATOMIC_RELAXED);
1028 + if (*v != init)
1029 + abort ();
1030 +
1031 + __atomic_fetch_xor (v, ~count, __ATOMIC_CONSUME);
1032 + if (*v != 0)
1033 + abort ();
1034 +
1035 + __atomic_xor_fetch (v, 0, __ATOMIC_ACQUIRE);
1036 + if (*v != 0)
1037 + abort ();
1038 +
1039 + __atomic_fetch_xor (v, ~count, __ATOMIC_RELEASE);
1040 + if (*v != init)
1041 + abort ();
1042 +
1043 + __atomic_fetch_xor (v, 0, __ATOMIC_ACQ_REL);
1044 + if (*v != init)
1045 + abort ();
1046 +
1047 + __atomic_xor_fetch (v, ~count, __ATOMIC_SEQ_CST);
1048 + if (*v != 0)
1049 + abort ();
1050 +}
1051 +
1052 +void
1053 +test_or (char* v)
1054 +{
1055 + *v = 0;
1056 + count = 1;
1057 +
1058 + __atomic_or_fetch (v, count, __ATOMIC_RELAXED);
1059 + if (*v != 1)
1060 + abort ();
1061 +
1062 + count *= 2;
1063 + __atomic_fetch_or (v, count, __ATOMIC_CONSUME);
1064 + if (*v != 3)
1065 + abort ();
1066 +
1067 + count *= 2;
1068 + __atomic_or_fetch (v, 4, __ATOMIC_ACQUIRE);
1069 + if (*v != 7)
1070 + abort ();
1071 +
1072 + count *= 2;
1073 + __atomic_fetch_or (v, 8, __ATOMIC_RELEASE);
1074 + if (*v != 15)
1075 + abort ();
1076 +
1077 + count *= 2;
1078 + __atomic_or_fetch (v, count, __ATOMIC_ACQ_REL);
1079 + if (*v != 31)
1080 + abort ();
1081 +
1082 + count *= 2;
1083 + __atomic_fetch_or (v, count, __ATOMIC_SEQ_CST);
1084 + if (*v != 63)
1085 + abort ();
1086 +}
1087 +
1088 +int
1089 +main ()
1090 +{
1091 + char* V[] = {&A.a, &A.b, &A.c, &A.d};
1092 +
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]);
1100 +
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]);
1107 +
1108 + test_add (V[i]);
1109 + test_sub (V[i]);
1110 + test_and (V[i]);
1111 + test_nand (V[i]);
1112 + test_xor (V[i]);
1113 + test_or (V[i]);
1114 + }
1115 +
1116 + return 0;
1117 +}
1118 --- /dev/null
1119 +++ b/gcc/testsuite/gcc.target/riscv/inline-atomics-4.c
1120 @@ -0,0 +1,566 @@
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" } */
1127 +
1128 +/* Test the execution of the __atomic_*OP builtin routines for a short. */
1129 +
1130 +extern void abort(void);
1131 +
1132 +short count, res;
1133 +const short init = ~0;
1134 +
1135 +struct A
1136 +{
1137 + short a;
1138 + short b;
1139 +} __attribute__ ((packed)) A;
1140 +
1141 +/* The fetch_op routines return the original value before the operation. */
1142 +
1143 +void
1144 +test_fetch_add (short* v)
1145 +{
1146 + *v = 0;
1147 + count = 1;
1148 +
1149 + if (__atomic_fetch_add (v, count, __ATOMIC_RELAXED) != 0)
1150 + abort ();
1151 +
1152 + if (__atomic_fetch_add (v, 1, __ATOMIC_CONSUME) != 1)
1153 + abort ();
1154 +
1155 + if (__atomic_fetch_add (v, count, __ATOMIC_ACQUIRE) != 2)
1156 + abort ();
1157 +
1158 + if (__atomic_fetch_add (v, 1, __ATOMIC_RELEASE) != 3)
1159 + abort ();
1160 +
1161 + if (__atomic_fetch_add (v, count, __ATOMIC_ACQ_REL) != 4)
1162 + abort ();
1163 +
1164 + if (__atomic_fetch_add (v, 1, __ATOMIC_SEQ_CST) != 5)
1165 + abort ();
1166 +}
1167 +
1168 +
1169 +void
1170 +test_fetch_sub (short* v)
1171 +{
1172 + *v = res = 20;
1173 + count = 0;
1174 +
1175 + if (__atomic_fetch_sub (v, count + 1, __ATOMIC_RELAXED) != res--)
1176 + abort ();
1177 +
1178 + if (__atomic_fetch_sub (v, 1, __ATOMIC_CONSUME) != res--)
1179 + abort ();
1180 +
1181 + if (__atomic_fetch_sub (v, count + 1, __ATOMIC_ACQUIRE) != res--)
1182 + abort ();
1183 +
1184 + if (__atomic_fetch_sub (v, 1, __ATOMIC_RELEASE) != res--)
1185 + abort ();
1186 +
1187 + if (__atomic_fetch_sub (v, count + 1, __ATOMIC_ACQ_REL) != res--)
1188 + abort ();
1189 +
1190 + if (__atomic_fetch_sub (v, 1, __ATOMIC_SEQ_CST) != res--)
1191 + abort ();
1192 +}
1193 +
1194 +void
1195 +test_fetch_and (short* v)
1196 +{
1197 + *v = init;
1198 +
1199 + if (__atomic_fetch_and (v, 0, __ATOMIC_RELAXED) != init)
1200 + abort ();
1201 +
1202 + if (__atomic_fetch_and (v, init, __ATOMIC_CONSUME) != 0)
1203 + abort ();
1204 +
1205 + if (__atomic_fetch_and (v, 0, __ATOMIC_ACQUIRE) != 0)
1206 + abort ();
1207 +
1208 + *v = ~*v;
1209 + if (__atomic_fetch_and (v, init, __ATOMIC_RELEASE) != init)
1210 + abort ();
1211 +
1212 + if (__atomic_fetch_and (v, 0, __ATOMIC_ACQ_REL) != init)
1213 + abort ();
1214 +
1215 + if (__atomic_fetch_and (v, 0, __ATOMIC_SEQ_CST) != 0)
1216 + abort ();
1217 +}
1218 +
1219 +void
1220 +test_fetch_nand (short* v)
1221 +{
1222 + *v = init;
1223 +
1224 + if (__atomic_fetch_nand (v, 0, __ATOMIC_RELAXED) != init)
1225 + abort ();
1226 +
1227 + if (__atomic_fetch_nand (v, init, __ATOMIC_CONSUME) != init)
1228 + abort ();
1229 +
1230 + if (__atomic_fetch_nand (v, 0, __ATOMIC_ACQUIRE) != 0 )
1231 + abort ();
1232 +
1233 + if (__atomic_fetch_nand (v, init, __ATOMIC_RELEASE) != init)
1234 + abort ();
1235 +
1236 + if (__atomic_fetch_nand (v, init, __ATOMIC_ACQ_REL) != 0)
1237 + abort ();
1238 +
1239 + if (__atomic_fetch_nand (v, 0, __ATOMIC_SEQ_CST) != init)
1240 + abort ();
1241 +}
1242 +
1243 +void
1244 +test_fetch_xor (short* v)
1245 +{
1246 + *v = init;
1247 + count = 0;
1248 +
1249 + if (__atomic_fetch_xor (v, count, __ATOMIC_RELAXED) != init)
1250 + abort ();
1251 +
1252 + if (__atomic_fetch_xor (v, ~count, __ATOMIC_CONSUME) != init)
1253 + abort ();
1254 +
1255 + if (__atomic_fetch_xor (v, 0, __ATOMIC_ACQUIRE) != 0)
1256 + abort ();
1257 +
1258 + if (__atomic_fetch_xor (v, ~count, __ATOMIC_RELEASE) != 0)
1259 + abort ();
1260 +
1261 + if (__atomic_fetch_xor (v, 0, __ATOMIC_ACQ_REL) != init)
1262 + abort ();
1263 +
1264 + if (__atomic_fetch_xor (v, ~count, __ATOMIC_SEQ_CST) != init)
1265 + abort ();
1266 +}
1267 +
1268 +void
1269 +test_fetch_or (short* v)
1270 +{
1271 + *v = 0;
1272 + count = 1;
1273 +
1274 + if (__atomic_fetch_or (v, count, __ATOMIC_RELAXED) != 0)
1275 + abort ();
1276 +
1277 + count *= 2;
1278 + if (__atomic_fetch_or (v, 2, __ATOMIC_CONSUME) != 1)
1279 + abort ();
1280 +
1281 + count *= 2;
1282 + if (__atomic_fetch_or (v, count, __ATOMIC_ACQUIRE) != 3)
1283 + abort ();
1284 +
1285 + count *= 2;
1286 + if (__atomic_fetch_or (v, 8, __ATOMIC_RELEASE) != 7)
1287 + abort ();
1288 +
1289 + count *= 2;
1290 + if (__atomic_fetch_or (v, count, __ATOMIC_ACQ_REL) != 15)
1291 + abort ();
1292 +
1293 + count *= 2;
1294 + if (__atomic_fetch_or (v, count, __ATOMIC_SEQ_CST) != 31)
1295 + abort ();
1296 +}
1297 +
1298 +/* The OP_fetch routines return the new value after the operation. */
1299 +
1300 +void
1301 +test_add_fetch (short* v)
1302 +{
1303 + *v = 0;
1304 + count = 1;
1305 +
1306 + if (__atomic_add_fetch (v, count, __ATOMIC_RELAXED) != 1)
1307 + abort ();
1308 +
1309 + if (__atomic_add_fetch (v, 1, __ATOMIC_CONSUME) != 2)
1310 + abort ();
1311 +
1312 + if (__atomic_add_fetch (v, count, __ATOMIC_ACQUIRE) != 3)
1313 + abort ();
1314 +
1315 + if (__atomic_add_fetch (v, 1, __ATOMIC_RELEASE) != 4)
1316 + abort ();
1317 +
1318 + if (__atomic_add_fetch (v, count, __ATOMIC_ACQ_REL) != 5)
1319 + abort ();
1320 +
1321 + if (__atomic_add_fetch (v, count, __ATOMIC_SEQ_CST) != 6)
1322 + abort ();
1323 +}
1324 +
1325 +
1326 +void
1327 +test_sub_fetch (short* v)
1328 +{
1329 + *v = res = 20;
1330 + count = 0;
1331 +
1332 + if (__atomic_sub_fetch (v, count + 1, __ATOMIC_RELAXED) != --res)
1333 + abort ();
1334 +
1335 + if (__atomic_sub_fetch (v, 1, __ATOMIC_CONSUME) != --res)
1336 + abort ();
1337 +
1338 + if (__atomic_sub_fetch (v, count + 1, __ATOMIC_ACQUIRE) != --res)
1339 + abort ();
1340 +
1341 + if (__atomic_sub_fetch (v, 1, __ATOMIC_RELEASE) != --res)
1342 + abort ();
1343 +
1344 + if (__atomic_sub_fetch (v, count + 1, __ATOMIC_ACQ_REL) != --res)
1345 + abort ();
1346 +
1347 + if (__atomic_sub_fetch (v, count + 1, __ATOMIC_SEQ_CST) != --res)
1348 + abort ();
1349 +}
1350 +
1351 +void
1352 +test_and_fetch (short* v)
1353 +{
1354 + *v = init;
1355 +
1356 + if (__atomic_and_fetch (v, 0, __ATOMIC_RELAXED) != 0)
1357 + abort ();
1358 +
1359 + *v = init;
1360 + if (__atomic_and_fetch (v, init, __ATOMIC_CONSUME) != init)
1361 + abort ();
1362 +
1363 + if (__atomic_and_fetch (v, 0, __ATOMIC_ACQUIRE) != 0)
1364 + abort ();
1365 +
1366 + *v = ~*v;
1367 + if (__atomic_and_fetch (v, init, __ATOMIC_RELEASE) != init)
1368 + abort ();
1369 +
1370 + if (__atomic_and_fetch (v, 0, __ATOMIC_ACQ_REL) != 0)
1371 + abort ();
1372 +
1373 + *v = ~*v;
1374 + if (__atomic_and_fetch (v, 0, __ATOMIC_SEQ_CST) != 0)
1375 + abort ();
1376 +}
1377 +
1378 +void
1379 +test_nand_fetch (short* v)
1380 +{
1381 + *v = init;
1382 +
1383 + if (__atomic_nand_fetch (v, 0, __ATOMIC_RELAXED) != init)
1384 + abort ();
1385 +
1386 + if (__atomic_nand_fetch (v, init, __ATOMIC_CONSUME) != 0)
1387 + abort ();
1388 +
1389 + if (__atomic_nand_fetch (v, 0, __ATOMIC_ACQUIRE) != init)
1390 + abort ();
1391 +
1392 + if (__atomic_nand_fetch (v, init, __ATOMIC_RELEASE) != 0)
1393 + abort ();
1394 +
1395 + if (__atomic_nand_fetch (v, init, __ATOMIC_ACQ_REL) != init)
1396 + abort ();
1397 +
1398 + if (__atomic_nand_fetch (v, 0, __ATOMIC_SEQ_CST) != init)
1399 + abort ();
1400 +}
1401 +
1402 +
1403 +
1404 +void
1405 +test_xor_fetch (short* v)
1406 +{
1407 + *v = init;
1408 + count = 0;
1409 +
1410 + if (__atomic_xor_fetch (v, count, __ATOMIC_RELAXED) != init)
1411 + abort ();
1412 +
1413 + if (__atomic_xor_fetch (v, ~count, __ATOMIC_CONSUME) != 0)
1414 + abort ();
1415 +
1416 + if (__atomic_xor_fetch (v, 0, __ATOMIC_ACQUIRE) != 0)
1417 + abort ();
1418 +
1419 + if (__atomic_xor_fetch (v, ~count, __ATOMIC_RELEASE) != init)
1420 + abort ();
1421 +
1422 + if (__atomic_xor_fetch (v, 0, __ATOMIC_ACQ_REL) != init)
1423 + abort ();
1424 +
1425 + if (__atomic_xor_fetch (v, ~count, __ATOMIC_SEQ_CST) != 0)
1426 + abort ();
1427 +}
1428 +
1429 +void
1430 +test_or_fetch (short* v)
1431 +{
1432 + *v = 0;
1433 + count = 1;
1434 +
1435 + if (__atomic_or_fetch (v, count, __ATOMIC_RELAXED) != 1)
1436 + abort ();
1437 +
1438 + count *= 2;
1439 + if (__atomic_or_fetch (v, 2, __ATOMIC_CONSUME) != 3)
1440 + abort ();
1441 +
1442 + count *= 2;
1443 + if (__atomic_or_fetch (v, count, __ATOMIC_ACQUIRE) != 7)
1444 + abort ();
1445 +
1446 + count *= 2;
1447 + if (__atomic_or_fetch (v, 8, __ATOMIC_RELEASE) != 15)
1448 + abort ();
1449 +
1450 + count *= 2;
1451 + if (__atomic_or_fetch (v, count, __ATOMIC_ACQ_REL) != 31)
1452 + abort ();
1453 +
1454 + count *= 2;
1455 + if (__atomic_or_fetch (v, count, __ATOMIC_SEQ_CST) != 63)
1456 + abort ();
1457 +}
1458 +
1459 +
1460 +/* Test the OP routines with a result which isn't used. Use both variations
1461 + within each function. */
1462 +
1463 +void
1464 +test_add (short* v)
1465 +{
1466 + *v = 0;
1467 + count = 1;
1468 +
1469 + __atomic_add_fetch (v, count, __ATOMIC_RELAXED);
1470 + if (*v != 1)
1471 + abort ();
1472 +
1473 + __atomic_fetch_add (v, count, __ATOMIC_CONSUME);
1474 + if (*v != 2)
1475 + abort ();
1476 +
1477 + __atomic_add_fetch (v, 1 , __ATOMIC_ACQUIRE);
1478 + if (*v != 3)
1479 + abort ();
1480 +
1481 + __atomic_fetch_add (v, 1, __ATOMIC_RELEASE);
1482 + if (*v != 4)
1483 + abort ();
1484 +
1485 + __atomic_add_fetch (v, count, __ATOMIC_ACQ_REL);
1486 + if (*v != 5)
1487 + abort ();
1488 +
1489 + __atomic_fetch_add (v, count, __ATOMIC_SEQ_CST);
1490 + if (*v != 6)
1491 + abort ();
1492 +}
1493 +
1494 +
1495 +void
1496 +test_sub (short* v)
1497 +{
1498 + *v = res = 20;
1499 + count = 0;
1500 +
1501 + __atomic_sub_fetch (v, count + 1, __ATOMIC_RELAXED);
1502 + if (*v != --res)
1503 + abort ();
1504 +
1505 + __atomic_fetch_sub (v, count + 1, __ATOMIC_CONSUME);
1506 + if (*v != --res)
1507 + abort ();
1508 +
1509 + __atomic_sub_fetch (v, 1, __ATOMIC_ACQUIRE);
1510 + if (*v != --res)
1511 + abort ();
1512 +
1513 + __atomic_fetch_sub (v, 1, __ATOMIC_RELEASE);
1514 + if (*v != --res)
1515 + abort ();
1516 +
1517 + __atomic_sub_fetch (v, count + 1, __ATOMIC_ACQ_REL);
1518 + if (*v != --res)
1519 + abort ();
1520 +
1521 + __atomic_fetch_sub (v, count + 1, __ATOMIC_SEQ_CST);
1522 + if (*v != --res)
1523 + abort ();
1524 +}
1525 +
1526 +void
1527 +test_and (short* v)
1528 +{
1529 + *v = init;
1530 +
1531 + __atomic_and_fetch (v, 0, __ATOMIC_RELAXED);
1532 + if (*v != 0)
1533 + abort ();
1534 +
1535 + *v = init;
1536 + __atomic_fetch_and (v, init, __ATOMIC_CONSUME);
1537 + if (*v != init)
1538 + abort ();
1539 +
1540 + __atomic_and_fetch (v, 0, __ATOMIC_ACQUIRE);
1541 + if (*v != 0)
1542 + abort ();
1543 +
1544 + *v = ~*v;
1545 + __atomic_fetch_and (v, init, __ATOMIC_RELEASE);
1546 + if (*v != init)
1547 + abort ();
1548 +
1549 + __atomic_and_fetch (v, 0, __ATOMIC_ACQ_REL);
1550 + if (*v != 0)
1551 + abort ();
1552 +
1553 + *v = ~*v;
1554 + __atomic_fetch_and (v, 0, __ATOMIC_SEQ_CST);
1555 + if (*v != 0)
1556 + abort ();
1557 +}
1558 +
1559 +void
1560 +test_nand (short* v)
1561 +{
1562 + *v = init;
1563 +
1564 + __atomic_fetch_nand (v, 0, __ATOMIC_RELAXED);
1565 + if (*v != init)
1566 + abort ();
1567 +
1568 + __atomic_fetch_nand (v, init, __ATOMIC_CONSUME);
1569 + if (*v != 0)
1570 + abort ();
1571 +
1572 + __atomic_nand_fetch (v, 0, __ATOMIC_ACQUIRE);
1573 + if (*v != init)
1574 + abort ();
1575 +
1576 + __atomic_nand_fetch (v, init, __ATOMIC_RELEASE);
1577 + if (*v != 0)
1578 + abort ();
1579 +
1580 + __atomic_fetch_nand (v, init, __ATOMIC_ACQ_REL);
1581 + if (*v != init)
1582 + abort ();
1583 +
1584 + __atomic_nand_fetch (v, 0, __ATOMIC_SEQ_CST);
1585 + if (*v != init)
1586 + abort ();
1587 +}
1588 +
1589 +
1590 +
1591 +void
1592 +test_xor (short* v)
1593 +{
1594 + *v = init;
1595 + count = 0;
1596 +
1597 + __atomic_xor_fetch (v, count, __ATOMIC_RELAXED);
1598 + if (*v != init)
1599 + abort ();
1600 +
1601 + __atomic_fetch_xor (v, ~count, __ATOMIC_CONSUME);
1602 + if (*v != 0)
1603 + abort ();
1604 +
1605 + __atomic_xor_fetch (v, 0, __ATOMIC_ACQUIRE);
1606 + if (*v != 0)
1607 + abort ();
1608 +
1609 + __atomic_fetch_xor (v, ~count, __ATOMIC_RELEASE);
1610 + if (*v != init)
1611 + abort ();
1612 +
1613 + __atomic_fetch_xor (v, 0, __ATOMIC_ACQ_REL);
1614 + if (*v != init)
1615 + abort ();
1616 +
1617 + __atomic_xor_fetch (v, ~count, __ATOMIC_SEQ_CST);
1618 + if (*v != 0)
1619 + abort ();
1620 +}
1621 +
1622 +void
1623 +test_or (short* v)
1624 +{
1625 + *v = 0;
1626 + count = 1;
1627 +
1628 + __atomic_or_fetch (v, count, __ATOMIC_RELAXED);
1629 + if (*v != 1)
1630 + abort ();
1631 +
1632 + count *= 2;
1633 + __atomic_fetch_or (v, count, __ATOMIC_CONSUME);
1634 + if (*v != 3)
1635 + abort ();
1636 +
1637 + count *= 2;
1638 + __atomic_or_fetch (v, 4, __ATOMIC_ACQUIRE);
1639 + if (*v != 7)
1640 + abort ();
1641 +
1642 + count *= 2;
1643 + __atomic_fetch_or (v, 8, __ATOMIC_RELEASE);
1644 + if (*v != 15)
1645 + abort ();
1646 +
1647 + count *= 2;
1648 + __atomic_or_fetch (v, count, __ATOMIC_ACQ_REL);
1649 + if (*v != 31)
1650 + abort ();
1651 +
1652 + count *= 2;
1653 + __atomic_fetch_or (v, count, __ATOMIC_SEQ_CST);
1654 + if (*v != 63)
1655 + abort ();
1656 +}
1657 +
1658 +int
1659 +main () {
1660 + short* V[] = {&A.a, &A.b};
1661 +
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]);
1669 +
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]);
1676 +
1677 + test_add (V[i]);
1678 + test_sub (V[i]);
1679 + test_and (V[i]);
1680 + test_nand (V[i]);
1681 + test_xor (V[i]);
1682 + test_or (V[i]);
1683 + }
1684 +
1685 + return 0;
1686 +}
1687 --- /dev/null
1688 +++ b/gcc/testsuite/gcc.target/riscv/inline-atomics-5.c
1689 @@ -0,0 +1,87 @@
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" } */
1695 +
1696 +/* Test the execution of the __atomic_compare_exchange_n builtin for a char. */
1697 +
1698 +extern void abort(void);
1699 +
1700 +char v = 0;
1701 +char expected = 0;
1702 +char max = ~0;
1703 +char desired = ~0;
1704 +char zero = 0;
1705 +
1706 +#define STRONG 0
1707 +#define WEAK 1
1708 +
1709 +int
1710 +main ()
1711 +{
1712 +
1713 + if (!__atomic_compare_exchange_n (&v, &expected, max, STRONG , __ATOMIC_RELAXED, __ATOMIC_RELAXED))
1714 + abort ();
1715 + if (expected != 0)
1716 + abort ();
1717 +
1718 + if (__atomic_compare_exchange_n (&v, &expected, 0, STRONG , __ATOMIC_ACQUIRE, __ATOMIC_RELAXED))
1719 + abort ();
1720 + if (expected != max)
1721 + abort ();
1722 +
1723 + if (!__atomic_compare_exchange_n (&v, &expected, 0, STRONG , __ATOMIC_RELEASE, __ATOMIC_ACQUIRE))
1724 + abort ();
1725 + if (expected != max)
1726 + abort ();
1727 + if (v != 0)
1728 + abort ();
1729 +
1730 + if (__atomic_compare_exchange_n (&v, &expected, desired, WEAK, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE))
1731 + abort ();
1732 + if (expected != 0)
1733 + abort ();
1734 +
1735 + if (!__atomic_compare_exchange_n (&v, &expected, desired, STRONG , __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST))
1736 + abort ();
1737 + if (expected != 0)
1738 + abort ();
1739 + if (v != max)
1740 + abort ();
1741 +
1742 + /* Now test the generic version. */
1743 +
1744 + v = 0;
1745 +
1746 + if (!__atomic_compare_exchange (&v, &expected, &max, STRONG, __ATOMIC_RELAXED, __ATOMIC_RELAXED))
1747 + abort ();
1748 + if (expected != 0)
1749 + abort ();
1750 +
1751 + if (__atomic_compare_exchange (&v, &expected, &zero, STRONG , __ATOMIC_ACQUIRE, __ATOMIC_RELAXED))
1752 + abort ();
1753 + if (expected != max)
1754 + abort ();
1755 +
1756 + if (!__atomic_compare_exchange (&v, &expected, &zero, STRONG , __ATOMIC_RELEASE, __ATOMIC_ACQUIRE))
1757 + abort ();
1758 + if (expected != max)
1759 + abort ();
1760 + if (v != 0)
1761 + abort ();
1762 +
1763 + if (__atomic_compare_exchange (&v, &expected, &desired, WEAK, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE))
1764 + abort ();
1765 + if (expected != 0)
1766 + abort ();
1767 +
1768 + if (!__atomic_compare_exchange (&v, &expected, &desired, STRONG , __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST))
1769 + abort ();
1770 + if (expected != 0)
1771 + abort ();
1772 + if (v != max)
1773 + abort ();
1774 +
1775 + return 0;
1776 +}
1777 --- /dev/null
1778 +++ b/gcc/testsuite/gcc.target/riscv/inline-atomics-6.c
1779 @@ -0,0 +1,87 @@
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" } */
1785 +
1786 +/* Test the execution of the __atomic_compare_exchange_n builtin for a short. */
1787 +
1788 +extern void abort(void);
1789 +
1790 +short v = 0;
1791 +short expected = 0;
1792 +short max = ~0;
1793 +short desired = ~0;
1794 +short zero = 0;
1795 +
1796 +#define STRONG 0
1797 +#define WEAK 1
1798 +
1799 +int
1800 +main ()
1801 +{
1802 +
1803 + if (!__atomic_compare_exchange_n (&v, &expected, max, STRONG , __ATOMIC_RELAXED, __ATOMIC_RELAXED))
1804 + abort ();
1805 + if (expected != 0)
1806 + abort ();
1807 +
1808 + if (__atomic_compare_exchange_n (&v, &expected, 0, STRONG , __ATOMIC_ACQUIRE, __ATOMIC_RELAXED))
1809 + abort ();
1810 + if (expected != max)
1811 + abort ();
1812 +
1813 + if (!__atomic_compare_exchange_n (&v, &expected, 0, STRONG , __ATOMIC_RELEASE, __ATOMIC_ACQUIRE))
1814 + abort ();
1815 + if (expected != max)
1816 + abort ();
1817 + if (v != 0)
1818 + abort ();
1819 +
1820 + if (__atomic_compare_exchange_n (&v, &expected, desired, WEAK, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE))
1821 + abort ();
1822 + if (expected != 0)
1823 + abort ();
1824 +
1825 + if (!__atomic_compare_exchange_n (&v, &expected, desired, STRONG , __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST))
1826 + abort ();
1827 + if (expected != 0)
1828 + abort ();
1829 + if (v != max)
1830 + abort ();
1831 +
1832 + /* Now test the generic version. */
1833 +
1834 + v = 0;
1835 +
1836 + if (!__atomic_compare_exchange (&v, &expected, &max, STRONG, __ATOMIC_RELAXED, __ATOMIC_RELAXED))
1837 + abort ();
1838 + if (expected != 0)
1839 + abort ();
1840 +
1841 + if (__atomic_compare_exchange (&v, &expected, &zero, STRONG , __ATOMIC_ACQUIRE, __ATOMIC_RELAXED))
1842 + abort ();
1843 + if (expected != max)
1844 + abort ();
1845 +
1846 + if (!__atomic_compare_exchange (&v, &expected, &zero, STRONG , __ATOMIC_RELEASE, __ATOMIC_ACQUIRE))
1847 + abort ();
1848 + if (expected != max)
1849 + abort ();
1850 + if (v != 0)
1851 + abort ();
1852 +
1853 + if (__atomic_compare_exchange (&v, &expected, &desired, WEAK, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE))
1854 + abort ();
1855 + if (expected != 0)
1856 + abort ();
1857 +
1858 + if (!__atomic_compare_exchange (&v, &expected, &desired, STRONG , __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST))
1859 + abort ();
1860 + if (expected != 0)
1861 + abort ();
1862 + if (v != max)
1863 + abort ();
1864 +
1865 + return 0;
1866 +}
1867 --- /dev/null
1868 +++ b/gcc/testsuite/gcc.target/riscv/inline-atomics-7.c
1869 @@ -0,0 +1,69 @@
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" } */
1875 +
1876 +/* Test the execution of the __atomic_exchange_n builtin for a char. */
1877 +
1878 +extern void abort(void);
1879 +
1880 +char v, count, ret;
1881 +
1882 +int
1883 +main ()
1884 +{
1885 + v = 0;
1886 + count = 0;
1887 +
1888 + if (__atomic_exchange_n (&v, count + 1, __ATOMIC_RELAXED) != count)
1889 + abort ();
1890 + count++;
1891 +
1892 + if (__atomic_exchange_n (&v, count + 1, __ATOMIC_ACQUIRE) != count)
1893 + abort ();
1894 + count++;
1895 +
1896 + if (__atomic_exchange_n (&v, count + 1, __ATOMIC_RELEASE) != count)
1897 + abort ();
1898 + count++;
1899 +
1900 + if (__atomic_exchange_n (&v, count + 1, __ATOMIC_ACQ_REL) != count)
1901 + abort ();
1902 + count++;
1903 +
1904 + if (__atomic_exchange_n (&v, count + 1, __ATOMIC_SEQ_CST) != count)
1905 + abort ();
1906 + count++;
1907 +
1908 + /* Now test the generic version. */
1909 +
1910 + count++;
1911 +
1912 + __atomic_exchange (&v, &count, &ret, __ATOMIC_RELAXED);
1913 + if (ret != count - 1 || v != count)
1914 + abort ();
1915 + count++;
1916 +
1917 + __atomic_exchange (&v, &count, &ret, __ATOMIC_ACQUIRE);
1918 + if (ret != count - 1 || v != count)
1919 + abort ();
1920 + count++;
1921 +
1922 + __atomic_exchange (&v, &count, &ret, __ATOMIC_RELEASE);
1923 + if (ret != count - 1 || v != count)
1924 + abort ();
1925 + count++;
1926 +
1927 + __atomic_exchange (&v, &count, &ret, __ATOMIC_ACQ_REL);
1928 + if (ret != count - 1 || v != count)
1929 + abort ();
1930 + count++;
1931 +
1932 + __atomic_exchange (&v, &count, &ret, __ATOMIC_SEQ_CST);
1933 + if (ret != count - 1 || v != count)
1934 + abort ();
1935 + count++;
1936 +
1937 + return 0;
1938 +}
1939 --- /dev/null
1940 +++ b/gcc/testsuite/gcc.target/riscv/inline-atomics-8.c
1941 @@ -0,0 +1,69 @@
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" } */
1947 +
1948 +/* Test the execution of the __atomic_X builtin for a short. */
1949 +
1950 +extern void abort(void);
1951 +
1952 +short v, count, ret;
1953 +
1954 +int
1955 +main ()
1956 +{
1957 + v = 0;
1958 + count = 0;
1959 +
1960 + if (__atomic_exchange_n (&v, count + 1, __ATOMIC_RELAXED) != count)
1961 + abort ();
1962 + count++;
1963 +
1964 + if (__atomic_exchange_n (&v, count + 1, __ATOMIC_ACQUIRE) != count)
1965 + abort ();
1966 + count++;
1967 +
1968 + if (__atomic_exchange_n (&v, count + 1, __ATOMIC_RELEASE) != count)
1969 + abort ();
1970 + count++;
1971 +
1972 + if (__atomic_exchange_n (&v, count + 1, __ATOMIC_ACQ_REL) != count)
1973 + abort ();
1974 + count++;
1975 +
1976 + if (__atomic_exchange_n (&v, count + 1, __ATOMIC_SEQ_CST) != count)
1977 + abort ();
1978 + count++;
1979 +
1980 + /* Now test the generic version. */
1981 +
1982 + count++;
1983 +
1984 + __atomic_exchange (&v, &count, &ret, __ATOMIC_RELAXED);
1985 + if (ret != count - 1 || v != count)
1986 + abort ();
1987 + count++;
1988 +
1989 + __atomic_exchange (&v, &count, &ret, __ATOMIC_ACQUIRE);
1990 + if (ret != count - 1 || v != count)
1991 + abort ();
1992 + count++;
1993 +
1994 + __atomic_exchange (&v, &count, &ret, __ATOMIC_RELEASE);
1995 + if (ret != count - 1 || v != count)
1996 + abort ();
1997 + count++;
1998 +
1999 + __atomic_exchange (&v, &count, &ret, __ATOMIC_ACQ_REL);
2000 + if (ret != count - 1 || v != count)
2001 + abort ();
2002 + count++;
2003 +
2004 + __atomic_exchange (&v, &count, &ret, __ATOMIC_SEQ_CST);
2005 + if (ret != count - 1 || v != count)
2006 + abort ();
2007 + count++;
2008 +
2009 + return 0;
2010 +}
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 ""
2016
2017 +/* Logic duplicated in gcc/gcc/config/riscv/sync.md for use when inlining is enabled */
2018 +
2019 #define GENERATE_FETCH_AND_OP(type, size, opname, insn, invert, cop) \
2020 type __sync_fetch_and_ ## opname ## _ ## size (type *p, type v) \
2021 { \