OSDN Git Service

* config/sparc/sparc.c: Include tree-pass.h.
authorsteven <steven@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 10 Apr 2013 21:03:44 +0000 (21:03 +0000)
committersteven <steven@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 10 Apr 2013 21:03:44 +0000 (21:03 +0000)
(TARGET_MACHINE_DEPENDENT_REORG): Do not redefine.
(sparc_reorg): Rename to sparc_do_work_around_errata.  Move to
head of file.  Change return type.  Split off gate function.
(sparc_gate_work_around_errata): New function.
(pass_work_around_errata): New pass definition.
(insert_pass_work_around_errata) New pass insert definition to
insert pass_work_around_errata just after delayed-branch scheduling.
(sparc_option_override): Insert the pass.
* config/sparc/t-sparc (sparc.o): Add TREE_PASS_H dependence.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@197681 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/sparc/sparc.c
gcc/config/sparc/t-sparc

index a47947f..927a9c0 100644 (file)
@@ -1,3 +1,16 @@
+2013-04-10  Steven Bosscher  <steven@gcc.gnu.org>
+
+       * config/sparc/sparc.c: Include tree-pass.h.
+       (TARGET_MACHINE_DEPENDENT_REORG): Do not redefine.
+       (sparc_reorg): Rename to sparc_do_work_around_errata.  Move to
+       head of file.  Change return type.  Split off gate function.
+       (sparc_gate_work_around_errata): New function.
+       (pass_work_around_errata): New pass definition.
+       (insert_pass_work_around_errata) New pass insert definition to
+       insert pass_work_around_errata just after delayed-branch scheduling.
+       (sparc_option_override): Insert the pass.
+       * config/sparc/t-sparc (sparc.o): Add TREE_PASS_H dependence.
+
 2013-04-10  David S. Miller  <davem@davemloft.net>
 
        * config/sparc/sparc.h (ASM_CPU_SPEC): Pass -Av8 if -mcpu=supersparc
index 4a73c73..56b95fe 100644 (file)
@@ -52,6 +52,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "params.h"
 #include "df.h"
 #include "opts.h"
+#include "tree-pass.h"
 
 /* Processor costs */
 
@@ -538,7 +539,6 @@ static void sparc_output_mi_thunk (FILE *, tree, HOST_WIDE_INT,
                                   HOST_WIDE_INT, tree);
 static bool sparc_can_output_mi_thunk (const_tree, HOST_WIDE_INT,
                                       HOST_WIDE_INT, const_tree);
-static void sparc_reorg (void);
 static struct machine_function * sparc_init_machine_status (void);
 static bool sparc_cannot_force_const_mem (enum machine_mode, rtx);
 static rtx sparc_tls_get_addr (void);
@@ -681,9 +681,6 @@ char sparc_hard_reg_printed[8];
 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK sparc_can_output_mi_thunk
 
-#undef TARGET_MACHINE_DEPENDENT_REORG
-#define TARGET_MACHINE_DEPENDENT_REORG sparc_reorg
-
 #undef TARGET_RTX_COSTS
 #define TARGET_RTX_COSTS sparc_rtx_costs
 #undef TARGET_ADDRESS_COST
@@ -808,6 +805,136 @@ char sparc_hard_reg_printed[8];
 
 struct gcc_target targetm = TARGET_INITIALIZER;
 
