This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Patch: Blackfin hardware errata workarounds for 4.0


This is a backport of a patch I checked in on the mainline yesterday. With -mcsync-anomaly, the compiler will insert extra nops when jumps or jump targets are too close to csync instructions.


Bernd
Index: ChangeLog
===================================================================
RCS file: /cvs/gcc/gcc/gcc/ChangeLog,v
retrieving revision 2.7592.2.311
diff -c -p -r2.7592.2.311 ChangeLog
*** ChangeLog	12 Jul 2005 09:50:52 -0000	2.7592.2.311
--- ChangeLog	12 Jul 2005 10:29:55 -0000
***************
*** 1,5 ****
--- 1,15 ----
  2005-07-12  Bernd Schmidt  <bernd.schmidt@analog.com>
  
+ 	* config/bfin/bfin.md (define_attr "type"): Add "sync".
+ 	(define_insn_reservation "alu"): Likewise.
+ 	(csync, ssync): Now of type sync.
+ 	* config/bfin/bfin.h (MASK_CSYNC, TARGET_CSYNC): Removed.
+ 	(MASK_CSYNC_ANOMALY, MASK_SPECLD_ANOMALY, TARGET_CSYNC_ANOMALY,
+ 	TARGET_SPECLD_ANOMALY): New.
+ 	* config/bfin/bfin.c: Include "insn-codes.h".
+ 	(bfin_reorg): Extend to handle the CSYNC anomaly as well.
+ 	* doc/invoke.texi: Document -mcsync-anomaly, -mspecld-anomaly.
+ 
  	* config/bfin/bfin.md (UNSPEC_VOLATILE_CSYNC, UNSPEC_VOLATILE_SSYNC):
  	New constants.
  	(csync, ssync): New insn patterns.
Index: doc/invoke.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/invoke.texi,v
retrieving revision 1.583.2.19
diff -c -p -r1.583.2.19 invoke.texi
*** doc/invoke.texi	6 Jun 2005 12:12:50 -0000	1.583.2.19
--- doc/invoke.texi	12 Jul 2005 10:30:04 -0000
*************** Objective-C and Objective-C++ Dialects}.
*** 400,408 ****
  -mcall-prologues  -mno-tablejump  -mtiny-stack  -mint8}
  
  @emph{Blackfin Options}
! @gccoptlist{-momit-leaf-frame-pointer -mno-omit-leaf-frame-pointer -mcsync @gol
! -mno-csync -mlow-64k -mno-low64k -mid-shared-library @gol
! -mno-id-shared-library -mshared-library-id=@var{n} @gol}
  
  @emph{CRIS Options}
  @gccoptlist{-mcpu=@var{cpu}  -march=@var{cpu}  -mtune=@var{cpu} @gol
--- 400,409 ----
  -mcall-prologues  -mno-tablejump  -mtiny-stack  -mint8}
  
  @emph{Blackfin Options}
