diff options
author | Andrew MacLeod <amacleod@redhat.com> | 2011-11-10 20:38:33 +0000 |
---|---|---|
committer | Andrew Macleod <amacleod@gcc.gnu.org> | 2011-11-10 20:38:33 +0000 |
commit | d660c35ea2ba7c23049d3c8c2e07bf7dbcf0aed9 (patch) | |
tree | 4138d94b9a849ba000843310e148fa8a6d8d6c8a /gcc | |
parent | 49fe93f41068a64691cb450cd5b9490dc81880ae (diff) | |
download | gcc-d660c35ea2ba7c23049d3c8c2e07bf7dbcf0aed9.zip gcc-d660c35ea2ba7c23049d3c8c2e07bf7dbcf0aed9.tar.gz gcc-d660c35ea2ba7c23049d3c8c2e07bf7dbcf0aed9.tar.bz2 |
re PR middle-end/51038 (29_atomics/atomic_flag/clear/1.cc test_and_set/explicit.cc implicit.cc)
PR middle-end/51038
libstdc++-v3
* include/bits/atomic_base.h (atomic_thread_fence): Call built-in.
(atomic_signal_fence): Call built-in.
(test_and_set, clear): Call new atomic built-ins.
gcc
* builtins.c (expand_builtin_atomic_clear): New. Expand atomic_clear.
(expand_builtin_atomic_test_and_set): New. Expand atomic test_and_set.
(expand_builtin): Add cases for test_and_set and clear.
* sync-builtins.def (BUILT_IN_ATOMIC_TEST_AND_SET): New.
(BUILT_IN_ATOMIC_CLEAR): New.
testsuite
* gcc.dg/atomic-invalid.c: Add test for invalid __atomic_clear models.
* gcc.dg/atomic-flag.c: New. Test __atomic_test_and_set and
__atomic_clear.
From-SVN: r181271
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/builtins.c | 71 | ||||
-rw-r--r-- | gcc/sync-builtins.def | 6 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 13 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/atomic-flag.c | 32 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/atomic-invalid.c | 7 |
6 files changed, 138 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9c7a2f8..1f8a56a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2011-11-10 Andrew MacLeod <amacleod@redhat.com> + + PR middle-end/51038 + * builtins.c (expand_builtin_atomic_clear): New. Expand atomic_clear. + (expand_builtin_atomic_test_and_set): New. Expand atomic test_and_set. + (expand_builtin): Add cases for test_and_set and clear. + * sync-builtins.def (BUILT_IN_ATOMIC_TEST_AND_SET): New. + (BUILT_IN_ATOMIC_CLEAR): New. + 2011-11-10 Roberto Agostino Vitillo <ravitillo@lbl.gov> PR debug/50983 @@ -37,8 +46,6 @@ be AND followed by NOT. * builtins.c (expand_builtin_atomic_fetch_op): Patchup code for NAND should be AND followed by NOT. - * testsuite/gcc.dg/atomic-noinline[-aux].c: Test no-inline NAND and - patchup code. 2011-11-10 Jakub Jelinek <jakub@redhat.com> diff --git a/gcc/builtins.c b/gcc/builtins.c index d949dbb..98dc636 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -5474,6 +5474,71 @@ expand_builtin_atomic_fetch_op (enum machine_mode mode, tree exp, rtx target, return ret; } + +/* Expand an atomic clear operation. + void _atomic_clear (BOOL *obj, enum memmodel) + EXP is the call expression. */ + +static rtx +expand_builtin_atomic_clear (tree exp) +{ + enum machine_mode mode; + rtx mem, ret; + enum memmodel model; + + mode = mode_for_size (BOOL_TYPE_SIZE, MODE_INT, 0); + mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode); + model = get_memmodel (CALL_EXPR_ARG (exp, 1)); + + if (model == MEMMODEL_ACQUIRE || model == MEMMODEL_ACQ_REL) + { + error ("invalid memory model for %<__atomic_store%>"); + return const0_rtx; + } + + /* Try issuing an __atomic_store, and allow fallback to __sync_lock_release. + Failing that, a store is issued by __atomic_store. The only way this can + fail is if the bool type is larger than a word size. Unlikely, but + handle it anyway for completeness. Assume a single threaded model since + there is no atomic support in this case, and no barriers are required. */ + ret = expand_atomic_store (mem, const0_rtx, model, true); + if (!ret) + emit_move_insn (mem, const0_rtx); + return const0_rtx; +} + +/* Expand an atomic test_and_set operation. + bool _atomic_test_and_set (BOOL *obj, enum memmodel) + EXP is the call expression. */ + +static rtx +expand_builtin_atomic_test_and_set (tree exp) +{ + rtx mem, ret; + enum memmodel model; + enum machine_mode mode; + + mode = mode_for_size (BOOL_TYPE_SIZE, MODE_INT, 0); + mem = get_builtin_sync_mem (CALL_EXPR_ARG (exp, 0), mode); + model = get_memmodel (CALL_EXPR_ARG (exp, 1)); + + /* Try issuing an exchange. If it is lock free, or if there is a limited + functionality __sync_lock_test_and_set, this will utilize it. */ + ret = expand_atomic_exchange (NULL_RTX, mem, const1_rtx, model, true); + if (ret) + return ret; + + /* Otherwise, there is no lock free support for test and set. Simply + perform a load and a store. Since this presumes a non-atomic architecture, + also assume single threadedness and don't issue barriers either. */ + + ret = gen_reg_rtx (mode); + emit_move_insn (ret, mem); + emit_move_insn (mem, const1_rtx); + return ret; +} + + /* Return true if (optional) argument ARG1 of size ARG0 is always lock free on this architecture. If ARG1 is NULL, use typical alignment for size ARG0. */ @@ -6702,6 +6767,12 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, if (target) return target; break; + + case BUILT_IN_ATOMIC_TEST_AND_SET: + return expand_builtin_atomic_test_and_set (exp); + + case BUILT_IN_ATOMIC_CLEAR: + return expand_builtin_atomic_clear (exp); case BUILT_IN_ATOMIC_ALWAYS_LOCK_FREE: return expand_builtin_atomic_always_lock_free (exp); diff --git a/gcc/sync-builtins.def b/gcc/sync-builtins.def index 1a2df9a..15ff479 100644 --- a/gcc/sync-builtins.def +++ b/gcc/sync-builtins.def @@ -259,6 +259,12 @@ DEF_SYNC_BUILTIN (BUILT_IN_SYNC_SYNCHRONIZE, "__sync_synchronize", /* __sync* builtins for the C++ memory model. */ +DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_TEST_AND_SET, "__atomic_test_and_set", + BT_FN_BOOL_VPTR_INT, ATTR_NOTHROW_LEAF_LIST) + +DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_CLEAR, "__atomic_clear", BT_FN_VOID_VPTR_INT, + ATTR_NOTHROW_LEAF_LIST) + DEF_SYNC_BUILTIN (BUILT_IN_ATOMIC_EXCHANGE, "__atomic_exchange", BT_FN_VOID_SIZE_VPTR_PTR_PTR_INT, ATTR_NOTHROW_LEAF_LIST) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e57b535..90eded9 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,16 @@ +2011-11-10 Andrew MacLeod <amacleod@redhat.com> + + PR middle-end/51038 + * gcc.dg/atomic-invalid.c: Add test for invalid __atomic_clear models. + * gcc.dg/atomic-flag.c: New. Test __atomic_test_and_set and + __atomic_clear. + +2011-11-10 Andrew MacLeod <amacleod@redhat.com> + + PR rtl-optimization/51040 + * testsuite/gcc.dg/atomic-noinline[-aux].c: Test no-inline NAND and + patchup code. + 2011-11-10 Jason Merrill <jason@redhat.com> PR c++/51079 diff --git a/gcc/testsuite/gcc.dg/atomic-flag.c b/gcc/testsuite/gcc.dg/atomic-flag.c new file mode 100644 index 0000000..771df2c --- /dev/null +++ b/gcc/testsuite/gcc.dg/atomic-flag.c @@ -0,0 +1,32 @@ +/* Test __atomic routines for existence and execution. */ +/* { dg-do run } */ + +#include <stdbool.h> + +/* Test that __atomic_test_and_set and __atomic_clear builtins execute. */ + +extern void abort(void); +bool a; + +main () +{ + bool b; + + __atomic_clear (&a, __ATOMIC_RELAXED); + if (a != 0) + abort (); + + b = __atomic_test_and_set (&a, __ATOMIC_SEQ_CST); + if (a != 1 || b != 0) + abort (); + + b = __atomic_test_and_set (&a, __ATOMIC_ACQ_REL); + if (b != 1 || a != 1) + abort (); + + __atomic_clear (&a, __ATOMIC_SEQ_CST); + if (a != 0) + abort (); + + return 0; +} diff --git a/gcc/testsuite/gcc.dg/atomic-invalid.c b/gcc/testsuite/gcc.dg/atomic-invalid.c index 2b73c91..48de91f 100644 --- a/gcc/testsuite/gcc.dg/atomic-invalid.c +++ b/gcc/testsuite/gcc.dg/atomic-invalid.c @@ -4,9 +4,11 @@ /* { dg-require-effective-target sync_int_long } */ #include <stddef.h> +#include <stdbool.h> int i, e, b; size_t s; +bool x; main () { @@ -26,4 +28,9 @@ main () i = __atomic_always_lock_free (s, NULL); /* { dg-error "non-constant argument" } */ __atomic_load_n (&i, 44); /* { dg-warning "invalid memory model" } */ + + __atomic_clear (&x, __ATOMIC_ACQUIRE); /* { dg-error "invalid memory model" } */ + + __atomic_clear (&x, __ATOMIC_ACQ_REL); /* { dg-error "invalid memory model" } */ + } |