bfin.md (define_attr "type"): Add "sync".
authorBernd Schmidt <bernd.schmidt@analog.com>
Mon, 11 Jul 2005 16:11:28 +0000 (16:11 +0000)
committerBernd Schmidt <bernds@gcc.gnu.org>
Mon, 11 Jul 2005 16:11:28 +0000 (16:11 +0000)
* config/bfin/bfin.md (define_attr "type"): Add "sync".
(define_insn_reservation "alu"): Likewise.
(csync, ssync): Now of type sync.
* config/bfin/bfin.h (TARGET_DEFAULT): Defaults to
-mcsync-anomaly -mspecld-anomaly.
* config/bfin/bfin.opt (mcsync): Remove.
(mcsync-anomaly, mspecld-anomaly): Add.
* config/bfin/bfin.c: Include "insn-codes.h".
(bfin_reorg): Extend to handle the CSYNC anomaly as well.
(TARGET_DEFAULT_TARGET_FLAGS): New.
* doc/invoke.texi: Document -mcsync-anomaly, -mspecld-anomaly.

From-SVN: r101880

gcc/ChangeLog
gcc/config/bfin/bfin.c
gcc/config/bfin/bfin.h
gcc/config/bfin/bfin.md
gcc/config/bfin/bfin.opt
gcc/doc/invoke.texi

index 7199ddd7012c6b8468838c7b77574aaa50fc6d62..b5147ab56ba8742a4153cd1c285c95968ee4703e 100644 (file)
@@ -1,3 +1,17 @@
+2005-07-11  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 (TARGET_DEFAULT): Defaults to
+       -mcsync-anomaly -mspecld-anomaly.
+       * config/bfin/bfin.opt (mcsync): Remove.
+       (mcsync-anomaly, mspecld-anomaly): Add.
+       * config/bfin/bfin.c: Include "insn-codes.h".
+       (bfin_reorg): Extend to handle the CSYNC anomaly as well.
+       (TARGET_DEFAULT_TARGET_FLAGS): New.
+       * doc/invoke.texi: Document -mcsync-anomaly, -mspecld-anomaly.
+
 2005-07-11  Steven Bosscher  <stevenb@suse.de>
 
        * basic-block.h: Give the BB flags enum a name, bb_flags.
index 1b43e1fbae71bdfd4c31eb6c1e3244a226c518e2..5be76bbec5a03c50e63c48376be3ad5f0c9fb71e 100644 (file)
@@ -28,6 +28,7 @@
 #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"
@@ -2470,9 +2471,11 @@ bfin_reorg (void)
   rtx insn, last_condjump = NULL_RTX;
   int cycles_since_jump = INT_MAX;
 
-  if (! TARGET_CSYNC)
+  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;
@@ -2500,30 +2503,110 @@ bfin_reorg (void)
       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 && cycles_since_jump < 3)
+         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;
 
-             pat = single_set (insn);
-             if (may_trap_p (SET_SRC (pat)))
+             delay_needed -= cycles_since_jump;
+
+             extract_insn (last_condjump);
+             if (optimize_size)
                {
-                 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);
+                 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;
+                   }
+               }
            }
        }
     }
@@ -2792,4 +2875,7 @@ bfin_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
 #undef TARGET_HANDLE_OPTION
 #define TARGET_HANDLE_OPTION bfin_handle_option
 
+#undef TARGET_DEFAULT_TARGET_FLAGS
+#define TARGET_DEFAULT_TARGET_FLAGS TARGET_DEFAULT
+
 struct gcc_target targetm = TARGET_INITIALIZER;
index 830222d509e6a2827c24cac884cce0903dc85413..7ced865f997c45fa31da957cbea46617d5646c03 100644 (file)
@@ -48,7 +48,7 @@ extern int target_flags;
 /* Generate DSP instructions, like DSP halfword loads */
 #define TARGET_DSP                     (1)
 
-#define TARGET_DEFAULT MASK_CSYNC
+#define TARGET_DEFAULT (MASK_SPECLD_ANOMALY | MASK_CSYNC_ANOMALY)
 
 /* Maximum number of library ids we permit */
 #define MAX_LIBRARY_ID 255
index 76d6e13d89a2a8524020ac49243cc7c5f6e02963..be430c8c6bab6d9d4b4549b08dbf71871f9ad827 100644 (file)
    (UNSPEC_VOLATILE_SSYNC 2)])
 
 (define_attr "type"
-  "move,mvi,mcld,mcst,dsp32,mult,alu0,shft,brcc,br,call,misc,compare,dummy"
+  "move,mvi,mcld,mcst,dsp32,mult,alu0,shft,brcc,br,call,misc,sync,compare,dummy"
   (const_string "misc"))
 
 ;; Scheduling definitions
 (define_cpu_unit "core" "bfin")
 
 (define_insn_reservation "alu" 1
-  (eq_attr "type" "move,mvi,mcst,dsp32,alu0,shft,brcc,br,call,misc,compare")
+  (eq_attr "type" "move,mvi,mcst,dsp32,alu0,shft,brcc,br,call,misc,sync,compare")
   "core")
 
 (define_insn_reservation "imul" 3
   [(unspec_volatile [(const_int 0)] UNSPEC_VOLATILE_CSYNC)]
   ""
   "csync;"
-  [(set_attr "type" "misc")])
+  [(set_attr "type" "sync")])
 
 (define_insn "ssync"
   [(unspec_volatile [(const_int 0)] UNSPEC_VOLATILE_SSYNC)]
   ""
   "ssync;"
-  [(set_attr "type" "misc")])
+  [(set_attr "type" "sync")])
 
 ;;; Vector instructions
 
index da5fd59d08fe041d7046cf7ddc043d56c44e4210..43f56c4d6241dcfd8a2c386c65b0c1ab0bdb5b87 100644 (file)
@@ -27,9 +27,14 @@ mlow64k
 Target Report Mask(LOW_64K)
 Program is entirely located in low 64k of memory
 
-mcsync
-Target Report Mask(CSYNC)
-Avoid speculative loads by inserting CSYNC or equivalent
+mcsync-anomaly
+Target Report Mask(CSYNC_ANOMALY)
+Work around a hardware anomaly by adding a number of NOPs before a
+CSYNC or SSYNC instruction.
+
+mspecld-anomaly
+Target Report Mask(SPECLD_ANOMALY)
+Avoid speculative loads to work around a hardware anomaly.
 
 mid-shared-library
 Target Report Mask(ID_SHARED_LIBRARY)
index fb9c64d84d00c95ff1ea87d8e5e13c7798242da3..8fa98600472dbd98e7642c695bd441c28dd7ad65 100644 (file)
@@ -414,8 +414,9 @@ Objective-C and Objective-C++ Dialects}.
 -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
+@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} @gol
 -mlong-calls  -mno-long-calls}
 
@@ -7403,16 +7404,27 @@ makes an extra register available in leaf functions.  The option
 @option{-fomit-frame-pointer} removes the frame pointer for all functions
 which might make debugging harder.
 
-@item -mcsync
-@opindex mcsync
+@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-csync
-@opindex mno-csync
+@item -mno-specld-anomaly
+@opindex mno-specld-anomaly
 Don't generate extra code to prevent speculative loads from occurring.
 
+@item -mcsync-anomaly
+@opindex mspecld-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-specld-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