re PR tree-optimization/90240 (ICE in try_improve_iv_set, at tree-ssa-loop-ivopts...
authorBin Cheng <bin.cheng@linux.alibaba.com>
Wed, 8 May 2019 11:24:38 +0000 (11:24 +0000)
committerBin Cheng <amker@gcc.gnu.org>
Wed, 8 May 2019 11:24:38 +0000 (11:24 +0000)
PR tree-optimization/90240
* tree-ssa-loop-ivopts.c (get_scaled_computation_cost_at): Scale cost
with respect to scaling factor pre-computed for each basic block.
(try_improve_iv_set): Return bool if best_cost equals to iv_ca cost.
(find_optimal_iv_set_1): Free iv_ca set if it has infinite_cost.
(COST_SCALING_FACTOR_BOUND, determine_scaling_factor): New.
(tree_ssa_iv_optimize_loop): Call determine_scaling_factor.  Extend
live range for array of loop's basic blocks.  Cleanup aux field of
loop's basic blocks.

gcc/testsuite
* gfortran.dg/graphite/pr90240.f: New test.

From-SVN: r271007

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gfortran.dg/graphite/pr90240.f [new file with mode: 0644]
gcc/tree-ssa-loop-ivopts.c

index e37aafc4d2a5fb7a8b9a374f59d6e12b5573d93f..be91d031277a5340e8249d1ee9e8c4291aba80aa 100644 (file)
@@ -1,3 +1,15 @@
+2019-05-08  Bin Cheng  <bin.cheng@linux.alibaba.com>
+
+       PR tree-optimization/90240
+       * tree-ssa-loop-ivopts.c (get_scaled_computation_cost_at): Scale cost
+       with respect to scaling factor pre-computed for each basic block.
+       (try_improve_iv_set): Return bool if best_cost equals to iv_ca cost.
+       (find_optimal_iv_set_1): Free iv_ca set if it has infinite_cost.
+       (COST_SCALING_FACTOR_BOUND, determine_scaling_factor): New.
+       (tree_ssa_iv_optimize_loop): Call determine_scaling_factor.  Extend
+       live range for array of loop's basic blocks.  Cleanup aux field of
+       loop's basic blocks.
+
 2019-05-08  Jakub Jelinek  <jakub@redhat.com>
 
        PR tree-optimization/90356
index d50e4e040ee422a141bc56e4cbbbdc29972f2f27..897a46a2cb3a9927565a13f00ca3f59af3595b0d 100644 (file)
@@ -1,3 +1,8 @@
+2018-05-08  Bin Cheng  <bin.cheng@linux.alibaba.com>
+
+       PR tree-optimization/90240
+       * gfortran.dg/graphite/pr90240.f: New test.
+
 2019-05-08  Li Jia He  <helijia@linux.ibm.com>
 
        PR other/90381
diff --git a/gcc/testsuite/gfortran.dg/graphite/pr90240.f b/gcc/testsuite/gfortran.dg/graphite/pr90240.f
new file mode 100644 (file)
index 0000000..0873f21
--- /dev/null
@@ -0,0 +1,18 @@
+! { dg-do compile }
+! { dg-options "-O1 -floop-nest-optimize" }
+
+      PARAMETER (n=1335, N2=1335)
+      COMMON  a(n,N2), b(n,N2), c(n,N2),
+     *        d(n,N2),
+     2        e(n,N2), f(n,N2),
+     *        g(n,N2), h(n,N2)               
+      DO 200 j=1,i
+      DO 300 k=1,l
+      a(k,j) = c(k,j)*g(k,j)*f(k+1,m)+f(k,m)+f(k,j)
+     2       +f(k+1,j)*h(k+1,j)
+      b(k,j+1) = d(k,j+1)*g(k,m)+g(k,j+1)
+     1       *e(k,m)+e(k,j+1)+e(k,j)+e(k+1,j)
+     2       *h(k,j+1)-h(k,j)
+  300 ENDDO
+  200 ENDDO
+      END
index a2b6b2b2312497333ea1c5c3999c0734b627cd4c..534e14638077a582b63b03696e0be3828626b1dd 100644 (file)
@@ -4557,22 +4557,25 @@ get_address_cost (struct ivopts_data *data, struct iv_use *use,
 static comp_cost
 get_scaled_computation_cost_at (ivopts_data *data, gimple *at, comp_cost cost)
 {
-   int loop_freq = data->current_loop->header->count.to_frequency (cfun);
-   int bb_freq = gimple_bb (at)->count.to_frequency (cfun);
-   if (loop_freq != 0)
-     {
-       gcc_assert (cost.scratch <= cost.cost);
-       int scaled_cost
-        = cost.scratch + (cost.cost - cost.scratch) * bb_freq / loop_freq;
+  if (data->speed
+      && data->current_loop->header->count.to_frequency (cfun) > 0)
+    {
+      basic_block bb = gimple_bb (at);
+      gcc_assert (cost.scratch <= cost.cost);
+      int scale_factor = (int)(intptr_t) bb->aux;
+      if (scale_factor == 1)
+       return cost;
 
-       if (dump_file && (dump_flags & TDF_DETAILS))
-        fprintf (dump_file, "Scaling cost based on bb prob "
-                 "by %2.2f: %d (scratch: %d) -> %d (%d/%d)\n",
-                 1.0f * bb_freq / loop_freq, cost.cost,
-                 cost.scratch, scaled_cost, bb_freq, loop_freq);
+      int scaled_cost
+       = cost.scratch + (cost.cost - cost.scratch) * scale_factor;
 
-       cost.cost = scaled_cost;
-     }
+      if (dump_file && (dump_flags & TDF_DETAILS))
+       fprintf (dump_file, "Scaling cost based on bb prob "
+                "by %2.2f: %d (scratch: %d) -> %d\n",
+                1.0f * scale_factor, cost.cost, cost.scratch, scaled_cost);
+
+      cost.cost = scaled_cost;
+    }
 
   return cost;
 }
@@ -6678,9 +6681,8 @@ try_improve_iv_set (struct ivopts_data *data,
     }
 
   iv_ca_delta_commit (data, ivs, best_delta, true);
-  gcc_assert (best_cost == iv_ca_cost (ivs));
   iv_ca_delta_free (&best_delta);
-  return true;
+  return best_cost == iv_ca_cost (ivs);
 }
 
 /* Attempts to find the optimal set of induction variables.  We do simple
@@ -6717,6 +6719,14 @@ find_optimal_iv_set_1 (struct ivopts_data *data, bool originalp)
        }
     }
 
+  /* If the set has infinite_cost, it can't be optimal.  */
+  if (iv_ca_cost (set).infinite_cost_p ())
+    {
+      if (dump_file && (dump_flags & TDF_DETAILS))
+       fprintf (dump_file,
+                "Overflow to infinite cost in try_improve_iv_set.\n");
+      iv_ca_free (&set);
+    }
   return set;
 }
 
