From: Soumya AR <[email protected]>
This patch adds tests to verify the correctness of atomic min/max builtins at
runtime and confirms CAS assembly on an actual target (in this case, aarch64).
- atomic-minmax.c: Checks that we emit the correct libgcc calls that get
resolved at runtime to determine if the system supports LSE or not. Also
does a runtime check.
- atomic-minmax-nolse.c: Checks for the correct non-LSE sequence using LL/SC
instructions.
- atomic-minmax-lse.c: Checks for the correct LSE instruction.
Currently, these 3 tests check for CAS calls, but once the aarch64 backend is
extended to support direct optabs for min/max, these tests will be overwritten
to min/max specific instructions.
Additionally, atomic-op-*.c tests are also extended with min/max for target
independent tests.
Bootstrapped and regression tested on aarch64-linux-gnu and x86_64-linux-gnu.
Cross-compiled and regression tested for arm-linux-gnueabihf-armv7-a and
aarch64-linux-gnu without LSE.
Signed-off-by: Soumya AR <[email protected]>
gcc/testsuite/ChangeLog:
* gcc.dg/atomic-op-1.c: Add min/max.
* gcc.dg/atomic-op-2.c: Likewise.
* gcc.dg/atomic-op-3.c: Likewise.
* gcc.dg/atomic-op-4.c: Likewise.
* gcc.dg/atomic-op-5.c: Likewise.
* gcc.target/aarch64/atomic-minmax-lse.c: New test.
* gcc.target/aarch64/atomic-minmax-nolse.c: New test.
* gcc.target/aarch64/atomic-minmax.c: New test.
* gcc.target/aarch64/atomic-minmax.x: New test.
---
gcc/testsuite/gcc.dg/atomic-op-1.c | 353 +++++++++++++++++
gcc/testsuite/gcc.dg/atomic-op-2.c | 353 +++++++++++++++++
gcc/testsuite/gcc.dg/atomic-op-3.c | 353 +++++++++++++++++
gcc/testsuite/gcc.dg/atomic-op-4.c | 353 +++++++++++++++++
gcc/testsuite/gcc.dg/atomic-op-5.c | 355 ++++++++++++++++++
.../gcc.target/aarch64/atomic-minmax-lse.c | 123 ++++++
.../gcc.target/aarch64/atomic-minmax-nolse.c | 183 +++++++++
.../gcc.target/aarch64/atomic-minmax.c | 129 +++++++
.../gcc.target/aarch64/atomic-minmax.x | 185 +++++++++
9 files changed, 2387 insertions(+)
create mode 100644 gcc/testsuite/gcc.target/aarch64/atomic-minmax-lse.c
create mode 100644 gcc/testsuite/gcc.target/aarch64/atomic-minmax-nolse.c
create mode 100644 gcc/testsuite/gcc.target/aarch64/atomic-minmax.c
create mode 100644 gcc/testsuite/gcc.target/aarch64/atomic-minmax.x
diff --git a/gcc/testsuite/gcc.dg/atomic-op-1.c
b/gcc/testsuite/gcc.dg/atomic-op-1.c
index a8a97c401b7..ed2fa629187 100644
--- a/gcc/testsuite/gcc.dg/atomic-op-1.c
+++ b/gcc/testsuite/gcc.dg/atomic-op-1.c
@@ -5,6 +5,8 @@
/* Test the execution of the __atomic_*OP builtin routines for a char. */
+#include "limits.h"
+
extern void abort(void);
char v, count, res;
@@ -167,6 +169,114 @@ test_fetch_or ()
abort ();
}
+void
+test_fetch_smin ()
+{
+ signed char sv = 10;
+
+ if (__atomic_fetch_min (&sv, 5, __ATOMIC_RELAXED) != 10)
+ abort ();
+
+ if (__atomic_fetch_min (&sv, 5, __ATOMIC_CONSUME) != 5)
+ abort ();
+
+ if (__atomic_fetch_min (&sv, -10, __ATOMIC_ACQUIRE) != 5)
+ abort ();
+
+ if (__atomic_fetch_min (&sv, -20, __ATOMIC_RELEASE) != -10)
+ abort ();
+
+ if (__atomic_fetch_min (&sv, SCHAR_MIN, __ATOMIC_ACQ_REL) != -20)
+ abort ();
+
+ if (__atomic_fetch_min (&sv, SCHAR_MAX, __ATOMIC_SEQ_CST) != SCHAR_MIN)
+ abort ();
+
+ if (sv != SCHAR_MIN)
+ abort ();
+}
+
+void
+test_fetch_umin ()
+{
+ unsigned char uv = 100;
+
+ if (__atomic_fetch_min (&uv, 50, __ATOMIC_RELAXED) != 100)
+ abort ();
+
+ if (__atomic_fetch_min (&uv, 50, __ATOMIC_CONSUME) != 50)
+ abort ();
+
+ if (__atomic_fetch_min (&uv, 75, __ATOMIC_ACQUIRE) != 50)
+ abort ();
+
+ if (__atomic_fetch_min (&uv, 10, __ATOMIC_RELEASE) != 50)
+ abort ();
+
+ if (__atomic_fetch_min (&uv, 0, __ATOMIC_ACQ_REL) != 10)
+ abort ();
+
+ if (__atomic_fetch_min (&uv, UCHAR_MAX, __ATOMIC_SEQ_CST) != 0)
+ abort ();
+
+ if (uv != 0)
+ abort ();
+}
+
+void
+test_fetch_smax ()
+{
+ signed char sv = -10;
+
+ if (__atomic_fetch_max (&sv, -5, __ATOMIC_RELAXED) != -10)
+ abort ();
+
+ if (__atomic_fetch_max (&sv, -5, __ATOMIC_CONSUME) != -5)
+ abort ();
+
+ if (__atomic_fetch_max (&sv, -20, __ATOMIC_ACQUIRE) != -5)
+ abort ();
+
+ if (__atomic_fetch_max (&sv, 10, __ATOMIC_RELEASE) != -5)
+ abort ();
+
+ if (__atomic_fetch_max (&sv, 50, __ATOMIC_ACQ_REL) != 10)
+ abort ();
+
+ if (__atomic_fetch_max (&sv, SCHAR_MAX, __ATOMIC_SEQ_CST) != 50)
+ abort ();
+
+ if (sv != SCHAR_MAX)
+ abort ();
+}
+
+void
+test_fetch_umax ()
+{
+ unsigned char uv = 10;
+
+ if (__atomic_fetch_max (&uv, 50, __ATOMIC_RELAXED) != 10)
+ abort ();
+
+ if (__atomic_fetch_max (&uv, 50, __ATOMIC_CONSUME) != 50)
+ abort ();
+
+ if (__atomic_fetch_max (&uv, 30, __ATOMIC_ACQUIRE) != 50)
+ abort ();
+
+ if (__atomic_fetch_max (&uv, 100, __ATOMIC_RELEASE) != 50)
+ abort ();
+
+ if (__atomic_fetch_max (&uv, 200, __ATOMIC_ACQ_REL) != 100)
+ abort ();
+
+ if (__atomic_fetch_max (&uv, UCHAR_MAX, __ATOMIC_SEQ_CST) != 200)
+ abort ();
+
+ if (uv != UCHAR_MAX)
+ abort ();
+}
+
/* The OP_fetch routines return the new value after the operation. */
void
@@ -328,6 +438,113 @@ test_or_fetch ()
abort ();
}
+void
+test_smin_fetch ()
+{
+ signed char sv = 10;
+
+ if (__atomic_min_fetch (&sv, 5, __ATOMIC_RELAXED) != 5)
+ abort ();
+
+ if (__atomic_min_fetch (&sv, 5, __ATOMIC_CONSUME) != 5)
+ abort ();
+
+ if (__atomic_min_fetch (&sv, -10, __ATOMIC_ACQUIRE) != -10)
+ abort ();
+
+ if (__atomic_min_fetch (&sv, -20, __ATOMIC_RELEASE) != -20)
+ abort ();
+
+ if (__atomic_min_fetch (&sv, SCHAR_MIN, __ATOMIC_ACQ_REL) != SCHAR_MIN)
+ abort ();
+
+ if (__atomic_min_fetch (&sv, SCHAR_MAX, __ATOMIC_SEQ_CST) != SCHAR_MIN)
+ abort ();
+
+ if (sv != SCHAR_MIN)
+ abort ();
+}
+
+void
+test_umin_fetch ()
+{
+ unsigned char uv = 100;
+
+ if (__atomic_min_fetch (&uv, 50, __ATOMIC_RELAXED) != 50)
+ abort ();
+
+ if (__atomic_min_fetch (&uv, 50, __ATOMIC_CONSUME) != 50)
+ abort ();
+
+ if (__atomic_min_fetch (&uv, 75, __ATOMIC_ACQUIRE) != 50)
+ abort ();
+
+ if (__atomic_min_fetch (&uv, 10, __ATOMIC_RELEASE) != 10)
+ abort ();
+
+ if (__atomic_min_fetch (&uv, 0, __ATOMIC_ACQ_REL) != 0)
+ abort ();
+
+ if (__atomic_min_fetch (&uv, UCHAR_MAX, __ATOMIC_SEQ_CST) != 0)
+ abort ();
+
+ if (uv != 0)
+ abort ();
+}
+
+void
+test_smax_fetch ()
+{
+ signed char sv = -10;
+
+ if (__atomic_max_fetch (&sv, -5, __ATOMIC_RELAXED) != -5)
+ abort ();
+
+ if (__atomic_max_fetch (&sv, -5, __ATOMIC_CONSUME) != -5)
+ abort ();
+
+ if (__atomic_max_fetch (&sv, -20, __ATOMIC_ACQUIRE) != -5)
+ abort ();
+
+ if (__atomic_max_fetch (&sv, 10, __ATOMIC_RELEASE) != 10)
+ abort ();
+
+ if (__atomic_max_fetch (&sv, 50, __ATOMIC_ACQ_REL) != 50)
+ abort ();
+
+ if (__atomic_max_fetch (&sv, SCHAR_MAX, __ATOMIC_SEQ_CST) != SCHAR_MAX)
+ abort ();
+
+ if (sv != SCHAR_MAX)
+ abort ();
+}
+
+void
+test_umax_fetch ()
+{
+ unsigned char uv = 10;
+
+ if (__atomic_max_fetch (&uv, 50, __ATOMIC_RELAXED) != 50)
+ abort ();
+
+ if (__atomic_max_fetch (&uv, 50, __ATOMIC_CONSUME) != 50)
+ abort ();
+
+ if (__atomic_max_fetch (&uv, 30, __ATOMIC_ACQUIRE) != 50)
+ abort ();
+
+ if (__atomic_max_fetch (&uv, 100, __ATOMIC_RELEASE) != 100)
+ abort ();
+
+ if (__atomic_max_fetch (&uv, 200, __ATOMIC_ACQ_REL) != 200)
+ abort ();
+
+ if (__atomic_max_fetch (&uv, UCHAR_MAX, __ATOMIC_SEQ_CST) != UCHAR_MAX)
+ abort ();
+
+ if (uv != UCHAR_MAX)
+ abort ();
+}
/* Test the OP routines with a result which isn't used. Use both variations
within each function. */
@@ -527,6 +744,130 @@ test_or ()
abort ();
}
+void
+test_smin ()
+{
+ signed char sv = 10;
+
+ __atomic_min_fetch (&sv, 5, __ATOMIC_RELAXED);
+ if (sv != 5)
+ abort ();
+
+ __atomic_fetch_min (&sv, 5, __ATOMIC_CONSUME);
+ if (sv != 5)
+ abort ();
+
+ __atomic_min_fetch (&sv, -10, __ATOMIC_ACQUIRE);
+ if (sv != -10)
+ abort ();
+
+ __atomic_fetch_min (&sv, -20, __ATOMIC_RELEASE);
+ if (sv != -20)
+ abort ();
+
+ __atomic_min_fetch (&sv, SCHAR_MIN, __ATOMIC_ACQ_REL);
+ if (sv != SCHAR_MIN)
+ abort ();
+
+ __atomic_fetch_min (&sv, SCHAR_MAX, __ATOMIC_SEQ_CST);
+
+ if (sv != SCHAR_MIN)
+ abort ();
+}
+
+void
+test_umin ()
+{
+ unsigned char uv = 100;
+
+ __atomic_min_fetch (&uv, 50, __ATOMIC_RELAXED);
+ if (uv != 50)
+ abort ();
+
+ __atomic_fetch_min (&uv, 50, __ATOMIC_CONSUME);
+ if (uv != 50)
+ abort ();
+
+ __atomic_min_fetch (&uv, 75, __ATOMIC_ACQUIRE);
+ if (uv != 50)
+ abort ();
+
+ __atomic_fetch_min (&uv, 10, __ATOMIC_RELEASE);
+ if (uv != 10)
+ abort ();
+
+ __atomic_min_fetch (&uv, 0, __ATOMIC_ACQ_REL);
+ if (uv != 0)
+ abort ();
+
+ __atomic_fetch_min (&uv, UCHAR_MAX, __ATOMIC_SEQ_CST);
+
+ if (uv != 0)
+ abort ();
+}
+
+void
+test_smax ()
+{
+ signed char sv = -10;
+
+ __atomic_max_fetch (&sv, -5, __ATOMIC_RELAXED);
+ if (sv != -5)
+ abort ();
+
+ __atomic_fetch_max (&sv, -5, __ATOMIC_CONSUME);
+ if (sv != -5)
+ abort ();
+
+ __atomic_max_fetch (&sv, -20, __ATOMIC_ACQUIRE);
+ if (sv != -5)
+ abort ();
+
+ __atomic_fetch_max (&sv, 10, __ATOMIC_RELEASE);
+ if (sv != 10)
+ abort ();
+
+ __atomic_max_fetch (&sv, 50, __ATOMIC_ACQ_REL);
+ if (sv != 50)
+ abort ();
+
+ __atomic_fetch_max (&sv, SCHAR_MAX, __ATOMIC_SEQ_CST);
+
+ if (sv != SCHAR_MAX)
+ abort ();
+}
+
+void
+test_umax ()
+{
+ unsigned char uv = 10;
+
+ __atomic_max_fetch (&uv, 50, __ATOMIC_RELAXED);
+ if (uv != 50)
+ abort ();
+
+ __atomic_fetch_max (&uv, 50, __ATOMIC_CONSUME);
+ if (uv != 50)
+ abort ();
+
+ __atomic_max_fetch (&uv, 30, __ATOMIC_ACQUIRE);
+ if (uv != 50)
+ abort ();
+
+ __atomic_fetch_max (&uv, 100, __ATOMIC_RELEASE);
+ if (uv != 100)
+ abort ();
+
+ __atomic_max_fetch (&uv, 200, __ATOMIC_ACQ_REL);
+ if (uv != 200)
+ abort ();
+
+ __atomic_fetch_max (&uv, UCHAR_MAX, __ATOMIC_SEQ_CST);
+
+ if (uv != UCHAR_MAX)
+ abort ();
+}
+
int
main ()
{
@@ -536,6 +877,10 @@ main ()
test_fetch_nand ();
test_fetch_xor ();
test_fetch_or ();
+ test_fetch_smin ();
+ test_fetch_umin ();
+ test_fetch_smax ();
+ test_fetch_umax ();
test_add_fetch ();
test_sub_fetch ();
@@ -543,6 +888,10 @@ main ()
test_nand_fetch ();
test_xor_fetch ();
test_or_fetch ();
+ test_smin_fetch ();
+ test_umin_fetch ();
+ test_smax_fetch ();
+ test_umax_fetch ();
test_add ();
test_sub ();
@@ -550,6 +899,10 @@ main ()
test_nand ();
test_xor ();
test_or ();
+ test_smin ();
+ test_umin ();
+ test_smax ();
+ test_umax ();
return 0;
}
diff --git a/gcc/testsuite/gcc.dg/atomic-op-2.c
b/gcc/testsuite/gcc.dg/atomic-op-2.c
index 949850345b5..95dcdd02097 100644
--- a/gcc/testsuite/gcc.dg/atomic-op-2.c
+++ b/gcc/testsuite/gcc.dg/atomic-op-2.c
@@ -6,6 +6,8 @@
/* Test the execution of the __atomic_*OP builtin routines for a short. */
+#include "limits.h"
+
extern void abort(void);
short v, count, res;
@@ -168,6 +170,114 @@ test_fetch_or ()
abort ();
}
+void
+test_fetch_smin ()
+{
+ short sv = 10;
+
+ if (__atomic_fetch_min (&sv, 5, __ATOMIC_RELAXED) != 10)
+ abort ();
+
+ if (__atomic_fetch_min (&sv, 5, __ATOMIC_CONSUME) != 5)
+ abort ();
+
+ if (__atomic_fetch_min (&sv, -10, __ATOMIC_ACQUIRE) != 5)
+ abort ();
+
+ if (__atomic_fetch_min (&sv, -20, __ATOMIC_RELEASE) != -10)
+ abort ();
+
+ if (__atomic_fetch_min (&sv, SHRT_MIN, __ATOMIC_ACQ_REL) != -20)
+ abort ();
+
+ if (__atomic_fetch_min (&sv, SHRT_MAX, __ATOMIC_SEQ_CST) != SHRT_MIN)
+ abort ();
+
+ if (sv != SHRT_MIN)
+ abort ();
+}
+
+void
+test_fetch_umin ()
+{
+ unsigned short uv = 100;
+
+ if (__atomic_fetch_min (&uv, 50, __ATOMIC_RELAXED) != 100)
+ abort ();
+
+ if (__atomic_fetch_min (&uv, 50, __ATOMIC_CONSUME) != 50)
+ abort ();
+
+ if (__atomic_fetch_min (&uv, 75, __ATOMIC_ACQUIRE) != 50)
+ abort ();
+
+ if (__atomic_fetch_min (&uv, 10, __ATOMIC_RELEASE) != 50)
+ abort ();
+
+ if (__atomic_fetch_min (&uv, 0, __ATOMIC_ACQ_REL) != 10)
+ abort ();
+
+ if (__atomic_fetch_min (&uv, USHRT_MAX, __ATOMIC_SEQ_CST) != 0)
+ abort ();
+
+ if (uv != 0)
+ abort ();
+}
+
+void
+test_fetch_smax ()
+{
+ short sv = -10;
+
+ if (__atomic_fetch_max (&sv, -5, __ATOMIC_RELAXED) != -10)
+ abort ();
+
+ if (__atomic_fetch_max (&sv, -5, __ATOMIC_CONSUME) != -5)
+ abort ();
+
+ if (__atomic_fetch_max (&sv, -20, __ATOMIC_ACQUIRE) != -5)
+ abort ();
+
+ if (__atomic_fetch_max (&sv, 10, __ATOMIC_RELEASE) != -5)
+ abort ();
+
+ if (__atomic_fetch_max (&sv, 50, __ATOMIC_ACQ_REL) != 10)
+ abort ();
+
+ if (__atomic_fetch_max (&sv, SHRT_MAX, __ATOMIC_SEQ_CST) != 50)
+ abort ();
+
+ if (sv != SHRT_MAX)
+ abort ();
+}
+
+void
+test_fetch_umax ()
+{
+ unsigned short uv = 10;
+
+ if (__atomic_fetch_max (&uv, 50, __ATOMIC_RELAXED) != 10)
+ abort ();
+
+ if (__atomic_fetch_max (&uv, 50, __ATOMIC_CONSUME) != 50)
+ abort ();
+
+ if (__atomic_fetch_max (&uv, 30, __ATOMIC_ACQUIRE) != 50)
+ abort ();
+
+ if (__atomic_fetch_max (&uv, 100, __ATOMIC_RELEASE) != 50)
+ abort ();
+
+ if (__atomic_fetch_max (&uv, 200, __ATOMIC_ACQ_REL) != 100)
+ abort ();
+
+ if (__atomic_fetch_max (&uv, USHRT_MAX, __ATOMIC_SEQ_CST) != 200)
+ abort ();
+
+ if (uv != USHRT_MAX)
+ abort ();
+}
+
/* The OP_fetch routines return the new value after the operation. */
void
@@ -329,6 +439,113 @@ test_or_fetch ()
abort ();
}
+void
+test_smin_fetch ()
+{
+ short sv = 10;
+
+ if (__atomic_min_fetch (&sv, 5, __ATOMIC_RELAXED) != 5)
+ abort ();
+
+ if (__atomic_min_fetch (&sv, 5, __ATOMIC_CONSUME) != 5)
+ abort ();
+
+ if (__atomic_min_fetch (&sv, -10, __ATOMIC_ACQUIRE) != -10)
+ abort ();
+
+ if (__atomic_min_fetch (&sv, -20, __ATOMIC_RELEASE) != -20)
+ abort ();
+
+ if (__atomic_min_fetch (&sv, SHRT_MIN, __ATOMIC_ACQ_REL) != SHRT_MIN)
+ abort ();
+
+ if (__atomic_min_fetch (&sv, SHRT_MAX, __ATOMIC_SEQ_CST) != SHRT_MIN)
+ abort ();
+
+ if (sv != SHRT_MIN)
+ abort ();
+}
+
+void
+test_umin_fetch ()
+{
+ unsigned short uv = 100;
+
+ if (__atomic_min_fetch (&uv, 50, __ATOMIC_RELAXED) != 50)
+ abort ();
+
+ if (__atomic_min_fetch (&uv, 50, __ATOMIC_CONSUME) != 50)
+ abort ();
+
+ if (__atomic_min_fetch (&uv, 75, __ATOMIC_ACQUIRE) != 50)
+ abort ();
+
+ if (__atomic_min_fetch (&uv, 10, __ATOMIC_RELEASE) != 10)
+ abort ();
+
+ if (__atomic_min_fetch (&uv, 0, __ATOMIC_ACQ_REL) != 0)
+ abort ();
+
+ if (__atomic_min_fetch (&uv, USHRT_MAX, __ATOMIC_SEQ_CST) != 0)
+ abort ();
+
+ if (uv != 0)
+ abort ();
+}
+
+void
+test_smax_fetch ()
+{
+ short sv = -10;
+
+ if (__atomic_max_fetch (&sv, -5, __ATOMIC_RELAXED) != -5)
+ abort ();
+
+ if (__atomic_max_fetch (&sv, -5, __ATOMIC_CONSUME) != -5)
+ abort ();
+
+ if (__atomic_max_fetch (&sv, -20, __ATOMIC_ACQUIRE) != -5)
+ abort ();
+
+ if (__atomic_max_fetch (&sv, 10, __ATOMIC_RELEASE) != 10)
+ abort ();
+
+ if (__atomic_max_fetch (&sv, 50, __ATOMIC_ACQ_REL) != 50)
+ abort ();
+
+ if (__atomic_max_fetch (&sv, SHRT_MAX, __ATOMIC_SEQ_CST) != SHRT_MAX)
+ abort ();
+
+ if (sv != SHRT_MAX)
+ abort ();
+}
+
+void
+test_umax_fetch ()
+{
+ unsigned short uv = 10;
+
+ if (__atomic_max_fetch (&uv, 50, __ATOMIC_RELAXED) != 50)
+ abort ();
+
+ if (__atomic_max_fetch (&uv, 50, __ATOMIC_CONSUME) != 50)
+ abort ();
+
+ if (__atomic_max_fetch (&uv, 30, __ATOMIC_ACQUIRE) != 50)
+ abort ();
+
+ if (__atomic_max_fetch (&uv, 100, __ATOMIC_RELEASE) != 100)
+ abort ();
+
+ if (__atomic_max_fetch (&uv, 200, __ATOMIC_ACQ_REL) != 200)
+ abort ();
+
+ if (__atomic_max_fetch (&uv, USHRT_MAX, __ATOMIC_SEQ_CST) != USHRT_MAX)
+ abort ();
+
+ if (uv != USHRT_MAX)
+ abort ();
+}
/* Test the OP routines with a result which isn't used. Use both variations
within each function. */
@@ -528,6 +745,130 @@ test_or ()
abort ();
}
+void
+test_smin ()
+{
+ short sv = 10;
+
+ __atomic_min_fetch (&sv, 5, __ATOMIC_RELAXED);
+ if (sv != 5)
+ abort ();
+
+ __atomic_fetch_min (&sv, 5, __ATOMIC_CONSUME);
+ if (sv != 5)
+ abort ();
+
+ __atomic_min_fetch (&sv, -10, __ATOMIC_ACQUIRE);
+ if (sv != -10)
+ abort ();
+
+ __atomic_fetch_min (&sv, -20, __ATOMIC_RELEASE);
+ if (sv != -20)
+ abort ();
+
+ __atomic_min_fetch (&sv, SHRT_MIN, __ATOMIC_ACQ_REL);
+ if (sv != SHRT_MIN)
+ abort ();
+
+ __atomic_fetch_min (&sv, SHRT_MAX, __ATOMIC_SEQ_CST);
+
+ if (sv != SHRT_MIN)
+ abort ();
+}
+
+void
+test_umin ()
+{
+ unsigned short uv = 100;
+
+ __atomic_min_fetch (&uv, 50, __ATOMIC_RELAXED);
+ if (uv != 50)
+ abort ();
+
+ __atomic_fetch_min (&uv, 50, __ATOMIC_CONSUME);
+ if (uv != 50)
+ abort ();
+
+ __atomic_min_fetch (&uv, 75, __ATOMIC_ACQUIRE);
+ if (uv != 50)
+ abort ();
+
+ __atomic_fetch_min (&uv, 10, __ATOMIC_RELEASE);
+ if (uv != 10)
+ abort ();
+
+ __atomic_min_fetch (&uv, 0, __ATOMIC_ACQ_REL);
+ if (uv != 0)
+ abort ();
+
+ __atomic_fetch_min (&uv, USHRT_MAX, __ATOMIC_SEQ_CST);
+
+ if (uv != 0)
+ abort ();
+}
+
+void
+test_smax ()
+{
+ short sv = -10;
+
+ __atomic_max_fetch (&sv, -5, __ATOMIC_RELAXED);
+ if (sv != -5)
+ abort ();
+
+ __atomic_fetch_max (&sv, -5, __ATOMIC_CONSUME);
+ if (sv != -5)
+ abort ();
+
+ __atomic_max_fetch (&sv, -20, __ATOMIC_ACQUIRE);
+ if (sv != -5)
+ abort ();
+
+ __atomic_fetch_max (&sv, 10, __ATOMIC_RELEASE);
+ if (sv != 10)
+ abort ();
+
+ __atomic_max_fetch (&sv, 50, __ATOMIC_ACQ_REL);
+ if (sv != 50)
+ abort ();
+
+ __atomic_fetch_max (&sv, SHRT_MAX, __ATOMIC_SEQ_CST);
+
+ if (sv != SHRT_MAX)
+ abort ();
+}
+
+void
+test_umax ()
+{
+ unsigned short uv = 10;
+
+ __atomic_max_fetch (&uv, 50, __ATOMIC_RELAXED);
+ if (uv != 50)
+ abort ();
+
+ __atomic_fetch_max (&uv, 50, __ATOMIC_CONSUME);
+ if (uv != 50)
+ abort ();
+
+ __atomic_max_fetch (&uv, 30, __ATOMIC_ACQUIRE);
+ if (uv != 50)
+ abort ();
+
+ __atomic_fetch_max (&uv, 100, __ATOMIC_RELEASE);
+ if (uv != 100)
+ abort ();
+
+ __atomic_max_fetch (&uv, 200, __ATOMIC_ACQ_REL);
+ if (uv != 200)
+ abort ();
+
+ __atomic_fetch_max (&uv, USHRT_MAX, __ATOMIC_SEQ_CST);
+
+ if (uv != USHRT_MAX)
+ abort ();
+}
+
int
main ()
{
@@ -537,6 +878,10 @@ main ()
test_fetch_nand ();
test_fetch_xor ();
test_fetch_or ();
+ test_fetch_smin ();
+ test_fetch_umin ();
+ test_fetch_smax ();
+ test_fetch_umax ();
test_add_fetch ();
test_sub_fetch ();
@@ -544,6 +889,10 @@ main ()
test_nand_fetch ();
test_xor_fetch ();
test_or_fetch ();
+ test_smin_fetch ();
+ test_umin_fetch ();
+ test_smax_fetch ();
+ test_umax_fetch ();
test_add ();
test_sub ();
@@ -551,6 +900,10 @@ main ()
test_nand ();
test_xor ();
test_or ();
+ test_smin ();
+ test_umin ();
+ test_smax ();
+ test_umax ();
return 0;
}
diff --git a/gcc/testsuite/gcc.dg/atomic-op-3.c
b/gcc/testsuite/gcc.dg/atomic-op-3.c
index 9a54a2a4178..d18cb582116 100644
--- a/gcc/testsuite/gcc.dg/atomic-op-3.c
+++ b/gcc/testsuite/gcc.dg/atomic-op-3.c
@@ -5,6 +5,8 @@
/* Test the execution of the __atomic_*OP builtin routines for an int. */
+#include "limits.h"
+
extern void abort(void);
int v, count, res;
@@ -167,6 +169,114 @@ test_fetch_or ()
abort ();
}
+void
+test_fetch_smin ()
+{
+ int sv = 10;
+
+ if (__atomic_fetch_min (&sv, 5, __ATOMIC_RELAXED) != 10)
+ abort ();
+
+ if (__atomic_fetch_min (&sv, 5, __ATOMIC_CONSUME) != 5)
+ abort ();
+
+ if (__atomic_fetch_min (&sv, -10, __ATOMIC_ACQUIRE) != 5)
+ abort ();
+
+ if (__atomic_fetch_min (&sv, -20, __ATOMIC_RELEASE) != -10)
+ abort ();
+
+ if (__atomic_fetch_min (&sv, INT_MIN, __ATOMIC_ACQ_REL) != -20)
+ abort ();
+
+ if (__atomic_fetch_min (&sv, INT_MAX, __ATOMIC_SEQ_CST) != INT_MIN)
+ abort ();
+
+ if (sv != INT_MIN)
+ abort ();
+}
+
+void
+test_fetch_umin ()
+{
+ unsigned int uv = 100;
+
+ if (__atomic_fetch_min (&uv, 50, __ATOMIC_RELAXED) != 100)
+ abort ();
+
+ if (__atomic_fetch_min (&uv, 50, __ATOMIC_CONSUME) != 50)
+ abort ();
+
+ if (__atomic_fetch_min (&uv, 75, __ATOMIC_ACQUIRE) != 50)
+ abort ();
+
+ if (__atomic_fetch_min (&uv, 10, __ATOMIC_RELEASE) != 50)
+ abort ();
+
+ if (__atomic_fetch_min (&uv, 0, __ATOMIC_ACQ_REL) != 10)
+ abort ();
+
+ if (__atomic_fetch_min (&uv, UINT_MAX, __ATOMIC_SEQ_CST) != 0)
+ abort ();
+
+ if (uv != 0)
+ abort ();
+}
+
+void
+test_fetch_smax ()
+{
+ int sv = -10;
+
+ if (__atomic_fetch_max (&sv, -5, __ATOMIC_RELAXED) != -10)
+ abort ();
+
+ if (__atomic_fetch_max (&sv, -5, __ATOMIC_CONSUME) != -5)
+ abort ();
+
+ if (__atomic_fetch_max (&sv, -20, __ATOMIC_ACQUIRE) != -5)
+ abort ();
+
+ if (__atomic_fetch_max (&sv, 10, __ATOMIC_RELEASE) != -5)
+ abort ();
+
+ if (__atomic_fetch_max (&sv, 50, __ATOMIC_ACQ_REL) != 10)
+ abort ();
+
+ if (__atomic_fetch_max (&sv, INT_MAX, __ATOMIC_SEQ_CST) != 50)
+ abort ();
+
+ if (sv != INT_MAX)
+ abort ();
+}
+
+void
+test_fetch_umax ()
+{
+ unsigned int uv = 10;
+
+ if (__atomic_fetch_max (&uv, 50, __ATOMIC_RELAXED) != 10)
+ abort ();
+
+ if (__atomic_fetch_max (&uv, 50, __ATOMIC_CONSUME) != 50)
+ abort ();
+
+ if (__atomic_fetch_max (&uv, 30, __ATOMIC_ACQUIRE) != 50)
+ abort ();
+
+ if (__atomic_fetch_max (&uv, 100, __ATOMIC_RELEASE) != 50)
+ abort ();
+
+ if (__atomic_fetch_max (&uv, 200, __ATOMIC_ACQ_REL) != 100)
+ abort ();
+
+ if (__atomic_fetch_max (&uv, UINT_MAX, __ATOMIC_SEQ_CST) != 200)
+ abort ();
+
+ if (uv != UINT_MAX)
+ abort ();
+}
+
/* The OP_fetch routines return the new value after the operation. */
void
@@ -328,6 +438,113 @@ test_or_fetch ()
abort ();
}
+void
+test_smin_fetch ()
+{
+ int sv = 10;
+
+ if (__atomic_min_fetch (&sv, 5, __ATOMIC_RELAXED) != 5)
+ abort ();
+
+ if (__atomic_min_fetch (&sv, 5, __ATOMIC_CONSUME) != 5)
+ abort ();
+
+ if (__atomic_min_fetch (&sv, -10, __ATOMIC_ACQUIRE) != -10)
+ abort ();
+
+ if (__atomic_min_fetch (&sv, -20, __ATOMIC_RELEASE) != -20)
+ abort ();
+
+ if (__atomic_min_fetch (&sv, INT_MIN, __ATOMIC_ACQ_REL) != INT_MIN)
+ abort ();
+
+ if (__atomic_min_fetch (&sv, INT_MAX, __ATOMIC_SEQ_CST) != INT_MIN)
+ abort ();
+
+ if (sv != INT_MIN)
+ abort ();
+}
+
+void
+test_umin_fetch ()
+{
+ unsigned int uv = 100;
+
+ if (__atomic_min_fetch (&uv, 50, __ATOMIC_RELAXED) != 50)
+ abort ();
+
+ if (__atomic_min_fetch (&uv, 50, __ATOMIC_CONSUME) != 50)
+ abort ();
+
+ if (__atomic_min_fetch (&uv, 75, __ATOMIC_ACQUIRE) != 50)
+ abort ();
+
+ if (__atomic_min_fetch (&uv, 10, __ATOMIC_RELEASE) != 10)
+ abort ();
+
+ if (__atomic_min_fetch (&uv, 0, __ATOMIC_ACQ_REL) != 0)
+ abort ();
+
+ if (__atomic_min_fetch (&uv, UINT_MAX, __ATOMIC_SEQ_CST) != 0)
+ abort ();
+
+ if (uv != 0)
+ abort ();
+}
+
+void
+test_smax_fetch ()
+{
+ int sv = -10;
+
+ if (__atomic_max_fetch (&sv, -5, __ATOMIC_RELAXED) != -5)
+ abort ();
+
+ if (__atomic_max_fetch (&sv, -5, __ATOMIC_CONSUME) != -5)
+ abort ();
+
+ if (__atomic_max_fetch (&sv, -20, __ATOMIC_ACQUIRE) != -5)
+ abort ();
+
+ if (__atomic_max_fetch (&sv, 10, __ATOMIC_RELEASE) != 10)
+ abort ();
+
+ if (__atomic_max_fetch (&sv, 50, __ATOMIC_ACQ_REL) != 50)
+ abort ();
+
+ if (__atomic_max_fetch (&sv, INT_MAX, __ATOMIC_SEQ_CST) != INT_MAX)
+ abort ();
+
+ if (sv != INT_MAX)
+ abort ();
+}
+
+void
+test_umax_fetch ()
+{
+ unsigned int uv = 10;
+
+ if (__atomic_max_fetch (&uv, 50, __ATOMIC_RELAXED) != 50)
+ abort ();
+
+ if (__atomic_max_fetch (&uv, 50, __ATOMIC_CONSUME) != 50)
+ abort ();
+
+ if (__atomic_max_fetch (&uv, 30, __ATOMIC_ACQUIRE) != 50)
+ abort ();
+
+ if (__atomic_max_fetch (&uv, 100, __ATOMIC_RELEASE) != 100)
+ abort ();
+
+ if (__atomic_max_fetch (&uv, 200, __ATOMIC_ACQ_REL) != 200)
+ abort ();
+
+ if (__atomic_max_fetch (&uv, UINT_MAX, __ATOMIC_SEQ_CST) != UINT_MAX)
+ abort ();
+
+ if (uv != UINT_MAX)
+ abort ();
+}
/* Test the OP routines with a result which isn't used. Use both variations
within each function. */
@@ -527,6 +744,130 @@ test_or ()
abort ();
}
+void
+test_smin ()
+{
+ int sv = 10;
+
+ __atomic_min_fetch (&sv, 5, __ATOMIC_RELAXED);
+ if (sv != 5)
+ abort ();
+
+ __atomic_fetch_min (&sv, 5, __ATOMIC_CONSUME);
+ if (sv != 5)
+ abort ();
+
+ __atomic_min_fetch (&sv, -10, __ATOMIC_ACQUIRE);
+ if (sv != -10)
+ abort ();
+
+ __atomic_fetch_min (&sv, -20, __ATOMIC_RELEASE);
+ if (sv != -20)
+ abort ();
+
+ __atomic_min_fetch (&sv, INT_MIN, __ATOMIC_ACQ_REL);
+ if (sv != INT_MIN)
+ abort ();
+
+ __atomic_fetch_min (&sv, INT_MAX, __ATOMIC_SEQ_CST);
+
+ if (sv != INT_MIN)
+ abort ();
+}
+
+void
+test_umin ()
+{
+ unsigned int uv = 100;
+
+ __atomic_min_fetch (&uv, 50, __ATOMIC_RELAXED);
+ if (uv != 50)
+ abort ();
+
+ __atomic_fetch_min (&uv, 50, __ATOMIC_CONSUME);
+ if (uv != 50)
+ abort ();
+
+ __atomic_min_fetch (&uv, 75, __ATOMIC_ACQUIRE);
+ if (uv != 50)
+ abort ();
+
+ __atomic_fetch_min (&uv, 10, __ATOMIC_RELEASE);
+ if (uv != 10)
+ abort ();
+
+ __atomic_min_fetch (&uv, 0, __ATOMIC_ACQ_REL);
+ if (uv != 0)
+ abort ();
+
+ __atomic_fetch_min (&uv, UINT_MAX, __ATOMIC_SEQ_CST);
+
+ if (uv != 0)
+ abort ();
+}
+
+void
+test_smax ()
+{
+ int sv = -10;
+
+ __atomic_max_fetch (&sv, -5, __ATOMIC_RELAXED);
+ if (sv != -5)
+ abort ();
+
+ __atomic_fetch_max (&sv, -5, __ATOMIC_CONSUME);
+ if (sv != -5)
+ abort ();
+
+ __atomic_max_fetch (&sv, -20, __ATOMIC_ACQUIRE);
+ if (sv != -5)
+ abort ();
+
+ __atomic_fetch_max (&sv, 10, __ATOMIC_RELEASE);
+ if (sv != 10)
+ abort ();
+
+ __atomic_max_fetch (&sv, 50, __ATOMIC_ACQ_REL);
+ if (sv != 50)
+ abort ();
+
+ __atomic_fetch_max (&sv, INT_MAX, __ATOMIC_SEQ_CST);
+
+ if (sv != INT_MAX)
+ abort ();
+}
+
+void
+test_umax ()
+{
+ unsigned int uv = 10;
+
+ __atomic_max_fetch (&uv, 50, __ATOMIC_RELAXED);
+ if (uv != 50)
+ abort ();
+
+ __atomic_fetch_max (&uv, 50, __ATOMIC_CONSUME);
+ if (uv != 50)
+ abort ();
+
+ __atomic_max_fetch (&uv, 30, __ATOMIC_ACQUIRE);
+ if (uv != 50)
+ abort ();
+
+ __atomic_fetch_max (&uv, 100, __ATOMIC_RELEASE);
+ if (uv != 100)
+ abort ();
+
+ __atomic_max_fetch (&uv, 200, __ATOMIC_ACQ_REL);
+ if (uv != 200)
+ abort ();
+
+ __atomic_fetch_max (&uv, UINT_MAX, __ATOMIC_SEQ_CST);
+
+ if (uv != UINT_MAX)
+ abort ();
+}
+
int
main ()
{
@@ -536,6 +877,10 @@ main ()
test_fetch_nand ();
test_fetch_xor ();
test_fetch_or ();
+ test_fetch_smin ();
+ test_fetch_umin ();
+ test_fetch_smax ();
+ test_fetch_umax ();
test_add_fetch ();
test_sub_fetch ();
@@ -543,6 +888,10 @@ main ()
test_nand_fetch ();
test_xor_fetch ();
test_or_fetch ();
+ test_smin_fetch ();
+ test_umin_fetch ();
+ test_smax_fetch ();
+ test_umax_fetch ();
test_add ();
test_sub ();
@@ -550,6 +899,10 @@ main ()
test_nand ();
test_xor ();
test_or ();
+ test_smin ();
+ test_umin ();
+ test_smax ();
+ test_umax ();
return 0;
}
diff --git a/gcc/testsuite/gcc.dg/atomic-op-4.c
b/gcc/testsuite/gcc.dg/atomic-op-4.c
index 6990b0e2d75..bd5e8582b6a 100644
--- a/gcc/testsuite/gcc.dg/atomic-op-4.c
+++ b/gcc/testsuite/gcc.dg/atomic-op-4.c
@@ -7,6 +7,8 @@
/* Test the execution of the __atomic_*OP builtin routines for long long. */
+#include "limits.h"
+
extern void abort(void);
long long v, count, res;
@@ -169,6 +171,114 @@ test_fetch_or ()
abort ();
}
+void
+test_fetch_smin ()
+{
+ long long sv = 10;
+
+ if (__atomic_fetch_min (&sv, 5, __ATOMIC_RELAXED) != 10)
+ abort ();
+
+ if (__atomic_fetch_min (&sv, 5, __ATOMIC_CONSUME) != 5)
+ abort ();
+
+ if (__atomic_fetch_min (&sv, -10, __ATOMIC_ACQUIRE) != 5)
+ abort ();
+
+ if (__atomic_fetch_min (&sv, -20, __ATOMIC_RELEASE) != -10)
+ abort ();
+
+ if (__atomic_fetch_min (&sv, LLONG_MIN, __ATOMIC_ACQ_REL) != -20)
+ abort ();
+
+ if (__atomic_fetch_min (&sv, LLONG_MAX, __ATOMIC_SEQ_CST) != LLONG_MIN)
+ abort ();
+
+ if (sv != LLONG_MIN)
+ abort ();
+}
+
+void
+test_fetch_umin ()
+{
+ unsigned long long uv = 100;
+
+ if (__atomic_fetch_min (&uv, 50, __ATOMIC_RELAXED) != 100)
+ abort ();
+
+ if (__atomic_fetch_min (&uv, 50, __ATOMIC_CONSUME) != 50)
+ abort ();
+
+ if (__atomic_fetch_min (&uv, 75, __ATOMIC_ACQUIRE) != 50)
+ abort ();
+
+ if (__atomic_fetch_min (&uv, 10, __ATOMIC_RELEASE) != 50)
+ abort ();
+
+ if (__atomic_fetch_min (&uv, 0, __ATOMIC_ACQ_REL) != 10)
+ abort ();
+
+ if (__atomic_fetch_min (&uv, ULLONG_MAX, __ATOMIC_SEQ_CST) != 0)
+ abort ();
+
+ if (uv != 0)
+ abort ();
+}
+
+void
+test_fetch_smax ()
+{
+ long long sv = -10;
+
+ if (__atomic_fetch_max (&sv, -5, __ATOMIC_RELAXED) != -10)
+ abort ();
+
+ if (__atomic_fetch_max (&sv, -5, __ATOMIC_CONSUME) != -5)
+ abort ();
+
+ if (__atomic_fetch_max (&sv, -20, __ATOMIC_ACQUIRE) != -5)
+ abort ();
+
+ if (__atomic_fetch_max (&sv, 10, __ATOMIC_RELEASE) != -5)
+ abort ();
+
+ if (__atomic_fetch_max (&sv, 50, __ATOMIC_ACQ_REL) != 10)
+ abort ();
+
+ if (__atomic_fetch_max (&sv, LLONG_MAX, __ATOMIC_SEQ_CST) != 50)
+ abort ();
+
+ if (sv != LLONG_MAX)
+ abort ();
+}
+
+void
+test_fetch_umax ()
+{
+ unsigned long long uv = 10;
+
+ if (__atomic_fetch_max (&uv, 50, __ATOMIC_RELAXED) != 10)
+ abort ();
+
+ if (__atomic_fetch_max (&uv, 50, __ATOMIC_CONSUME) != 50)
+ abort ();
+
+ if (__atomic_fetch_max (&uv, 30, __ATOMIC_ACQUIRE) != 50)
+ abort ();
+
+ if (__atomic_fetch_max (&uv, 100, __ATOMIC_RELEASE) != 50)
+ abort ();
+
+ if (__atomic_fetch_max (&uv, 200, __ATOMIC_ACQ_REL) != 100)
+ abort ();
+
+ if (__atomic_fetch_max (&uv, ULLONG_MAX, __ATOMIC_SEQ_CST) != 200)
+ abort ();
+
+ if (uv != ULLONG_MAX)
+ abort ();
+}
+
/* The OP_fetch routines return the new value after the operation. */
void
@@ -330,6 +440,113 @@ test_or_fetch ()
abort ();
}
+void
+test_smin_fetch ()
+{
+ long long sv = 10;
+
+ if (__atomic_min_fetch (&sv, 5, __ATOMIC_RELAXED) != 5)
+ abort ();
+
+ if (__atomic_min_fetch (&sv, 5, __ATOMIC_CONSUME) != 5)
+ abort ();
+
+ if (__atomic_min_fetch (&sv, -10, __ATOMIC_ACQUIRE) != -10)
+ abort ();
+
+ if (__atomic_min_fetch (&sv, -20, __ATOMIC_RELEASE) != -20)
+ abort ();
+
+ if (__atomic_min_fetch (&sv, LLONG_MIN, __ATOMIC_ACQ_REL) != LLONG_MIN)
+ abort ();
+
+ if (__atomic_min_fetch (&sv, LLONG_MAX, __ATOMIC_SEQ_CST) != LLONG_MIN)
+ abort ();
+
+ if (sv != LLONG_MIN)
+ abort ();
+}
+
+void
+test_umin_fetch ()
+{
+ unsigned long long uv = 100;
+
+ if (__atomic_min_fetch (&uv, 50, __ATOMIC_RELAXED) != 50)
+ abort ();
+
+ if (__atomic_min_fetch (&uv, 50, __ATOMIC_CONSUME) != 50)
+ abort ();
+
+ if (__atomic_min_fetch (&uv, 75, __ATOMIC_ACQUIRE) != 50)
+ abort ();
+
+ if (__atomic_min_fetch (&uv, 10, __ATOMIC_RELEASE) != 10)
+ abort ();
+
+ if (__atomic_min_fetch (&uv, 0, __ATOMIC_ACQ_REL) != 0)
+ abort ();
+
+ if (__atomic_min_fetch (&uv, ULLONG_MAX, __ATOMIC_SEQ_CST) != 0)
+ abort ();
+
+ if (uv != 0)
+ abort ();
+}
+
+void
+test_smax_fetch ()
+{
+ long long sv = -10;
+
+ if (__atomic_max_fetch (&sv, -5, __ATOMIC_RELAXED) != -5)
+ abort ();
+
+ if (__atomic_max_fetch (&sv, -5, __ATOMIC_CONSUME) != -5)
+ abort ();
+
+ if (__atomic_max_fetch (&sv, -20, __ATOMIC_ACQUIRE) != -5)
+ abort ();
+
+ if (__atomic_max_fetch (&sv, 10, __ATOMIC_RELEASE) != 10)
+ abort ();
+
+ if (__atomic_max_fetch (&sv, 50, __ATOMIC_ACQ_REL) != 50)
+ abort ();
+
+ if (__atomic_max_fetch (&sv, LLONG_MAX, __ATOMIC_SEQ_CST) != LLONG_MAX)
+ abort ();
+
+ if (sv != LLONG_MAX)
+ abort ();
+}
+
+void
+test_umax_fetch ()
+{
+ unsigned long long uv = 10;
+
+ if (__atomic_max_fetch (&uv, 50, __ATOMIC_RELAXED) != 50)
+ abort ();
+
+ if (__atomic_max_fetch (&uv, 50, __ATOMIC_CONSUME) != 50)
+ abort ();
+
+ if (__atomic_max_fetch (&uv, 30, __ATOMIC_ACQUIRE) != 50)
+ abort ();
+
+ if (__atomic_max_fetch (&uv, 100, __ATOMIC_RELEASE) != 100)
+ abort ();
+
+ if (__atomic_max_fetch (&uv, 200, __ATOMIC_ACQ_REL) != 200)
+ abort ();
+
+ if (__atomic_max_fetch (&uv, ULLONG_MAX, __ATOMIC_SEQ_CST) != ULLONG_MAX)
+ abort ();
+
+ if (uv != ULLONG_MAX)
+ abort ();
+}
/* Test the OP routines with a result which isn't used. Use both variations
within each function. */
@@ -529,6 +746,130 @@ test_or ()
abort ();
}
+void
+test_smin ()
+{
+ long long sv = 10;
+
+ __atomic_min_fetch (&sv, 5, __ATOMIC_RELAXED);
+ if (sv != 5)
+ abort ();
+
+ __atomic_fetch_min (&sv, 5, __ATOMIC_CONSUME);
+ if (sv != 5)
+ abort ();
+
+ __atomic_min_fetch (&sv, -10, __ATOMIC_ACQUIRE);
+ if (sv != -10)
+ abort ();
+
+ __atomic_fetch_min (&sv, -20, __ATOMIC_RELEASE);
+ if (sv != -20)
+ abort ();
+
+ __atomic_min_fetch (&sv, LLONG_MIN, __ATOMIC_ACQ_REL);
+ if (sv != LLONG_MIN)
+ abort ();
+
+ __atomic_fetch_min (&sv, LLONG_MAX, __ATOMIC_SEQ_CST);
+
+ if (sv != LLONG_MIN)
+ abort ();
+}
+
+void
+test_umin ()
+{
+ unsigned long long uv = 100;
+
+ __atomic_min_fetch (&uv, 50, __ATOMIC_RELAXED);
+ if (uv != 50)
+ abort ();
+
+ __atomic_fetch_min (&uv, 50, __ATOMIC_CONSUME);
+ if (uv != 50)
+ abort ();
+
+ __atomic_min_fetch (&uv, 75, __ATOMIC_ACQUIRE);
+ if (uv != 50)
+ abort ();
+
+ __atomic_fetch_min (&uv, 10, __ATOMIC_RELEASE);
+ if (uv != 10)
+ abort ();
+
+ __atomic_min_fetch (&uv, 0, __ATOMIC_ACQ_REL);
+ if (uv != 0)
+ abort ();
+
+ __atomic_fetch_min (&uv, ULLONG_MAX, __ATOMIC_SEQ_CST);
+
+ if (uv != 0)
+ abort ();
+}
+
+void
+test_smax ()
+{
+ long long sv = -10;
+
+ __atomic_max_fetch (&sv, -5, __ATOMIC_RELAXED);
+ if (sv != -5)
+ abort ();
+
+ __atomic_fetch_max (&sv, -5, __ATOMIC_CONSUME);
+ if (sv != -5)
+ abort ();
+
+ __atomic_max_fetch (&sv, -20, __ATOMIC_ACQUIRE);
+ if (sv != -5)
+ abort ();
+
+ __atomic_fetch_max (&sv, 10, __ATOMIC_RELEASE);
+ if (sv != 10)
+ abort ();
+
+ __atomic_max_fetch (&sv, 50, __ATOMIC_ACQ_REL);
+ if (sv != 50)
+ abort ();
+
+ __atomic_fetch_max (&sv, LLONG_MAX, __ATOMIC_SEQ_CST);
+
+ if (sv != LLONG_MAX)
+ abort ();
+}
+
+void
+test_umax ()
+{
+ unsigned long long uv = 10;
+
+ __atomic_max_fetch (&uv, 50, __ATOMIC_RELAXED);
+ if (uv != 50)
+ abort ();
+
+ __atomic_fetch_max (&uv, 50, __ATOMIC_CONSUME);
+ if (uv != 50)
+ abort ();
+
+ __atomic_max_fetch (&uv, 30, __ATOMIC_ACQUIRE);
+ if (uv != 50)
+ abort ();
+
+ __atomic_fetch_max (&uv, 100, __ATOMIC_RELEASE);
+ if (uv != 100)
+ abort ();
+
+ __atomic_max_fetch (&uv, 200, __ATOMIC_ACQ_REL);
+ if (uv != 200)
+ abort ();
+
+ __atomic_fetch_max (&uv, ULLONG_MAX, __ATOMIC_SEQ_CST);
+
+ if (uv != ULLONG_MAX)
+ abort ();
+}
+
int
main ()
{
@@ -538,6 +879,10 @@ main ()
test_fetch_nand ();
test_fetch_xor ();
test_fetch_or ();
+ test_fetch_smin ();
+ test_fetch_umin ();
+ test_fetch_smax ();
+ test_fetch_umax ();
test_add_fetch ();
test_sub_fetch ();
@@ -545,6 +890,10 @@ main ()
test_nand_fetch ();
test_xor_fetch ();
test_or_fetch ();
+ test_smin_fetch ();
+ test_umin_fetch ();
+ test_smax_fetch ();
+ test_umax_fetch ();
test_add ();
test_sub ();
@@ -552,6 +901,10 @@ main ()
test_nand ();
test_xor ();
test_or ();
+ test_smin ();
+ test_umin ();
+ test_smax ();
+ test_umax ();
return 0;
}
diff --git a/gcc/testsuite/gcc.dg/atomic-op-5.c
b/gcc/testsuite/gcc.dg/atomic-op-5.c
index 1407f3fe3b2..b0c4c16a7b4 100644
--- a/gcc/testsuite/gcc.dg/atomic-op-5.c
+++ b/gcc/testsuite/gcc.dg/atomic-op-5.c
@@ -8,6 +8,10 @@
extern void abort(void);
+#define SINT128_MIN ((__int128_t)((__uint128_t)1 << (sizeof(__int128_t) * 8 -
1)))
+#define SINT128_MAX ((__int128_t)~SINT128_MIN)
+#define UINT128_MAX ((__uint128_t)~0)
+
__int128_t v, count, res;
const __int128_t init = ~0;
@@ -168,6 +172,114 @@ test_fetch_or ()
abort ();
}
+void
+test_fetch_smin ()
+{
+ __int128_t sv = 10;
+
+ if (__atomic_fetch_min (&sv, 5, __ATOMIC_RELAXED) != 10)
+ abort ();
+
+ if (__atomic_fetch_min (&sv, 5, __ATOMIC_CONSUME) != 5)
+ abort ();
+
+ if (__atomic_fetch_min (&sv, -10, __ATOMIC_ACQUIRE) != 5)
+ abort ();
+
+ if (__atomic_fetch_min (&sv, -20, __ATOMIC_RELEASE) != -10)
+ abort ();
+
+ if (__atomic_fetch_min (&sv, SINT128_MIN, __ATOMIC_ACQ_REL) != -20)
+ abort ();
+
+ if (__atomic_fetch_min (&sv, SINT128_MAX, __ATOMIC_SEQ_CST) != SINT128_MIN)
+ abort ();
+
+ if (sv != SINT128_MIN)
+ abort ();
+}
+
+void
+test_fetch_umin ()
+{
+ __uint128_t uv = 100;
+
+ if (__atomic_fetch_min (&uv, 50, __ATOMIC_RELAXED) != 100)
+ abort ();
+
+ if (__atomic_fetch_min (&uv, 50, __ATOMIC_CONSUME) != 50)
+ abort ();
+
+ if (__atomic_fetch_min (&uv, 75, __ATOMIC_ACQUIRE) != 50)
+ abort ();
+
+ if (__atomic_fetch_min (&uv, 10, __ATOMIC_RELEASE) != 50)
+ abort ();
+
+ if (__atomic_fetch_min (&uv, 0, __ATOMIC_ACQ_REL) != 10)
+ abort ();
+
+ if (__atomic_fetch_min (&uv, UINT128_MAX, __ATOMIC_SEQ_CST) != 0)
+ abort ();
+
+ if (uv != 0)
+ abort ();
+}
+
+void
+test_fetch_smax ()
+{
+ __int128_t sv = -10;
+
+ if (__atomic_fetch_max (&sv, -5, __ATOMIC_RELAXED) != -10)
+ abort ();
+
+ if (__atomic_fetch_max (&sv, -5, __ATOMIC_CONSUME) != -5)
+ abort ();
+
+ if (__atomic_fetch_max (&sv, -20, __ATOMIC_ACQUIRE) != -5)
+ abort ();
+
+ if (__atomic_fetch_max (&sv, 10, __ATOMIC_RELEASE) != -5)
+ abort ();
+
+ if (__atomic_fetch_max (&sv, 50, __ATOMIC_ACQ_REL) != 10)
+ abort ();
+
+ if (__atomic_fetch_max (&sv, SINT128_MAX, __ATOMIC_SEQ_CST) != 50)
+ abort ();
+
+ if (sv != SINT128_MAX)
+ abort ();
+}
+
+void
+test_fetch_umax ()
+{
+ __uint128_t uv = 10;
+
+ if (__atomic_fetch_max (&uv, 50, __ATOMIC_RELAXED) != 10)
+ abort ();
+
+ if (__atomic_fetch_max (&uv, 50, __ATOMIC_CONSUME) != 50)
+ abort ();
+
+ if (__atomic_fetch_max (&uv, 30, __ATOMIC_ACQUIRE) != 50)
+ abort ();
+
+ if (__atomic_fetch_max (&uv, 100, __ATOMIC_RELEASE) != 50)
+ abort ();
+
+ if (__atomic_fetch_max (&uv, 200, __ATOMIC_ACQ_REL) != 100)
+ abort ();
+
+ if (__atomic_fetch_max (&uv, UINT128_MAX, __ATOMIC_SEQ_CST) != 200)
+ abort ();
+
+ if (uv != UINT128_MAX)
+ abort ();
+}
+
/* The OP_fetch routines return the new value after the operation. */
void
@@ -329,6 +441,113 @@ test_or_fetch ()
abort ();
}
+void
+test_smin_fetch ()
+{
+ __int128_t sv = 10;
+
+ if (__atomic_min_fetch (&sv, 5, __ATOMIC_RELAXED) != 5)
+ abort ();
+
+ if (__atomic_min_fetch (&sv, 5, __ATOMIC_CONSUME) != 5)
+ abort ();
+
+ if (__atomic_min_fetch (&sv, -10, __ATOMIC_ACQUIRE) != -10)
+ abort ();
+
+ if (__atomic_min_fetch (&sv, -20, __ATOMIC_RELEASE) != -20)
+ abort ();
+
+ if (__atomic_min_fetch (&sv, SINT128_MIN, __ATOMIC_ACQ_REL) != SINT128_MIN)
+ abort ();
+
+ if (__atomic_min_fetch (&sv, SINT128_MAX, __ATOMIC_SEQ_CST) != SINT128_MIN)
+ abort ();
+
+ if (sv != SINT128_MIN)
+ abort ();
+}
+
+void
+test_umin_fetch ()
+{
+ __uint128_t uv = 100;
+
+ if (__atomic_min_fetch (&uv, 50, __ATOMIC_RELAXED) != 50)
+ abort ();
+
+ if (__atomic_min_fetch (&uv, 50, __ATOMIC_CONSUME) != 50)
+ abort ();
+
+ if (__atomic_min_fetch (&uv, 75, __ATOMIC_ACQUIRE) != 50)
+ abort ();
+
+ if (__atomic_min_fetch (&uv, 10, __ATOMIC_RELEASE) != 10)
+ abort ();
+
+ if (__atomic_min_fetch (&uv, 0, __ATOMIC_ACQ_REL) != 0)
+ abort ();
+
+ if (__atomic_min_fetch (&uv, UINT128_MAX, __ATOMIC_SEQ_CST) != 0)
+ abort ();
+
+ if (uv != 0)
+ abort ();
+}
+
+void
+test_smax_fetch ()
+{
+ __int128_t sv = -10;
+
+ if (__atomic_max_fetch (&sv, -5, __ATOMIC_RELAXED) != -5)
+ abort ();
+
+ if (__atomic_max_fetch (&sv, -5, __ATOMIC_CONSUME) != -5)
+ abort ();
+
+ if (__atomic_max_fetch (&sv, -20, __ATOMIC_ACQUIRE) != -5)
+ abort ();
+
+ if (__atomic_max_fetch (&sv, 10, __ATOMIC_RELEASE) != 10)
+ abort ();
+
+ if (__atomic_max_fetch (&sv, 50, __ATOMIC_ACQ_REL) != 50)
+ abort ();
+
+ if (__atomic_max_fetch (&sv, SINT128_MAX, __ATOMIC_SEQ_CST) != SINT128_MAX)
+ abort ();
+
+ if (sv != SINT128_MAX)
+ abort ();
+}
+
+void
+test_umax_fetch ()
+{
+ __uint128_t uv = 10;
+
+ if (__atomic_max_fetch (&uv, 50, __ATOMIC_RELAXED) != 50)
+ abort ();
+
+ if (__atomic_max_fetch (&uv, 50, __ATOMIC_CONSUME) != 50)
+ abort ();
+
+ if (__atomic_max_fetch (&uv, 30, __ATOMIC_ACQUIRE) != 50)
+ abort ();
+
+ if (__atomic_max_fetch (&uv, 100, __ATOMIC_RELEASE) != 100)
+ abort ();
+
+ if (__atomic_max_fetch (&uv, 200, __ATOMIC_ACQ_REL) != 200)
+ abort ();
+
+ if (__atomic_max_fetch (&uv, UINT128_MAX, __ATOMIC_SEQ_CST) != UINT128_MAX)
+ abort ();
+
+ if (uv != UINT128_MAX)
+ abort ();
+}
/* Test the OP routines with a result which isn't used. Use both variations
within each function. */
@@ -528,6 +747,130 @@ test_or ()
abort ();
}
+void
+test_smin ()
+{
+ __int128_t sv = 10;
+
+ __atomic_min_fetch (&sv, 5, __ATOMIC_RELAXED);
+ if (sv != 5)
+ abort ();
+
+ __atomic_fetch_min (&sv, 5, __ATOMIC_CONSUME);
+ if (sv != 5)
+ abort ();
+
+ __atomic_min_fetch (&sv, -10, __ATOMIC_ACQUIRE);
+ if (sv != -10)
+ abort ();
+
+ __atomic_fetch_min (&sv, -20, __ATOMIC_RELEASE);
+ if (sv != -20)
+ abort ();
+
+ __atomic_min_fetch (&sv, SINT128_MIN, __ATOMIC_ACQ_REL);
+ if (sv != SINT128_MIN)
+ abort ();
+
+ __atomic_fetch_min (&sv, SINT128_MAX, __ATOMIC_SEQ_CST);
+
+ if (sv != SINT128_MIN)
+ abort ();
+}
+
+void
+test_umin ()
+{
+ __uint128_t uv = 100;
+
+ __atomic_min_fetch (&uv, 50, __ATOMIC_RELAXED);
+ if (uv != 50)
+ abort ();
+
+ __atomic_fetch_min (&uv, 50, __ATOMIC_CONSUME);
+ if (uv != 50)
+ abort ();
+
+ __atomic_min_fetch (&uv, 75, __ATOMIC_ACQUIRE);
+ if (uv != 50)
+ abort ();
+
+ __atomic_fetch_min (&uv, 10, __ATOMIC_RELEASE);
+ if (uv != 10)
+ abort ();
+
+ __atomic_min_fetch (&uv, 0, __ATOMIC_ACQ_REL);
+ if (uv != 0)
+ abort ();
+
+ __atomic_fetch_min (&uv, UINT128_MAX, __ATOMIC_SEQ_CST);
+
+ if (uv != 0)
+ abort ();
+}
+
+void
+test_smax ()
+{
+ __int128_t sv = -10;
+
+ __atomic_max_fetch (&sv, -5, __ATOMIC_RELAXED);
+ if (sv != -5)
+ abort ();
+
+ __atomic_fetch_max (&sv, -5, __ATOMIC_CONSUME);
+ if (sv != -5)
+ abort ();
+
+ __atomic_max_fetch (&sv, -20, __ATOMIC_ACQUIRE);
+ if (sv != -5)
+ abort ();
+
+ __atomic_fetch_max (&sv, 10, __ATOMIC_RELEASE);
+ if (sv != 10)
+ abort ();
+
+ __atomic_max_fetch (&sv, 50, __ATOMIC_ACQ_REL);
+ if (sv != 50)
+ abort ();
+
+ __atomic_fetch_max (&sv, SINT128_MAX, __ATOMIC_SEQ_CST);
+
+ if (sv != SINT128_MAX)
+ abort ();
+}
+
+void
+test_umax ()
+{
+ __uint128_t uv = 10;
+
+ __atomic_max_fetch (&uv, 50, __ATOMIC_RELAXED);
+ if (uv != 50)
+ abort ();
+
+ __atomic_fetch_max (&uv, 50, __ATOMIC_CONSUME);
+ if (uv != 50)
+ abort ();
+
+ __atomic_max_fetch (&uv, 30, __ATOMIC_ACQUIRE);
+ if (uv != 50)
+ abort ();
+
+ __atomic_fetch_max (&uv, 100, __ATOMIC_RELEASE);
+ if (uv != 100)
+ abort ();
+
+ __atomic_max_fetch (&uv, 200, __ATOMIC_ACQ_REL);
+ if (uv != 200)
+ abort ();
+
+ __atomic_fetch_max (&uv, UINT128_MAX, __ATOMIC_SEQ_CST);
+
+ if (uv != UINT128_MAX)
+ abort ();
+}
+
int
main ()
{
@@ -537,6 +880,10 @@ main ()
test_fetch_nand ();
test_fetch_xor ();
test_fetch_or ();
+ test_fetch_smin ();
+ test_fetch_umin ();
+ test_fetch_smax ();
+ test_fetch_umax ();
test_add_fetch ();
test_sub_fetch ();
@@ -544,6 +891,10 @@ main ()
test_nand_fetch ();
test_xor_fetch ();
test_or_fetch ();
+ test_smin_fetch ();
+ test_umin_fetch ();
+ test_smax_fetch ();
+ test_umax_fetch ();
test_add ();
test_sub ();
@@ -551,6 +902,10 @@ main ()
test_nand ();
test_xor ();
test_or ();
+ test_smin ();
+ test_umin ();
+ test_smax ();
+ test_umax ();
return 0;
}
diff --git a/gcc/testsuite/gcc.target/aarch64/atomic-minmax-lse.c
b/gcc/testsuite/gcc.target/aarch64/atomic-minmax-lse.c
new file mode 100644
index 00000000000..19e078d0ee9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/atomic-minmax-lse.c
@@ -0,0 +1,123 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target aarch64_asm_lse_ok } */
+/* { dg-options "-march=armv8-a+lse" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "atomic-minmax.x"
+
+/* { dg-final { scan-assembler-not "\tldxr*" } } */
+/* { dg-final { scan-assembler-not "\tldaxr*" } } */
+/* { dg-final { scan-assembler-not "\tstxr*" } } */
+/* { dg-final { scan-assembler-not "\tstlxr*" } } */
+
+/*
+** test_smin_s8:
+** ...
+** casalb w[0-9]+, w[0-9]+, \[x[0-9]+\]
+** ...
+*/
+
+/*
+** test_smax_s8:
+** ...
+** casalb w[0-9]+, w[0-9]+, \[x[0-9]+\]
+** ...
+*/
+
+/*
+** test_smin_s16:
+** ...
+** casalh w[0-9]+, w[0-9]+, \[x[0-9]+\]
+** ...
+*/
+
+/*
+** test_smax_s16:
+** ...
+** casalh w[0-9]+, w[0-9]+, \[x[0-9]+\]
+** ...
+*/
+
+/*
+** test_smin_s32:
+** ...
+** casal w[0-9]+, w[0-9]+, \[x[0-9]+\]
+** ...
+*/
+
+/*
+** test_smax_s32:
+** ...
+** casal w[0-9]+, w[0-9]+, \[x[0-9]+\]
+** ...
+*/
+
+/*
+** test_smin_s64:
+** ...
+** casal x[0-9]+, x[0-9]+, \[x[0-9]+\]
+** ...
+*/
+
+/*
+** test_smax_s64:
+** ...
+** casal x[0-9]+, x[0-9]+, \[x[0-9]+\]
+** ...
+*/
+
+/*
+** test_umin_u8:
+** ...
+** casalb w[0-9]+, w[0-9]+, \[x[0-9]+\]
+** ...
+*/
+
+/*
+** test_umax_u8:
+** ...
+** casalb w[0-9]+, w[0-9]+, \[x[0-9]+\]
+** ...
+*/
+
+/*
+** test_umin_u16:
+** ...
+** casalh w[0-9]+, w[0-9]+, \[x[0-9]+\]
+** ...
+*/
+
+/*
+** test_umax_u16:
+** ...
+** casalh w[0-9]+, w[0-9]+, \[x[0-9]+\]
+** ...
+*/
+
+/*
+** test_umin_u32:
+** ...
+** casal w[0-9]+, w[0-9]+, \[x[0-9]+\]
+** ...
+*/
+
+/*
+** test_umax_u32:
+** ...
+** casal w[0-9]+, w[0-9]+, \[x[0-9]+\]
+** ...
+*/
+
+/*
+** test_umin_u64:
+** ...
+** casal x[0-9]+, x[0-9]+, \[x[0-9]+\]
+** ...
+*/
+
+/*
+** test_umax_u64:
+** ...
+** casal x[0-9]+, x[0-9]+, \[x[0-9]+\]
+** ...
+*/
\ No newline at end of file
diff --git a/gcc/testsuite/gcc.target/aarch64/atomic-minmax-nolse.c
b/gcc/testsuite/gcc.target/aarch64/atomic-minmax-nolse.c
new file mode 100644
index 00000000000..74ec877adce
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/atomic-minmax-nolse.c
@@ -0,0 +1,183 @@
+/* { dg-do compile } */
+/* { dg-options "-march=armv8-a+nolse -mno-outline-atomics" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "atomic-minmax.x"
+
+/* { dg-final { scan-assembler-not "\tcas*" } } */
+/* { dg-final { scan-assembler-not "__aarch64_*" } } */
+
+/*
+** test_smin_s8:
+** ...
+** ldxrb w[0-9]+, \[x[0-9]+\]
+** cmp w[0-9]+, w[0-9]+, uxtb
+** bne .*
+** stlxrb w[0-9]+, w[0-9]+, \[x[0-9]+\]
+** cbnz w[0-9]+, .*
+** ...
+*/
+
+/*
+** test_smax_s8:
+** ...
+** ldxrb w[0-9]+, \[x[0-9]+\]
+** cmp w[0-9]+, w[0-9]+, uxtb
+** bne .*
+** stlxrb w[0-9]+, w[0-9]+, \[x[0-9]+\]
+** cbnz w[0-9]+, .*
+** ...
+*/
+
+/*
+** test_smin_s16:
+** ...
+** ldxrh w[0-9]+, \[x[0-9]+\]
+** cmp w[0-9]+, w[0-9]+, uxth
+** bne .*
+** stlxrh w[0-9]+, w[0-9]+, \[x[0-9]+\]
+** cbnz w[0-9]+, .*
+** ...
+*/
+
+/*
+** test_smax_s16:
+** ...
+** ldxrh w[0-9]+, \[x[0-9]+\]
+** cmp w[0-9]+, w[0-9]+, uxth
+** bne .*
+** stlxrh w[0-9]+, w[0-9]+, \[x[0-9]+\]
+** cbnz w[0-9]+, .*
+** ...
+*/
+/*
+** test_smin_s32:
+** ...
+** ldxr w[0-9]+, \[x[0-9]+\]
+** cmp w[0-9]+, w[0-9]+
+** bne .*
+** stlxr w[0-9]+, w[0-9]+, \[x[0-9]+\]
+** cbnz w[0-9]+, .*
+** ...
+*/
+
+/*
+** test_smax_s32:
+** ...
+** ldxr w[0-9]+, \[x[0-9]+\]
+** cmp w[0-9]+, w[0-9]+
+** bne .*
+** stlxr w[0-9]+, w[0-9]+, \[x[0-9]+\]
+** cbnz w[0-9]+, .*
+** ...
+*/
+
+/*
+** test_smin_s64:
+** ...
+** ldxr x[0-9]+, \[x[0-9]+\]
+** cmp x[0-9]+, x[0-9]+
+** bne .*
+** stlxr w[0-9]+, x[0-9]+, \[x[0-9]+\]
+** cbnz w[0-9]+, .*
+** ...
+*/
+
+/*
+** test_smin_s64:
+** ...
+** ldxr x[0-9]+, \[x[0-9]+\]
+** cmp x[0-9]+, x[0-9]+
+** bne .*
+** stlxr w[0-9]+, x[0-9]+, \[x[0-9]+\]
+** cbnz w[0-9]+, .*
+** ...
+*/
+
+/*
+** test_umin_u8:
+** ...
+** ldxrb w[0-9]+, \[x[0-9]+\]
+** cmp w[0-9]+, w[0-9]+, uxtb
+** bne .*
+** stlxrb w[0-9]+, w[0-9]+, \[x[0-9]+\]
+** cbnz w[0-9]+, .*
+** ...
+*/
+
+/*
+** test_umax_u8:
+** ...
+** ldxrb w[0-9]+, \[x[0-9]+\]
+** cmp w[0-9]+, w[0-9]+, uxtb
+** bne .*
+** stlxrb w[0-9]+, w[0-9]+, \[x[0-9]+\]
+** cbnz w[0-9]+, .*
+** ...
+*/
+
+/*
+** test_umin_u16:
+** ...
+** ldxrh w[0-9]+, \[x[0-9]+\]
+** cmp w[0-9]+, w[0-9]+, uxth
+** bne .*
+** stlxrh w[0-9]+, w[0-9]+, \[x[0-9]+\]
+** cbnz w[0-9]+, .*
+** ...
+*/
+
+/*
+** test_umax_u16:
+** ...
+** ldxrh w[0-9]+, \[x[0-9]+\]
+** cmp w[0-9]+, w[0-9]+, uxth
+** bne .*
+** stlxrh w[0-9]+, w[0-9]+, \[x[0-9]+\]
+** cbnz w[0-9]+, .*
+** ...
+*/
+
+/*
+** test_umin_u32:
+** ...
+** ldxr w[0-9]+, \[x[0-9]+\]
+** cmp w[0-9]+, w[0-9]+
+** bne .*
+** stlxr w[0-9]+, w[0-9]+, \[x[0-9]+\]
+** cbnz w[0-9]+, .*
+** ...
+*/
+
+/*
+** test_umax_u32:
+** ...
+** ldxr w[0-9]+, \[x[0-9]+\]
+** cmp w[0-9]+, w[0-9]+
+** bne .*
+** stlxr w[0-9]+, w[0-9]+, \[x[0-9]+\]
+** cbnz w[0-9]+, .*
+** ...
+*/
+
+/*
+** test_umin_u64:
+** ...
+** ldxr x[0-9]+, \[x[0-9]+\]
+** cmp x[0-9]+, x[0-9]+
+** bne .*
+** stlxr w[0-9]+, x[0-9]+, \[x[0-9]+\]
+** cbnz w[0-9]+, .*
+** ...
+*/
+
+/*
+** test_umax_u64:
+** ...
+** ldxr x[0-9]+, \[x[0-9]+\]
+** cmp x[0-9]+, x[0-9]+
+** bne .*
+** stlxr w[0-9]+, x[0-9]+, \[x[0-9]+\]
+** cbnz w[0-9]+, .*
+** ...
+*/
\ No newline at end of file
diff --git a/gcc/testsuite/gcc.target/aarch64/atomic-minmax.c
b/gcc/testsuite/gcc.target/aarch64/atomic-minmax.c
new file mode 100644
index 00000000000..f61082e288b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/atomic-minmax.c
@@ -0,0 +1,129 @@
+/* { dg-do run } */
+/* { dg-options "--save-temps" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "atomic-minmax.x"
+
+int main ()
+{
+ run_tests();
+ return 0;
+}
+
+/* { dg-final { scan-assembler-not "\tcas*" } } */
+/* { dg-final { scan-assembler-not "\tldxr*" } } */
+/* { dg-final { scan-assembler-not "\tldaxr*" } } */
+/* { dg-final { scan-assembler-not "\tstxr*" } } */
+/* { dg-final { scan-assembler-not "\tstlxr*" } } */
+
+/*
+** test_smin_s8:
+** ...
+** bl __aarch64_cas1_sync
+** ...
+*/
+
+/*
+** test_smax_s8:
+** ...
+** bl __aarch64_cas1_sync
+** ...
+*/
+
+/*
+** test_smin_s16:
+** ...
+** bl __aarch64_cas2_sync
+** ...
+*/
+
+/*
+** test_smax_s16:
+** ...
+** bl __aarch64_cas2_sync
+** ...
+*/
+
+/*
+** test_smin_s32:
+** ...
+** bl __aarch64_cas4_sync
+** ...
+*/
+
+/*
+** test_smax_s32:
+** ...
+** bl __aarch64_cas4_sync
+** ...
+*/
+
+/*
+** test_smin_s64:
+** ...
+** bl __aarch64_cas8_sync
+** ...
+*/
+
+/*
+** test_smax_s64:
+** ...
+** bl __aarch64_cas8_sync
+** ...
+*/
+
+/*
+** test_umin_u8:
+** ...
+** bl __aarch64_cas1_sync
+** ...
+*/
+
+/*
+** test_umax_u8:
+** ...
+** bl __aarch64_cas1_sync
+** ...
+*/
+
+/*
+** test_umin_u16:
+** ...
+** bl __aarch64_cas2_sync
+** ...
+*/
+
+/*
+** test_umax_u16:
+** ...
+** bl __aarch64_cas2_sync
+** ...
+*/
+
+/*
+** test_umin_u32:
+** ...
+** bl __aarch64_cas4_sync
+** ...
+*/
+
+/*
+** test_umax_u32:
+** ...
+** bl __aarch64_cas4_sync
+** ...
+*/
+
+/*
+** test_umin_u64:
+** ...
+** bl __aarch64_cas8_sync
+** ...
+*/
+
+/*
+** test_umax_u64:
+** ...
+** bl __aarch64_cas8_sync
+** ...
+*/
diff --git a/gcc/testsuite/gcc.target/aarch64/atomic-minmax.x
b/gcc/testsuite/gcc.target/aarch64/atomic-minmax.x
new file mode 100644
index 00000000000..e9e21d3f2db
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/atomic-minmax.x
@@ -0,0 +1,185 @@
+#include <stdint.h>
+
+extern void abort(void);
+
+#define TEST_FETCH_OP(TYPE, VAR, OP, INIT, ARG, EXPECTED_OLD, EXPECTED_NEW,
MEM_ORDER) \
+ do { \
+ VAR = INIT; \
+ TYPE old_val = __atomic_fetch_##OP(&VAR, ARG, MEM_ORDER); \
+ TYPE new_val = VAR; \
+ if (old_val != EXPECTED_OLD) { \
+ abort(); \
+ } \
+ if (new_val != EXPECTED_NEW) { \
+ abort(); \
+ } \
+ } while (0)
+
+#define TEST_OP_FETCH(TYPE, VAR, OP, INIT, ARG, EXPECTED_OLD, EXPECTED_NEW,
MEM_ORDER) \
+ do { \
+ VAR = INIT; \
+ TYPE result = __atomic_##OP##_fetch(&VAR, ARG, MEM_ORDER); \
+ TYPE new_val = VAR; \
+ if (result != EXPECTED_NEW) { \
+ abort(); \
+ } \
+ if (new_val != EXPECTED_NEW) { \
+ abort(); \
+ } \
+ } while (0)
+
+#define GEN_TYPE_TESTS(TYPE, VAR, SUFFIX, IS_SIGNED) \
+ TYPE VAR; \
+ void test_##SUFFIX() { \
+ TEST_FETCH_OP(TYPE, VAR, min, 10, 5, 10, 5, __ATOMIC_RELAXED); \
+ TEST_FETCH_OP(TYPE, VAR, min, 10, 20, 10, 10, __ATOMIC_SEQ_CST); \
+ TEST_FETCH_OP(TYPE, VAR, max, 10, 20, 10, 20, __ATOMIC_ACQUIRE); \
+ TEST_FETCH_OP(TYPE, VAR, max, 10, 5, 10, 10, __ATOMIC_RELEASE); \
+ \
+ TEST_OP_FETCH(TYPE, VAR, min, 10, 5, 10, 5, __ATOMIC_CONSUME); \
+ TEST_OP_FETCH(TYPE, VAR, min, 10, 20, 10, 10, __ATOMIC_ACQ_REL); \
+ TEST_OP_FETCH(TYPE, VAR, max, 10, 20, 10, 20, __ATOMIC_RELAXED); \
+ TEST_OP_FETCH(TYPE, VAR, max, 10, 5, 10, 10, __ATOMIC_SEQ_CST); \
+ \
+ if (IS_SIGNED) { \
+ TEST_FETCH_OP(TYPE, VAR, min, -10, -20, -10, -20, __ATOMIC_ACQUIRE); \
+ TEST_FETCH_OP(TYPE, VAR, max, -10, 5, -10, 5, __ATOMIC_RELEASE); \
+ TEST_FETCH_OP(TYPE, VAR, min, -5, -3, -5, -5, __ATOMIC_RELAXED); \
+ TEST_FETCH_OP(TYPE, VAR, max, -20, -10, -20, -10, __ATOMIC_SEQ_CST); \
+ TEST_OP_FETCH(TYPE, VAR, min, -100, 50, -100, -100, __ATOMIC_ACQ_REL); \
+ TEST_OP_FETCH(TYPE, VAR, max, -50, -60, -50, -50, __ATOMIC_CONSUME); \
+ } \
+ }
+
+GEN_TYPE_TESTS(int8_t, s8_var_test, s8, 1)
+GEN_TYPE_TESTS(int16_t, s16_var_test, s16, 1)
+GEN_TYPE_TESTS(int32_t, s32_var_test, s32, 1)
+GEN_TYPE_TESTS(int64_t, s64_var_test, s64, 1)
+
+GEN_TYPE_TESTS(uint8_t, u8_var_test, u8, 0)
+GEN_TYPE_TESTS(uint16_t, u16_var_test, u16, 0)
+GEN_TYPE_TESTS(uint32_t, u32_var_test, u32, 0)
+GEN_TYPE_TESTS(uint64_t, u64_var_test, u64, 0)
+
+void run_tests() {
+ test_s8();
+ test_s16();
+ test_s32();
+ test_s64();
+ test_u8();
+ test_u16();
+ test_u32();
+ test_u64();
+}
+
+int8_t s8_var = 0;
+
+int8_t
+test_smin_s8 (int8_t a)
+{
+ return __atomic_fetch_min (&s8_var, a, __ATOMIC_RELAXED);
+}
+
+int8_t
+test_smax_s8 (int8_t a)
+{
+ return __atomic_fetch_max (&s8_var, a, __ATOMIC_RELEASE);
+}
+
+int16_t s16_var = 0;
+
+int16_t
+test_smin_s16 (int16_t a)
+{
+ return __atomic_fetch_min (&s16_var, a, __ATOMIC_ACQUIRE);
+}
+
+int16_t
+test_smax_s16 (int16_t a)
+{
+ return __atomic_fetch_max (&s16_var, a, __ATOMIC_ACQ_REL);
+}
+
+int32_t s32_var = 0;
+
+int32_t
+test_smin_s32 (int32_t a)
+{
+ return __atomic_fetch_min (&s32_var, a, __ATOMIC_RELAXED);
+}
+
+int32_t
+test_smax_s32 (int32_t a)
+{
+ return __atomic_fetch_max (&s32_var, a, __ATOMIC_SEQ_CST);
+}
+
+int64_t s64_var = 0;
+
+int64_t
+test_smin_s64 (int64_t a)
+{
+ return __atomic_fetch_min (&s64_var, a, __ATOMIC_ACQUIRE);
+}
+
+int64_t
+test_smax_s64 (int64_t a)
+{
+ return __atomic_fetch_max (&s64_var, a, __ATOMIC_RELAXED);
+}
+
+uint8_t u8_var = 0;
+
+uint8_t
+test_umin_u8 (uint8_t a)
+{
+ return __atomic_fetch_min (&u8_var, a, __ATOMIC_RELAXED);
+}
+
+uint8_t
+test_umax_u8 (uint8_t a)
+{
+ return __atomic_fetch_max (&u8_var, a, __ATOMIC_CONSUME);
+}
+
+uint16_t u16_var = 0;
+
+uint16_t
+test_umin_u16 (uint16_t a)
+{
+ return __atomic_fetch_min (&u16_var, a, __ATOMIC_ACQUIRE);
+}
+
+uint16_t
+test_umax_u16 (uint16_t a)
+{
+ return __atomic_fetch_max (&u16_var, a, __ATOMIC_RELEASE);
+}
+
+uint32_t u32_var = 0;
+
+uint32_t
+test_umin_u32 (uint32_t a)
+{
+ return __atomic_fetch_min (&u32_var, a, __ATOMIC_ACQ_REL);
+}
+
+uint32_t
+test_umax_u32 (uint32_t a)
+{
+ return __atomic_fetch_max (&u32_var, a, __ATOMIC_RELAXED);
+}
+
+uint64_t u64_var = 0;
+
+uint64_t
+test_umin_u64 (uint64_t a)
+{
+ return __atomic_fetch_min (&u64_var, a, __ATOMIC_RELAXED);
+}
+
+uint64_t
+test_umax_u64 (uint64_t a)
+{
+ return __atomic_fetch_max (&u64_var, a, __ATOMIC_ACQ_REL);
+}
\ No newline at end of file
--
2.44.0