OSDN Git Service

SMS: Support instructions with REG_INC_NOTE
authorrevitale <revitale@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 30 Sep 2011 13:25:30 +0000 (13:25 +0000)
committerrevitale <revitale@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 30 Sep 2011 13:25:30 +0000 (13:25 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@179381 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/ddg.c
gcc/ddg.h
gcc/modulo-sched.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/sms-10.c [new file with mode: 0644]

index b0756d0..bbf1897 100644 (file)
@@ -1,5 +1,14 @@
 2011-09-30  Revital Eres  <revital.eres@linaro.org>
 
+       * ddg.c (autoinc_var_is_used_p): New function.
+       (create_ddg_dep_from_intra_loop_link,
+       add_cross_iteration_register_deps): Call it.
+       * ddg.h (autoinc_var_is_used_p): Declare.
+       * modulo-sched.c (generate_reg_moves): Call autoinc_var_is_used_p.
+       (sms_schedule): Handle instructions with REG_INC.
+
+2011-09-30  Revital Eres  <revital.eres@linaro.org>
+
        * modulo-sched.c (generate_reg_moves): Skip instructions that
        do not set a register and verify no regmoves are created for
        !single_set instructions.
index 856fa4e..2b1cfe8 100644 (file)
--- a/gcc/ddg.c
+++ b/gcc/ddg.c
@@ -145,6 +145,27 @@ mem_access_insn_p (rtx insn)
   return rtx_mem_access_p (PATTERN (insn));
 }
 
+/* Return true if DEF_INSN contains address being auto-inc or auto-dec
+   which is used in USE_INSN.  Otherwise return false.  The result is
+   being used to decide whether to remove the edge between def_insn and
+   use_insn when -fmodulo-sched-allow-regmoves is set.  This function
+   doesn't need to consider the specific address register; no reg_moves
+   will be allowed for any life range defined by def_insn and used
+   by use_insn, if use_insn uses an address register auto-inc'ed by
+   def_insn.  */
+bool
+autoinc_var_is_used_p (rtx def_insn, rtx use_insn)
+{
+  rtx note;
+
+  for (note = REG_NOTES (def_insn); note; note = XEXP (note, 1))
+    if (REG_NOTE_KIND (note) == REG_INC
+       && reg_referenced_p (XEXP (note, 0), PATTERN (use_insn)))
+      return true;
+
+  return false;
+}
+
 /* Computes the dependence parameters (latency, distance etc.), creates
    a ddg_edge and adds it to the given DDG.  */
 static void
@@ -173,10 +194,15 @@ create_ddg_dep_from_intra_loop_link (ddg_ptr g, ddg_node_ptr src_node,
      compensate for that by generating reg-moves based on the life-range
      analysis.  The anti-deps that will be deleted are the ones which
      have true-deps edges in the opposite direction (in other words
-     the kernel has only one def of the relevant register).  TODO:
-     support the removal of all anti-deps edges, i.e. including those
+     the kernel has only one def of the relevant register).
+     If the address that is being auto-inc or auto-dec in DEST_NODE
+     is used in SRC_NODE then do not remove the edge to make sure
+     reg-moves will not be created for this address.  
+     TODO: support the removal of all anti-deps edges, i.e. including those
      whose register has multiple defs in the loop.  */
-  if (flag_modulo_sched_allow_regmoves && (t == ANTI_DEP && dt == REG_DEP))
+  if (flag_modulo_sched_allow_regmoves 
+      && (t == ANTI_DEP && dt == REG_DEP)
+      && !autoinc_var_is_used_p (dest_node->insn, src_node->insn))
     {
       rtx set;
 
@@ -302,10 +328,14 @@ add_cross_iteration_register_deps (ddg_ptr g, df_ref last_def)
          gcc_assert (first_def_node);
 
          /* Always create the edge if the use node is a branch in
-            order to prevent the creation of reg-moves.  */
+            order to prevent the creation of reg-moves.  
+            If the address that is being auto-inc or auto-dec in LAST_DEF
+            is used in USE_INSN then do not remove the edge to make sure
+            reg-moves will not be created for that address.  */
           if (DF_REF_ID (last_def) != DF_REF_ID (first_def)
               || !flag_modulo_sched_allow_regmoves
-             || JUMP_P (use_node->insn))
+             || JUMP_P (use_node->insn)
+              || autoinc_var_is_used_p (DF_REF_INSN (last_def), use_insn))
             create_ddg_dep_no_link (g, use_node, first_def_node, ANTI_DEP,
                                     REG_DEP, 1);
 
index e17e534..8452a36 100644 (file)
--- a/gcc/ddg.h
+++ b/gcc/ddg.h
@@ -186,4 +186,6 @@ void free_ddg_all_sccs (ddg_all_sccs_ptr);
 int find_nodes_on_paths (sbitmap result, ddg_ptr, sbitmap from, sbitmap to);
 int longest_simple_path (ddg_ptr, int from, int to, sbitmap via);
 
+bool autoinc_var_is_used_p (rtx, rtx);
+
 #endif /* GCC_DDG_H */
index 7c33be5..57186ec 100644 (file)
@@ -506,6 +506,10 @@ generate_reg_moves (partial_schedule_ptr ps, bool rescan)
                   we assume no regmoves are generated as the doloop
                   instructions are tied to the branch with an edge.  */
                gcc_assert (set);
+               /* If the instruction contains auto-inc register then
+                  validate that the regmov is being generated for the
+                  target regsiter rather then the inc'ed register.     */
+               gcc_assert (!autoinc_var_is_used_p (u->insn, e->dest->insn));
              }
            
            nreg_moves = MAX (nreg_moves, nreg_moves4e);
