public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Richard Biener <rguenther@suse.de>
To: gcc-patches@gcc.gnu.org
Subject: Re: [PATCH] Fix PR55555
Date: Mon, 17 Dec 2012 15:28:00 -0000	[thread overview]
Message-ID: <alpine.LNX.2.00.1212171625330.14089@zhemvz.fhfr.qr> (raw)
In-Reply-To: <alpine.LNX.2.00.1212171349060.14089@zhemvz.fhfr.qr>

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;
+ }

  reply	other threads:[~2012-12-17 15:28 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-12-17 12:54 Richard Biener
2012-12-17 15:28 ` Richard Biener [this message]
2012-12-18 13:04   ` Richard Biener

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=alpine.LNX.2.00.1212171625330.14089@zhemvz.fhfr.qr \
    --to=rguenther@suse.de \
    --cc=gcc-patches@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).