diff mbox series

Fix PR89182

Message ID alpine.LSU.2.20.1902061022590.23386@zhemvz.fhfr.qr
State New
Headers show
Series Fix PR89182 | expand

Commit Message

Richard Biener Feb. 6, 2019, 9:24 a.m. UTC
This adds a cache around scalar_evolution_in_region avoiding re-analysis
during code-generation where out-of-date SSA form can cause minor
differences in SCEV analysis (follow_copies_to_constant ...).

Bootstrap and regtest running on x86_64-unknown-linux-gnu.

It leaves a (tiny) hole via scev_analyzable_p but I refrained from
more refactoring at this point w/o a good reason (testcase).

Richard.

2019-02-06  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/89182
	* graphite.h (cached_scalar_evolution_in_region): Declare.
	* graphite.c (struct seir_cache_key): New.
	(struct sese_scev_hash): Likewise.
	(seir_cache): New global.
	(cached_scalar_evolution_in_region): New function.
	(graphite_transform_loops): Allocate and release seir_cache.
	* graphite-isl-ast-to-gimple.c (get_rename_from_scev): Use
	cached_scalar_evolution_in_region.
	* graphite-scop-detection.c (scop_detection::can_represent_loop):
	Simplify.
	(scop_detection::graphite_can_represent_expr: Use
	cached_scalar_evolution_in_region.
	(scop_detection::stmt_simple_for_scop_p): Likewise.
	(find_params_in_bb): Likewise.
	(gather_bbs::before_dom_children): Likewise.
	* graphite-sese-to-poly.c (create_pw_aff_from_tree): Likewise.
	(add_loop_constraints): Likewise.

	* gfortran.dg/graphite/pr89182.f90: New testcase.
diff mbox series

Patch

Index: gcc/graphite-isl-ast-to-gimple.c
===================================================================
--- gcc/graphite-isl-ast-to-gimple.c	(revision 268572)
+++ gcc/graphite-isl-ast-to-gimple.c	(working copy)
@@ -1092,7 +1092,8 @@  tree translate_isl_ast_to_gimple::
 get_rename_from_scev (tree old_name, gimple_seq *stmts, loop_p loop,
 		      vec<tree> iv_map)
 {
-  tree scev = scalar_evolution_in_region (region->region, loop, old_name);
+  tree scev = cached_scalar_evolution_in_region (region->region,
+						 loop, old_name);
 
   /* At this point we should know the exact scev for each
      scalar SSA_NAME used in the scop: all the other scalar
Index: gcc/graphite-scop-detection.c
===================================================================
--- gcc/graphite-scop-detection.c	(revision 268572)
+++ gcc/graphite-scop-detection.c	(working copy)
@@ -568,8 +568,6 @@  scop_detection::can_represent_loop (loop
     && niter_desc.control.no_overflow
     && (niter = number_of_latch_executions (loop))
     && !chrec_contains_undetermined (niter)
-    && !chrec_contains_undetermined (scalar_evolution_in_region (scop,
-								 loop, niter))
     && graphite_can_represent_expr (scop, loop, niter);
 }
 
@@ -924,7 +922,7 @@  bool
 scop_detection::graphite_can_represent_expr (sese_l scop, loop_p loop,
 					     tree expr)
 {
-  tree scev = scalar_evolution_in_region (scop, loop, expr);
+  tree scev = cached_scalar_evolution_in_region (scop, loop, expr);
   return graphite_can_represent_scev (scop, scev);
 }
 
@@ -1061,7 +1059,8 @@  scop_detection::stmt_simple_for_scop_p (
 	FOR_EACH_SSA_TREE_OPERAND (op, stmt, i, SSA_OP_USE)
 	  if (scev_analyzable_p (op, scop)
 	      && chrec_contains_undetermined
-		   (scalar_evolution_in_region (scop, bb->loop_father, op)))
+		   (cached_scalar_evolution_in_region (scop,
+						       bb->loop_father, op)))
 	    {
 	      DEBUG_PRINT (dp << "[scop-detection-fail] "
 			   << "Graphite cannot code-gen stmt:\n";
@@ -1190,10 +1189,10 @@  find_params_in_bb (sese_info_p region, g
   FOR_EACH_VEC_ELT (GBB_CONDITIONS (gbb), i, stmt)
     {
       loop_p loop = gimple_bb (stmt)->loop_father;
-      tree lhs = scalar_evolution_in_region (region->region, loop,
-					     gimple_cond_lhs (stmt));
-      tree rhs = scalar_evolution_in_region (region->region, loop,
-					     gimple_cond_rhs (stmt));
+      tree lhs = cached_scalar_evolution_in_region (region->region, loop,
+						    gimple_cond_lhs (stmt));
+      tree rhs = cached_scalar_evolution_in_region (region->region, loop,
+						    gimple_cond_rhs (stmt));
       gcc_assert (!chrec_contains_undetermined (lhs)
 		  && !chrec_contains_undetermined (rhs));
 
@@ -1492,8 +1491,8 @@  gather_bbs::before_dom_children (basic_b
       tree nb_iters = number_of_latch_executions (loop);
       if (chrec_contains_symbols (nb_iters))
 	{
-	  nb_iters = scalar_evolution_in_region (region->region,
-						 loop, nb_iters);
+	  nb_iters = cached_scalar_evolution_in_region (region->region,
+							loop, nb_iters);
 	  scan_tree_for_params (region, nb_iters);
 	}
     }
Index: gcc/graphite-sese-to-poly.c
===================================================================
--- gcc/graphite-sese-to-poly.c	(revision 268572)
+++ gcc/graphite-sese-to-poly.c	(working copy)
@@ -328,7 +328,7 @@  create_pw_aff_from_tree (poly_bb_p pbb,
 {
   scop_p scop = PBB_SCOP (pbb);
 
-  t = scalar_evolution_in_region (scop->scop_info->region, loop, t);
+  t = cached_scalar_evolution_in_region (scop->scop_info->region, loop, t);
 
   gcc_assert (!chrec_contains_undetermined (t));
   gcc_assert (!automatically_generated_chrec_p (t));
@@ -782,7 +782,7 @@  add_loop_constraints (scop_p scop, __isl
     }
   /* loop_i <= expr_nb_iters */
   gcc_assert (!chrec_contains_undetermined (nb_iters));
-  nb_iters = scalar_evolution_in_region (region, loop, nb_iters);
+  nb_iters = cached_scalar_evolution_in_region (region, loop, nb_iters);
   gcc_assert (!chrec_contains_undetermined (nb_iters));
 
   isl_pw_aff *aff_nb_iters = extract_affine (scop, nb_iters,
Index: gcc/graphite.c
===================================================================
--- gcc/graphite.c	(revision 268572)
+++ gcc/graphite.c	(working copy)
@@ -210,6 +210,63 @@  print_graphite_statistics (FILE* file, v
     print_graphite_scop_statistics (file, scop);
 }
 
+struct seir_cache_key
+{
+  hashval_t hash;
+  int entry_dest;
+  int exit_src;
+  int loop_num;
+  tree expr;
+};
+
+struct sese_scev_hash : typed_noop_remove <seir_cache_key>
+{
+  typedef seir_cache_key value_type;
+  typedef seir_cache_key compare_type;
+  static hashval_t hash (const seir_cache_key &key) { return key.hash; }
+  static bool
+  equal (const seir_cache_key &key1, const seir_cache_key &key2)
+  {
+    return (key1.hash == key2.hash
+	    && key1.entry_dest == key2.entry_dest
+	    && key1.exit_src == key2.exit_src
+	    && key1.loop_num == key2.loop_num
+	    && operand_equal_p (key1.expr, key2.expr, 0));
+  }
+  static void mark_deleted (seir_cache_key &key) { key.expr = NULL_TREE; }
+  static void mark_empty (seir_cache_key &key) { key.entry_dest = 0; }
+  static bool is_deleted (const seir_cache_key &key) { return !key.expr; }
+  static bool is_empty (const seir_cache_key &key) { return key.entry_dest == 0; }
+};
+
+static hash_map<sese_scev_hash, tree> *seir_cache;
+
+/* Same as scalar_evolution_in_region but caches results so we avoid
+   re-computing evolutions during transform phase.  */
+
+tree
+cached_scalar_evolution_in_region (const sese_l &region, loop_p loop,
+				   tree expr)
+{
+  seir_cache_key key;
+  key.entry_dest = region.entry->dest->index;
+  key.exit_src = region.exit->src->index;
+  key.loop_num = loop->num;
+  key.expr = expr;
+  inchash::hash hstate (0);
+  hstate.add_int (key.entry_dest);
+  hstate.add_int (key.exit_src);
+  hstate.add_int (key.loop_num);
+  inchash::add_expr (key.expr, hstate);
+  key.hash = hstate.end ();
+  
+  bool existed;
+  tree &chrec = seir_cache->get_or_insert (key, &existed);
+  if (!existed)
+    chrec = scalar_evolution_in_region (region, loop, expr);
+  return chrec;
+}
+
 /* Deletes all scops in SCOPS.  */
 
 static void
@@ -385,6 +442,8 @@  graphite_transform_loops (void)
       print_loops (dump_file, 3);
     }
 
+  seir_cache = new hash_map<sese_scev_hash, tree>;
+
   calculate_dominance_info (CDI_POST_DOMINATORS);
   build_scops (&scops);
   free_dominance_info (CDI_POST_DOMINATORS);
@@ -420,6 +479,9 @@  graphite_transform_loops (void)
 	  }
       }
 
