[PATCH] Fix PR58484

Richard Biener rguenther@suse.de
Fri Sep 20 13:53:00 GMT 2013


I am testing the following patch which fixes PR58484, the ICE
compiling 416.gamess after my PR58417 fix.

The issue is that now the chrec cache during instantiation is
again dependent on the block we instantiate below due to the
possible recursion through analyze_scalar_evolution.  Thus the
patch re-instantiates the original hash (still in the more
allocation friendly variant).

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

Richard.

2013-09-20  Richard Biener  <rguenther@suse.de>

	PR middle-end/58484
	* tree-scalar-evolution.c (struct scev_info_str): Shrink by
	remembering SSA name version and block index.
	(new_scev_info_str): Adjust.
	(hash_scev_info): Likewise.  Also hash the block index.
	(eq_scev_info): Adjust.
	(find_var_scev_info): Likewise.
	(struct instantiate_cache_entry): Remove.
	(struct instantiate_cache_type): Use a htab to map name, block
	to chrec.
	(instantiate_cache_type::~instantiate_cache_type): Adjust.
	(get_instantiated_value_entry): Likewise.
	(hash_idx_scev_info, eq_idx_scev_info): New functions.
	(instantiate_scev_name): Adjust.

	* gfortran.dg/pr58484.f: New testcase.

Index: gcc/tree-scalar-evolution.c
===================================================================
*** gcc/tree-scalar-evolution.c	(revision 202775)
--- gcc/tree-scalar-evolution.c	(working copy)
*************** static tree analyze_scalar_evolution_1 (
*** 269,281 ****
  static tree analyze_scalar_evolution_for_address_of (struct loop *loop,
  						     tree var);
  
! /* The cached information about an SSA name VAR, claiming that below
!    basic block INSTANTIATED_BELOW, the value of VAR can be expressed
!    as CHREC.  */
  
  struct GTY(()) scev_info_str {
!   basic_block instantiated_below;
!   tree var;
    tree chrec;
  };
  
--- 269,281 ----
  static tree analyze_scalar_evolution_for_address_of (struct loop *loop,
  						     tree var);
  
! /* The cached information about an SSA name with version NAME_VERSION,
!    claiming that below basic block with index INSTANTIATED_BELOW, the
!    value of the SSA name can be expressed as CHREC.  */
  
  struct GTY(()) scev_info_str {
!   unsigned int name_version;
!   int instantiated_below;
    tree chrec;
  };
  
*************** new_scev_info_str (basic_block instantia
*** 309,317 ****
    struct scev_info_str *res;
  
    res = ggc_alloc_scev_info_str ();
!   res->var = var;
    res->chrec = chrec_not_analyzed_yet;
!   res->instantiated_below = instantiated_below;
  
    return res;
  }
--- 309,317 ----
    struct scev_info_str *res;
  
    res = ggc_alloc_scev_info_str ();
!   res->name_version = SSA_NAME_VERSION (var);
    res->chrec = chrec_not_analyzed_yet;
!   res->instantiated_below = instantiated_below->index;
  
    return res;
  }
*************** new_scev_info_str (basic_block instantia
*** 319,327 ****
  /* Computes a hash function for database element ELT.  */
  
  static inline hashval_t
! hash_scev_info (const void *elt)
  {
!   return SSA_NAME_VERSION (((const struct scev_info_str *) elt)->var);
  }
  
  /* Compares database elements E1 and E2.  */
--- 319,328 ----
  /* Computes a hash function for database element ELT.  */
  
  static inline hashval_t
! hash_scev_info (const void *elt_)
  {
!   const struct scev_info_str *elt = (const struct scev_info_str *) elt_;
!   return elt->name_version ^ elt->instantiated_below;
  }
  
  /* Compares database elements E1 and E2.  */
*************** eq_scev_info (const void *e1, const void
*** 332,338 ****
    const struct scev_info_str *elt1 = (const struct scev_info_str *) e1;
    const struct scev_info_str *elt2 = (const struct scev_info_str *) e2;
  
!   return (elt1->var == elt2->var
  	  && elt1->instantiated_below == elt2->instantiated_below);
  }
  
--- 333,339 ----
    const struct scev_info_str *elt1 = (const struct scev_info_str *) e1;
    const struct scev_info_str *elt2 = (const struct scev_info_str *) e2;
  
!   return (elt1->name_version == elt2->name_version
  	  && elt1->instantiated_below == elt2->instantiated_below);
  }
  