@@ -7522,6 +7532,49 @@ loop_body_includes_call (basic_block *body, unsigned num_nodes)
   return false;
 }
 
+/* Determine cost scaling factor for basic blocks in loop.  */
+#define COST_SCALING_FACTOR_BOUND (20)
+
+static void
+determine_scaling_factor (struct ivopts_data *data, basic_block *body)
+{
+  int lfreq = data->current_loop->header->count.to_frequency (cfun);
+  if (!data->speed || lfreq <= 0)
+    return;
+
+  int max_freq = lfreq;
+  for (unsigned i = 0; i < data->current_loop->num_nodes; i++)
+    {
+      body[i]->aux = (void *)(intptr_t) 1;
+      if (max_freq < body[i]->count.to_frequency (cfun))
+       max_freq = body[i]->count.to_frequency (cfun);
+    }
+  if (max_freq > lfreq)
+    {
+      int divisor, factor;
+      /* Check if scaling factor itself needs to be scaled by the bound.  This
+        is to avoid overflow when scaling cost according to profile info.  */
+      if (max_freq / lfreq > COST_SCALING_FACTOR_BOUND)
+       {
+         divisor = max_freq;
+         factor = COST_SCALING_FACTOR_BOUND;
+       }
+      else
+       {
+         divisor = lfreq;
+         factor = 1;
+       }
+      for (unsigned i = 0; i < data->current_loop->num_nodes; i++)
+       {
+         int bfreq = body[i]->count.to_frequency (cfun);
+         if (bfreq <= lfreq)
+           continue;
+
+         body[i]->aux = (void*)(intptr_t) (factor * bfreq / divisor);
+       }
+    }
+}
+
 /* Optimizes the LOOP.  Returns true if anything changed.  */
 
 static bool
@@ -7560,7 +7613,6 @@ tree_ssa_iv_optimize_loop (struct ivopts_data *data, struct loop *loop,
   body = get_loop_body (loop);
   data->body_includes_call = loop_body_includes_call (body, loop->num_nodes);
   renumber_gimple_stmt_uids_in_blocks (body, loop->num_nodes);
-  free (body);
 
   data->loop_single_exit_p = exit != NULL && loop_only_exit_p (loop, exit);
 
@@ -7574,6 +7626,9 @@ tree_ssa_iv_optimize_loop (struct ivopts_data *data, struct loop *loop,
   if (data->vgroups.length () > MAX_CONSIDERED_GROUPS)
     goto finish;
 
+  /* Determine cost scaling factor for basic blocks in loop.  */
+  determine_scaling_factor (data, body);
+
   /* Finds candidates for the induction variables (item 2).  */
   find_iv_candidates (data);
 
@@ -7584,6 +7639,9 @@ tree_ssa_iv_optimize_loop (struct ivopts_data *data, struct loop *loop,
 
   /* Find the optimal set of induction variables (item 3, part 2).  */
   iv_ca = find_optimal_iv_set (data);
+  /* Cleanup basic block aux field.  */
+  for (unsigned i = 0; i < data->current_loop->num_nodes; i++)
+    body[i]->aux = NULL;
   if (!iv_ca)
     goto finish;
   changed = true;
@@ -7599,6 +7657,7 @@ tree_ssa_iv_optimize_loop (struct ivopts_data *data, struct loop *loop,
   remove_unused_ivs (data, toremove);
 
 finish:
+  free (body);
   free_loop_data (data);
 
   return changed;