From patchwork Wed Jun 14 08:26:40 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Cederman X-Patchwork-Id: 775661 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]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3wnfrD4zGpz9s7g for ; Wed, 14 Jun 2017 18:27:08 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="glDsLm9B"; dkim-atps=neutral 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:cc:subject:date:message-id; q=dns; s=default; b=boUDIGAX9tvH 0oW4eUxqtXaUUQeSwJUnnXJmU1jDOeGi2iYQiw7iaiX2qKidGgRpso4gkTlOUO8V Q8RRI6pExIn0aFOock34rUnZAddQ6RS57nxci2LxqwKdnETJxM6rTjm0o5KbGtGd U1DNYX1cEQfvppWcECb7l2J7iI5Mrsg= 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:cc:subject:date:message-id; s=default; bh=EnjxvBFeO0WBDoRxOM 8ytvzME3c=; b=glDsLm9BJwtg5gCaI6QhK4RCoWDuRakD6a+Fa94Xnc1vrt+ASx Qu0pjyNeZhz4Hm4EKpnbOd0A9fPHaR02k8qSAJ+mSFrJdizDk2O052vE5krFcN6q cK18wloiTVQ0Y0OOPzg/U8i06bgguhxiXedg13mLSo4aAyGgL45qZw8eg= Received: (qmail 85034 invoked by alias); 14 Jun 2017 08:26: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 84982 invoked by uid 89); 14 Jun 2017 08:26:49 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-24.1 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_LAZY_DOMAIN_SECURITY, RCVD_IN_DNSWL_LOW autolearn=ham version=3.3.2 spammy=*after X-HELO: bin-vsp-out-01.atm.binero.net Received: from bin-mail-out-05.binero.net (HELO bin-vsp-out-01.atm.binero.net) (195.74.38.228) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 14 Jun 2017 08:26:46 +0000 X-Halon-ID: 33927423-50db-11e7-b75a-005056917a89 Authorized-sender: cederman@gaisler.com Received: from localhost.localdomain (unknown [81.170.187.120]) by bin-vsp-out-01.atm.binero.net (Halon Mail Gateway) with ESMTPA; Wed, 14 Jun 2017 10:26:44 +0200 (CEST) From: Daniel Cederman To: gcc-patches@gcc.gnu.org Cc: daniel@gaisler.com, ebotcazou@adacore.com Subject: [PATCH] [SPARC] Add a workaround for the LEON3FT store-store errata Date: Wed, 14 Jun 2017 10:26:40 +0200 Message-Id: <20170614082640.31509-1-cederman@gaisler.com> X-IsSubscribed: yes Hello all, I'm resending this patch with an update that fixes an issue when using it together with the -mflat flag. - This patch adds a workaround to the Sparc backend for the LEON3FT store-store errata. It is enabled using the -mfix-b2bst flag. The workaround inserts NOP instructions to prevent the following two instruction sequences from being generated: std -> stb/sth/st/std stb/sth/st -> any single non-store/load instruction -> stb/sth/st/std The __FIX_B2BST define can be used to only enable workarounds in assembly code when the flag is used. See GRLIB-TN-0009, "LEON3FT Stale Cache Entry After Store with Data Tag Parity Error", for more information. gcc/ChangeLog: 2017-01-18 Daniel Cederman * config/sparc/sparc.c (sparc_do_work_around_errata): Insert NOP instructions to prevent sequences that can trigger the store-store errata for certain LEON3FT processors. Enable with -mfix-b2bst. (sparc_option_override): -mfix-ut699 implies -mfix-b2bst. * config/sparc/sparc-c.c (sparc_target_macros): Define __FIX_B2BST. * config/sparc/sparc.md: Prevent stores in delay slot. * config/sparc/sparc.opt: Add -mfix-b2bst flag. * doc/invoke.texi: Document -mfix-b2bst flag. --- gcc/config/sparc/sparc-c.c | 3 ++ gcc/config/sparc/sparc.c | 107 ++++++++++++++++++++++++++++++++++++++++++++- gcc/config/sparc/sparc.md | 10 ++++- gcc/config/sparc/sparc.opt | 4 ++ gcc/doc/invoke.texi | 7 ++- 5 files changed, 126 insertions(+), 5 deletions(-) diff --git a/gcc/config/sparc/sparc-c.c b/gcc/config/sparc/sparc-c.c index 9603173..6979f9c 100644 --- a/gcc/config/sparc/sparc-c.c +++ b/gcc/config/sparc/sparc-c.c @@ -60,4 +60,7 @@ sparc_target_macros (void) cpp_define (parse_in, "__VIS__=0x100"); cpp_define (parse_in, "__VIS=0x100"); } + + if (sparc_fix_b2bst) + builtin_define_std ("__FIX_B2BST"); } diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c index 95a64a4..d5225e0 100644 --- a/gcc/config/sparc/sparc.c +++ b/gcc/config/sparc/sparc.c @@ -896,6 +896,12 @@ mem_ref (rtx x) to properly detect the various hazards. Therefore, this machine specific pass runs as late as possible. */ +/* True if INSN is a md pattern or asm statement. */ +#define USEFUL_INSN_P(INSN) \ + (NONDEBUG_INSN_P (INSN) \ + && GET_CODE (PATTERN (INSN)) != USE \ + && GET_CODE (PATTERN (INSN)) != CLOBBER) + static unsigned int sparc_do_work_around_errata (void) { @@ -915,6 +921,98 @@ sparc_do_work_around_errata (void) if (rtx_sequence *seq = dyn_cast (PATTERN (insn))) insn = seq->insn (1); + /* Look for a double-word store. */ + if (sparc_fix_b2bst + && NONJUMP_INSN_P (insn) + && (set = single_set (insn)) != NULL_RTX + && GET_MODE_SIZE (GET_MODE (SET_DEST (set))) == 8 + && MEM_P (SET_DEST (set))) + { + next = next_active_insn (insn); + if (!next) + break; + + /* Skip empty assembly statements. */ + if ((GET_CODE(PATTERN(next)) == UNSPEC_VOLATILE) || + (USEFUL_INSN_P (next) + && (asm_noperands (PATTERN (next))>=0) + && !strcmp (decode_asm_operands (PATTERN (next), + NULL, NULL, NULL, + NULL, NULL), ""))) + next = next_active_insn (next); + if (!next) + break; + + /* If the insn is a branch, then it cannot be problematic. */ + if (!NONJUMP_INSN_P (next) || GET_CODE (PATTERN (next)) == SEQUENCE) + continue; + + if ((set = single_set (next)) == NULL_RTX) + continue; + + /* Add NOP if double-word store is followed by any type of store. */ + if (MEM_P (SET_DEST (set))) + insert_nop = true; + } + else + /* Look for single-word, half-word, or byte store. */ + if (sparc_fix_b2bst + && NONJUMP_INSN_P (insn) + && (set = single_set (insn)) != NULL_RTX + && GET_MODE_SIZE (GET_MODE (SET_DEST (set))) <= 4 + && MEM_P (SET_DEST (set))) + { + rtx_insn *after; + + next = next_active_insn (insn); + if (!next) + break; + + /* Skip empty assembly statements. */ + if ((GET_CODE(PATTERN(next)) == UNSPEC_VOLATILE) || + (USEFUL_INSN_P (next) + && (asm_noperands (PATTERN (next))>=0) + && !strcmp (decode_asm_operands (PATTERN (next), + NULL, NULL, NULL, + NULL, NULL), ""))) + next = next_active_insn (next); + if (!next) + break; + + /* If the insn is a branch, then it cannot be problematic. */ + if (!NONJUMP_INSN_P (next) || GET_CODE (PATTERN (next)) == SEQUENCE) + continue; + + /* If the insn is a load or store, then it cannot be problematic. */ + if ((set = single_set (next)) != NULL_RTX + && (MEM_P (SET_DEST (set)) || MEM_P (SET_SRC (set)))) + continue; + + after = next_active_insn (next); + if (!after) + continue; + + /* Skip empty assembly statements. */ + if ((GET_CODE(PATTERN(after)) == UNSPEC_VOLATILE) || + (USEFUL_INSN_P (after) + && (asm_noperands (PATTERN (after))>=0) + && !strcmp (decode_asm_operands (PATTERN (after), + NULL, NULL, NULL, + NULL, NULL), ""))) + after = next_active_insn (after); + if (!after) + break; + + /* If the insn is a branch, then it cannot be problematic. */ + if (!NONJUMP_INSN_P (after) || GET_CODE (PATTERN (after)) == SEQUENCE) + continue; + + /* Add NOP if third instruction is a store. */ + if (((set = single_set (after)) != NULL_RTX) + && MEM_P (SET_DEST (set))) + insert_nop = true; + } + else /* Look for a single-word load into an odd-numbered FP register. */ if (sparc_fix_at697f && NONJUMP_INSN_P (insn) @@ -1167,8 +1265,9 @@ public: /* opt_pass methods: */ virtual bool gate (function *) { - /* The only errata we handle are those of the AT697F and UT699. */ - return sparc_fix_at697f != 0 || sparc_fix_ut699 != 0; + /* The only errata we handle are those of the AT697F, + UT699, and certain LEON3FT. */ + return sparc_fix_at697f || sparc_fix_ut699 || sparc_fix_b2bst; } virtual unsigned int execute (function *) @@ -1527,6 +1626,10 @@ sparc_option_override (void) if (!(target_flags_explicit & MASK_LRA)) target_flags |= MASK_LRA; + /* -mfix-ut699 implies -mfix-b2bst. */ + if (sparc_fix_ut699) + sparc_fix_b2bst = 1; + /* Supply a default value for align_functions. */ if (align_functions == 0) { diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md index 5c5096b..6c1b1e3 100644 --- a/gcc/config/sparc/sparc.md +++ b/gcc/config/sparc/sparc.md @@ -329,6 +329,10 @@ (symbol_ref "(sparc_fix_ut699 != 0 ? FIX_UT699_TRUE : FIX_UT699_FALSE)")) +(define_attr "fix_b2bst" "false,true" + (symbol_ref "(sparc_fix_b2bst != 0 + ? FIX_B2BST_TRUE : FIX_B2BST_FALSE)")) + ;; Length (in # of insns). ;; Beware that setting a length greater or equal to 3 for conditional branches ;; has a side-effect (see output_cbranch and output_v9branch). @@ -476,6 +480,8 @@ (define_attr "in_branch_delay" "false,true" (cond [(eq_attr "type" "uncond_branch,branch,cbcond,uncond_cbcond,call,sibcall,call_no_delay_slot,multi") (const_string "false") + (and (eq_attr "fix_b2bst" "true") (eq_attr "type" "store,fpstore")) + (const_string "false") (and (eq_attr "fix_ut699" "true") (eq_attr "type" "load,sload")) (const_string "false") (and (eq_attr "fix_ut699" "true") @@ -6061,7 +6067,7 @@ (div:DF (match_operand:DF 1 "register_operand" "e") (match_operand:DF 2 "register_operand" "e")))] "TARGET_FPU && sparc_fix_ut699" - "fdivd\t%1, %2, %0\n\tstd\t%0, [%%sp-8]" + "fdivd\t%1, %2, %0\n\tnop\n\tstd\t%0, [%%sp-8]\n\tnop" [(set_attr "type" "fpdivd") (set_attr "fptype" "double") (set_attr "length" "2")]) @@ -6313,7 +6319,7 @@ [(set (match_operand:DF 0 "register_operand" "=e") (sqrt:DF (match_operand:DF 1 "register_operand" "e")))] "TARGET_FPU && sparc_fix_ut699" - "fsqrtd\t%1, %0\n\tstd\t%0, [%%sp-8]" + "fsqrtd\t%1, %0\n\tnop\n\tstd\t%0, [%%sp-8]\n\tnop" [(set_attr "type" "fpsqrtd") (set_attr "fptype" "double") (set_attr "length" "2")]) diff --git a/gcc/config/sparc/sparc.opt b/gcc/config/sparc/sparc.opt index 86f85d9..02b52be 100644 --- a/gcc/config/sparc/sparc.opt +++ b/gcc/config/sparc/sparc.opt @@ -230,6 +230,10 @@ mfix-ut699 Target Report RejectNegative Var(sparc_fix_ut699) Enable workarounds for the errata of the UT699 processor. +mfix-b2bst +Target Report RejectNegative Var(sparc_fix_b2bst) +Enable workarounds for LEON3FT store-store errata + Mask(LONG_DOUBLE_128) ;; Use 128-bit long double diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 653bc07..d4682dc 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -1126,7 +1126,7 @@ See RS/6000 and PowerPC Options. -mvis2 -mno-vis2 -mvis3 -mno-vis3 @gol -mcbcond -mno-cbcond -mfmaf -mno-fmaf @gol -mpopc -mno-popc -msubxc -mno-subxc@gol --mfix-at697f -mfix-ut699 @gol +-mfix-at697f -mfix-ut699 -mfix-b2bst @gol -mlra -mno-lra} @emph{SPU Options} @@ -23696,6 +23696,11 @@ processor (which corresponds to erratum #13 of the AT697E processor). @opindex mfix-ut699 Enable the documented workarounds for the floating-point errata and the data cache nullify errata of the UT699 processor. + +@item -mfix-b2bst +@opindex mfix-b2bst +Enable the documented workaround for the back-to-back store errata of +certain LEON3FT processors. @end table These @samp{-m} options are supported in addition to the above