This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix PR58417


This PR shows that we may not fold chrec operations with chrecs
that are not properly instantiated (and thus may contain symbols
that are defined in the varying loop).  To fix that the patch
makes sure to instantiate them and adds asserts to catch issues
elsewhere (hopefully not too many).  For this to work the
recursion prevention of instantiation has to be globalized
as we can recurse through analyze_scalar_evolution.  This also
fixes a reallocation issue with the current cache.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk.

Richard.

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

	PR tree-optimization/58417
	* tree-chrec.c (chrec_fold_plus_1): Assert that we do not
	have chrecs with symbols defined in the loop as operands.
	(chrec_fold_multiply): Likewise.
	* tree-scalar-evolution.c (interpret_rhs_expr): Instantiate
	parameters before folding binary operations.
	(struct instantiate_cache_entry_hasher): Remove.
	(struct instantiate_cache_type): Use a pointer-map.
	(instantiate_cache_type::instantiate_cache_type): New function.
	(instantiate_cache_type::get): Likewise.
	(instantiate_cache_type::set): Likewise.
	(instantiate_cache_type::~instantiate_cache_type): Adjust.
	(get_instantiated_value_entry): Likewise.
	(global_cache): New global.
	(instantiate_scev_r, instantiate_scev_poly, instantiate_scev_binary,
	instantiate_array_ref, instantiate_scev_convert, instantiate_scev_3,
	instantiate_scev_2, instantiate_scev_1): Do not pass along cache.
	(instantiate_scev_name): Adjust.
	(instantiate_scev): Construct global instead of local cache.
	(resolve_mixers): Likewise.

	* gcc.dg/torture/pr58417.c: New testcase.