+/* We use a machine specific pass to enable workarounds for errata.
+   We need to have the (essentially) final form of the insn stream in order
+   to properly detect the various hazards.  Therefore, this machine specific
+   pass runs as late as possible.  The pass is inserted in the pass pipeline
+   at the end of sparc_options_override.  */
+
+static bool
+sparc_gate_work_around_errata (void)
+{
+  /* The only erratum we handle for now is that of the AT697F processor.  */
+  return sparc_fix_at697f != 0;
+}
+
+static unsigned int
+sparc_do_work_around_errata (void)
+{
+  rtx insn, next;
+
+  /* Now look for specific patterns in the insn stream.  */
+  for (insn = get_insns (); insn; insn = next)
+    {
+      bool insert_nop = false;
+      rtx set;
+
+      /* Look for a single-word load into an odd-numbered FP register.  */
+      if (NONJUMP_INSN_P (insn)
+         && (set = single_set (insn)) != NULL_RTX
+         && GET_MODE_SIZE (GET_MODE (SET_SRC (set))) == 4
+         && MEM_P (SET_SRC (set))
+         && REG_P (SET_DEST (set))
+         && REGNO (SET_DEST (set)) > 31
+         && REGNO (SET_DEST (set)) % 2 != 0)
+       {
+         /* The wrong dependency is on the enclosing double register.  */
+         unsigned int x = REGNO (SET_DEST (set)) - 1;
+         unsigned int src1, src2, dest;
+         int code;
+
+         /* If the insn has a delay slot, then it cannot be problematic.  */
+         next = next_active_insn (insn);
+         if (NONJUMP_INSN_P (next) && GET_CODE (PATTERN (next)) == SEQUENCE)
+           code = -1;
+         else
+           {
+             extract_insn (next);
+             code = INSN_CODE (next);
+           }
+
+         switch (code)
+           {
+           case CODE_FOR_adddf3:
+           case CODE_FOR_subdf3:
+           case CODE_FOR_muldf3:
+           case CODE_FOR_divdf3:
+             dest = REGNO (recog_data.operand[0]);
+             src1 = REGNO (recog_data.operand[1]);
+             src2 = REGNO (recog_data.operand[2]);
+             if (src1 != src2)
+               {
+                 /* Case [1-4]:
+                                ld [address], %fx+1
+                                FPOPd %f{x,y}, %f{y,x}, %f{x,y}  */
+                 if ((src1 == x || src2 == x)
+                     && (dest == src1 || dest == src2))
+                   insert_nop = true;
+               }
+             else
+               {
+                 /* Case 5:
+                            ld [address], %fx+1
+                            FPOPd %fx, %fx, %fx  */
+                 if (src1 == x
+                     && dest == src1
+                     && (code == CODE_FOR_adddf3 || code == CODE_FOR_muldf3))
+                   insert_nop = true;
+               }
+             break;
+
+           case CODE_FOR_sqrtdf2:
+             dest = REGNO (recog_data.operand[0]);
+             src1 = REGNO (recog_data.operand[1]);
+             /* Case 6:
+                        ld [address], %fx+1
+                        fsqrtd %fx, %fx  */
+             if (src1 == x && dest == src1)
+               insert_nop = true;
+             break;
+
+           default:
+             break;
+           }
+       }
+      else
+       next = NEXT_INSN (insn);
+
+      if (insert_nop)
+       emit_insn_after (gen_nop (), insn);
+    }
+  return 0;
+}
+
+struct rtl_opt_pass pass_work_around_errata =
+{
+ {
+  RTL_PASS,
+  "errata",                            /* name */
+  OPTGROUP_NONE,                       /* optinfo_flags */
+  sparc_gate_work_around_errata,       /* gate */
+  sparc_do_work_around_errata,         /* execute */
+  NULL,                                        /* sub */
+  NULL,                                        /* next */
+  0,                                   /* static_pass_number */
+  TV_MACH_DEP,                         /* tv_id */
+  0,                                   /* properties_required */
+  0,                                   /* properties_provided */
+  0,                                   /* properties_destroyed */
+  0,                                   /* todo_flags_start */
+  TODO_verify_rtl_sharing,             /* todo_flags_finish */
+ }
+};
+
+struct register_pass_info insert_pass_work_around_errata =
+{
+  &pass_work_around_errata.pass,       /* pass */
+  "dbr",                               /* reference_pass_name */
+  1,                                   /* ref_pass_instance_number */
+  PASS_POS_INSERT_AFTER                        /* po_op */
+};
+
+/* Helpers for TARGET_DEBUG_OPTIONS.  */
 static void
 dump_target_flag_bits (const int flags)
 {
@@ -1245,6 +1372,13 @@ sparc_option_override (void)
      pessimizes for double floating-point registers.  */
   if (!global_options_set.x_flag_ira_share_save_slots)
     flag_ira_share_save_slots = 0;
+
+  /* We register a machine specific pass to work around errata, if any.
+     The pass mut be scheduled as late as possible so that we have the
+     (essentially) final form of the insn stream to work on.
+     Registering the pass must be done at start up.  It's convenient to
+     do it here.  */
+  register_pass (&insert_pass_work_around_errata);
 }
 \f
 /* Miscellaneous utilities.  */
@@ -10906,107 +11040,6 @@ sparc_can_output_mi_thunk (const_tree thunk_fndecl ATTRIBUTE_UNUSED,
   return (vcall_offset >= -32768 || ! fixed_regs[5]);
 }
 
