Fix PR middle-end/20177 and add test case.
authorhagog <hagog@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 21 Mar 2005 18:49:29 +0000 (18:49 +0000)
committerhagog <hagog@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 21 Mar 2005 18:49:29 +0000 (18:49 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@96828 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/ddg.c
gcc/modulo-sched.c
gcc/passes.c
gcc/testsuite/gcc.dg/20050321-1.c [new file with mode: 0644]

index 241c544..b87be58 100644 (file)
@@ -1,3 +1,17 @@
+2005-03-21 Mostafa Hagog <mustafa@il.ibm.com>
+
+       PR middle-end/20177
+       * ddg.c (create_ddg_dependence): Ignore reg-anti dependency.
+       * modulo-sched.c (const_iteration_count): Return on NULL
+       pre-header.
+       (print_node_sched_params): Return on NULL dump_file.
+       (generate_reg_moves): Handle reg-anti dependencies and disregard
+       closing branch when generating register moves.
+       (sms_schedule): Mark the SMSed block dirty.
+       * passes.c (rest_of_handle_sms): Call update_life_info for all
+       basic-blocks.
+       * testsuite/gcc.dg/20050321-1.c: New test.
+
 2005-03-21  Bob Wilson  <bob.wilson@acm.org>
 
        * config/xtensa/lib1funcs.asm (__mulsi3): Use symbolic name for ACCLO.
index a54a87c..5a2cbee 100644 (file)
--- a/gcc/ddg.c
+++ b/gcc/ddg.c
@@ -187,6 +187,8 @@ create_ddg_dependence (ddg_ptr g, ddg_node_ptr src_node,
       else
        free (e);
     }
+  else if (t == ANTI_DEP && dt == REG_DEP)
+    free (e);  /* We can fix broken anti register deps using reg-moves.  */
   else
     add_edge_to_ddg (g, e);
 }