Index: gcc/tree-chrec.c
===================================================================
*** gcc/tree-chrec.c	(revision 202681)
--- gcc/tree-chrec.c	(working copy)
*************** chrec_fold_plus_1 (enum tree_code code,
*** 268,276 ****
--- 268,281 ----
    switch (TREE_CODE (op0))
      {
      case POLYNOMIAL_CHREC:
+       gcc_checking_assert
+ 	(!chrec_contains_symbols_defined_in_loop (op0, CHREC_VARIABLE (op0)));
        switch (TREE_CODE (op1))
  	{
  	case POLYNOMIAL_CHREC:
+ 	  gcc_checking_assert
+ 	    (!chrec_contains_symbols_defined_in_loop (op1,
+ 						      CHREC_VARIABLE (op1)));
  	  return chrec_fold_plus_poly_poly (code, type, op0, op1);
  
  	CASE_CONVERT:
*************** chrec_fold_plus_1 (enum tree_code code,
*** 298,303 ****
--- 303,311 ----
        switch (TREE_CODE (op1))
  	{
  	case POLYNOMIAL_CHREC:
+ 	  gcc_checking_assert
+ 	    (!chrec_contains_symbols_defined_in_loop (op1,
+ 						      CHREC_VARIABLE (op1)));
  	  if (code == PLUS_EXPR || code == POINTER_PLUS_EXPR)
  	    return build_polynomial_chrec
  	      (CHREC_VARIABLE (op1),
*************** chrec_fold_multiply (tree type,
*** 396,404 ****
--- 404,417 ----
    switch (TREE_CODE (op0))
      {
      case POLYNOMIAL_CHREC:
+       gcc_checking_assert
+ 	(!chrec_contains_symbols_defined_in_loop (op0, CHREC_VARIABLE (op0)));
        switch (TREE_CODE (op1))
  	{
  	case POLYNOMIAL_CHREC:
+ 	  gcc_checking_assert
+ 	    (!chrec_contains_symbols_defined_in_loop (op1,
+ 						      CHREC_VARIABLE (op1)));
  	  return chrec_fold_multiply_poly_poly (type, op0, op1);
  
  	CASE_CONVERT:
*************** chrec_fold_multiply (tree type,
*** 431,436 ****
--- 444,452 ----
        switch (TREE_CODE (op1))
  	{
  	case POLYNOMIAL_CHREC:
+ 	  gcc_checking_assert
+ 	    (!chrec_contains_symbols_defined_in_loop (op1,
+ 						      CHREC_VARIABLE (op1)));
  	  return build_polynomial_chrec
  	    (CHREC_VARIABLE (op1),
  	     chrec_fold_multiply (type, CHREC_LEFT (op1), op0),
Index: gcc/tree-scalar-evolution.c
===================================================================
*** gcc/tree-scalar-evolution.c	(revision 202681)
--- gcc/tree-scalar-evolution.c	(working copy)
*************** interpret_rhs_expr (struct loop *loop, g
*** 1648,1653 ****
--- 1648,1655 ----
  	      chrec2 = analyze_scalar_evolution (loop, rhs2);
  	      chrec1 = chrec_convert (type, chrec1, at_stmt);
  	      chrec2 = chrec_convert (TREE_TYPE (rhs2), chrec2, at_stmt);
+ 	      chrec1 = instantiate_parameters (loop, chrec1);
+ 	      chrec2 = instantiate_parameters (loop, chrec2);
  	      res = chrec_fold_plus (type, chrec1, chrec2);
  	    }
  	  else
*************** interpret_rhs_expr (struct loop *loop, g
*** 1661,1666 ****
--- 1663,1669 ----
  	    {
  	      chrec2 = analyze_scalar_evolution (loop, offset);
  	      chrec2 = chrec_convert (TREE_TYPE (offset), chrec2, at_stmt);
+ 	      chrec2 = instantiate_parameters (loop, chrec2);
  	      res = chrec_fold_plus (type, res, chrec2);
  	    }
  
*************** interpret_rhs_expr (struct loop *loop, g
*** 1671,1676 ****
--- 1674,1680 ----
  	      unitpos = size_int (bitpos / BITS_PER_UNIT);
  	      chrec3 = analyze_scalar_evolution (loop, unitpos);
  	      chrec3 = chrec_convert (TREE_TYPE (unitpos), chrec3, at_stmt);
+ 	      chrec3 = instantiate_parameters (loop, chrec3);
  	      res = chrec_fold_plus (type, res, chrec3);
  	    }
          }
*************** interpret_rhs_expr (struct loop *loop, g
*** 1683,1688 ****
--- 1687,1694 ----
        chrec2 = analyze_scalar_evolution (loop, rhs2);
        chrec1 = chrec_convert (type, chrec1, at_stmt);
        chrec2 = chrec_convert (TREE_TYPE (rhs2), chrec2, at_stmt);
+       chrec1 = instantiate_parameters (loop, chrec1);
+       chrec2 = instantiate_parameters (loop, chrec2);
        res = chrec_fold_plus (type, chrec1, chrec2);
        break;
  
*************** interpret_rhs_expr (struct loop *loop, g
*** 1691,1696 ****
--- 1697,1704 ----
        chrec2 = analyze_scalar_evolution (loop, rhs2);
        chrec1 = chrec_convert (type, chrec1, at_stmt);
        chrec2 = chrec_convert (type, chrec2, at_stmt);
+       chrec1 = instantiate_parameters (loop, chrec1);
+       chrec2 = instantiate_parameters (loop, chrec2);
        res = chrec_fold_plus (type, chrec1, chrec2);
        break;
  
*************** interpret_rhs_expr (struct loop *loop, g
*** 1699,1704 ****
--- 1707,1714 ----
        chrec2 = analyze_scalar_evolution (loop, rhs2);
        chrec1 = chrec_convert (type, chrec1, at_stmt);
        chrec2 = chrec_convert (type, chrec2, at_stmt);
+       chrec1 = instantiate_parameters (loop, chrec1);
+       chrec2 = instantiate_parameters (loop, chrec2);
        res = chrec_fold_minus (type, chrec1, chrec2);
        break;
  
*************** interpret_rhs_expr (struct loop *loop, g
*** 1706,1711 ****
--- 1716,1722 ----
        chrec1 = analyze_scalar_evolution (loop, rhs1);
        chrec1 = chrec_convert (type, chrec1, at_stmt);
        /* TYPE may be integer, real or complex, so use fold_convert.  */
+       chrec1 = instantiate_parameters (loop, chrec1);
        res = chrec_fold_multiply (type, chrec1,
  				 fold_convert (type, integer_minus_one_node));
        break;
*************** interpret_rhs_expr (struct loop *loop, g
*** 1714,1719 ****
--- 1725,1731 ----
        /* Handle ~X as -1 - X.  */
        chrec1 = analyze_scalar_evolution (loop, rhs1);
        chrec1 = chrec_convert (type, chrec1, at_stmt);
+       chrec1 = instantiate_parameters (loop, chrec1);
        res = chrec_fold_minus (type,
  			      fold_convert (type, integer_minus_one_node),
  			      chrec1);
*************** interpret_rhs_expr (struct loop *loop, g
*** 1724,1729 ****
--- 1736,1743 ----
        chrec2 = analyze_scalar_evolution (loop, rhs2);
        chrec1 = chrec_convert (type, chrec1, at_stmt);
        chrec2 = chrec_convert (type, chrec2, at_stmt);
+       chrec1 = instantiate_parameters (loop, chrec1);
+       chrec2 = instantiate_parameters (loop, chrec2);
        res = chrec_fold_multiply (type, chrec1, chrec2);
        break;
  
*************** struct instantiate_cache_entry
*** 2057,2134 ****
    tree chrec;
  };
  
- struct instantiate_cache_entry_hasher : typed_noop_remove <uintptr_t>
- {
-   typedef uintptr_t value_type;
-   typedef instantiate_cache_entry compare_type;
-   static inline hashval_t hash (const value_type *);
-   static inline bool equal (const value_type *, const compare_type *);
- };
- 
  struct instantiate_cache_type
  {
!   hash_table <instantiate_cache_entry_hasher> htab;
    vec<instantiate_cache_entry> entries;
  
    ~instantiate_cache_type ();
  };
  
  instantiate_cache_type::~instantiate_cache_type ()
  {
!   if (htab.is_created ())
      {
!       htab.dispose ();
        entries.release ();
      }
  }
  
! static instantiate_cache_type *ctbl;
! 
! inline hashval_t
! instantiate_cache_entry_hasher::hash (const value_type *idx)
! {
!   instantiate_cache_entry *elt
!     = &ctbl->entries[reinterpret_cast <uintptr_t> (idx) - 2];
!   return SSA_NAME_VERSION (elt->name);
! }
! 
! inline bool
! instantiate_cache_entry_hasher::equal (const value_type *idx1,
! 				       const compare_type *elt2)
! {
!   compare_type *elt1 = &ctbl->entries[reinterpret_cast <uintptr_t> (idx1) - 2];
!   return elt1->name == elt2->name;
! }
  
! /* Returns from CACHE a pointer to the cached chrec for NAME.  */
! 
! static tree *
  get_instantiated_value_entry (instantiate_cache_type &cache, tree name)
  {
!   struct instantiate_cache_entry e;
!   uintptr_t **slot;
! 
!   if (!cache.htab.is_created ())
      {
!       cache.htab.create (10);
        cache.entries.create (10);
      }
  
!   ctbl = &cache;
! 
!   e.name = name;
!   slot = cache.htab.find_slot_with_hash (&e, SSA_NAME_VERSION (name), INSERT);
!   if (!*slot)
      {
        e.chrec = chrec_not_analyzed_yet;
        cache.entries.safe_push (e);
-       *slot = reinterpret_cast <uintptr_t *>
- 	  ((uintptr_t) cache.entries.length () + 1);
      }
  
!   return &cache.entries[reinterpret_cast <uintptr_t> (*slot) - 2].chrec;
  }
  
  /* Return the closed_loop_phi node for VAR.  If there is none, return
     NULL_TREE.  */
  
--- 2071,2126 ----
    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 ();
+   tree get (unsigned slot) { return entries[slot].chrec; }
+   void set (unsigned slot, tree chrec) { entries[slot].chrec = chrec; }
  };
  
  instantiate_cache_type::~instantiate_cache_type ()
  {
!   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.  */
  
*************** loop_closed_phi_def (tree var)
*** 2160,2166 ****
  }
  
  static tree instantiate_scev_r (basic_block, struct loop *, struct loop *,
! 				tree, bool, instantiate_cache_type &, int);
  
  /* Analyze all the parameters of the chrec, between INSTANTIATE_BELOW
     and EVOLUTION_LOOP, that were left under a symbolic form.
--- 2152,2158 ----
  }
  
  static tree instantiate_scev_r (basic_block, struct loop *, struct loop *,
! 				tree, bool, int);
  
  /* Analyze all the parameters of the chrec, between INSTANTIATE_BELOW
     and EVOLUTION_LOOP, that were left under a symbolic form.
*************** static tree
*** 2180,2186 ****
  instantiate_scev_name (basic_block instantiate_below,
  		       struct loop *evolution_loop, struct loop *inner_loop,
  		       tree chrec,
! 		       bool fold_conversions, instantiate_cache_type &cache,
  		       int size_expr)
  {
    tree res;
--- 2172,2178 ----
  instantiate_scev_name (basic_block instantiate_below,
  		       struct loop *evolution_loop, struct loop *inner_loop,
  		       tree chrec,
! 		       bool fold_conversions,
  		       int size_expr)
  {
    tree res;
*************** instantiate_scev_name (basic_block insta
*** 2203,2215 ****
  
       | a_2 -> {0, +, 1, +, a_2}_1  */
  
!   tree *si;
!   si = get_instantiated_value_entry (cache, chrec);
!   if (*si != chrec_not_analyzed_yet)
!     return *si;
  
    /* On recursion return chrec_dont_know.  */
!   *si = chrec_dont_know;
  
    def_loop = find_common_loop (evolution_loop, def_bb->loop_father);
  
--- 2195,2206 ----
  
       | 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);
  
    /* On recursion return chrec_dont_know.  */
!   global_cache->set (si, chrec_dont_know);
  
    def_loop = find_common_loop (evolution_loop, def_bb->loop_father);
  
*************** instantiate_scev_name (basic_block insta
*** 2242,2248 ****
  	  res = compute_overall_effect_of_inner_loop (loop, res);
  	  res = instantiate_scev_r (instantiate_below, evolution_loop,
  				    inner_loop, res,
! 				    fold_conversions, cache, size_expr);
  	}
        else if (!dominated_by_p (CDI_DOMINATORS, instantiate_below,
  				gimple_bb (SSA_NAME_DEF_STMT (res))))
--- 2233,2239 ----
  	  res = compute_overall_effect_of_inner_loop (loop, res);
  	  res = instantiate_scev_r (instantiate_below, evolution_loop,
  				    inner_loop, res,
! 				    fold_conversions, size_expr);
  	}
        else if (!dominated_by_p (CDI_DOMINATORS, instantiate_below,
  				gimple_bb (SSA_NAME_DEF_STMT (res))))
*************** instantiate_scev_name (basic_block insta
*** 2259,2269 ****
        else
  	res = instantiate_scev_r (instantiate_below, evolution_loop,
  				  inner_loop, res,
! 				  fold_conversions, cache, size_expr);
      }
  
    /* Store the correct value to the cache.  */
!   *si = res;
    return res;
  }
  
--- 2250,2260 ----
        else
  	res = instantiate_scev_r (instantiate_below, evolution_loop,
  				  inner_loop, res,
! 				  fold_conversions, size_expr);
      }
  
    /* Store the correct value to the cache.  */
!   global_cache->set (si, res);
    return res;
  }
  
*************** instantiate_scev_name (basic_block insta
*** 2284,2304 ****
  static tree
  instantiate_scev_poly (basic_block instantiate_below,
  		       struct loop *evolution_loop, struct loop *,
! 		       tree chrec,
! 		       bool fold_conversions, instantiate_cache_type &cache,
! 		       int size_expr)
  {
    tree op1;
    tree op0 = instantiate_scev_r (instantiate_below, evolution_loop,
  				 get_chrec_loop (chrec),
! 				 CHREC_LEFT (chrec), fold_conversions, cache,
  				 size_expr);
    if (op0 == chrec_dont_know)
      return chrec_dont_know;
  
    op1 = instantiate_scev_r (instantiate_below, evolution_loop,
  			    get_chrec_loop (chrec),
! 			    CHREC_RIGHT (chrec), fold_conversions, cache,
  			    size_expr);
    if (op1 == chrec_dont_know)
      return chrec_dont_know;
--- 2275,2293 ----
  static tree
  instantiate_scev_poly (basic_block instantiate_below,
  		       struct loop *evolution_loop, struct loop *,
! 		       tree chrec, bool fold_conversions, int size_expr)
  {
    tree op1;
    tree op0 = instantiate_scev_r (instantiate_below, evolution_loop,
  				 get_chrec_loop (chrec),
! 				 CHREC_LEFT (chrec), fold_conversions,
  				 size_expr);
    if (op0 == chrec_dont_know)
      return chrec_dont_know;
  
    op1 = instantiate_scev_r (instantiate_below, evolution_loop,
  			    get_chrec_loop (chrec),
! 			    CHREC_RIGHT (chrec), fold_conversions,
  			    size_expr);
    if (op1 == chrec_dont_know)
      return chrec_dont_know;
*************** instantiate_scev_binary (basic_block ins
*** 2332,2351 ****
  			 struct loop *evolution_loop, struct loop *inner_loop,
  			 tree chrec, enum tree_code code,
  			 tree type, tree c0, tree c1,
! 			 bool fold_conversions,
! 			 instantiate_cache_type &cache,
! 			 int size_expr)
  {
    tree op1;
    tree op0 = instantiate_scev_r (instantiate_below, evolution_loop, inner_loop,
! 				 c0, fold_conversions, cache,
! 				 size_expr);
    if (op0 == chrec_dont_know)
      return chrec_dont_know;
  
    op1 = instantiate_scev_r (instantiate_below, evolution_loop, inner_loop,
! 			    c1, fold_conversions, cache,
! 			    size_expr);
    if (op1 == chrec_dont_know)
      return chrec_dont_know;
  
--- 2321,2336 ----
  			 struct loop *evolution_loop, struct loop *inner_loop,
  			 tree chrec, enum tree_code code,
  			 tree type, tree c0, tree c1,
! 			 bool fold_conversions, int size_expr)
  {
    tree op1;
    tree op0 = instantiate_scev_r (instantiate_below, evolution_loop, inner_loop,
! 				 c0, fold_conversions, size_expr);
    if (op0 == chrec_dont_know)
      return chrec_dont_know;
  
    op1 = instantiate_scev_r (instantiate_below, evolution_loop, inner_loop,
! 			    c1, fold_conversions, size_expr);
    if (op1 == chrec_dont_know)
      return chrec_dont_know;
  
*************** instantiate_scev_binary (basic_block ins
*** 2392,2406 ****
  static tree
  instantiate_array_ref (basic_block instantiate_below,
  		       struct loop *evolution_loop, struct loop *inner_loop,
! 		       tree chrec,
! 		       bool fold_conversions, instantiate_cache_type &cache,
! 		       int size_expr)
  {
    tree res;
    tree index = TREE_OPERAND (chrec, 1);
    tree op1 = instantiate_scev_r (instantiate_below, evolution_loop,
  				 inner_loop, index,
! 				 fold_conversions, cache, size_expr);
  
    if (op1 == chrec_dont_know)
      return chrec_dont_know;
--- 2377,2389 ----
  static tree
  instantiate_array_ref (basic_block instantiate_below,
  		       struct loop *evolution_loop, struct loop *inner_loop,
! 		       tree chrec, bool fold_conversions, int size_expr)
  {
    tree res;
    tree index = TREE_OPERAND (chrec, 1);
    tree op1 = instantiate_scev_r (instantiate_below, evolution_loop,
  				 inner_loop, index,
! 				 fold_conversions, size_expr);
  
    if (op1 == chrec_dont_know)
      return chrec_dont_know;
*************** instantiate_array_ref (basic_block insta
*** 2431,2444 ****
  static tree
  instantiate_scev_convert (basic_block instantiate_below,
  			  struct loop *evolution_loop, struct loop *inner_loop,
! 			  tree chrec,
! 			  tree type, tree op,
! 			  bool fold_conversions,
! 			  instantiate_cache_type &cache, int size_expr)
  {
    tree op0 = instantiate_scev_r (instantiate_below, evolution_loop,
  				 inner_loop, op,
! 				 fold_conversions, cache, size_expr);
  
    if (op0 == chrec_dont_know)
      return chrec_dont_know;
--- 2414,2425 ----
  static tree
  instantiate_scev_convert (basic_block instantiate_below,
  			  struct loop *evolution_loop, struct loop *inner_loop,
! 			  tree chrec, tree type, tree op,
! 			  bool fold_conversions, int size_expr)
  {
    tree op0 = instantiate_scev_r (instantiate_below, evolution_loop,
  				 inner_loop, op,
! 				 fold_conversions, size_expr);
  
    if (op0 == chrec_dont_know)
      return chrec_dont_know;
*************** instantiate_scev_not (basic_block instan
*** 2483,2494 ****
  		      struct loop *evolution_loop, struct loop *inner_loop,
  		      tree chrec,
  		      enum tree_code code, tree type, tree op,
! 		      bool fold_conversions, instantiate_cache_type &cache,
! 		      int size_expr)
  {
    tree op0 = instantiate_scev_r (instantiate_below, evolution_loop,
  				 inner_loop, op,
! 				 fold_conversions, cache, size_expr);
  
    if (op0 == chrec_dont_know)
      return chrec_dont_know;
--- 2464,2474 ----
  		      struct loop *evolution_loop, struct loop *inner_loop,
  		      tree chrec,
  		      enum tree_code code, tree type, tree op,
! 		      bool fold_conversions, int size_expr)
  {
    tree op0 = instantiate_scev_r (instantiate_below, evolution_loop,
  				 inner_loop, op,
! 				 fold_conversions, size_expr);
  
    if (op0 == chrec_dont_know)
      return chrec_dont_know;
*************** static tree
*** 2533,2557 ****
  instantiate_scev_3 (basic_block instantiate_below,
  		    struct loop *evolution_loop, struct loop *inner_loop,
  		    tree chrec,
! 		    bool fold_conversions, instantiate_cache_type &cache,
! 		    int size_expr)
  {
    tree op1, op2;
    tree op0 = instantiate_scev_r (instantiate_below, evolution_loop,
  				 inner_loop, TREE_OPERAND (chrec, 0),
! 				 fold_conversions, cache, size_expr);
    if (op0 == chrec_dont_know)
      return chrec_dont_know;
  
    op1 = instantiate_scev_r (instantiate_below, evolution_loop,
  			    inner_loop, TREE_OPERAND (chrec, 1),
! 			    fold_conversions, cache, size_expr);
    if (op1 == chrec_dont_know)
      return chrec_dont_know;
  
    op2 = instantiate_scev_r (instantiate_below, evolution_loop,
  			    inner_loop, TREE_OPERAND (chrec, 2),
! 			    fold_conversions, cache, size_expr);
    if (op2 == chrec_dont_know)
      return chrec_dont_know;
  
--- 2513,2536 ----
  instantiate_scev_3 (basic_block instantiate_below,
  		    struct loop *evolution_loop, struct loop *inner_loop,
  		    tree chrec,
! 		    bool fold_conversions, int size_expr)
  {
    tree op1, op2;
    tree op0 = instantiate_scev_r (instantiate_below, evolution_loop,
  				 inner_loop, TREE_OPERAND (chrec, 0),
! 				 fold_conversions, size_expr);
    if (op0 == chrec_dont_know)
      return chrec_dont_know;
  
    op1 = instantiate_scev_r (instantiate_below, evolution_loop,
  			    inner_loop, TREE_OPERAND (chrec, 1),
! 			    fold_conversions, size_expr);
    if (op1 == chrec_dont_know)
      return chrec_dont_know;
  
    op2 = instantiate_scev_r (instantiate_below, evolution_loop,
  			    inner_loop, TREE_OPERAND (chrec, 2),
! 			    fold_conversions, size_expr);
    if (op2 == chrec_dont_know)
      return chrec_dont_know;
  
*************** static tree
*** 2582,2600 ****
  instantiate_scev_2 (basic_block instantiate_below,
  		    struct loop *evolution_loop, struct loop *inner_loop,
  		    tree chrec,
! 		    bool fold_conversions, instantiate_cache_type &cache,
! 		    int size_expr)
  {
    tree op1;
    tree op0 = instantiate_scev_r (instantiate_below, evolution_loop,
  				 inner_loop, TREE_OPERAND (chrec, 0),
! 				 fold_conversions, cache, size_expr);
    if (op0 == chrec_dont_know)
      return chrec_dont_know;
  
    op1 = instantiate_scev_r (instantiate_below, evolution_loop,
  			    inner_loop, TREE_OPERAND (chrec, 1),
! 			    fold_conversions, cache, size_expr);
    if (op1 == chrec_dont_know)
      return chrec_dont_know;
  
--- 2561,2578 ----
  instantiate_scev_2 (basic_block instantiate_below,
  		    struct loop *evolution_loop, struct loop *inner_loop,
  		    tree chrec,
! 		    bool fold_conversions, int size_expr)
  {
    tree op1;
    tree op0 = instantiate_scev_r (instantiate_below, evolution_loop,
  				 inner_loop, TREE_OPERAND (chrec, 0),
! 				 fold_conversions, size_expr);
    if (op0 == chrec_dont_know)
      return chrec_dont_know;
  
    op1 = instantiate_scev_r (instantiate_below, evolution_loop,
  			    inner_loop, TREE_OPERAND (chrec, 1),
! 			    fold_conversions, size_expr);
    if (op1 == chrec_dont_know)
      return chrec_dont_know;
  
*************** static tree
*** 2623,2634 ****
  instantiate_scev_1 (basic_block instantiate_below,
  		    struct loop *evolution_loop, struct loop *inner_loop,
  		    tree chrec,
! 		    bool fold_conversions, instantiate_cache_type &cache,
! 		    int size_expr)
  {
    tree op0 = instantiate_scev_r (instantiate_below, evolution_loop,
  				 inner_loop, TREE_OPERAND (chrec, 0),
! 				 fold_conversions, cache, size_expr);
  
    if (op0 == chrec_dont_know)
      return chrec_dont_know;
--- 2601,2611 ----
  instantiate_scev_1 (basic_block instantiate_below,
  		    struct loop *evolution_loop, struct loop *inner_loop,
  		    tree chrec,
! 		    bool fold_conversions, int size_expr)
  {
    tree op0 = instantiate_scev_r (instantiate_below, evolution_loop,
  				 inner_loop, TREE_OPERAND (chrec, 0),
! 				 fold_conversions, size_expr);
  
    if (op0 == chrec_dont_know)
      return chrec_dont_know;
*************** static tree
*** 2657,2664 ****
  instantiate_scev_r (basic_block instantiate_below,
  		    struct loop *evolution_loop, struct loop *inner_loop,
  		    tree chrec,
! 		    bool fold_conversions, instantiate_cache_type &cache,
! 		    int size_expr)
  {
    /* Give up if the expression is larger than the MAX that we allow.  */
    if (size_expr++ > PARAM_VALUE (PARAM_SCEV_MAX_EXPR_SIZE))
--- 2634,2640 ----
  instantiate_scev_r (basic_block instantiate_below,
  		    struct loop *evolution_loop, struct loop *inner_loop,
  		    tree chrec,
! 		    bool fold_conversions, int size_expr)
  {
    /* Give up if the expression is larger than the MAX that we allow.  */
    if (size_expr++ > PARAM_VALUE (PARAM_SCEV_MAX_EXPR_SIZE))
*************** instantiate_scev_r (basic_block instanti
*** 2674,2685 ****
      case SSA_NAME:
        return instantiate_scev_name (instantiate_below, evolution_loop,
  				    inner_loop, chrec,
! 				    fold_conversions, cache, size_expr);
  
      case POLYNOMIAL_CHREC:
        return instantiate_scev_poly (instantiate_below, evolution_loop,
  				    inner_loop, chrec,
! 				    fold_conversions, cache, size_expr);
  
      case POINTER_PLUS_EXPR:
      case PLUS_EXPR:
--- 2650,2661 ----
      case SSA_NAME:
        return instantiate_scev_name (instantiate_below, evolution_loop,
  				    inner_loop, chrec,
! 				    fold_conversions, size_expr);
  
      case POLYNOMIAL_CHREC:
        return instantiate_scev_poly (instantiate_below, evolution_loop,
  				    inner_loop, chrec,
! 				    fold_conversions, size_expr);
  
      case POINTER_PLUS_EXPR:
      case PLUS_EXPR:
*************** instantiate_scev_r (basic_block instanti
*** 2690,2702 ****
  				      TREE_CODE (chrec), chrec_type (chrec),
  				      TREE_OPERAND (chrec, 0),
  				      TREE_OPERAND (chrec, 1),
! 				      fold_conversions, cache, size_expr);
  
      CASE_CONVERT:
        return instantiate_scev_convert (instantiate_below, evolution_loop,
  				       inner_loop, chrec,
  				       TREE_TYPE (chrec), TREE_OPERAND (chrec, 0),
! 				       fold_conversions, cache, size_expr);
  
      case NEGATE_EXPR:
      case BIT_NOT_EXPR:
--- 2666,2678 ----
  				      TREE_CODE (chrec), chrec_type (chrec),
  				      TREE_OPERAND (chrec, 0),
  				      TREE_OPERAND (chrec, 1),
! 				      fold_conversions, size_expr);
  
      CASE_CONVERT:
        return instantiate_scev_convert (instantiate_below, evolution_loop,
  				       inner_loop, chrec,
  				       TREE_TYPE (chrec), TREE_OPERAND (chrec, 0),
! 				       fold_conversions, size_expr);
  
      case NEGATE_EXPR:
      case BIT_NOT_EXPR:
*************** instantiate_scev_r (basic_block instanti
*** 2704,2710 ****
  				   inner_loop, chrec,
  				   TREE_CODE (chrec), TREE_TYPE (chrec),
  				   TREE_OPERAND (chrec, 0),
! 				   fold_conversions, cache, size_expr);
  
      case ADDR_EXPR:
      case SCEV_NOT_KNOWN:
--- 2680,2686 ----
  				   inner_loop, chrec,
  				   TREE_CODE (chrec), TREE_TYPE (chrec),
  				   TREE_OPERAND (chrec, 0),
! 				   fold_conversions, size_expr);
  
      case ADDR_EXPR:
      case SCEV_NOT_KNOWN:
*************** instantiate_scev_r (basic_block instanti
*** 2716,2722 ****
      case ARRAY_REF:
        return instantiate_array_ref (instantiate_below, evolution_loop,
  				    inner_loop, chrec,
! 				    fold_conversions, cache, size_expr);
  
      default:
        break;
--- 2692,2698 ----
      case ARRAY_REF:
        return instantiate_array_ref (instantiate_below, evolution_loop,
  				    inner_loop, chrec,
! 				    fold_conversions, size_expr);
  
      default:
        break;
*************** instantiate_scev_r (basic_block instanti
*** 2730,2746 ****
      case 3:
        return instantiate_scev_3 (instantiate_below, evolution_loop,
  				 inner_loop, chrec,
! 				 fold_conversions, cache, size_expr);
  
      case 2:
        return instantiate_scev_2 (instantiate_below, evolution_loop,
  				 inner_loop, chrec,
! 				 fold_conversions, cache, size_expr);
  
      case 1:
        return instantiate_scev_1 (instantiate_below, evolution_loop,
  				 inner_loop, chrec,
! 				 fold_conversions, cache, size_expr);
  
      case 0:
        return chrec;
--- 2706,2722 ----
      case 3:
        return instantiate_scev_3 (instantiate_below, evolution_loop,
  				 inner_loop, chrec,
! 				 fold_conversions, size_expr);
  
      case 2:
        return instantiate_scev_2 (instantiate_below, evolution_loop,
  				 inner_loop, chrec,
! 				 fold_conversions, size_expr);
  
      case 1:
        return instantiate_scev_1 (instantiate_below, evolution_loop,
  				 inner_loop, chrec,
! 				 fold_conversions, size_expr);
  
      case 0:
        return chrec;
*************** instantiate_scev (basic_block instantiat
*** 2764,2770 ****
  		  tree chrec)
  {
    tree res;
-   instantiate_cache_type cache;
  
    if (dump_file && (dump_flags & TDF_SCEV))
      {
--- 2740,2745 ----
*************** instantiate_scev (basic_block instantiat
*** 2776,2783 ****
        fprintf (dump_file, ")\n");
      }
  
    res = instantiate_scev_r (instantiate_below, evolution_loop,
! 			    NULL, chrec, false, cache, 0);
  
    if (dump_file && (dump_flags & TDF_SCEV))
      {
--- 2751,2771 ----
        fprintf (dump_file, ")\n");
      }
  
+   bool destr = false;
+   if (!global_cache)
+     {
+       global_cache = new instantiate_cache_type;
+       destr = true;
+     }
+ 
    res = instantiate_scev_r (instantiate_below, evolution_loop,
! 			    NULL, chrec, false, 0);
! 
!   if (destr)
!     {
!       delete global_cache;
!       global_cache = NULL;
!     }
  
    if (dump_file && (dump_flags & TDF_SCEV))
      {
*************** instantiate_scev (basic_block instantiat
*** 2797,2805 ****
  tree
  resolve_mixers (struct loop *loop, tree chrec)
  {
!   instantiate_cache_type cache;
    tree ret = instantiate_scev_r (block_before_loop (loop), loop, NULL,
! 				 chrec, true, cache, 0);
    return ret;
  }
  
--- 2785,2806 ----
  tree
  resolve_mixers (struct loop *loop, tree chrec)
  {
!   bool destr = false;
!   if (!global_cache)
!     {
!       global_cache = new instantiate_cache_type;
!       destr = true;
!     }
! 
    tree ret = instantiate_scev_r (block_before_loop (loop), loop, NULL,
! 				 chrec, true, 0);
! 
!   if (destr)
!     {
!       delete global_cache;
!       global_cache = NULL;
!     }
! 
    return ret;
  }
  
Index: gcc/testsuite/gcc.dg/torture/pr58417.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr58417.c	(revision 0)
--- gcc/testsuite/gcc.dg/torture/pr58417.c	(working copy)
***************
*** 0 ****
--- 1,25 ----
+ /* { dg-do run } */
+ 
+ long long arr[6] = {0, 1, 2, 3, 4, 5};
+ extern  void abort (void);
+ void __attribute__((noinline,noclone))
+ foo (long long sum)
+ {
+   asm ("");
+ }
+ int main()
+ {
+   int i, n = 5;
+   long long sum = 0, prevsum = 0;
+ 
+   for(i = 1; i <= n; i++)
+     {
+       foo (sum);
+       sum = (i - 1) * arr[i] - prevsum;
+       prevsum += arr[i];
+     }
+ 
+   if (sum != 10)
+     abort ();
+   return 0;
+ }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]