public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH-v4] [SPARC] Add a workaround for the LEON3FT store-store errata
@ 2017-07-07 11:43 Daniel Cederman
  2017-07-11  7:21 ` Eric Botcazou
  0 siblings, 1 reply; 3+ messages in thread
From: Daniel Cederman @ 2017-07-07 11:43 UTC (permalink / raw)
  To: ebotcazou; +Cc: gcc-patches, sebastian.huber, davem, daniel

This patch adds a workaround to the Sparc backend for the LEON3FT
store-store errata. It is enabled when using the -mfix-ut699,
-mfix-ut700, or -mfix-gr712rc 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-07-07  Daniel Cederman  <cederman@gaisler.com>

	* 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.
	(sparc_option_override): -mfix-ut699, -mfix-ut700, and
	-mfix-gr712rc enables the errata workaround.
	* config/sparc/sparc.md: Prevent stores in delay slot.
	* config/sparc/sparc.opt: Add -mfix-ut700 and -mfix-gr712rc flag.
	* doc/invoke.texi: Document -mfix-ut700 and -mfix-gr712rc flag.
---
 gcc/config/sparc/sparc.c   | 98 +++++++++++++++++++++++++++++++++++++++++++++-
 gcc/config/sparc/sparc.md  | 10 ++++-
 gcc/config/sparc/sparc.opt | 12 ++++++
 gcc/doc/invoke.texi        | 14 ++++++-
 4 files changed, 128 insertions(+), 6 deletions(-)

diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index 790a036..ebf2eda 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,81 @@ sparc_do_work_around_errata (void)
 	if (rtx_sequence *seq = dyn_cast <rtx_sequence *> (PATTERN (insn)))
 	  insn = seq->insn (1);
 
+      /* Look for either of these two sequences:
+
+	 Sequence A:
+	 1. store of word size or less (e.g. st / stb / sth / stf)
+	 2. any single instruction that is not a load or store
+	 3. any store instruction (e.g. st / stb / sth / stf / std / stdf)
+
+	 Sequence B:
+	 1. store of double word size (e.g. std / stdf)
+	 2. any store instruction (e.g. st / stb / sth / stf / std / stdf)  */
+      if (sparc_fix_b2bst
+	  && NONJUMP_INSN_P (insn)
+	  && (set = single_set (insn)) != NULL_RTX
+	  && MEM_P (SET_DEST (set)))
+	{
+	  /* Sequence B begins with a double-word store.  */
+	  bool seq_b = GET_MODE_SIZE (GET_MODE (SET_DEST (set))) == 8;
+	  rtx_insn *after;
+	  int i;
+
+	  next = next_active_insn (insn);
+	  if (!next)
+	    break;
+
+	  for (after = next, i = 0; i < 2; i++)
+	    {
+	      /* 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)
+		break;
+
+	      /* Sequence B is only two instructions long.  */
+	      if (seq_b)
+		{
+		  /* Add NOP if followed by a store.  */
+		  if ((set = single_set (after)) != NULL_RTX
+		      && MEM_P (SET_DEST (set)))
+		    insert_nop = true;
+
+		  /* Otherwise it is ok.  */
+		  break;
+		}
+
+	      /* If the second instruction is a load or a store,
+		 then the sequence cannot be problematic.  */
+	      if (i == 0)
+		{
+		  if (((set = single_set (after)) != NULL_RTX)
+		      && (MEM_P (SET_DEST (set)) || MEM_P (SET_SRC (set))))
+		    break;
+
+		  after = next_active_insn (after);
+		  if (!after)
+		    break;
+		}
+
+	      /* Add NOP if third instruction is a store.  */
+	      if (i == 1
+		  && ((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 +1248,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 *)
@@ -1519,6 +1601,18 @@ sparc_option_override (void)
   if (!(target_flags_explicit & MASK_LRA))
     target_flags |= MASK_LRA;
 
+  /* -mfix-ut699 enables the back-to-back store errata workaround.  */
+  if (sparc_fix_ut699)
+    sparc_fix_b2bst = 1;
+
+  /* -mfix-ut700 enables the back-to-back store errata workaround.  */
+  if (sparc_fix_ut700)
+    sparc_fix_b2bst = 1;
+
+  /* -mfix-gr712rc enables the back-to-back store errata workaround.  */
+  if (sparc_fix_gr712rc)
+    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..a44945f 100644
--- a/gcc/config/sparc/sparc.opt
+++ b/gcc/config/sparc/sparc.opt
@@ -230,6 +230,18 @@ mfix-ut699
 Target Report RejectNegative Var(sparc_fix_ut699)
 Enable workarounds for the errata of the UT699 processor.
 
+mfix-ut700
+Target Report RejectNegative Var(sparc_fix_ut700)
+Enable workarounds for the errata of the UT699E/UT700 processor.
+
+mfix-gr712rc
+Target Report RejectNegative Var(sparc_fix_gr712rc)
+Enable workarounds for the errata of the GR712RC processor.
+
+;; Enable workaround for back-to-back store errata
+TargetVariable
+unsigned int sparc_fix_b2bst
+
 Mask(LONG_DOUBLE_128)
 ;; Use 128-bit long double
 
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index d0b9050..e866d13 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -1127,8 +1127,8 @@ 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
--mlra  -mno-lra}
+-mfix-at697f  -mfix-ut699 -mfix-ut700 @gol
+-mfix-gr712rc -mlra  -mno-lra}
 
 @emph{SPU Options}
 @gccoptlist{-mwarn-reloc  -merror-reloc @gol
@@ -24074,6 +24074,16 @@ 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-ut700
+@opindex mfix-ut700
+Enable the documented workaround for the back-to-back store errata of
+the UT699E/UT700 processor.
+
+@item -mfix-gr712rc
+@opindex mfix-gr712rc
+Enable the documented workaround for the back-to-back store errata of
+the GR712RC processor.
 @end table
 
 These @samp{-m} options are supported in addition to the above
-- 
2.9.3

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH-v4] [SPARC] Add a workaround for the LEON3FT store-store errata
  2017-07-07 11:43 [PATCH-v4] [SPARC] Add a workaround for the LEON3FT store-store errata Daniel Cederman
@ 2017-07-11  7:21 ` Eric Botcazou
  2017-07-11  8:19   ` Daniel Cederman
  0 siblings, 1 reply; 3+ messages in thread
From: Eric Botcazou @ 2017-07-11  7:21 UTC (permalink / raw)
  To: Daniel Cederman; +Cc: gcc-patches, sebastian.huber, davem, daniel

> 2017-07-07  Daniel Cederman  <cederman@gaisler.com>
> 
> 	* 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.
> 	(sparc_option_override): -mfix-ut699, -mfix-ut700, and
> 	-mfix-gr712rc enables the errata workaround.
> 	* config/sparc/sparc.md: Prevent stores in delay slot.
> 	* config/sparc/sparc.opt: Add -mfix-ut700 and -mfix-gr712rc flag.
> 	* doc/invoke.texi: Document -mfix-ut700 and -mfix-gr712rc flag.

Applied without the undocumented tweaks to the divdf3_fix and sqrtdf2_fix 
patterns.  Why are 2 nops necessary here?  The stored value doesn't matter.
And the length attribute should be adjusted if nops are added to the pattern.

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH-v4] [SPARC] Add a workaround for the LEON3FT store-store errata
  2017-07-11  7:21 ` Eric Botcazou
@ 2017-07-11  8:19   ` Daniel Cederman
  0 siblings, 0 replies; 3+ messages in thread
From: Daniel Cederman @ 2017-07-11  8:19 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: gcc-patches, sebastian.huber, davem, daniel

On 2017-07-11 09:21, Eric Botcazou wrote:
> 
> Applied without the undocumented tweaks to the divdf3_fix and sqrtdf2_fix
> patterns.  Why are 2 nops necessary here?  The stored value doesn't matter.
> And the length attribute should be adjusted if nops are added to the pattern.
> 

The first nop was added to prevent sequence A from appearing (store -> 
fdivd -> std). But as you say, it is not needed as we do not read the 
value written by the std. The second nop was added to prevent sequence B 
(std -> store) and this one seems necessary as the value written by the 
store might be used later. OK to submit a new patch with only the second 
nop and a correct length attribute?

-- 
Daniel Cederman
Cobham Gaisler

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2017-07-11  8:19 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-07-07 11:43 [PATCH-v4] [SPARC] Add a workaround for the LEON3FT store-store errata Daniel Cederman
2017-07-11  7:21 ` Eric Botcazou
2017-07-11  8:19   ` Daniel Cederman

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).