Bug 21029 - [4.1 Regression] vrp miscompiles Ada front-end, drops loop exit test in well-defined wrap-around circumstances
Summary: [4.1 Regression] vrp miscompiles Ada front-end, drops loop exit test in well-...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: tree-optimization (show other bugs)
Version: 4.1.0
: P2 normal
Target Milestone: 4.1.0
Assignee: Not yet assigned to anyone
URL:
Keywords: build, wrong-code
: 21773 (view as bug list)
Depends on: 18373
Blocks: 21861
  Show dependency treegraph
 
Reported: 2005-04-14 20:16 UTC by Alexandre Oliva
Modified: 2023-12-31 19:11 UTC (History)
9 users (show)

See Also:
Host:
Target:
Build:
Known to work: 4.0.0
Known to fail: 4.1.0
Last reconfirmed: 2005-04-14 20:25:02


Attachments
C testcase that triggers the bug (443 bytes, text/plain)
2005-04-14 20:19 UTC, Alexandre Oliva
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Alexandre Oliva 2005-04-14 20:16:08 UTC
csets___elabb gets miscompiled in stage2, such that stage3 enters and endless
loop compiling ada.ads.  Unfortunately, vrp seldom kicks in, so it's a bit
difficult to duplicate the problem.  Perhaps it would make sense to add a
command-line option to force vrp on, and add that to torture, just to see how it
goes?
Comment 1 Diego Novillo 2005-04-14 20:18:56 UTC
Subject: Re:  New: vrp miscompiles Ada front-end, drops loop exit test in well-defined wrap-around circumstances

On Thu, Apr 14, 2005 at 08:16:09PM -0000, aoliva at gcc dot gnu dot org wrote:

> Unfortunately, vrp seldom kicks in, so it's a bit difficult to
> duplicate the problem.
>
Hmm?  VRP is automatically enabled at -O2 and higher.


Diego.
Comment 2 Alexandre Oliva 2005-04-14 20:19:45 UTC
Created attachment 8632 [details]
C testcase that triggers the bug

The problem is that (from the vrp dump):

Simulating statement (from ssa_edges): jD.1487_6 = (intD.0) iD.1486_1;

Visiting statement:
jD.1487_6 = (intD.0) iD.1486_1;

(analyze_scalar_evolution
  (loop_nb = 1)
  (scalar = j_6)
(get_scalar_evolution
  (scalar = j_6)
  (scalar_evolution = {123, +, 1}_1))
(set_scalar_evolution
  (scalar = j_6)
  (scalar_evolution = {123, +, 1}_1))
)
Found new range [123, 2147483647] for j_6

[...]

Visiting statement:
if (jD.1487_6 < 0) goto <L2>; else goto <L1>;


Visiting conditional with predicate: j_6 < 0
With known ranges
	j_6: [123, 2147483647]

Predicate evaluates to: 0
Comment 3 Andrew Pinski 2005-04-14 20:25:02 UTC
The other thing is that signed integer wrapping is defined if we add -fwrapv which means we now miss 
compile some java programs too.