! @gccoptlist{-momit-leaf-frame-pointer -mno-omit-leaf-frame-pointer @gol
! -mspecld-anomaly -mno-specld-anomaly -mcsync-anomaly -mno-csync-anomaly @gol
! -mlow-64k -mno-low64k -mid-shared-library @gol
! -mno-id-shared-library -mshared-library-id=@var{n}}
  
  @emph{CRIS Options}
  @gccoptlist{-mcpu=@var{cpu}  -march=@var{cpu}  -mtune=@var{cpu} @gol
*************** makes an extra register available in lea
*** 7144,7159 ****
  @option{-fomit-frame-pointer} removes the frame pointer for all functions
  which might make debugging harder.
  
! @item -mcsync
! @opindex mcsync
  When enabled, the compiler will ensure that the generated code does not
  contain speculative loads after jump instructions.  This option is enabled
  by default.
  
! @item -mno-csync
! @opindex mno-csync
  Don't generate extra code to prevent speculative loads from occurring.
  
  @item -mlow-64k
  @opindex mlow-64k
  When enabled, the compiler is free to take advantage of the knowledge that
--- 7145,7171 ----
  @option{-fomit-frame-pointer} removes the frame pointer for all functions
  which might make debugging harder.
  
! @item -mspecld-anomaly
! @opindex mspecld-anomaly
  When enabled, the compiler will ensure that the generated code does not
  contain speculative loads after jump instructions.  This option is enabled
  by default.
  
! @item -mno-specld-anomaly
! @opindex mno-specld-anomaly
  Don't generate extra code to prevent speculative loads from occurring.
  
+ @item -mcsync-anomaly
+ @opindex mcsync-anomaly
+ When enabled, the compiler will ensure that the generated code does not
+ contain CSYNC or SSYNC instructions too soon after conditional branches.
+ This option is enabled by default.
+ 
+ @item -mno-csync-anomaly
+ @opindex mno-csync-anomaly
+ Don't generate extra code to prevent CSYNC or SSYNC instructions from
+ occurring too soon after a conditional branch.
+ 
  @item -mlow-64k
  @opindex mlow-64k
  When enabled, the compiler is free to take advantage of the knowledge that
Index: config/bfin/bfin.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/bfin/bfin.c,v
retrieving revision 1.5.2.3
diff -c -p -r1.5.2.3 bfin.c
*** config/bfin/bfin.c	12 Jul 2005 09:51:37 -0000	1.5.2.3
--- config/bfin/bfin.c	12 Jul 2005 10:30:05 -0000
***************
*** 28,33 ****
--- 28,34 ----
  #include "hard-reg-set.h"
  #include "real.h"
  #include "insn-config.h"
+ #include "insn-codes.h"
  #include "conditions.h"
  #include "insn-flags.h"
  #include "output.h"
*************** bfin_reorg (void)
*** 2470,2478 ****
    rtx insn, last_condjump = NULL_RTX;
    int cycles_since_jump = INT_MAX;
  
!   if (! TARGET_CSYNC)
      return;
  
    for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
      {
        rtx pat;
--- 2471,2481 ----
    rtx insn, last_condjump = NULL_RTX;
    int cycles_since_jump = INT_MAX;
  
!   if (! TARGET_SPECLD_ANOMALY || ! TARGET_CSYNC_ANOMALY)
      return;
  
+   /* First pass: find predicted-false branches; if something after them
+      needs nops, insert them or change the branch to predict true.  */
    for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
      {
        rtx pat;
*************** bfin_reorg (void)
*** 2500,2529 ****
        else if (INSN_P (insn))
  	{
  	  enum attr_type type = get_attr_type (insn);
  	  if (cycles_since_jump < INT_MAX)
  	    cycles_since_jump++;
  
! 	  if (type == TYPE_MCLD && cycles_since_jump < 3)
  	    {
  	      rtx pat;
  
! 	      pat = single_set (insn);
! 	      if (may_trap_p (SET_SRC (pat)))
! 		{
! 		  int num_clobbers;
! 		  rtx *op = recog_data.operand;
  
! 		  extract_insn (last_condjump);
! 		  if (optimize_size)
! 		    pat = gen_cbranch_predicted_taken (op[0], op[1], op[2],
! 						       op[3]);
! 		  else
! 		    pat = gen_cbranch_with_nops (op[0], op[1], op[2], op[3],
! 						 GEN_INT (3 - cycles_since_jump));
! 		  PATTERN (last_condjump) = pat;
! 		  INSN_CODE (last_condjump) = recog (pat, insn, &num_clobbers);
  		  cycles_since_jump = INT_MAX;
  		}
  	    }
  	}
      }
--- 2503,2612 ----
        else if (INSN_P (insn))
  	{
  	  enum attr_type type = get_attr_type (insn);
+ 	  int delay_needed = 0;
  	  if (cycles_since_jump < INT_MAX)
  	    cycles_since_jump++;
  
! 	  if (type == TYPE_MCLD && TARGET_SPECLD_ANOMALY)
! 	    {
! 	      rtx pat = single_set (insn);
! 	      if (may_trap_p (SET_SRC (pat)))
! 		delay_needed = 3;
! 	    }
! 	  else if (type == TYPE_SYNC && TARGET_CSYNC_ANOMALY)
! 	    delay_needed = 4;
! 
! 	  if (delay_needed > cycles_since_jump)
  	    {
  	      rtx pat;
+ 	      int num_clobbers;
+ 	      rtx *op = recog_data.operand;
  
! 	      delay_needed -= cycles_since_jump;
  
! 	      extract_insn (last_condjump);
! 	      if (optimize_size)
! 		{
! 		  pat = gen_cbranch_predicted_taken (op[0], op[1], op[2],
! 						     op[3]);
  		  cycles_since_jump = INT_MAX;
  		}
+ 	      else
+ 		/* Do not adjust cycles_since_jump in this case, so that
+ 		   we'll increase the number of NOPs for a subsequent insn
+ 		   if necessary.  */
+ 		pat = gen_cbranch_with_nops (op[0], op[1], op[2], op[3],
+ 					     GEN_INT (delay_needed));
+ 	      PATTERN (last_condjump) = pat;
+ 	      INSN_CODE (last_condjump) = recog (pat, insn, &num_clobbers);
+ 	    }
+ 	}
+     }
+   /* Second pass: for predicted-true branches, see if anything at the
+      branch destination needs extra nops.  */
+   if (! TARGET_CSYNC_ANOMALY)
+     return;
+ 
+   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+     {
+       if (JUMP_P (insn)
+ 	  && any_condjump_p (insn)
+ 	  && (INSN_CODE (insn) == CODE_FOR_cbranch_predicted_taken
+ 	      || cbranch_predicted_taken_p (insn)))
+ 	{
+ 	  rtx target = JUMP_LABEL (insn);
+ 	  rtx label = target;
+ 	  cycles_since_jump = 0;
+ 	  for (; target && cycles_since_jump < 3; target = NEXT_INSN (target))
+ 	    {
+ 	      rtx pat;
+ 
+ 	      if (NOTE_P (target) || BARRIER_P (target) || LABEL_P (target))
+ 		continue;
+ 
+ 	      pat = PATTERN (target);
+ 	      if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
+ 		  || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC
+ 		  || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0)
+ 		continue;
+ 
+ 	      if (INSN_P (target))
+ 		{
+ 		  enum attr_type type = get_attr_type (target);
+ 		  int delay_needed = 0;
+ 		  if (cycles_since_jump < INT_MAX)
+ 		    cycles_since_jump++;
+ 
+ 		  if (type == TYPE_SYNC && TARGET_CSYNC_ANOMALY)
+ 		    delay_needed = 2;
+ 
+ 		  if (delay_needed > cycles_since_jump)
+ 		    {
+ 		      rtx prev = prev_real_insn (label);
+ 		      delay_needed -= cycles_since_jump;
+ 		      if (dump_file)
+ 			fprintf (dump_file, "Adding %d nops after %d\n",
+ 				 delay_needed, INSN_UID (label));
+ 		      if (JUMP_P (prev)
+ 			  && INSN_CODE (prev) == CODE_FOR_cbranch_with_nops)
+ 			{
+ 			  rtx x;
+ 			  HOST_WIDE_INT v;
+ 
+ 			  if (dump_file)
+ 			    fprintf (dump_file,
+ 				     "Reducing nops on insn %d.\n",
+ 				     INSN_UID (prev));
+ 			  x = PATTERN (prev);
+ 			  x = XVECEXP (x, 0, 1);
+ 			  v = INTVAL (XVECEXP (x, 0, 0)) - delay_needed;
+ 			  XVECEXP (x, 0, 0) = GEN_INT (v);
+ 			}
+ 		      while (delay_needed-- > 0)
+ 			emit_insn_after (gen_nop (), label);
+ 		      break;
+ 		    }
+ 		}
  	    }
  	}
      }