+  delete seir_cache;
+  seir_cache = NULL;
+
   if (changed)
     {
       mark_virtual_operands_for_renaming (cfun);
Index: gcc/graphite.h
===================================================================
--- gcc/graphite.h	(revision 268572)
+++ gcc/graphite.h	(working copy)
@@ -460,6 +460,7 @@  carries_deps (__isl_keep isl_union_map *
 extern bool build_poly_scop (scop_p);
 extern bool graphite_regenerate_ast_isl (scop_p);
 extern void build_scops (vec<scop_p> *);
+extern tree cached_scalar_evolution_in_region (const sese_l &, loop_p, tree);
 extern void dot_all_sese (FILE *, vec<sese_l> &);
 extern void dot_sese (sese_l &);
 extern void dot_cfg ();
Index: gcc/testsuite/gfortran.dg/graphite/pr89182.f90
===================================================================
--- gcc/testsuite/gfortran.dg/graphite/pr89182.f90	(nonexistent)
+++ gcc/testsuite/gfortran.dg/graphite/pr89182.f90	(working copy)
@@ -0,0 +1,31 @@ 
+! { dg-do compile }
+! { dg-options "-O3 -fgraphite-identity --param max-completely-peeled-insns=8" }
+
+MODULE hfx_contract_block
+  INTEGER, PARAMETER :: dp=8
+CONTAINS
+  SUBROUTINE contract_block(mb_max,mc_max,kbc,ks_bc)
+    REAL(KIND=dp) :: kbc(mb_max*mc_max), ks_bc
+    CALL block_1_2_1_2(kbc,ks_bc)
+    CALL block_1_2_1_3(kbc,ks_bc)
+    CALL block_1_2_1_3(kbc,ks_bc)
+  END SUBROUTINE contract_block
+  SUBROUTINE block_1_2_1_2(kbc,ks_bc)
+    REAL(KIND=dp) :: kbc(2*1), ks_bc
+    DO mc = 1,2
+       DO mb = 1,2
+          kbc((mc-1)*2+mb) = ks_bc
+       END DO
+    END DO
+  END SUBROUTINE block_1_2_1_2
+  SUBROUTINE block_1_2_1_3(kbc,ks_bc)
+    REAL(KIND=dp) :: kbc(2*1), ks_bc
+    DO md = 1,3
+       DO mc = 1,1
+          DO mb = 1,2
+             kbc((mc-1)*2+mb) = kbc((mc-1)*2+mb) - ks_bc
+          END DO
+       END DO
+    END DO
+  END SUBROUTINE block_1_2_1_3
+END MODULE hfx_contract_block