From: Alexander Monakov Date: Mon, 4 Sep 2017 10:16:37 +0000 (+0300) Subject: optabs: ensure atomic_load/stores have compiler barriers X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=d8c40eff56f69877b33c697ded756d50fde90c27;p=gcc.git optabs: ensure atomic_load/stores have compiler barriers PR rtl-optimization/57448 PR target/67458 PR target/81316 * optabs.c (expand_atomic_load): Place compiler memory barriers if using atomic_load pattern. (expand_atomic_store): Likewise. testsuite/ * gcc.dg/atomic/pr80640-2.c: New testcase. * gcc.dg/atomic/pr81316.c: New testcase. From-SVN: r251643 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 50d5e26f96a..5102356fcd4 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2017-09-04 Alexander Monakov + + PR rtl-optimization/57448 + PR target/67458 + PR target/81316 + * optabs.c (expand_atomic_load): Place compiler memory barriers if + using atomic_load pattern. + (expand_atomic_store): Likewise. + 2017-09-04 Jakub Jelinek PR sanitizer/81981 diff --git a/gcc/optabs.c b/gcc/optabs.c index b7f1e2c6491..b65707080ee 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -6344,12 +6344,20 @@ expand_atomic_load (rtx target, rtx mem, enum memmodel model) if (icode != CODE_FOR_nothing) { struct expand_operand ops[3]; + rtx_insn *last = get_last_insn (); + if (is_mm_seq_cst (model)) + expand_asm_memory_barrier (); create_output_operand (&ops[0], target, mode); create_fixed_operand (&ops[1], mem); create_integer_operand (&ops[2], model); if (maybe_expand_insn (icode, 3, ops)) - return ops[0].value; + { + if (!is_mm_relaxed (model)) + expand_asm_memory_barrier (); + return ops[0].value; + } + delete_insns_since (last); } /* If the size of the object is greater than word size on this target, @@ -6394,11 +6402,19 @@ expand_atomic_store (rtx mem, rtx val, enum memmodel model, bool use_release) icode = direct_optab_handler (atomic_store_optab, mode); if (icode != CODE_FOR_nothing) { + rtx_insn *last = get_last_insn (); + if (!is_mm_relaxed (model)) + expand_asm_memory_barrier (); create_fixed_operand (&ops[0], mem); create_input_operand (&ops[1], val, mode); create_integer_operand (&ops[2], model); if (maybe_expand_insn (icode, 3, ops)) - return const0_rtx; + { + if (is_mm_seq_cst (model)) + expand_asm_memory_barrier (); + return const0_rtx; + } + delete_insns_since (last); } /* If using __sync_lock_release is a viable alternative, try it. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 0d9e44798e6..20b24b6faaf 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2017-09-04 Alexander Monakov + + PR rtl-optimization/57448 + PR target/67458 + PR target/81316 + * gcc.dg/atomic/pr80640-2.c: New testcase. + * gcc.dg/atomic/pr81316.c: New testcase. + 2017-09-04 Tom de Vries PR tree-optimization/82052 diff --git a/gcc/testsuite/gcc.dg/atomic/pr80640-2.c b/gcc/testsuite/gcc.dg/atomic/pr80640-2.c new file mode 100644 index 00000000000..a735054090d --- /dev/null +++ b/gcc/testsuite/gcc.dg/atomic/pr80640-2.c @@ -0,0 +1,32 @@ +/* { dg-do run } */ +/* { dg-options "-pthread" } */ +/* { dg-require-effective-target pthread } */ + +#include + +static volatile int sem1; +static _Atomic int sem2; + +static void *f(void *va) +{ + void **p = va; + if (*p) return *p; + sem1 = 1; + while (!__atomic_load_n(&sem2, __ATOMIC_ACQUIRE)); + // GCC used to RTL-CSE this and the first load, causing 0 to be returned + return *p; +} + +int main() +{ + void *p = 0; + pthread_t thr; + if (pthread_create(&thr, 0, f, &p)) + return 2; + while (!sem1); + __atomic_thread_fence(__ATOMIC_ACQUIRE); + p = &p; + __atomic_store_n(&sem2, 1, __ATOMIC_RELEASE); + pthread_join(thr, &p); + return !p; +} diff --git a/gcc/testsuite/gcc.dg/atomic/pr81316.c b/gcc/testsuite/gcc.dg/atomic/pr81316.c new file mode 100644 index 00000000000..ef10095718e --- /dev/null +++ b/gcc/testsuite/gcc.dg/atomic/pr81316.c @@ -0,0 +1,29 @@ +/* { dg-do run } */ +/* { dg-options "-pthread" } */ +/* { dg-require-effective-target pthread } */ + +#include +#include + +static _Atomic int sem1; + +static void *f(void *va) +{ + void **p = va; + while (!__atomic_load_n(&sem1, __ATOMIC_ACQUIRE)); + exit(!*p); +} + +int main(int argc) +{ + void *p = 0; + pthread_t thr; + if (pthread_create(&thr, 0, f, &p)) + return 2; + // GCC used to RTL-DSE this store + p = &p; + __atomic_store_n(&sem1, 1, __ATOMIC_RELEASE); + int r = -1; + while (r < 0) asm("":"+r"(r)); + return r; +}