Index: config/bfin/bfin.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/bfin/bfin.h,v
retrieving revision 1.3.4.1
diff -c -p -r1.3.4.1 bfin.h
*** config/bfin/bfin.h	25 Apr 2005 10:40:25 -0000	1.3.4.1
--- config/bfin/bfin.h	12 Jul 2005 10:30:06 -0000
*************** extern int target_flags;
*** 48,68 ****
  /* Generate DSP instructions, like DSP halfword loads */
  #define TARGET_DSP			(1)
  
! #define TARGET_DEFAULT MASK_CSYNC
  
  /* Don't create frame pointers for leaf functions */
  #define TARGET_OMIT_LEAF_FRAME_POINTER (target_flags & MASK_OMIT_LEAF_FRAME_POINTER)
  #define TARGET_LOW_64K                 (target_flags & MASK_LOW_64K)
! #define TARGET_CSYNC		       (target_flags & MASK_CSYNC)
  #define TARGET_ID_SHARED_LIBRARY       (target_flags & MASK_ID_SHARED_LIBRARY)
  
  #define MASK_OMIT_LEAF_FRAME_POINTER 0x00000001
! #define MASK_CSYNC                   0x00000002
  #define MASK_LOW_64K           	     0x00000004
  /* Compile using library ID based shared libraries.
   * Set a specific ID using the -mshared-library-id=xxx option.
   */
  #define MASK_ID_SHARED_LIBRARY	     0x00000008
  
  #define TARGET_SWITCHES  {\
    { "omit-leaf-frame-pointer",	  MASK_OMIT_LEAF_FRAME_POINTER,		\
--- 48,70 ----
  /* Generate DSP instructions, like DSP halfword loads */
  #define TARGET_DSP			(1)
  
! #define TARGET_DEFAULT (MASK_CSYNC_ANOMALY | MASK_SPECLD_ANOMALY)
  
  /* Don't create frame pointers for leaf functions */
  #define TARGET_OMIT_LEAF_FRAME_POINTER (target_flags & MASK_OMIT_LEAF_FRAME_POINTER)
  #define TARGET_LOW_64K                 (target_flags & MASK_LOW_64K)
! #define TARGET_CSYNC_ANOMALY	       (target_flags & MASK_CSYNC_ANOMALY)
! #define TARGET_SPECLD_ANOMALY	       (target_flags & MASK_SPECLD_ANOMALY)
  #define TARGET_ID_SHARED_LIBRARY       (target_flags & MASK_ID_SHARED_LIBRARY)
  
  #define MASK_OMIT_LEAF_FRAME_POINTER 0x00000001
! #define MASK_CSYNC_ANOMALY           0x00000002
  #define MASK_LOW_64K           	     0x00000004
  /* Compile using library ID based shared libraries.
   * Set a specific ID using the -mshared-library-id=xxx option.
   */
  #define MASK_ID_SHARED_LIBRARY	     0x00000008
+ #define MASK_SPECLD_ANOMALY          0x00000010
  
  #define TARGET_SWITCHES  {\
    { "omit-leaf-frame-pointer",	  MASK_OMIT_LEAF_FRAME_POINTER,		\
*************** extern int target_flags;
*** 73,88 ****
      "Program is located in low 64K of memory" },			\
    { "no-low64k",	         -MASK_LOW_64K,				\
      "Program is not located in low 64K of memory (default)"},		\
!   { "csync",		         MASK_CSYNC,				\
!     "Avoid speculative loads by inserting CSYNC or equivalent"},	\
!   { "no-csync",			-MASK_CSYNC,				\
      "Do not generate extra code to avoid speculative loads"},		\
    { "id-shared-library", MASK_ID_SHARED_LIBRARY,			\
      "Enable ID based shared library" },					\
    { "no-id-shared-library", -MASK_ID_SHARED_LIBRARY,			\
      "Disable ID based shared library" },				\
    { "", TARGET_DEFAULT,							\
!     "default: csync"}}
  
  /* This macro is similar to `TARGET_SWITCHES' but defines names of
     command options that have values.  Its definition is an
--- 75,94 ----
      "Program is located in low 64K of memory" },			\
    { "no-low64k",	         -MASK_LOW_64K,				\
      "Program is not located in low 64K of memory (default)"},		\
!   { "specld-anomaly",		 MASK_SPECLD_ANOMALY,			\
!     "Avoid speculative loads"},						\
!   { "no-specld-anomaly",	-MASK_SPECLD_ANOMALY,			\
      "Do not generate extra code to avoid speculative loads"},		\
+   { "csync-anomaly",		 MASK_CSYNC_ANOMALY,			\
+     "Avoid CSYNC/SSYNC after conditional jumps"},			\
+   { "no-csync-anomaly",		-MASK_CSYNC_ANOMALY,			\
+     "Do not generate extra code to avoid CSYNC/SSYNC after condjumps"},	\
    { "id-shared-library", MASK_ID_SHARED_LIBRARY,			\
      "Enable ID based shared library" },					\
    { "no-id-shared-library", -MASK_ID_SHARED_LIBRARY,			\
      "Disable ID based shared library" },				\
    { "", TARGET_DEFAULT,							\
!     "default: csync-anomaly, specld-anomaly"}}
  
  /* This macro is similar to `TARGET_SWITCHES' but defines names of
     command options that have values.  Its definition is an
Index: config/bfin/bfin.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/bfin/bfin.md,v
retrieving revision 1.1.8.3
diff -c -p -r1.1.8.3 bfin.md
*** config/bfin/bfin.md	12 Jul 2005 09:51:37 -0000	1.1.8.3
--- config/bfin/bfin.md	12 Jul 2005 10:30:06 -0000
***************
*** 125,131 ****
     (UNSPEC_VOLATILE_SSYNC 2)])
  
  (define_attr "type"
!   "move,mvi,mcld,mcst,dsp32,mult,alu0,shft,brcc,br,call,misc,compare,dummy"
    (const_string "misc"))
  
  ;; Scheduling definitions
--- 125,131 ----
     (UNSPEC_VOLATILE_SSYNC 2)])
  
  (define_attr "type"
!   "move,mvi,mcld,mcst,dsp32,mult,alu0,shft,brcc,br,call,misc,sync,compare,dummy"
    (const_string "misc"))
  
  ;; Scheduling definitions
***************
*** 135,141 ****
  (define_cpu_unit "core" "bfin")
  
  (define_insn_reservation "alu" 1
!   (eq_attr "type" "move,mvi,mcst,dsp32,alu0,shft,brcc,br,call,misc,compare")
    "core")
  
  (define_insn_reservation "imul" 3
--- 135,141 ----
  (define_cpu_unit "core" "bfin")
  
  (define_insn_reservation "alu" 1
!   (eq_attr "type" "move,mvi,mcst,dsp32,alu0,shft,brcc,br,call,misc,sync,compare")
    "core")
  
  (define_insn_reservation "imul" 3
***************
*** 1852,1864 ****
    [(unspec_volatile [(const_int 0)] UNSPEC_VOLATILE_CSYNC)]
    ""
    "csync;"
!   [(set_attr "type" "misc")])
  
  (define_insn "ssync"
    [(unspec_volatile [(const_int 0)] UNSPEC_VOLATILE_SSYNC)]
    ""
    "ssync;"
!   [(set_attr "type" "misc")])
  
  ;;; Vector instructions
  
--- 1852,1864 ----
    [(unspec_volatile [(const_int 0)] UNSPEC_VOLATILE_CSYNC)]
    ""
    "csync;"
!   [(set_attr "type" "sync")])
  
  (define_insn "ssync"
    [(unspec_volatile [(const_int 0)] UNSPEC_VOLATILE_SSYNC)]
    ""
    "ssync;"
!   [(set_attr "type" "sync")])
  
  ;;; Vector instructions
  

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]