index 5671727..8677316 100644 (file)
@@ -337,6 +337,10 @@ const_iteration_count (rtx count_reg, basic_block pre_header,
 {
   rtx insn;
   rtx head, tail;
+
+  if (! pre_header)
+    return NULL_RTX;
+
   get_block_head_tail (pre_header->index, &head, &tail);
 
   for (insn = tail; insn != PREV_INSN (head); insn = PREV_INSN (insn))
@@ -399,6 +403,8 @@ print_node_sched_params (FILE * dump_file, int num_nodes)
 {
   int i;
 
+  if (! dump_file)
+    return;
   for (i = 0; i < num_nodes; i++)
     {
       node_sched_params_ptr nsp = &node_sched_params[i];
@@ -441,14 +447,17 @@ calculate_maxii (ddg_ptr g)
   return maxii;
 }
 
-
-/* Given the partial schedule, generate register moves when the length
-   of the register live range is more than ii; the number of moves is
-   determined according to the following equation:
-               SCHED_TIME (use) - SCHED_TIME (def)   { 1 broken loop-carried
-   nreg_moves = ----------------------------------- - {   dependence.
-                             ii                      { 0 if not.
-   This handles the modulo-variable-expansions (mve's) needed for the ps.  */
+/*
+   Breaking intra-loop register anti-dependences:
+   Each intra-loop register anti-dependence implies a cross-iteration true
+   dependence of distance 1. Therefore, we can remove such false dependencies
+   and figure out if the partial schedule broke them by checking if (for a
+   true-dependence of distance 1): SCHED_TIME (def) < SCHED_TIME (use) and
+   if so generate a register move.   The number of such moves is equal to:
+              SCHED_TIME (use) - SCHED_TIME (def)       { 0 broken
+   nreg_moves = ----------------------------------- + 1 - {   dependecnce.
+                            ii                          { 1 if not.
+*/
 static void
 generate_reg_moves (partial_schedule_ptr ps)
 {
@@ -472,6 +481,9 @@ generate_reg_moves (partial_schedule_ptr ps)
          {
            int nreg_moves4e = (SCHED_TIME (e->dest) - SCHED_TIME (e->src)) / ii;
 
+            if (e->distance == 1)
+              nreg_moves4e = (SCHED_TIME (e->dest) - SCHED_TIME (e->src) + ii) / ii;
+
            /* If dest precedes src in the schedule of the kernel, then dest
               will read before src writes and we can save one reg_copy.  */
            if (SCHED_ROW (e->dest) == SCHED_ROW (e->src)
@@ -495,6 +507,9 @@ generate_reg_moves (partial_schedule_ptr ps)
          {
            int dest_copy = (SCHED_TIME (e->dest) - SCHED_TIME (e->src)) / ii;
 
+           if (e->distance == 1)
+             dest_copy = (SCHED_TIME (e->dest) - SCHED_TIME (e->src) + ii) / ii;
+
            if (SCHED_ROW (e->dest) == SCHED_ROW (e->src)
                && SCHED_COLUMN (e->dest) < SCHED_COLUMN (e->src))
              dest_copy--;
@@ -538,7 +553,8 @@ normalize_sched_times (partial_schedule_ptr ps)
   int amount = PS_MIN_CYCLE (ps);
   int ii = ps->ii;
 
-  for (i = 0; i < g->num_nodes; i++)
+  /* Don't include the closing branch assuming that it is the last node.  */
+  for (i = 0; i < g->num_nodes - 1; i++)
     {
       ddg_node_ptr u = &g->nodes[i];
       int normalized_time = SCHED_TIME (u) - amount;
@@ -607,7 +623,7 @@ duplicate_insns_of_cycles (partial_schedule_ptr ps, int from_stage,
            /* SCHED_STAGE (u_node) >= from_stage == 0.  Generate increasing
               number of reg_moves starting with the second occurrence of
               u_node, which is generated if its SCHED_STAGE <= to_stage.  */
-           i_reg_moves = to_stage - SCHED_STAGE (u_node);
+           i_reg_moves = to_stage - SCHED_STAGE (u_node) + 1;
            i_reg_moves = MAX (i_reg_moves, 0);
            i_reg_moves = MIN (i_reg_moves, SCHED_NREG_MOVES (u_node));
 
@@ -1107,6 +1123,8 @@ sms_schedule (FILE *dump_file)
             scheduling passes doesn't touch it.  */
          if (! flag_resched_modulo_sched)
            g->bb->flags |= BB_DISABLE_SCHEDULE;
+         /* The life-info is not valid any more.  */
+         g->bb->flags |= BB_DIRTY;
 
          generate_reg_moves (ps);
          if (dump_file)
index 7bb661d..1121d0c 100644 (file)
@@ -575,6 +575,8 @@ rest_of_handle_partition_blocks (void)
 static void
 rest_of_handle_sms (void)
 {
+  sbitmap blocks;
+
   timevar_push (TV_SMS);
   open_dump_file (DFI_sms, current_function_decl);
 
@@ -587,10 +589,14 @@ rest_of_handle_sms (void)
   /* Update the life information, because we add pseudos.  */
   max_regno = max_reg_num ();
   allocate_reg_info (max_regno, FALSE, FALSE);
-  update_life_info_in_dirty_blocks (UPDATE_LIFE_GLOBAL_RM_NOTES,
-                                   (PROP_DEATH_NOTES
-                                    | PROP_KILL_DEAD_CODE
-                                    | PROP_SCAN_DEAD_CODE));
+  blocks = sbitmap_alloc (last_basic_block);
+  sbitmap_ones (blocks);
+  update_life_info (blocks, UPDATE_LIFE_GLOBAL_RM_NOTES,
+                   (PROP_DEATH_NOTES
+                    | PROP_REG_INFO
+                    | PROP_KILL_DEAD_CODE
+                    | PROP_SCAN_DEAD_CODE));
+
   no_new_pseudos = 1;
 
   ggc_collect ();
diff --git a/gcc/testsuite/gcc.dg/20050321-1.c b/gcc/testsuite/gcc.dg/20050321-1.c
new file mode 100644 (file)
index 0000000..01c68cd
--- /dev/null
@@ -0,0 +1,26 @@
+/* This caused an ICE on powerpc-linux-gnu due to not 
+   up-to-date life info (PR middle-end/20177).  */
+
+/* { dg-do compile } */
+/* { dg-options "-O2 -fmodulo-sched" } */
+extern void * malloc (long);
+
+struct s {
+    int k;
+};
+
+int n;
+struct s *a1, *(*use)[];
+float (*vector)[];
+
+void
+foo (float *V)
+{
+  int i, used = 0;
+
+  vector = malloc (i * sizeof (float));
+  while ((*use)[used] != a1)
+    used += 1;
+  for (i = 0; i < n; i++)
+    *V += (*vector)[i];
+}