From patchwork Wed Aug 2 17:45:46 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Monakov X-Patchwork-Id: 796729 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-459652-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="pgwa3xNv"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3xN0wY2Hhhz9ryr for ; Thu, 3 Aug 2017 03:46:04 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:date:message-id; q=dns; s=default; b=bALzlzIpIhGWTrM pNwzRNwsSKNBtzn04kL+WcJgj7vVsjwgnBzo6DceIw6quJtro8YbKOJtPAqCMuvr XRxhDOV7J4SCP/C4eGgOCdQH1fHwAogaZH28mX72uzK+TK/Xg3i/xRzrNeSyBraq GdMRgIiIT8WVravLzkg3N80yAQu8= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:date:message-id; s=default; bh=8ADmCm319bBEO3bM1WrGu aYB78o=; b=pgwa3xNvC7spI68QpgVJ+Z1oH3IJacw3M71YpMNJcNBc2saQIRVBt omR9yetTkq28nQbUygguBIXM1EGeXQWsF8S9qOltFgmXFBPlI2OXr7oHpPmyGUpd lCIREWoxedYg0dIE/UVr/oS0fxWyHjrtKg8LBfuCUPQW5+UkWi8QZU= Received: (qmail 6783 invoked by alias); 2 Aug 2017 17:45:55 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 6733 invoked by uid 89); 2 Aug 2017 17:45:52 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-24.7 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RP_MATCHES_RCVD, SPF_PASS autolearn=ham version=3.3.2 spammy= X-HELO: smtp.ispras.ru Received: from bran.ispras.ru (HELO smtp.ispras.ru) (83.149.199.196) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 02 Aug 2017 17:45:50 +0000 Received: from monopod.intra.ispras.ru (monopod.intra.ispras.ru [10.10.3.121]) by smtp.ispras.ru (Postfix) with ESMTP id 4FF2B5FB67 for ; Wed, 2 Aug 2017 20:45:48 +0300 (MSK) From: Alexander Monakov To: gcc-patches@gcc.gnu.org Subject: [PATCH 1/3] optabs: ensure mem_thread_fence is a compiler barrier Date: Wed, 2 Aug 2017 20:45:46 +0300 Message-Id: <20170802174548.12344-1-amonakov@ispras.ru> As recently discussed in the previous thread for PR 80640, some targets have sufficiently strong hardware memory ordering that implementation of C11 atomic fences might not need machine barriers. However, a compiler memory barrier nevertheless must be present, and at least two targets (x86, s390) got this wrong in their .md expanders. Handle it in the middle-end by detecting empty expansion and emitting a compiler memory barrier. If the backend produced non-empty RTL, expect that it's using the same RTX structure as in "memory_barrier" (__sync_synchronize) expansion, which must be a compiler memory on its own. A followup refactor is possible in expand_mem_thread_fence to make it start with if (is_mm_relaxed (model)) return; as it's not useful to pass __ATOMIC_RELAXED model to gen_mem_thread_fence. PR target/80640 * doc/md.texi (mem_thread_fence): Remove mention of mode. Clarify that empty expansion is handled by placing a compiler barrier. * optabs.c (expand_mem_thread_fence): Place a compiler barrier if targetm.gen_mem_thread_fence produced no instructions. testsuite/ * gcc.dg/atomic/pr80640.c: New testcase. --- gcc/doc/md.texi | 9 +++++++-- gcc/optabs.c | 7 ++++++- gcc/testsuite/gcc.dg/atomic/pr80640.c | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/atomic/pr80640.c diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index ea959208c98..0be161a08dc 100644 --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -7044,11 +7044,16 @@ If these patterns are not defined, attempts will be made to use counterparts. If none of these are available a compare-and-swap loop will be used. -@cindex @code{mem_thread_fence@var{mode}} instruction pattern -@item @samp{mem_thread_fence@var{mode}} +@cindex @code{mem_thread_fence} instruction pattern +@item @samp{mem_thread_fence} This pattern emits code required to implement a thread fence with memory model semantics. Operand 0 is the memory model to be used. +Expanding this pattern may produce no instructions if no machine barrier +is required on the target for given memory model. In that case, unless +memory model is @code{__ATOMIC_RELAXED}, a compiler memory barrier is +emitted automatically. + If this pattern is not specified, all memory models except @code{__ATOMIC_RELAXED} will result in issuing a @code{sync_synchronize} barrier pattern. diff --git a/gcc/optabs.c b/gcc/optabs.c index a9900657a58..d568ca376fe 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -6298,7 +6298,12 @@ void expand_mem_thread_fence (enum memmodel model) { if (targetm.have_mem_thread_fence ()) - emit_insn (targetm.gen_mem_thread_fence (GEN_INT (model))); + { + rtx_insn *last = get_last_insn (); + emit_insn (targetm.gen_mem_thread_fence (GEN_INT (model))); + if (last == get_last_insn () && !is_mm_relaxed (model)) + expand_asm_memory_barrier (); + } else if (!is_mm_relaxed (model)) { if (targetm.have_memory_barrier ()) diff --git a/gcc/testsuite/gcc.dg/atomic/pr80640.c b/gcc/testsuite/gcc.dg/atomic/pr80640.c new file mode 100644 index 00000000000..fd17978a482 --- /dev/null +++ b/gcc/testsuite/gcc.dg/atomic/pr80640.c @@ -0,0 +1,34 @@ +/* { dg-do run } */ +/* { dg-options "-pthread" } */ +/* { dg-require-effective-target pthread } */ + +#include + +static volatile int sem1; +static volatile int sem2; + +static void *f(void *va) +{ + void **p = va; + if (*p) return *p; + sem1 = 1; + while (!sem2); + __atomic_thread_fence(__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_thread_fence(__ATOMIC_RELEASE); + sem2 = 1; + pthread_join(thr, &p); + return !p; +}