-/* We use the machine specific reorg pass to enable workarounds for errata.  */
-
-static void
-sparc_reorg (void)
-{
-  rtx insn, next;
-
-  /* The only erratum we handle for now is that of the AT697F processor.  */
-  if (!sparc_fix_at697f)
-    return;
-
-  /* We need to have the (essentially) final form of the insn stream in order
-     to properly detect the various hazards.  Run delay slot scheduling.  */
-  if (optimize > 0 && flag_delayed_branch)
-    {
-      cleanup_barriers ();
-      dbr_schedule (get_insns ());
-    }
-
-  /* Now look for specific patterns in the insn stream.  */
-  for (insn = get_insns (); insn; insn = next)
-    {
-      bool insert_nop = false;
-      rtx set;
-
-      /* Look for a single-word load into an odd-numbered FP register.  */
-      if (NONJUMP_INSN_P (insn)
-         && (set = single_set (insn)) != NULL_RTX
-         && GET_MODE_SIZE (GET_MODE (SET_SRC (set))) == 4
-         && MEM_P (SET_SRC (set))
-         && REG_P (SET_DEST (set))
-         && REGNO (SET_DEST (set)) > 31
-         && REGNO (SET_DEST (set)) % 2 != 0)
-       {
-         /* The wrong dependency is on the enclosing double register.  */
-         unsigned int x = REGNO (SET_DEST (set)) - 1;
-         unsigned int src1, src2, dest;
-         int code;
-
-         /* If the insn has a delay slot, then it cannot be problematic.  */
-         next = next_active_insn (insn);
-         if (NONJUMP_INSN_P (next) && GET_CODE (PATTERN (next)) == SEQUENCE)
-           code = -1;
-         else
-           {
-             extract_insn (next);
-             code = INSN_CODE (next);
-           }
-
-         switch (code)
-           {
-           case CODE_FOR_adddf3:
-           case CODE_FOR_subdf3:
-           case CODE_FOR_muldf3:
-           case CODE_FOR_divdf3:
-             dest = REGNO (recog_data.operand[0]);
-             src1 = REGNO (recog_data.operand[1]);
-             src2 = REGNO (recog_data.operand[2]);
-             if (src1 != src2)
-               {
-                 /* Case [1-4]:
-                                ld [address], %fx+1
-                                FPOPd %f{x,y}, %f{y,x}, %f{x,y}  */
-                 if ((src1 == x || src2 == x)
-                     && (dest == src1 || dest == src2))
-                   insert_nop = true;
-               }
-             else
-               {
-                 /* Case 5:
-                            ld [address], %fx+1
-                            FPOPd %fx, %fx, %fx  */
-                 if (src1 == x
-                     && dest == src1
-                     && (code == CODE_FOR_adddf3 || code == CODE_FOR_muldf3))
-                   insert_nop = true;
-               }
-             break;
-
-           case CODE_FOR_sqrtdf2:
-             dest = REGNO (recog_data.operand[0]);
-             src1 = REGNO (recog_data.operand[1]);
-             /* Case 6:
-                        ld [address], %fx+1
-                        fsqrtd %fx, %fx  */
-             if (src1 == x && dest == src1)
-               insert_nop = true;
-             break;
-
-           default:
-             break;
-           }
-       }
-      else
-       next = NEXT_INSN (insn);
-
-      if (insert_nop)
-       emit_insn_after (gen_nop (), insn);
-    }
-}
-
 /* How to allocate a 'struct machine_function'.  */
 
 static struct machine_function *
index d7b17fb..664f4a4 100644 (file)
@@ -23,7 +23,7 @@ sparc.o: $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
   insn-codes.h conditions.h output.h $(INSN_ATTR_H) $(FLAGS_H) \
   $(FUNCTION_H) $(EXCEPT_H) $(EXPR_H) $(OPTABS_H) $(RECOG_H) \
   $(DIAGNOSTIC_CORE_H) $(GGC_H) $(TM_P_H) debug.h $(TARGET_H) \
-  $(TARGET_DEF_H) $(COMMON_TARGET_H) $(GIMPLE_H) \
+  $(TARGET_DEF_H) $(COMMON_TARGET_H) $(GIMPLE_H) $(TREE_PASS_H) \
   langhooks.h reload.h $(PARAMS_H) $(DF_H) $(OPTS_H) \
   gt-sparc.h