Confirmed.
Comment 4 Andrew Pinski 2005-04-14 20:42:23 UTC
(In reply to comment #3)
> The other thing is that signed integer wrapping is defined if we add -fwrapv which means we now 
miss 
> compile some java programs too.

Actually I tried basically the same program with the casts removed and it worked, it has to do with the 
casts.
Comment 5 Alexandre Oliva 2005-04-15 02:40:34 UTC
> Hmm?  VRP is automatically enabled at -O2 and higher.

But it doesn't run unless we find some ASSERT_EXPR, and if all we have is a
simple loop, no such ASSERT_EXPR is introduced.
Comment 6 Alexandre Oliva 2005-04-15 05:56:41 UTC
Subject: [PR tree-optimization/21029, RFC] harmful chrec type conversions

I started out by handling the specific case that the Ada front-end
triggers, reduced to function f() in the attached testcase.  Later on,
as I understood the failure more, I figured I'd exercise some other
cases, and painted myself into a corner in which each combination of
widening-or-narrowing signedness-changing-or-not conversion that
chrec_convert() might be asked to handle would be harmed by simply
converting CHREC_LEFT and CHREC_RIGHT to the requested type, and the
strategy we already used for widening conversions gave us correct
results.

Are there good reasons to try to perform the conversions in place and
try to work around the loss of information elsewhere, or is this
approach reasonable?

This is not a final patch; if the idea is considered sound, I'd simply
remove the if and the then-dead remaining code in chrec_convert.
Meanwhile, I'm bootstrapping this on amd64-linux-gnu.

Comments?

Index: gcc/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	PR tree-optimization/21029
	* tree-chrec.c (chrec_convert): Handle same-precision integral
	types that differ in signedness like widening conversions.

Index: gcc/tree-chrec.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-chrec.c,v
retrieving revision 2.14
diff -u -p -r2.14 tree-chrec.c
--- gcc/tree-chrec.c 5 Apr 2005 07:06:23 -0000 2.14
+++ gcc/tree-chrec.c 15 Apr 2005 05:40:27 -0000
@@ -1033,7 +1033,16 @@ chrec_convert (tree type, 
   if (ct == type)
     return chrec;
 
-  if (TYPE_PRECISION (ct) < TYPE_PRECISION (type))
+  if (1 /* Even truncations need to carry information about
+	   well-defined overflows in narrowing conversions that might
+	   have invoked undefined behavior should the operations be
+	   performed directly in the narrow type.  */
+      || TYPE_PRECISION (ct) < TYPE_PRECISION (type)
+      /* Sign changes may involve well-defined overflows; avoid
+	 silently dropping the signedness change.
+	 ??? Should we limit ourselves to same-precision types here?  */
+      || (INTEGRAL_TYPE_P (ct) && INTEGRAL_TYPE_P (type)
+	  && TYPE_UNSIGNED (ct) != TYPE_UNSIGNED (type)))
     return count_ev_in_wider_type (type, chrec);
 
   switch (TREE_CODE (chrec))
Index: gcc/testsuite/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	PR tree-optimization/21029
	* gcc.dg/tree-ssa/pr21029.c: New.

Index: gcc/testsuite/gcc.dg/tree-ssa/pr21029.c
===================================================================
RCS file: gcc/testsuite/gcc.dg/tree-ssa/pr21029.c
diff -N gcc/testsuite/gcc.dg/tree-ssa/pr21029.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gcc/testsuite/gcc.dg/tree-ssa/pr21029.c 15 Apr 2005 05:40:41 -0000
@@ -0,0 +1,176 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+/* PR tree-optimization/21029
+
+   f() used to get optimized to an infinite loop by tree-vrp, because
+   j is assumed to be non-negative.  Even though the conversion from
+   unsigned to signed has unspecified results if the expression value
+   is not representable in the signed type, the compiler itself (e.g.,
+   the Ada front end) depends on wrap-around behavior.  */
+
+unsigned int g(void) {
+  return (unsigned int)g;
+}
+
+unsigned int f(void) {
+  unsigned int k = g ();
+
+  unsigned char i = 123;
+  signed char j;
+
+  do
+    if ((j = (signed char) i) < 0)
+      break;
+    else
+      i++;
+  while (1);
+
+  /* This is here just so that the compiler introduces ASSERT_EXPR so
+     as to run the vrp pass.  Yuck.  */
+  if (i <= k)
+    k = i - 2;
+  else
+    k = k + 3;
+
+  return k;
+}
+
+/* Now let's torture it a bit further.  Narrowing conversions need
+   similar treatment.  */
+
+unsigned int f1 (void) {
+  unsigned int k = g ();
+
+  unsigned short i = 123;
+  signed char j;
+
+  do
+    if ((j = (signed char) i) < 0)
+      break;
+    else
+      i++;
+  while (1);
+
+  /* This is here just so that the compiler introduces ASSERT_EXPR so
+     as to run the vrp pass.  Yuck.  */
+  if (i <= k)
+    k = i - 2;
+  else
+    k = k + 3;
+
+  return k;
+}
+
+/* And so do widening conversions.  */
+
+unsigned int f2 (void) {
+  unsigned int k = g ();
+
+  unsigned char i = 123;
+  signed short j;
+
+  do
+    if ((j = (signed short) (signed char) i) < 0)
+      break;
+    else
+      i++;
+  while (1);
+
+  /* This is here just so that the compiler introduces ASSERT_EXPR so
+     as to run the vrp pass.  Yuck.  */
+  if (i <= k)
+    k = i - 2;
+  else
+    k = k + 3;
+
+  return k;
+}
+
+/* Check same-sign truncations with an increment that turns into
+   decrements.  */
+
+unsigned int f3 (void) {
+  unsigned int k = g ();
+
+  signed short i = 5;
+  signed char j;
+
+  do
+    if ((j = (signed char) i) < 0)
+      break;
+    else
+      i += 255;
+  while (1);
+
+  /* This is here just so that the compiler introduces ASSERT_EXPR so
+     as to run the vrp pass.  Yuck.  */
+  if (i <= k)
+    k = i - 2;
+  else
+    k = k + 3;
+
+  return k;
+}
+
+/* Check that the truncation above doesn't confuse the result of the
+   test after a widening conversion.  */
+
+unsigned int f4 (void) {
+  unsigned int k = g ();
+
+  signed short i = -123;
+  signed int j;
+
+  do
+    if ((j = (signed int) (signed char) i) > 0)
+      break;
+    else
+      i += 255;
+  while (1);
+
+  /* This is here just so that the compiler introduces ASSERT_EXPR so
+     as to run the vrp pass.  Yuck.  */
+  if (i <= k)
+    k = i - 2;
+  else
+    k = k + 3;
+
+  return k;
+}
+
+/* Even if we omit the widening truncation, the narrowing truncation
+   is implementation-defined.  */
+
+unsigned int f5 (void) {
+  unsigned int k = g ();
+
+  signed long i = -123;
+  signed char j;
+
+  do
+    if ((j = (signed char) i) > 0)
+      break;
+    else
+      i += 255;
+  while (1);
+
+  /* This is here just so that the compiler introduces ASSERT_EXPR so
+     as to run the vrp pass.  Yuck.  */
+  if (i <= k)
+    k = i - 2;
+  else
+    k = k + 3;
+
+  return k;
+}
+
+int main (void) {
+  f ();
+  f1 ();
+  f2 ();
+  f3 ();
+  f4 ();
+  f5 ();
+  return 0;
+}

-- 
Alexandre Oliva             http://www.ic.unicamp.br/~oliva/
Red Hat Compiler Engineer   aoliva@{redhat.com, gcc.gnu.org}
Free Software Evangelist  oliva@{lsd.ic.unicamp.br, gnu.org}
Comment 7 Giovanni Bajo 2005-04-15 13:10:42 UTC
Then, shouldn't your patch check -fwrapv somehow? And if Ada relies on wrap 
around, does it enable -fwrapv?
Comment 8 Andrew Pinski 2005-04-15 13:39:04 UTC
(In reply to comment #7)
> Then, shouldn't your patch check -fwrapv somehow? And if Ada relies on wrap 
> around, does it enable -fwrapv?

Huh, the testcase is still defined C even though signed overflow is undefined since it is overflowing 
while in unsigned.
Comment 9 Laurent GUERBY 2005-04-15 20:44:25 UTC
With your patch I'm able to bootstrap but I get a few ACATS FAIL:

FAIL:	c41203a
FAIL:	c41203b
FAIL:	c52102b
FAIL:	c52102d
FAIL:	c52103x
FAIL:	c62002a
FAIL:	cdd2a02
FAIL:	cxa5012
FAIL:	cxg2009
FAIL:	cxh1001

The first 8 are wrong code, cxa5012 will be fixed by my patch soon
and the two last are ICEs, here is cxg2009:

/home/guerby/work/gcc/build/build-20050415T203732/gcc/xgcc -c
-B/home/guerby/work/gcc/build/build-20050415T203732/gcc/ -gnatws -O2
-I/home/guerby/work/gcc/build/build-20050415T203732/gcc/testsuite/ada/acats/support
cxg2009.adb
+===========================GNAT BUG DETECTED==============================+
| 4.1.0 20050415 (experimental) (x86_64-unknown-linux-gnu) GCC error:      |
| in set_value_range, at tree-vrp.c:124                                    |
| Error detected at cxg2009.adb:421:5                                      |
Comment 10 Andrew Pinski 2005-04-16 13:47:42 UTC
Patch here: <http://gcc.gnu.org/ml/gcc-patches/2005-04/msg01691.html>.
Comment 11 sebastian.pop@cri.ensmp.fr 2005-04-29 19:51:45 UTC
Subject: Re: [PR tree-optimization/21029, RFC] harmful chrec type conversions

Thanks to Roger Sayle for pointing me at this PR.

Alexandre Oliva wrote:
> 
> This is not a final patch; if the idea is considered sound, I'd simply
> remove the if and the then-dead remaining code in chrec_convert.

The code following the if is not dead, at least it still is used in
some cases after hand inlining count_ev_in_wider_type.  I would
propose this patch that is about the same as yours

> Index: gcc/ChangeLog
> from  Alexandre Oliva  <aoliva@redhat.com>
> 
> 	PR tree-optimization/21029
> 	* tree-chrec.c (chrec_convert): Handle same-precision integral
> 	types that differ in signedness like widening conversions.
> 

with some more changes as follow:

	* tree-chrec.c (chrec_convert): Handle same-precision integral
	types that differ in signedness like widening conversions.
	Inline count_ev_in_wider_type.
	* tree-chrec.h (count_ev_in_wider_type): Remove declaration.
	* tree-scalar-evolution.c (count_ev_in_wider_type): Removed.

Zdenek, does this change look right to you?


Index: tree-chrec.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-chrec.c,v
retrieving revision 2.15
diff -c -3 -p -r2.15 tree-chrec.c
*** tree-chrec.c	21 Apr 2005 08:48:51 -0000	2.15
--- tree-chrec.c	29 Apr 2005 19:31:51 -0000
*************** tree 
*** 1036,1085 ****
  chrec_convert (tree type, 
  	       tree chrec)
  {
!   tree ct;
!   
    if (automatically_generated_chrec_p (chrec))
      return chrec;
!   
    ct = chrec_type (chrec);
    if (ct == type)
      return chrec;
  
!   if (TYPE_PRECISION (ct) < TYPE_PRECISION (type))
!     return count_ev_in_wider_type (type, chrec);
! 
!   switch (TREE_CODE (chrec))
      {
!     case POLYNOMIAL_CHREC:
!       return build_polynomial_chrec (CHREC_VARIABLE (chrec),
! 				     chrec_convert (type,
! 						    CHREC_LEFT (chrec)),
! 				     chrec_convert (type,
! 						    CHREC_RIGHT (chrec)));
! 
!     default:
!       {
! 	tree res = fold_convert (type, chrec);
! 
! 	/* Don't propagate overflows.  */
! 	TREE_OVERFLOW (res) = 0;
! 	if (CONSTANT_CLASS_P (res))
! 	  TREE_CONSTANT_OVERFLOW (res) = 0;
! 
! 	/* But reject constants that don't fit in their type after conversion.
! 	   This can happen if TYPE_MIN_VALUE or TYPE_MAX_VALUE are not the
! 	   natural values associated with TYPE_PRECISION and TYPE_UNSIGNED,
! 	   and can cause problems later when computing niters of loops.  Note
! 	   that we don't do the check before converting because we don't want
! 	   to reject conversions of negative chrecs to unsigned types.  */
! 	if (TREE_CODE (res) == INTEGER_CST
! 	    && TREE_CODE (type) == INTEGER_TYPE
! 	    && !int_fits_type_p (res, type))
! 	  res = chrec_dont_know;
! 
! 	return res;
!       }
      }
  }
  
  /* Returns the type of the chrec.  */
--- 1036,1104 ----
  chrec_convert (tree type, 
  	       tree chrec)
  {
!   tree ct, base, step;
!   struct loop *loop;
! 
    if (automatically_generated_chrec_p (chrec))
      return chrec;
! 
    ct = chrec_type (chrec);
    if (ct == type)
      return chrec;
  
!   if (!evolution_function_is_affine_p (chrec))
      {
!       switch (TREE_CODE (chrec))
! 	{
! 	case POLYNOMIAL_CHREC:
! 	  return build_polynomial_chrec (CHREC_VARIABLE (chrec),
! 					 chrec_convert (type,
! 							CHREC_LEFT (chrec)),
! 					 chrec_convert (type,
! 							CHREC_RIGHT (chrec)));
! 
! 	default:
! 	  {
! 	    tree res = fold_convert (type, chrec);
! 
! 	    /* Don't propagate overflows.  */
! 	    TREE_OVERFLOW (res) = 0;
! 	    if (CONSTANT_CLASS_P (res))
! 	      TREE_CONSTANT_OVERFLOW (res) = 0;
! 
! 	    /* But reject constants that don't fit in their type after
! 	       conversion.  This can happen if TYPE_MIN_VALUE or
! 	       TYPE_MAX_VALUE are not the natural values associated
! 	       with TYPE_PRECISION and TYPE_UNSIGNED, and can cause
! 	       problems later when computing niters of loops.  Note
! 	       that we don't do the check before converting because we
! 	       don't want to reject conversions of negative chrecs to
! 	       unsigned types.  */
! 	    if (TREE_CODE (res) == INTEGER_CST
! 		&& TREE_CODE (type) == INTEGER_TYPE
! 		&& !int_fits_type_p (res, type))
! 	      res = chrec_dont_know;
! 
! 	    return res;
! 	  }
! 	}
      }
+ 
+   /* BASE and STEP are INTEGER_CSTs.  */
+   base = CHREC_LEFT (chrec);
+   step = CHREC_RIGHT (chrec);
+   loop = current_loops->parray[CHREC_VARIABLE (chrec)];
+ 
+   /* TODO -- if we knew the statement at that the conversion occurs,
+      we could pass it to can_count_iv_in_wider_type and get a better
+      result.  */
+   step = can_count_iv_in_wider_type (loop, type, base, step, NULL_TREE);
+   if (!step)
+     return fold_convert (type, chrec);
+ 
+   base = chrec_convert (type, base);
+ 
+   return build_polynomial_chrec (CHREC_VARIABLE (chrec), base, step);
  }
  
  /* Returns the type of the chrec.  */
Index: tree-chrec.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-chrec.h,v
retrieving revision 2.8
diff -c -3 -p -r2.8 tree-chrec.h
*** tree-chrec.h	28 Apr 2005 05:38:34 -0000	2.8
--- tree-chrec.h	29 Apr 2005 19:31:51 -0000
*************** extern tree chrec_fold_plus (tree, tree,
*** 68,74 ****
  extern tree chrec_fold_minus (tree, tree, tree);
  extern tree chrec_fold_multiply (tree, tree, tree);
  extern tree chrec_convert (tree, tree);
- extern tree count_ev_in_wider_type (tree, tree);
  extern tree chrec_type (tree);
  
  /* Operations.  */
--- 68,73 ----
Index: tree-scalar-evolution.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-scalar-evolution.c,v
retrieving revision 2.21
diff -c -3 -p -r2.21 tree-scalar-evolution.c
*** tree-scalar-evolution.c	21 Apr 2005 08:48:53 -0000	2.21
--- tree-scalar-evolution.c	29 Apr 2005 19:31:52 -0000
*************** find_var_scev_info (tree var)
*** 350,382 ****
    return &res->chrec;
  }
  
- /* Tries to express CHREC in wider type TYPE.  */
- 
- tree
- count_ev_in_wider_type (tree type, tree chrec)
- {
-   tree base, step;
-   struct loop *loop;
- 
-   if (!evolution_function_is_affine_p (chrec))
-     return fold_convert (type, chrec);
- 
-   base = CHREC_LEFT (chrec);
-   step = CHREC_RIGHT (chrec);
-   loop = current_loops->parray[CHREC_VARIABLE (chrec)];
- 
-   /* TODO -- if we knew the statement at that the conversion occurs,
-      we could pass it to can_count_iv_in_wider_type and get a better
-      result.  */
-   step = can_count_iv_in_wider_type (loop, type, base, step, NULL_TREE);
-   if (!step)
-     return fold_convert (type, chrec);
-   base = chrec_convert (type, base);
- 
-   return build_polynomial_chrec (CHREC_VARIABLE (chrec),
- 				 base, step);
- }
- 
  /* Return true when CHREC contains symbolic names defined in
     LOOP_NB.  */
  
--- 350,355 ----
Comment 12 Zdenek Dvorak 2005-04-30 07:54:12 UTC
Subject: Re: [PR tree-optimization/21029, RFC] harmful chrec type conversions

Hello,

> Alexandre Oliva wrote:
> > 
> > This is not a final patch; if the idea is considered sound, I'd simply
> > remove the if and the then-dead remaining code in chrec_convert.
> 
> The code following the if is not dead, at least it still is used in
> some cases after hand inlining count_ev_in_wider_type.  I would
> propose this patch that is about the same as yours
> 
> > Index: gcc/ChangeLog
> > from  Alexandre Oliva  <aoliva@redhat.com>
> > 
> > 	PR tree-optimization/21029
> > 	* tree-chrec.c (chrec_convert): Handle same-precision integral
> > 	types that differ in signedness like widening conversions.
> > 
> 
> with some more changes as follow:
> 
> 	* tree-chrec.c (chrec_convert): Handle same-precision integral
> 	types that differ in signedness like widening conversions.
> 	Inline count_ev_in_wider_type.
> 	* tree-chrec.h (count_ev_in_wider_type): Remove declaration.
> 	* tree-scalar-evolution.c (count_ev_in_wider_type): Removed.
> 
> Zdenek, does this change look right to you?

no.  There is one major bug -- 

> !   if (!evolution_function_is_affine_p (chrec))
>       {
> !       switch (TREE_CODE (chrec))
> ! 	{
> ! 	case POLYNOMIAL_CHREC:
> ! 	  return build_polynomial_chrec (CHREC_VARIABLE (chrec),
> ! 					 chrec_convert (type,
> ! 							CHREC_LEFT (chrec)),
> ! 					 chrec_convert (type,
> ! 							CHREC_RIGHT (chrec)));
> ! 

this is completely bogus -- you will always convert the
POLYNOMIAL_CHREC with nonconstant step, regardless of the correctness.

There are also a few minor changes that would be recommendable for the
final patch:

1) The can_count_ev_in_wider_type should be renamed to more appropriate
   name, given that it is now used even for shortening the value.
2) This function should be extended to really handle such conversions
   efficiently. I.e. to always allow shortening to unsigned types,
   and to always allow shortening to arbitrary types with -fwrapv.
   Also, I am not quite sure at the moment that the current code of
   can_count_ev_in_wider_type really works if the required conversion
   is not extending, this should be checked.

Zdenek

> 
> Index: tree-chrec.c
> ===================================================================
> RCS file: /cvs/gcc/gcc/gcc/tree-chrec.c,v
> retrieving revision 2.15
> diff -c -3 -p -r2.15 tree-chrec.c
> *** tree-chrec.c	21 Apr 2005 08:48:51 -0000	2.15
> --- tree-chrec.c	29 Apr 2005 19:31:51 -0000
> *************** tree 
> *** 1036,1085 ****
>   chrec_convert (tree type, 
>   	       tree chrec)
>   {
> !   tree ct;
> !   
>     if (automatically_generated_chrec_p (chrec))
>       return chrec;
> !   
>     ct = chrec_type (chrec);
>     if (ct == type)
>       return chrec;
>   
> !   if (TYPE_PRECISION (ct) < TYPE_PRECISION (type))
> !     return count_ev_in_wider_type (type, chrec);
> ! 
> !   switch (TREE_CODE (chrec))
>       {
> !     case POLYNOMIAL_CHREC:
> !       return build_polynomial_chrec (CHREC_VARIABLE (chrec),
> ! 				     chrec_convert (type,
> ! 						    CHREC_LEFT (chrec)),
> ! 				     chrec_convert (type,
> ! 						    CHREC_RIGHT (chrec)));
> ! 
> !     default:
> !       {
> ! 	tree res = fold_convert (type, chrec);
> ! 
> ! 	/* Don't propagate overflows.  */
> ! 	TREE_OVERFLOW (res) = 0;
> ! 	if (CONSTANT_CLASS_P (res))
> ! 	  TREE_CONSTANT_OVERFLOW (res) = 0;
> ! 
> ! 	/* But reject constants that don't fit in their type after conversion.
> ! 	   This can happen if TYPE_MIN_VALUE or TYPE_MAX_VALUE are not the
> ! 	   natural values associated with TYPE_PRECISION and TYPE_UNSIGNED,
> ! 	   and can cause problems later when computing niters of loops.  Note
> ! 	   that we don't do the check before converting because we don't want
> ! 	   to reject conversions of negative chrecs to unsigned types.  */
> ! 	if (TREE_CODE (res) == INTEGER_CST
> ! 	    && TREE_CODE (type) == INTEGER_TYPE
> ! 	    && !int_fits_type_p (res, type))
> ! 	  res = chrec_dont_know;
> ! 
> ! 	return res;
> !       }
>       }
>   }
>   
>   /* Returns the type of the chrec.  */
> --- 1036,1104 ----
>   chrec_convert (tree type, 
>   	       tree chrec)
>   {
> !   tree ct, base, step;
> !   struct loop *loop;
> ! 
>     if (automatically_generated_chrec_p (chrec))
>       return chrec;
> ! 
>     ct = chrec_type (chrec);
>     if (ct == type)
>       return chrec;
>   
> !   if (!evolution_function_is_affine_p (chrec))
>       {
> !       switch (TREE_CODE (chrec))
> ! 	{
> ! 	case POLYNOMIAL_CHREC:
> ! 	  return build_polynomial_chrec (CHREC_VARIABLE (chrec),
> ! 					 chrec_convert (type,
> ! 							CHREC_LEFT (chrec)),
> ! 					 chrec_convert (type,
> ! 							CHREC_RIGHT (chrec)));
> ! 
> ! 	default:
> ! 	  {
> ! 	    tree res = fold_convert (type, chrec);
> ! 
> ! 	    /* Don't propagate overflows.  */
> ! 	    TREE_OVERFLOW (res) = 0;
> ! 	    if (CONSTANT_CLASS_P (res))
> ! 	      TREE_CONSTANT_OVERFLOW (res) = 0;
> ! 
> ! 	    /* But reject constants that don't fit in their type after
> ! 	       conversion.  This can happen if TYPE_MIN_VALUE or
> ! 	       TYPE_MAX_VALUE are not the natural values associated
> ! 	       with TYPE_PRECISION and TYPE_UNSIGNED, and can cause
> ! 	       problems later when computing niters of loops.  Note
> ! 	       that we don't do the check before converting because we
> ! 	       don't want to reject conversions of negative chrecs to
> ! 	       unsigned types.  */
> ! 	    if (TREE_CODE (res) == INTEGER_CST
> ! 		&& TREE_CODE (type) == INTEGER_TYPE
> ! 		&& !int_fits_type_p (res, type))
> ! 	      res = chrec_dont_know;
> ! 
> ! 	    return res;
> ! 	  }
> ! 	}
>       }
> + 
> +   /* BASE and STEP are INTEGER_CSTs.  */
> +   base = CHREC_LEFT (chrec);
> +   step = CHREC_RIGHT (chrec);
> +   loop = current_loops->parray[CHREC_VARIABLE (chrec)];
> + 
> +   /* TODO -- if we knew the statement at that the conversion occurs,
> +      we could pass it to can_count_iv_in_wider_type and get a better
> +      result.  */
> +   step = can_count_iv_in_wider_type (loop, type, base, step, NULL_TREE);
> +   if (!step)
> +     return fold_convert (type, chrec);
> + 
> +   base = chrec_convert (type, base);
> + 
> +   return build_polynomial_chrec (CHREC_VARIABLE (chrec), base, step);
>   }
>   
>   /* Returns the type of the chrec.  */
> Index: tree-chrec.h
> ===================================================================
> RCS file: /cvs/gcc/gcc/gcc/tree-chrec.h,v
> retrieving revision 2.8
> diff -c -3 -p -r2.8 tree-chrec.h
> *** tree-chrec.h	28 Apr 2005 05:38:34 -0000	2.8
> --- tree-chrec.h	29 Apr 2005 19:31:51 -0000
> *************** extern tree chrec_fold_plus (tree, tree,
> *** 68,74 ****
>   extern tree chrec_fold_minus (tree, tree, tree);
>   extern tree chrec_fold_multiply (tree, tree, tree);
>   extern tree chrec_convert (tree, tree);
> - extern tree count_ev_in_wider_type (tree, tree);
>   extern tree chrec_type (tree);
>   
>   /* Operations.  */
> --- 68,73 ----
> Index: tree-scalar-evolution.c
> ===================================================================
> RCS file: /cvs/gcc/gcc/gcc/tree-scalar-evolution.c,v
> retrieving revision 2.21
> diff -c -3 -p -r2.21 tree-scalar-evolution.c
> *** tree-scalar-evolution.c	21 Apr 2005 08:48:53 -0000	2.21
> --- tree-scalar-evolution.c	29 Apr 2005 19:31:52 -0000
> *************** find_var_scev_info (tree var)
> *** 350,382 ****
>     return &res->chrec;
>   }
>   
> - /* Tries to express CHREC in wider type TYPE.  */
> - 
> - tree
> - count_ev_in_wider_type (tree type, tree chrec)
> - {
> -   tree base, step;
> -   struct loop *loop;
> - 
> -   if (!evolution_function_is_affine_p (chrec))
> -     return fold_convert (type, chrec);
> - 
> -   base = CHREC_LEFT (chrec);
> -   step = CHREC_RIGHT (chrec);
> -   loop = current_loops->parray[CHREC_VARIABLE (chrec)];
> - 
> -   /* TODO -- if we knew the statement at that the conversion occurs,
> -      we could pass it to can_count_iv_in_wider_type and get a better
> -      result.  */
> -   step = can_count_iv_in_wider_type (loop, type, base, step, NULL_TREE);
> -   if (!step)
> -     return fold_convert (type, chrec);
> -   base = chrec_convert (type, base);
> - 
> -   return build_polynomial_chrec (CHREC_VARIABLE (chrec),
> - 				 base, step);
> - }
> - 
>   /* Return true when CHREC contains symbolic names defined in
>      LOOP_NB.  */
>   
> --- 350,355 ----
Comment 13 Diego Novillo 2005-05-13 18:20:04 UTC
Sebastian, would you mind taking a look at this?  It's assigned to me but it's
likely that you will be able to figure out what's going on in chrec more
quickly.  And I won't have time to look at this for a few more days.


Thanks.  Diego.
Comment 14 Andrew Pinski 2005-05-26 18:15:50 UTC
*** Bug 21773 has been marked as a duplicate of this bug. ***
Comment 15 GCC Commits 2005-06-02 02:57:44 UTC
Subject: Bug 21029

CVSROOT:	/cvs/gcc
Module name:	gcc
Changes by:	dnovillo@gcc.gnu.org	2005-06-02 02:57:15

Modified files:
	gcc            : ChangeLog fold-const.c tree-flow.h 
	                 tree-ssa-ccp.c tree-ssa-copy.c 
	                 tree-ssa-propagate.c tree-ssa-propagate.h 
	                 tree-vrp.c tree.h 
	gcc/testsuite  : ChangeLog 
	gcc/testsuite/gcc.dg/tree-ssa: pr14841.c pr21658.c 
Added files:
	gcc/testsuite/gcc.dg/tree-ssa: pr14341.c pr20701.c pr21029.c 
	                               pr21086.c pr21090.c pr21332.c 
	                               pr21458.c vrp01.c vrp02.c vrp03.c 
	                               vrp04.c vrp05.c vrp06.c vrp07.c 
	                               vrp08.c vrp09.c vrp10.c vrp11.c 
	                               vrp12.c vrp13.c 

Log message:
	2005-06-01  Diego Novillo  <dnovillo@redhat.com>
	
	PR 14341, PR 21332, PR 20701, PR 21029, PR 21086, PR 21090
	PR 21289, PR 21348, PR 21367, PR 21368, PR 21458.
	* fold-const.c (invert_tree_comparison): Make extern.
	* tree-flow.h (enum value_range_type): Move to tree-ssa-propagate.
	(struct value_range_def): Limewise.
	(get_value_range): Remove.
	(dump_value_range): Remove.
	(dump_all_value_ranges): Remove.
	(debug_all_value_ranges): Remove.
	(vrp_evaluate_conditional): Declare.
	* tree-ssa-propagate.c (struct prop_stats_d): Add field
	num_pred_folded.
	(substitute_and_fold): Add argument use_ranges_p.
	Update all callers.
	If use_ranges_p is true, call fold_predicate_in to fold
	predicates using range information.
	Ignore ASSERT_EXPRs.
	Change debugging output to only show statements that have been
	folded.
	(replace_phi_args_in): Move debugging output code from
	substitute and fold.
	(fold_predicate_in): New local function.
	* tree-ssa-propagate.h (enum value_range_type): Move from
	tree-flow.h.
	(struct value_range_d): Likewise.
	Add field 'equiv'.
	(value_range_t): Rename from value_range.
	* tree-vrp.c (found_in_subgraph): Rename from found.
	(get_opposite_operand): Remove.
	(struct assert_locus_d): Declare.
	(assert_locus_t): Declare.
	(need_assert_for): Declare.
	(asserts_for): Declare.
	(blocks_visited): Declare.
	(vr_value): Declare.
	(set_value_range): Add argument 'equiv'.
	Don't drop to VARYING ranges that cover all values in the
	type.
	Make deep copy of equivalence set 'equiv'.
	(copy_value_range): New local function.
	(set_value_range_to_undefined): New local function.
	(compare_values): Return -2 if either value has overflowed.
	(range_includes_zero_p): New local function.
	(extract_range_from_assert): Flip the predicate code if the
	name being asserted is on the RHS of the predicate.
	Avoid creating unnecessary symbolic ranges if the comparison
	includes another name with a known numeric range.
	Update the equivalnce set of the new range when asserting
	EQ_EXPR predicates.
	(extract_range_from_ssa_name): Update the equivalence set of
	the new range with VAR.
	(extract_range_from_binary_expr): Also handle TRUTH_*_EXPR.
	If -fwrapv is used, set the resulting range to VARYING if the
	operation overflows.  Otherwise, use TYPE_MIN_VALUE and
	TYPE_MAX_VALUE to represent -INF and +INF.
	Fix handling of *_DIV_EXPR.
	(extract_range_from_unary_expr): Handle MINUS_EXPR and
	ABS_EXPR properly by switching the range around if necessary.
	(extract_range_from_comparison): New local function.
	(extract_range_from_expr): Call it.
	(adjust_range_with_scev): Do not adjust the range if using
	wrapping arithmetic (-fwrapv).
	(dump_value_range): Also show equivalence set.
	Show -INF and +INF for TYPE_MIN_VALUE and TYPE_MAX_VALUE.
	(build_assert_expr_for): Also build ASSERT_EXPR for EQ_EXPR.
	(infer_value_range): Change return value to bool.
	Add arguments 'comp_code_p' and 'val_p'.
	Do not attempt to infer ranges from statements that may throw.
	Store the comparison code in comp_code_p.
	Store the other operand to be used in the predicate in val_p.
	(dump_asserts_for): New.
	(debug_asserts_for): New.
	(dump_all_asserts): New.
	(debug_all_asserts): New.
	(register_new_assert_for): New.
	(register_edge_assert_for): New.
	(find_conditional_asserts): New.
	(find_assert_locations): New.
	(process_assert_insertions_for): New.
	(process_assert_insertions): New.
	(insert_range_assertions): Initialize found_in_subgraph,
	blocks_visited, need_assert_for and asserts_for.
	Call find_assert_locations and process_assert_insertions.
	(remove_range_assertions): Add more documentation.
	(vrp_initialize): Change return type to void.
	Do not try to guess if running VRP is worth it.
	(compare_name_with_value): New.
	(compare_names): New.
	(vrp_evaluate_conditional): Add argument 'use_equiv_p'.  If
	use_equiv_p is true, call compare_names and
	compare_name_with_value to compare all the ranges for every
	name in the equivalence set of the predicate operands.
	Update all callers.
	(vrp_meet): Try harder not to derive a VARYING range.
	If two values meet, the resulting equivalence set is the
	intersection of the two equivalence sets.
	(vrp_visit_phi_node): Call copy_value_range to get the current
	range information of the LHS.
	(vrp_finalize): Create a value vector representing all the
	names that ended up with exactly one value in their range.
	Call substitute_and_fold.
	(execute_vrp): Document equivalence sets in ranges.
	* tree.h (SSA_NAME_VALUE_RANGE): Remove.
	(struct tree_ssa_name): Remove field value_range.
	(invert_tree_comparison): Declare.
	
	testsuite/ChangeLog
	
	2005-06-01  Diego Novillo  <dnovillo@redhat.com>
	
	PR 14341, PR 21332, PR 20701, PR 21086, PR 21090
	PR 21289, PR 21348, PR 21367, PR 21368, PR 21458.
	* gcc.dg/tree-ssa/pr14341.c: New test.
	* gcc.dg/tree-ssa/pr14841.c: New test.
	* gcc.dg/tree-ssa/pr20701.c: New test.
	* gcc.dg/tree-ssa/pr21086.c: New test.
	* gcc.dg/tree-ssa/pr21090.c: New test.
	* gcc.dg/tree-ssa/pr21332.c: New test.
	* gcc.dg/tree-ssa/pr21458.c: New test.
	* gcc.dg/tree-ssa/pr21658.c: New test.
	* gcc.dg/tree-ssa/vrp01.c: New test.
	* gcc.dg/tree-ssa/vrp02.c: New test.
	* gcc.dg/tree-ssa/vrp03.c: New test.
	* gcc.dg/tree-ssa/vrp04.c: New test.
	* gcc.dg/tree-ssa/vrp05.c: New test.
	* gcc.dg/tree-ssa/vrp06.c: New test.
	* gcc.dg/tree-ssa/vrp07.c: New test.
	* gcc.dg/tree-ssa/vrp08.c: New test.
	* gcc.dg/tree-ssa/vrp09.c: New test.
	* gcc.dg/tree-ssa/vrp10.c: New test.
	* gcc.dg/tree-ssa/vrp11.c: New test.
	* gcc.dg/tree-ssa/vrp12.c: New test.
	* gcc.dg/tree-ssa/vrp13.c: New test.
	
	2005-06-01  Alexandre Oliva  <aoliva@redhat.com>
	
	PR 21029
	* gcc.dg/tree-ssa/pr21029.c: New test.

Patches:
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&r1=2.8989&r2=2.8990
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/fold-const.c.diff?cvsroot=gcc&r1=1.589&r2=1.590
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/tree-flow.h.diff?cvsroot=gcc&r1=2.114&r2=2.115
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/tree-ssa-ccp.c.diff?cvsroot=gcc&r1=2.77&r2=2.78
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/tree-ssa-copy.c.diff?cvsroot=gcc&r1=2.32&r2=2.33
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/tree-ssa-propagate.c.diff?cvsroot=gcc&r1=2.22&r2=2.23
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/tree-ssa-propagate.h.diff?cvsroot=gcc&r1=2.3&r2=2.4
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/tree-vrp.c.diff?cvsroot=gcc&r1=2.18&r2=2.19
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/tree.h.diff?cvsroot=gcc&r1=1.732&r2=1.733
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/ChangeLog.diff?cvsroot=gcc&r1=1.5574&r2=1.5575
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/tree-ssa/pr14341.c.diff?cvsroot=gcc&r1=NONE&r2=1.1
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/tree-ssa/pr20701.c.diff?cvsroot=gcc&r1=NONE&r2=1.1
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/tree-ssa/pr21029.c.diff?cvsroot=gcc&r1=NONE&r2=1.1
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/tree-ssa/pr21086.c.diff?cvsroot=gcc&r1=NONE&r2=1.1
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/tree-ssa/pr21090.c.diff?cvsroot=gcc&r1=NONE&r2=1.1
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/tree-ssa/pr21332.c.diff?cvsroot=gcc&r1=NONE&r2=1.1
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/tree-ssa/pr21458.c.diff?cvsroot=gcc&r1=NONE&r2=1.1
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/tree-ssa/vrp01.c.diff?cvsroot=gcc&r1=NONE&r2=1.1
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/tree-ssa/vrp02.c.diff?cvsroot=gcc&r1=NONE&r2=1.1
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/tree-ssa/vrp03.c.diff?cvsroot=gcc&r1=NONE&r2=1.1
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/tree-ssa/vrp04.c.diff?cvsroot=gcc&r1=NONE&r2=1.1
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/tree-ssa/vrp05.c.diff?cvsroot=gcc&r1=NONE&r2=1.1
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/tree-ssa/vrp06.c.diff?cvsroot=gcc&r1=NONE&r2=1.1
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/tree-ssa/vrp07.c.diff?cvsroot=gcc&r1=NONE&r2=1.1
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/tree-ssa/vrp08.c.diff?cvsroot=gcc&r1=NONE&r2=1.1
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/tree-ssa/vrp09.c.diff?cvsroot=gcc&r1=NONE&r2=1.1
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/tree-ssa/vrp10.c.diff?cvsroot=gcc&r1=NONE&r2=1.1
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/tree-ssa/vrp11.c.diff?cvsroot=gcc&r1=NONE&r2=1.1
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/tree-ssa/vrp12.c.diff?cvsroot=gcc&r1=NONE&r2=1.1
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/tree-ssa/vrp13.c.diff?cvsroot=gcc&r1=NONE&r2=1.1
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/tree-ssa/pr14841.c.diff?cvsroot=gcc&r1=1.1&r2=1.2
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/tree-ssa/pr21658.c.diff?cvsroot=gcc&r1=1.1&r2=1.2

Comment 16 Diego Novillo 2005-06-02 03:14:14 UTC
Fixed.  http://gcc.gnu.org/ml/gcc-patches/2005-06/msg00127.html
Comment 17 Andreas Schwab 2005-06-02 08:51:41 UTC
Not. http://gcc.gnu.org/ml/gcc-patches/2005-06/msg00128.html  
Comment 18 Diego Novillo 2005-06-02 17:15:18 UTC
(In reply to comment #17)
> Not. http://gcc.gnu.org/ml/gcc-patches/2005-06/msg00128.html  

Open a new PR.  This is a completely different and not related to VRP.  Closing.
Comment 19 Andreas Schwab 2005-06-08 09:45:36 UTC
This is still not fixed. 
Comment 20 Andrew Pinski 2005-06-08 12:29:50 UTC
(In reply to comment #19)
> This is still not fixed. 

But this time it is not VRP which is causing the problem but the Ada front-end, I will file a new bug.