From patchwork Tue Nov 1 04:53:50 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 123021 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id AA519B6F88 for ; Tue, 1 Nov 2011 15:54:11 +1100 (EST) Received: (qmail 31142 invoked by alias); 1 Nov 2011 04:54:08 -0000 Received: (qmail 31132 invoked by uid 22791); 1 Nov 2011 04:54:07 -0000 X-SWARE-Spam-Status: No, hits=-2.5 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW X-Spam-Check-By: sourceware.org Received: from mail-yw0-f47.google.com (HELO mail-yw0-f47.google.com) (209.85.213.47) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 01 Nov 2011 04:53:53 +0000 Received: by ywf9 with SMTP id 9so7604941ywf.20 for ; Mon, 31 Oct 2011 21:53:53 -0700 (PDT) Received: by 10.150.237.5 with SMTP id k5mr12939990ybh.4.1320123233053; Mon, 31 Oct 2011 21:53:53 -0700 (PDT) Received: from pebble.twiddle.home (c-98-203-235-125.hsd1.wa.comcast.net. [98.203.235.125]) by mx.google.com with ESMTPS id l18sm31443025anb.22.2011.10.31.21.53.51 (version=TLSv1/SSLv3 cipher=OTHER); Mon, 31 Oct 2011 21:53:52 -0700 (PDT) Message-ID: <4EAF7B5E.5050700@twiddle.net> Date: Mon, 31 Oct 2011 21:53:50 -0700 From: Richard Henderson User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.23) Gecko/20110928 Fedora/3.1.15-1.fc14 Thunderbird/3.1.15 MIME-Version: 1.0 To: GCC Patches CC: ak@linux.intel.com, Jakub Jelinek , ubizjak@gmail.com, amacleod@redhat.com Subject: [cxx-mem-model] i386 atomic load/store 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 I'm considering the following. Does anyone believe this i386/i486 decision re DImode is a mistake? Should I limit that to Pentium by checking cmpxchg? r~ diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 7ce57d8..7d28e43 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -248,6 +248,9 @@ ;; For BMI2 support UNSPEC_PDEP UNSPEC_PEXT + + ;; For __atomic support + UNSPEC_MOVA ]) (define_c_enum "unspecv" [ diff --git a/gcc/config/i386/sync.md b/gcc/config/i386/sync.md index e5579b1..da08e92 100644 --- a/gcc/config/i386/sync.md +++ b/gcc/config/i386/sync.md @@ -46,6 +46,88 @@ "lock{%;} or{l}\t{$0, (%%esp)|DWORD PTR [esp], 0}" [(set_attr "memory" "unknown")]) +;; ??? From volume 3 section 7.1.1 Guaranteed Atomic Operations, +;; Only beginning at Pentium family processors do we get any guarantee of +;; atomicity in aligned 64-bit quantities. Beginning at P6, we get a +;; guarantee for 64-bit accesses that do not cross a cacheline boundary. +;; This distinction is ignored below, since I *suspect* that FSTLL will +;; appear atomic from the point of view of user-level threads even back +;; on the 80386; I suspect that the non-atomicity can only be seen from +;; other bus-level devices. +;; +;; Importantly, *no* processor makes atomicity guarantees for larger +;; accesses. In particular, there's no way to perform an atomic TImode +;; move, despite the apparent applicability of MOVDQA et al. + +(define_mode_iterator ATOMIC + [QI HI SI (DI "TARGET_64BIT || TARGET_80387 || TARGET_SSE")]) + +(define_expand "atomic_load" + [(set (match_operand:ATOMIC 0 "register_operand" "") + (unspec:ATOMIC [(match_operand:ATOMIC 1 "memory_operand" "") + (match_operand:SI 2 "const_int_operand" "")] + UNSPEC_MOVA))] + "" +{ + /* For DImode on 32-bit, we can use the FPU to perform the load. */ + if (mode == DImode && !TARGET_64BIT) + emit_insn (gen_atomic_loaddi_fpu (operands[1], operands[2])); + else + emit_move_insn (operands[0], operands[1]); + DONE; +}) + +(define_insn_and_split "atomic_loaddi_fpu" + [(set (match_operand:DI 0 "register_operand" "=fx") + (unspec:DI [(match_operand:DI 1 "memory_operand" "m")] + UNSPEC_MOVA))] + "!TARGET_64BIT && (TARGET_80387 || TARGET_SSE)" + "#" + "&& reload_completed" + [(set (match_dup 0) (match_dup 1))]) + +(define_expand "atomic_store" + [(set (match_operand:ATOMIC 0 "memory_operand" "") + (unspec:ATOMIC [(match_operand:ATOMIC 1 "register_operand" "") + (match_operand:SI 2 "const_int_operand" "")] + UNSPEC_MOVA))] + "" +{ + enum memmodel model = (enum memmodel) INTVAL (operands[2]); + + if (mode == DImode && !TARGET_64BIT) + { + /* For DImode on 32-bit, we can use the FPU to perform the store. */ + emit_insn (gen_atomic_storedi_fpu (operands[1], operands[2])); + if (model == MEMMODEL_SEQ_CST) + emit_insn (gen_mem_thread_fence (operands[2])); + } + else + { + /* For non-seq-cst stores, we can simply just perform the store. */ + if (model != MEMMODEL_SEQ_CST) + { + emit_move_insn (operands[0], operands[1]); + DONE; + } + + /* For sub-word-size, sequentialy-consistent stores, use xchg. */ + emit_insn (gen_atomic_exchange (gen_reg_rtx (mode), + operands[0], operands[1], + operands[2])); + } + DONE; +}) + +(define_insn_and_split "atomic_storedi_fpu" + [(set (match_operand:DI 0 "memory_operand" "=m") + (unspec:DI [(match_operand:DI 1 "register_operand" "fx")] + UNSPEC_MOVA))] + "!TARGET_64BIT && (TARGET_80387 || TARGET_SSE)" + "#" + "&& reload_completed" + [(set (match_dup 0) (match_dup 1))]) + (define_expand "atomic_compare_and_swap" [(match_operand:QI 0 "register_operand" "") ;; bool success output (match_operand:SWI124 1 "register_operand" "") ;; oldval output