*************** find_var_scev_info (basic_block instanti
*** 355,362 ****
    struct scev_info_str tmp;
    PTR *slot;
  
!   tmp.var = var;
!   tmp.instantiated_below = instantiated_below;
    slot = htab_find_slot (scalar_evolution_info, &tmp, INSERT);
  
    if (!*slot)
--- 356,363 ----
    struct scev_info_str tmp;
    PTR *slot;
  
!   tmp.name_version = SSA_NAME_VERSION (var);
!   tmp.instantiated_below = instantiated_below->index;
    slot = htab_find_slot (scalar_evolution_info, &tmp, INSERT);
  
    if (!*slot)
*************** analyze_scalar_evolution_in_loop (struct
*** 2065,2080 ****
     instantiating a CHREC or resolving mixers.  For this use
     instantiated_below is always the same.  */
  
- struct instantiate_cache_entry
- {
-   tree name;
-   tree chrec;
- };
- 
  struct instantiate_cache_type
  {
!   pointer_map<unsigned> *map;
!   vec<instantiate_cache_entry> entries;
  
    instantiate_cache_type () : map (NULL), entries(vNULL) {}
    ~instantiate_cache_type ();
--- 2066,2075 ----
     instantiating a CHREC or resolving mixers.  For this use
     instantiated_below is always the same.  */
  
  struct instantiate_cache_type
  {
!   htab_t map;
!   vec<scev_info_str> entries;
  
    instantiate_cache_type () : map (NULL), entries(vNULL) {}
    ~instantiate_cache_type ();
*************** instantiate_cache_type::~instantiate_cac
*** 2086,2125 ****
  {
    if (map != NULL)
      {
!       delete map;
        entries.release ();
      }
  }
  
  /* Returns from CACHE the slot number of the cached chrec for NAME.  */
  
  static unsigned
! get_instantiated_value_entry (instantiate_cache_type &cache, tree name)
  {
    if (!cache.map)
      {
!       cache.map = new pointer_map<unsigned>;
        cache.entries.create (10);
      }
  
!   bool existed_p;
!   unsigned *slot = cache.map->insert (name, &existed_p);
!   if (!existed_p)
      {
-       struct instantiate_cache_entry e;
-       e.name = name;
        e.chrec = chrec_not_analyzed_yet;
!       *slot = cache.entries.length ();
        cache.entries.safe_push (e);
      }
  
!   return *slot;
  }
  
- /* Cache to avoid infinite recursion when instantiating an SSA name.
-    Live during the outermost instantiate_scev or resolve_mixers call.  */
- static instantiate_cache_type *global_cache;
- 
  
  /* Return the closed_loop_phi node for VAR.  If there is none, return
     NULL_TREE.  */
--- 2081,2140 ----
  {
    if (map != NULL)
      {
!       htab_delete (map);
        entries.release ();
      }
  }
  
+ /* Cache to avoid infinite recursion when instantiating an SSA name.
+    Live during the outermost instantiate_scev or resolve_mixers call.  */
+ static instantiate_cache_type *global_cache;
+ 
+ /* Computes a hash function for database element ELT.  */
+ 
+ static inline hashval_t
+ hash_idx_scev_info (const void *elt_)
+ {
+   unsigned idx = ((size_t) elt_) - 2;
+   return hash_scev_info (&global_cache->entries[idx]);
+ }
+ 
+ /* Compares database elements E1 and E2.  */
+ 
+ static inline int
+ eq_idx_scev_info (const void *e1, const void *e2)
+ {
+   unsigned idx1 = ((size_t) e1) - 2;
+   return eq_scev_info (&global_cache->entries[idx1], e2);
+ }
+ 
  /* Returns from CACHE the slot number of the cached chrec for NAME.  */
  
  static unsigned
! get_instantiated_value_entry (instantiate_cache_type &cache,
! 			      tree name, basic_block instantiate_below)
  {
    if (!cache.map)
      {
!       cache.map = htab_create (10, hash_idx_scev_info, eq_idx_scev_info, NULL);
        cache.entries.create (10);
      }
  
!   scev_info_str e;
!   e.name_version = SSA_NAME_VERSION (name);
!   e.instantiated_below = instantiate_below->index;
!   void **slot = htab_find_slot_with_hash (cache.map, &e,
! 					  hash_scev_info (&e), INSERT);
!   if (!*slot)
      {
        e.chrec = chrec_not_analyzed_yet;
!       *slot = (void *)(size_t)(cache.entries.length () + 2);
        cache.entries.safe_push (e);
      }
  
!   return ((size_t)*slot) - 2;
  }
  
  
  /* Return the closed_loop_phi node for VAR.  If there is none, return
     NULL_TREE.  */
*************** instantiate_scev_name (basic_block insta
*** 2195,2201 ****
  
       | a_2 -> {0, +, 1, +, a_2}_1  */
  
!   unsigned si = get_instantiated_value_entry (*global_cache, chrec);
    if (global_cache->get (si) != chrec_not_analyzed_yet)
      return global_cache->get (si);
  
--- 2210,2217 ----
  
       | a_2 -> {0, +, 1, +, a_2}_1  */
  
!   unsigned si = get_instantiated_value_entry (*global_cache,
! 					      chrec, instantiate_below);
    if (global_cache->get (si) != chrec_not_analyzed_yet)
      return global_cache->get (si);
  
Index: gcc/testsuite/gfortran.dg/pr58484.f
===================================================================
*** gcc/testsuite/gfortran.dg/pr58484.f	(revision 0)
--- gcc/testsuite/gfortran.dg/pr58484.f	(working copy)
***************
*** 0 ****
--- 1,15 ----
+ ! { dg-do compile }
+ ! { dg-options "-O2" }
+       SUBROUTINE UMPSE(AIBJ,NOC,NDIM,NOCA,NVIRA,NOCCA,E2)
+       DIMENSION AIBJ(NOC,NDIM,*)
+       DO 20 MA=1,NVIRA
+       DO 20 MI=1,NOCA
+          DO 10 MB=1,MA
+          MBI = MI+NOCA*(MB-1)
+          DO 10 MJ=1,NOCCA
+             DUM = AIBJ(MJ,MAI,MB)-AIBJ(MJ,MBI,MA)
+             E2A = E2A-DUM
+    10    CONTINUE
+    20 CONTINUE
+       E2  = E2+E2A
+       END



More information about the Gcc-patches mailing list