public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Fix PR55555
@ 2012-12-17 12:54 Richard Biener
  2012-12-17 15:28 ` Richard Biener
  0 siblings, 1 reply; 3+ messages in thread
From: Richard Biener @ 2012-12-17 12:54 UTC (permalink / raw)
  To: gcc-patches


The following patch fixes a miscompilation due to bogus loop iteration
bound derived from array accesses in an inner loop.  idx_infer_loop_bounds
analyzes the evoultion of an SSA name with respect to a loop it is not
defined in - which seems to lead to random weird behavior.  The correct
thing to do (as documented) is to analyze the evolution with respect
to the loop the stmt we are interested in is in.

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

Thanks,
Richard.

2012-12-17  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/55555
	* tree-ssa-loop-niter.c (idx_infer_loop_bounds): Properly
	analyze evolution of the index for the loop it is used in.

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

Index: gcc/tree-ssa-loop-niter.c
===================================================================
*** gcc/tree-ssa-loop-niter.c	(revision 194552)
--- gcc/tree-ssa-loop-niter.c	(working copy)
*************** idx_infer_loop_bounds (tree base, tree *
*** 2671,2677 ****
        upper = false;
      }
  
!   ev = instantiate_parameters (loop, analyze_scalar_evolution (loop, *idx));
    init = initial_condition (ev);
    step = evolution_part_in_loop_num (ev, loop->num);
  
--- 2671,2682 ----
        upper = false;
      }
  
!   struct loop *dloop = loop_containing_stmt (data->stmt);
!   if (!dloop)
!     return true;
! 
!   ev = analyze_scalar_evolution (dloop, *idx);
!   ev = instantiate_parameters (loop, ev);
    init = initial_condition (ev);
    step = evolution_part_in_loop_num (ev, loop->num);
  
Index: gcc/testsuite/gcc.dg/torture/pr55555.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr55555.c	(revision 0)
--- gcc/testsuite/gcc.dg/torture/pr55555.c	(working copy)
***************
*** 0 ****
--- 1,34 ----
+ /* { dg-do run } */
+ 
+ double s[4] = { 1.0, 2.0, 3.0, 4.0 }, pol_x[2] = { 5.0, 6.0 };
+ 
+ __attribute__((noinline)) int
+ foo (void)
+ {
+   double coef_x[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+   int lxp = 0;
+   if (lxp <= 1)
+     do
+       {
+ 	double t = pol_x[lxp];
+ 	long S;
+ 	long l = lxp * 4L - 1;
+ 	for (S = 1; S <= 4; S++)
+ 	  coef_x[S + l] = coef_x[S + l] + s[S - 1] * t;
+       }
+     while (lxp++ != 1);
+   asm volatile ("" : : "r" (coef_x) : "memory");
+   for (lxp = 0; lxp < 8; lxp++)
+     if (coef_x[lxp] != ((lxp & 3) + 1) * (5.0 + (lxp >= 4)))
+       __builtin_abort ();
+   return 1;
+ }
+ 
+ int
+ main ()
+ {
+   asm volatile ("" : : : "memory");
+   if (!foo ())
+     __builtin_abort ();
+   return 0;
+ }

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] Fix PR55555
  2012-12-17 12:54 [PATCH] Fix PR55555 Richard Biener
@ 2012-12-17 15:28 ` Richard Biener
  2012-12-18 13:04   ` Richard Biener
  0 siblings, 1 reply; 3+ messages in thread
From: Richard Biener @ 2012-12-17 15:28 UTC (permalink / raw)
  To: gcc-patches

On Mon, 17 Dec 2012, Richard Biener wrote:

> 
> The following patch fixes a miscompilation due to bogus loop iteration
> bound derived from array accesses in an inner loop.  idx_infer_loop_bounds
> analyzes the evoultion of an SSA name with respect to a loop it is not
> defined in - which seems to lead to random weird behavior.  The correct
> thing to do (as documented) is to analyze the evolution with respect
> to the loop the stmt we are interested in is in.
> 
> Bootstrap and regtest ongoing on x86_64-unknown-linux-gnu.

Which shows that the very old fix for PR40281 isn't complete
(the patch regresses PR55687 again).  So the following extends
that fix.  I wonder whether we instead want to pass down
CHREC_VARIABLE and avoid doing the instantiation in the first
place ...

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

Comments welcome.

Thanks,
Richard.

2012-12-17  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/55555
	* tree-ssa-loop-niter.c (idx_infer_loop_bounds): Properly
	analyze evolution of the index for the loop it is used in.
	* tree-scalar-evolution.c (instantiate_scev_poly): Generalize
	fix for PR40281 and prune invalid SCEVs.

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

Index: gcc/tree-ssa-loop-niter.c
===================================================================
*** gcc/tree-ssa-loop-niter.c	(revision 194552)
--- gcc/tree-ssa-loop-niter.c	(working copy)
*************** idx_infer_loop_bounds (tree base, tree *
*** 2671,2677 ****
        upper = false;
      }
  
!   ev = instantiate_parameters (loop, analyze_scalar_evolution (loop, *idx));
    init = initial_condition (ev);
    step = evolution_part_in_loop_num (ev, loop->num);
  
--- 2671,2682 ----
        upper = false;
      }
  
!   struct loop *dloop = loop_containing_stmt (data->stmt);
!   if (!dloop)
!     return true;
! 
!   ev = analyze_scalar_evolution (dloop, *idx);
!   ev = instantiate_parameters (loop, ev);
    init = initial_condition (ev);
    step = evolution_part_in_loop_num (ev, loop->num);
  
Index: gcc/tree-scalar-evolution.c
===================================================================
*** gcc/tree-scalar-evolution.c	(revision 194552)
--- gcc/tree-scalar-evolution.c	(working copy)
*************** instantiate_scev_poly (basic_block insta
*** 2268,2295 ****
    if (op0 == chrec_dont_know)
      return chrec_dont_know;
  
    op1 = instantiate_scev_r (instantiate_below, evolution_loop,
  			    CHREC_RIGHT (chrec), fold_conversions, cache,
  			    size_expr);
    if (op1 == chrec_dont_know)
      return chrec_dont_know;
  
!   if (CHREC_LEFT (chrec) != op0
!       || CHREC_RIGHT (chrec) != op1)
      {
!       unsigned var = CHREC_VARIABLE (chrec);
! 
!       /* When the instantiated stride or base has an evolution in an
! 	 innermost loop, return chrec_dont_know, as this is not a
! 	 valid SCEV representation.  In the reduced testcase for
! 	 PR40281 we would have {0, +, {1, +, 1}_2}_1 that has no
! 	 meaning.  */
!       if ((tree_is_chrec (op0) && CHREC_VARIABLE (op0) > var)
! 	  || (tree_is_chrec (op1) && CHREC_VARIABLE (op1) > var))
  	return chrec_dont_know;
  
        op1 = chrec_convert_rhs (chrec_type (op0), op1, NULL);
!       chrec = build_polynomial_chrec (var, op0, op1);
      }
  
    return chrec;
--- 2268,2322 ----
    if (op0 == chrec_dont_know)
      return chrec_dont_know;
  
+   /* When the instantiated stride or base has an evolution in an
+      innermost loop, return chrec_dont_know, as this is not a
+      valid SCEV representation.  In the reduced testcase for
+      PR40281 we would have {0, +, {1, +, 1}_2}_1 that has no
+      meaning.  */
+   if (tree_does_not_contain_chrecs (op0))
+     ;
+   else
+     {
+       tree tem = op0;
+       while (TREE_CODE (tem) != POLYNOMIAL_CHREC)
+ 	{
+ 	  if (CONVERT_EXPR_P (tem))
+ 	    tem = TREE_OPERAND (tem, 0);
+ 	  else
+ 	    return chrec_dont_know;
+ 	}
+       if (!flow_loop_nested_p (get_chrec_loop (tem), get_chrec_loop (chrec)))
+ 	return chrec_dont_know;
+     }
+ 
    op1 = instantiate_scev_r (instantiate_below, evolution_loop,
  			    CHREC_RIGHT (chrec), fold_conversions, cache,
  			    size_expr);
    if (op1 == chrec_dont_know)
      return chrec_dont_know;
  
!   /* See above.  */
!   if (tree_does_not_contain_chrecs (op1))
!     ;
!   else
      {
!       tree tem = op1;
!       while (TREE_CODE (tem) != POLYNOMIAL_CHREC)
! 	{
! 	  if (CONVERT_EXPR_P (tem))
! 	    tem = TREE_OPERAND (tem, 0);
! 	  else
! 	    return chrec_dont_know;
! 	}
!       if (!flow_loop_nested_p (get_chrec_loop (tem), get_chrec_loop (chrec)))
  	return chrec_dont_know;
+     }
  
+   if (CHREC_LEFT (chrec) != op0
+       || CHREC_RIGHT (chrec) != op1)
+     {
        op1 = chrec_convert_rhs (chrec_type (op0), op1, NULL);
!       chrec = build_polynomial_chrec (CHREC_VARIABLE (chrec), op0, op1);
      }
  
    return chrec;
Index: gcc/testsuite/gcc.dg/torture/pr55555.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr55555.c	(revision 0)
--- gcc/testsuite/gcc.dg/torture/pr55555.c	(working copy)
***************
*** 0 ****
--- 1,34 ----
+ /* { dg-do run } */
+ 
+ double s[4] = { 1.0, 2.0, 3.0, 4.0 }, pol_x[2] = { 5.0, 6.0 };
+ 
+ __attribute__((noinline)) int
+ foo (void)
+ {
+   double coef_x[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+   int lxp = 0;
+   if (lxp <= 1)
+     do
+       {
+ 	double t = pol_x[lxp];
+ 	long S;
+ 	long l = lxp * 4L - 1;
+ 	for (S = 1; S <= 4; S++)
+ 	  coef_x[S + l] = coef_x[S + l] + s[S - 1] * t;
+       }
+     while (lxp++ != 1);
+   asm volatile ("" : : "r" (coef_x) : "memory");
+   for (lxp = 0; lxp < 8; lxp++)
+     if (coef_x[lxp] != ((lxp & 3) + 1) * (5.0 + (lxp >= 4)))
+       __builtin_abort ();
+   return 1;
+ }
+ 
+ int
+ main ()
+ {
+   asm volatile ("" : : : "memory");
+   if (!foo ())
+     __builtin_abort ();
+   return 0;
+ }

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] Fix PR55555
  2012-12-17 15:28 ` Richard Biener