@@ -1281,12 +1285,10 @@ sms_schedule (void)
        continue;
       }
 
-      /* Don't handle BBs with calls or barriers or auto-increment insns 
-        (to avoid creating invalid reg-moves for the auto-increment insns),
+      /* Don't handle BBs with calls or barriers
         or !single_set with the exception of instructions that include
         count_reg---these instructions are part of the control part
         that do-loop recognizes.
-         ??? Should handle auto-increment insns.
          ??? Should handle insns defining subregs.  */
      for (insn = head; insn != NEXT_INSN (tail); insn = NEXT_INSN (insn))
       {
@@ -1297,7 +1299,6 @@ sms_schedule (void)
             || (NONDEBUG_INSN_P (insn) && !JUMP_P (insn)
                 && !single_set (insn) && GET_CODE (PATTERN (insn)) != USE
                 && !reg_mentioned_p (count_reg, insn))
-            || (FIND_REG_INC_NOTE (insn, NULL_RTX) != 0)
             || (INSN_P (insn) && (set = single_set (insn))
                 && GET_CODE (SET_DEST (set)) == SUBREG))
         break;
@@ -1311,8 +1312,6 @@ sms_schedule (void)
                fprintf (dump_file, "SMS loop-with-call\n");
              else if (BARRIER_P (insn))
                fprintf (dump_file, "SMS loop-with-barrier\n");
-              else if (FIND_REG_INC_NOTE (insn, NULL_RTX) != 0)
-                fprintf (dump_file, "SMS reg inc\n");
               else if ((NONDEBUG_INSN_P (insn) && !JUMP_P (insn)
                 && !single_set (insn) && GET_CODE (PATTERN (insn)) != USE))
                 fprintf (dump_file, "SMS loop-with-not-single-set\n");
index 1ad0777..0b1e69f 100644 (file)
@@ -1,3 +1,7 @@
+2011-09-30  Revital Eres  <revital.eres@linaro.org>
+
+       * gcc.dg/sms-10.c: New file
+
 2011-09-30  Ramana Radhakrishnan  <ramana.radhakrishnan@linaro.org>
 
        * gcc.target/arm/pr50099.c: New test.
diff --git a/gcc/testsuite/gcc.dg/sms-10.c b/gcc/testsuite/gcc.dg/sms-10.c
new file mode 100644 (file)
index 0000000..c1de07f
--- /dev/null
@@ -0,0 +1,119 @@
+ /* { dg-do run } */
+ /* { dg-options "-O2 -fmodulo-sched -fmodulo-sched-allow-regmoves -fdump-rtl-sms" } */
+
+
+typedef __SIZE_TYPE__ size_t;
+extern void *malloc (size_t);
+extern void free (void *);
+extern void abort (void);
+
+struct regstat_n_sets_and_refs_t
+{
+  int sets;
+  int refs;
+};
+
+struct regstat_n_sets_and_refs_t *regstat_n_sets_and_refs;
+
+struct df_reg_info
+{
+  unsigned int n_refs;
+};
+
+struct df_d
+{
+  struct df_reg_info **def_regs;
+  struct df_reg_info **use_regs;
+};
+struct df_d *df;
+
+static inline int
+REG_N_SETS (int regno)
+{
+  return regstat_n_sets_and_refs[regno].sets;
+}
+
+__attribute__ ((noinline))
+     int max_reg_num (void)
+{
+  return 100;
+}
+
+__attribute__ ((noinline))
+     void regstat_init_n_sets_and_refs (void)
+{
+  unsigned int i;
+  unsigned int max_regno = max_reg_num ();
+
+  for (i = 0; i < max_regno; i++)
+    {
+      (regstat_n_sets_and_refs[i].sets = (df->def_regs[(i)]->n_refs));
+      (regstat_n_sets_and_refs[i].refs =
+       (df->use_regs[(i)]->n_refs) + REG_N_SETS (i));
+    }
+}
+
+int a_sets[100] =
+  { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+  21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+  40, 41, 42,
+  43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+  62, 63, 64,
+  65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
+  84, 85, 86,
+  87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99
+};
+
+int a_refs[100] =
+  { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38,
+  40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76,
+  78, 80, 82,
+  84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116,
+  118, 120,
+  122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150,
+  152, 154, 156,
+  158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, 184, 186,
+  188, 190, 192,
+  194, 196, 198
+};
+
+int
+main ()
+{
+  struct df_reg_info *b[100], *c[100];
+  struct df_d df1;
+  size_t s = sizeof (struct df_reg_info);
+  struct regstat_n_sets_and_refs_t a[100];
+
+  df = &df1;
+  regstat_n_sets_and_refs = a;
+  int i;
+
+  for (i = 0; i < 100; i++)
+    {
+      b[i] = (struct df_reg_info *) malloc (s);
+      b[i]->n_refs = i;
+      c[i] = (struct df_reg_info *) malloc (s);
+      c[i]->n_refs = i;
+    }
+
+  df1.def_regs = b;
+  df1.use_regs = c;
+  regstat_init_n_sets_and_refs ();
+
+  for (i = 0; i < 100; i++)
+    if ((a[i].sets != a_sets[i]) || (a[i].refs != a_refs[i]))
+      abort ();
+
+  for (i = 0; i < 100; i++)
+    {
+      free (b[i]);
+      free (c[i]);
+    }
+
+  return 0;
+}
+
+/* { dg-final { scan-rtl-dump-times "SMS succeeded" 1 "sms" { target powerpc*-*-* } } } */
+/* { dg-final { cleanup-rtl-dump "sms" } } */
+