@ 2012-12-18 13:04   ` Richard Biener
  0 siblings, 0 replies; 3+ messages in thread
From: Richard Biener @ 2012-12-18 13:04 UTC (permalink / raw)
  To: gcc-patches

On Mon, 17 Dec 2012, Richard Biener wrote:

> On Mon, 17 Dec 2012, Richard Biener wrote:
> 
> > 
> > The following patch fixes a miscompilation due to bogus loop iteration
> > bound derived from array accesses in an inner loop.  idx_infer_loop_bounds
> > analyzes the evoultion of an SSA name with respect to a loop it is not
> > defined in - which seems to lead to random weird behavior.  The correct
> > thing to do (as documented) is to analyze the evolution with respect
> > to the loop the stmt we are interested in is in.
> > 
> > Bootstrap and regtest ongoing on x86_64-unknown-linux-gnu.
> 
> Which shows that the very old fix for PR40281 isn't complete
> (the patch regresses PR55687 again).  So the following extends
> that fix.  I wonder whether we instead want to pass down
> CHREC_VARIABLE and avoid doing the instantiation in the first
> place ...

So I revisited this and reworked it so that it avoids doing the
instantiation in the first place.  Which makes SCEV stronger
so I need to fixup gcc.dg/vect/vect-iv-11.c (now two vectorized
locations, one in the inlined copy in main).  Also with this
patch I see

FAIL: gcc.dg/tree-ssa/reassoc-19.c scan-tree-dump-times reassoc2 " \\\\+ " 
0

as we now have

  <bb 2>:
  goto <bb 4>;

  <bb 3>:
  _7 = (sizetype) element_6(D);
  _8 = -_7;
  rite_9 = rite_1 + _8;
  bar (left_5(D), rite_9, element_6(D));

  <bb 4>:
  # rite_1 = PHI <rite_3(D)(2), rite_9(3)>
  if (left_5(D) <= rite_1)
    goto <bb 3>;
  else
    goto <bb 5>;

while before we had

<bb 2>:
  goto <bb 4>;

<bb 3>:
  D.1716_5 = (long unsigned int) element_4(D);
  D.1717_6 = -D.1716_5;
  D.1733_12 = (sizetype) rite_1;
  D.1734_11 = (long unsigned int) element_4(D);
  D.1735_13 = -D.1734_11;
  D.1736_14 = D.1733_12 - D.1734_11;
  D.1737_15 = (char *) D.1736_14;
  rite_7 = D.1737_15;
  bar (left_3(D), rite_7, element_4(D));

<bb 4>:
  # rite_1 = PHI <rite_2(D)(2), rite_7(3)>
  if (left_3(D) <= rite_1)
    goto <bb 3>;
  else
    goto <bb 5>;

I will investigate what the original bug was about and come up
with a fix (likely to the testcase) as a followup.

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

Richard.

2012-12-18  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/55555
	* tree-ssa-loop-niter.c (idx_infer_loop_bounds): Properly
	analyze evolution of the index for the loop it is used in.
	* tree-scalar-evolution.c (instantiate_scev_name): Take
	inner loop we will be creating a chrec for.  Generalize
	fix for PR40281 and prune invalid SCEVs.
	(instantiate_scev_poly): Likewise - pass down inner loop
	we will be creating a chrec for.
	(instantiate_scev_binary): Take and pass through inner loop.
	(instantiate_array_ref): Likewise.
	(instantiate_scev_convert): Likewise.
	(instantiate_scev_not): Likewise.
	(instantiate_scev_3): Likewise.
	(instantiate_scev_2): Likewise.
	(instantiate_scev_1): Likewise.
	(instantiate_scev_r): Likewise.
	(resolve_mixers): Adjust.
	(instantiate_scev): Likewise.

	* gcc.dg/torture/pr55555.c: New testcase.
	* gcc.dg/vect/vect-iv-11.c: Adjust.

Index: gcc/tree-ssa-loop-niter.c
===================================================================
*** gcc/tree-ssa-loop-niter.c	(revision 194552)
--- gcc/tree-ssa-loop-niter.c	(working copy)
*************** idx_infer_loop_bounds (tree base, tree *
*** 2671,2677 ****
        upper = false;
      }
  
!   ev = instantiate_parameters (loop, analyze_scalar_evolution (loop, *idx));
    init = initial_condition (ev);
    step = evolution_part_in_loop_num (ev, loop->num);
  
--- 2671,2682 ----
        upper = false;
      }
  
!   struct loop *dloop = loop_containing_stmt (data->stmt);
!   if (!dloop)
!     return true;
! 
!   ev = analyze_scalar_evolution (dloop, *idx);
!   ev = instantiate_parameters (loop, ev);
    init = initial_condition (ev);
    step = evolution_part_in_loop_num (ev, loop->num);
  
Index: gcc/tree-scalar-evolution.c
===================================================================
*** gcc/tree-scalar-evolution.c	(revision 194552)
--- gcc/tree-scalar-evolution.c	(working copy)
*************** loop_closed_phi_def (tree var)
*** 2147,2154 ****
    return NULL_TREE;
  }
  
! static tree instantiate_scev_r (basic_block, struct loop *, tree, bool,
! 				htab_t, int);
  
  /* Analyze all the parameters of the chrec, between INSTANTIATE_BELOW
     and EVOLUTION_LOOP, that were left under a symbolic form.
--- 2147,2154 ----
    return NULL_TREE;
  }
  
! static tree instantiate_scev_r (basic_block, struct loop *, struct loop *,
! 				tree, bool, htab_t, int);
  
  /* Analyze all the parameters of the chrec, between INSTANTIATE_BELOW
     and EVOLUTION_LOOP, that were left under a symbolic form.
*************** static tree instantiate_scev_r (basic_bl
*** 2166,2172 ****
  
  static tree
  instantiate_scev_name (basic_block instantiate_below,
! 		       struct loop *evolution_loop, tree chrec,
  		       bool fold_conversions, htab_t cache, int size_expr)
  {
    tree res;
--- 2166,2173 ----
  
  static tree
  instantiate_scev_name (basic_block instantiate_below,
! 		       struct loop *evolution_loop, struct loop *inner_loop,
! 		       tree chrec,
  		       bool fold_conversions, htab_t cache, int size_expr)
  {
    tree res;
*************** instantiate_scev_name (basic_block insta
*** 2225,2231 ****
  	  loop_p loop = loop_containing_stmt (SSA_NAME_DEF_STMT (chrec));
  	  res = analyze_scalar_evolution (loop, chrec);
  	  res = compute_overall_effect_of_inner_loop (loop, res);
! 	  res = instantiate_scev_r (instantiate_below, evolution_loop, res,
  				    fold_conversions, cache, size_expr);
  	}
        else if (!dominated_by_p (CDI_DOMINATORS, instantiate_below,
--- 2226,2233 ----
  	  loop_p loop = loop_containing_stmt (SSA_NAME_DEF_STMT (chrec));
  	  res = analyze_scalar_evolution (loop, chrec);
  	  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,
*************** instantiate_scev_name (basic_block insta
*** 2234,2241 ****
      }
  
    else if (res != chrec_dont_know)
!     res = instantiate_scev_r (instantiate_below, evolution_loop, res,
! 			      fold_conversions, cache, size_expr);
  
    /* Store the correct value to the cache.  */
    set_instantiated_value (cache, instantiate_below, chrec, res);
--- 2236,2251 ----
      }
  
    else if (res != chrec_dont_know)
!     {
!       if (inner_loop
! 	  && !flow_loop_nested_p (def_bb->loop_father, inner_loop))
! 	/* ???  We could try to compute the overall effect of the loop here.  */
! 	res = chrec_dont_know;
!       else
! 	res = instantiate_scev_r (instantiate_below, evolution_loop,
! 				  inner_loop, res,
! 				  fold_conversions, cache, size_expr);
!     }
  
    /* Store the correct value to the cache.  */
    set_instantiated_value (cache, instantiate_below, chrec, res);
*************** instantiate_scev_name (basic_block insta
*** 2258,2274 ****
  
  static tree
  instantiate_scev_poly (basic_block instantiate_below,
! 		       struct loop *evolution_loop, tree chrec,
  		       bool fold_conversions, htab_t cache, int size_expr)
  {
    tree op1;
    tree op0 = instantiate_scev_r (instantiate_below, evolution_loop,
  				 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,
  			    CHREC_RIGHT (chrec), fold_conversions, cache,
  			    size_expr);
    if (op1 == chrec_dont_know)
--- 2268,2287 ----
  
  static tree
  instantiate_scev_poly (basic_block instantiate_below,
! 		       struct loop *evolution_loop, struct loop *,
! 		       tree chrec,
  		       bool fold_conversions, htab_t 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)
*************** instantiate_scev_poly (basic_block insta
*** 2277,2295 ****
    if (CHREC_LEFT (chrec) != op0
        || CHREC_RIGHT (chrec) != op1)
      {
-       unsigned var = CHREC_VARIABLE (chrec);
- 
-       /* When the instantiated stride or base has an evolution in an
- 	 innermost loop, return chrec_dont_know, as this is not a
- 	 valid SCEV representation.  In the reduced testcase for
- 	 PR40281 we would have {0, +, {1, +, 1}_2}_1 that has no
- 	 meaning.  */
-       if ((tree_is_chrec (op0) && CHREC_VARIABLE (op0) > var)
- 	  || (tree_is_chrec (op1) && CHREC_VARIABLE (op1) > var))
- 	return chrec_dont_know;
- 
        op1 = chrec_convert_rhs (chrec_type (op0), op1, NULL);
!       chrec = build_polynomial_chrec (var, op0, op1);
      }
  
    return chrec;
--- 2290,2297 ----
    if (CHREC_LEFT (chrec) != op0
        || CHREC_RIGHT (chrec) != op1)
      {
        op1 = chrec_convert_rhs (chrec_type (op0), op1, NULL);
!       chrec = build_polynomial_chrec (CHREC_VARIABLE (chrec), op0, op1);
      }
  
    return chrec;
*************** instantiate_scev_poly (basic_block insta
*** 2311,2328 ****
  
  static tree
  instantiate_scev_binary (basic_block instantiate_below,
! 			 struct loop *evolution_loop, tree chrec, enum tree_code code,
  			 tree type, tree c0, tree c1,
  			 bool fold_conversions, htab_t cache, int size_expr)
  {
    tree op1;
!   tree op0 = instantiate_scev_r (instantiate_below, evolution_loop,
  				 c0, fold_conversions, cache,
  				 size_expr);
    if (op0 == chrec_dont_know)
      return chrec_dont_know;
  
!   op1 = instantiate_scev_r (instantiate_below, evolution_loop,
  			    c1, fold_conversions, cache,
  			    size_expr);
    if (op1 == chrec_dont_know)
--- 2313,2331 ----
  
  static tree
  instantiate_scev_binary (basic_block instantiate_below,
! 			 struct loop *evolution_loop, struct loop *inner_loop,
! 			 tree chrec, enum tree_code code,
  			 tree type, tree c0, tree c1,
  			 bool fold_conversions, htab_t 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)
*************** instantiate_scev_binary (basic_block ins
*** 2370,2381 ****
  
  static tree
  instantiate_array_ref (basic_block instantiate_below,
! 		       struct loop *evolution_loop, tree chrec,
  		       bool fold_conversions, htab_t cache, int size_expr)
  {
    tree res;
    tree index = TREE_OPERAND (chrec, 1);
!   tree op1 = instantiate_scev_r (instantiate_below, evolution_loop, index,
  				 fold_conversions, cache, size_expr);
  
    if (op1 == chrec_dont_know)
--- 2373,2386 ----
  
  static tree
  instantiate_array_ref (basic_block instantiate_below,
! 		       struct loop *evolution_loop, struct loop *inner_loop,
! 		       tree chrec,
  		       bool fold_conversions, htab_t 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)
*************** instantiate_array_ref (basic_block insta
*** 2406,2416 ****
  
  static tree
  instantiate_scev_convert (basic_block instantiate_below,
! 			  struct loop *evolution_loop, tree chrec,
  			  tree type, tree op,
  			  bool fold_conversions, htab_t cache, int size_expr)
  {
!   tree op0 = instantiate_scev_r (instantiate_below, evolution_loop, op,
  				 fold_conversions, cache, size_expr);
  
    if (op0 == chrec_dont_know)
--- 2411,2423 ----
  
  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, htab_t 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)
*************** instantiate_scev_convert (basic_block in
*** 2453,2463 ****
  
  static tree
  instantiate_scev_not (basic_block instantiate_below,
! 		      struct loop *evolution_loop, tree chrec,
  		      enum tree_code code, tree type, tree op,
  		      bool fold_conversions, htab_t cache, int size_expr)
  {
!   tree op0 = instantiate_scev_r (instantiate_below, evolution_loop, op,
  				 fold_conversions, cache, size_expr);
  
    if (op0 == chrec_dont_know)
--- 2460,2472 ----
  
  static tree
  instantiate_scev_not (basic_block instantiate_below,
! 		      struct loop *evolution_loop, struct loop *inner_loop,
! 		      tree chrec,
  		      enum tree_code code, tree type, tree op,
  		      bool fold_conversions, htab_t 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)
*************** instantiate_scev_not (basic_block instan
*** 2501,2524 ****
  
  static tree
  instantiate_scev_3 (basic_block instantiate_below,
! 		    struct loop *evolution_loop, tree chrec,
  		    bool fold_conversions, htab_t cache, int size_expr)
  {
    tree op1, op2;
    tree op0 = instantiate_scev_r (instantiate_below, evolution_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,
! 			    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,
! 			    TREE_OPERAND (chrec, 2),
  			    fold_conversions, cache, size_expr);
    if (op2 == chrec_dont_know)
      return chrec_dont_know;
--- 2510,2534 ----
  
  static tree
  instantiate_scev_3 (basic_block instantiate_below,
! 		    struct loop *evolution_loop, struct loop *inner_loop,
! 		    tree chrec,
  		    bool fold_conversions, htab_t 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;
*************** instantiate_scev_3 (basic_block instanti
*** 2548,2565 ****
  
  static tree
  instantiate_scev_2 (basic_block instantiate_below,
! 		    struct loop *evolution_loop, tree chrec,
  		    bool fold_conversions, htab_t cache, int size_expr)
  {
    tree op1;
    tree op0 = instantiate_scev_r (instantiate_below, evolution_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,
! 			    TREE_OPERAND (chrec, 1),
  			    fold_conversions, cache, size_expr);
    if (op1 == chrec_dont_know)
      return chrec_dont_know;
--- 2558,2576 ----
  
  static tree
  instantiate_scev_2 (basic_block instantiate_below,
! 		    struct loop *evolution_loop, struct loop *inner_loop,
! 		    tree chrec,
  		    bool fold_conversions, htab_t 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;
*************** instantiate_scev_2 (basic_block instanti
*** 2587,2597 ****
  
  static tree
  instantiate_scev_1 (basic_block instantiate_below,
! 		    struct loop *evolution_loop, tree chrec,
  		    bool fold_conversions, htab_t cache, int size_expr)
  {
    tree op0 = instantiate_scev_r (instantiate_below, evolution_loop,
! 				 TREE_OPERAND (chrec, 0),
  				 fold_conversions, cache, size_expr);
  
    if (op0 == chrec_dont_know)
--- 2598,2609 ----
  
  static tree
  instantiate_scev_1 (basic_block instantiate_below,
! 		    struct loop *evolution_loop, struct loop *inner_loop,
! 		    tree chrec,
  		    bool fold_conversions, htab_t 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)
*************** instantiate_scev_1 (basic_block instanti
*** 2619,2625 ****
  
  static tree
  instantiate_scev_r (basic_block instantiate_below,
! 		    struct loop *evolution_loop, tree chrec,
  		    bool fold_conversions, htab_t cache, int size_expr)
  {
    /* Give up if the expression is larger than the MAX that we allow.  */
--- 2631,2638 ----
  
  static tree
  instantiate_scev_r (basic_block instantiate_below,
! 		    struct loop *evolution_loop, struct loop *inner_loop,
! 		    tree chrec,
  		    bool fold_conversions, htab_t cache, int size_expr)
  {
    /* Give up if the expression is larger than the MAX that we allow.  */
*************** instantiate_scev_r (basic_block instanti
*** 2634,2664 ****
    switch (TREE_CODE (chrec))
      {
      case SSA_NAME:
!       return instantiate_scev_name (instantiate_below, evolution_loop, chrec,
  				    fold_conversions, cache, size_expr);
  
      case POLYNOMIAL_CHREC:
!       return instantiate_scev_poly (instantiate_below, evolution_loop, chrec,
  				    fold_conversions, cache, size_expr);
  
      case POINTER_PLUS_EXPR:
      case PLUS_EXPR:
      case MINUS_EXPR:
      case MULT_EXPR:
!       return instantiate_scev_binary (instantiate_below, evolution_loop, chrec,
  				      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, chrec,
  				       TREE_TYPE (chrec), TREE_OPERAND (chrec, 0),
  				       fold_conversions, cache, size_expr);
  
      case NEGATE_EXPR:
      case BIT_NOT_EXPR:
!       return instantiate_scev_not (instantiate_below, evolution_loop, chrec,
  				   TREE_CODE (chrec), TREE_TYPE (chrec),
  				   TREE_OPERAND (chrec, 0),
  				   fold_conversions, cache, size_expr);
--- 2647,2682 ----
    switch (TREE_CODE (chrec))
      {
      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:
      case MINUS_EXPR:
      case MULT_EXPR:
!       return instantiate_scev_binary (instantiate_below, evolution_loop,
! 				      inner_loop, chrec,
  				      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:
!       return instantiate_scev_not (instantiate_below, evolution_loop,
! 				   inner_loop, chrec,
  				   TREE_CODE (chrec), TREE_TYPE (chrec),
  				   TREE_OPERAND (chrec, 0),
  				   fold_conversions, cache, size_expr);
*************** instantiate_scev_r (basic_block instanti
*** 2671,2677 ****
        return chrec_known;
  
      case ARRAY_REF:
!       return instantiate_array_ref (instantiate_below, evolution_loop, chrec,
  				    fold_conversions, cache, size_expr);
  
      default:
--- 2689,2696 ----
        return chrec_known;
  
      case ARRAY_REF:
!       return instantiate_array_ref (instantiate_below, evolution_loop,
! 				    inner_loop, chrec,
  				    fold_conversions, cache, size_expr);
  
      default:
*************** instantiate_scev_r (basic_block instanti
*** 2684,2698 ****
    switch (TREE_CODE_LENGTH (TREE_CODE (chrec)))
      {
      case 3:
!       return instantiate_scev_3 (instantiate_below, evolution_loop, chrec,
  				 fold_conversions, cache, size_expr);
  
      case 2:
!       return instantiate_scev_2 (instantiate_below, evolution_loop, chrec,
  				 fold_conversions, cache, size_expr);
  
      case 1:
!       return instantiate_scev_1 (instantiate_below, evolution_loop, chrec,
  				 fold_conversions, cache, size_expr);
  
      case 0:
--- 2703,2720 ----
    switch (TREE_CODE_LENGTH (TREE_CODE (chrec)))
      {
      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:
*************** instantiate_scev (basic_block instantiat
*** 2729,2736 ****
        fprintf (dump_file, ")\n");
      }
  
!   res = instantiate_scev_r (instantiate_below, evolution_loop, chrec, false,
! 			    cache, 0);
  
    if (dump_file && (dump_flags & TDF_SCEV))
      {
--- 2751,2758 ----
        fprintf (dump_file, ")\n");
      }
  
!   res = instantiate_scev_r (instantiate_below, evolution_loop,
! 			    NULL, chrec, false, cache, 0);
  
    if (dump_file && (dump_flags & TDF_SCEV))
      {
*************** tree
*** 2753,2760 ****
  resolve_mixers (struct loop *loop, tree chrec)
  {
    htab_t cache = htab_create (10, hash_scev_info, eq_scev_info, del_scev_info);
!   tree ret = instantiate_scev_r (block_before_loop (loop), loop, chrec, true,
! 				 cache, 0);
    htab_delete (cache);
    return ret;
  }
--- 2775,2782 ----
  resolve_mixers (struct loop *loop, tree chrec)
  {
    htab_t cache = htab_create (10, hash_scev_info, eq_scev_info, del_scev_info);
!   tree ret = instantiate_scev_r (block_before_loop (loop), loop, NULL,
! 				 chrec, true, cache, 0);
    htab_delete (cache);
    return ret;
  }
Index: gcc/testsuite/gcc.dg/torture/pr55555.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr55555.c	(revision 0)
--- gcc/testsuite/gcc.dg/torture/pr55555.c	(working copy)
***************
*** 0 ****
--- 1,34 ----
+ /* { dg-do run } */
+ 
+ double s[4] = { 1.0, 2.0, 3.0, 4.0 }, pol_x[2] = { 5.0, 6.0 };
+ 
+ __attribute__((noinline)) int
+ foo (void)
+ {
+   double coef_x[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+   int lxp = 0;
+   if (lxp <= 1)
+     do
+       {
+ 	double t = pol_x[lxp];
+ 	long S;
+ 	long l = lxp * 4L - 1;
+ 	for (S = 1; S <= 4; S++)
+ 	  coef_x[S + l] = coef_x[S + l] + s[S - 1] * t;
+       }
+     while (lxp++ != 1);
+   asm volatile ("" : : "r" (coef_x) : "memory");
+   for (lxp = 0; lxp < 8; lxp++)
+     if (coef_x[lxp] != ((lxp & 3) + 1) * (5.0 + (lxp >= 4)))
+       __builtin_abort ();
+   return 1;
+ }
+ 
+ int
+ main ()
+ {
+   asm volatile ("" : : : "memory");
+   if (!foo ())
+     __builtin_abort ();
+   return 0;
+ }
Index: gcc/testsuite/gcc.dg/vect/vect-iv-11.c
===================================================================
*** gcc/testsuite/gcc.dg/vect/vect-iv-11.c	(revision 194552)
--- gcc/testsuite/gcc.dg/vect/vect-iv-11.c	(working copy)
***************
*** 3,9 ****
  #include <stdarg.h>
  #include "tree-vect.h"
  
! int main1 (int len)
  {  
    int s = 0;
    int i = len;
--- 3,10 ----
  #include <stdarg.h>
  #include "tree-vect.h"
  
! int __attribute__((noinline,noclone))
! main1 (int len)
  {  
    int s = 0;
    int i = len;

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2012-12-18 13:04 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-12-17 12:54 [PATCH] Fix PR55555 Richard Biener
2012-12-17 15:28 ` Richard Biener
2012-12-18 13:04   ` Richard Biener

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).