[Bug tree-optimization/22236] [4.1 Regression] wrong code for casts and scev

Sebastian Pop sebastian.pop@cri.ensmp.fr
Tue Jul 26 10:06:00 GMT 2005


After inlining, we end up with a loop containing the following code:

   b.0_3 = (signed char) b_8;
   D.1621_4 = (int) b.0_3;
   a_5 = (signed char) D.1621_4;
   D.1640_6 = (int) a_5;
   b_7 = D.1640_6 - 127;
   if (b_7 > 1) goto <L3>; else goto <L9>;
   
that is equivalent to:

   b_7 = ((int) (signed char) (int) (signed char) b_8) - 127;
   if (b_7 > 1) goto <L3>; else goto <L9>;

with b_8 = (unsigned char) {1, +, 1}

   b_7 = ((int) (signed char) (int) (signed char) {(uchar)1, +, (uchar)1}) - 127;
   if (b_7 > 1) goto <L3>; else goto <L9>;

A sequence of unsigned char 1, 2, ..., 255 has to be converted to
signed char that would wrap with -fwrapv: 1, 2, ..., 127, -128, ...
So here is a patch that keeps the cast if the sequence wraps.  The
remaining problem is that with this patch, chrec_convert gets more
picky about the things that it transforms: in some of the testcases of
the vectorizer, we get some fails because the number of iterations is
not known, making scev_probably_wraps_p to return true, and finally
the conversion is kept.

I have bootstrapped this patch on x86_64, but there are some
regressions:

FAIL: gcc.dg/vect/vect-46.c scan-tree-dump-times vectorized 1 loops 1
FAIL: gcc.dg/vect/vect-50.c scan-tree-dump-times vectorized 1 loops 1
FAIL: gcc.dg/vect/vect-50.c scan-tree-dump-times Vectorizing an unaligned access 2
FAIL: gcc.dg/vect/vect-50.c scan-tree-dump-times Alignment of access forced using peeling 1
FAIL: gcc.dg/vect/vect-52.c scan-tree-dump-times vectorized 1 loops 1
FAIL: gcc.dg/vect/vect-52.c scan-tree-dump-times Vectorizing an unaligned access 2
FAIL: gcc.dg/vect/vect-58.c scan-tree-dump-times vectorized 1 loops 1
FAIL: gcc.dg/vect/vect-58.c scan-tree-dump-times Alignment of access forced using peeling 1
FAIL: gcc.dg/vect/vect-60.c scan-tree-dump-times vectorized 1 loops 1
FAIL: gcc.dg/vect/vect-60.c scan-tree-dump-times Vectorizing an unaligned access 2
FAIL: gcc.dg/vect/vect-92.c scan-tree-dump-times vectorized 1 loops 3
FAIL: gcc.dg/vect/vect-92.c scan-tree-dump-times Alignment of access forced using peeling 3

In all these cases, the loop bound is a parameter.  If IP-constant
propagation is not used, chrec_convert has not enough information for
removing the cast.  I propose to modify all these testcases to make
the loop bound explicit.

FAIL: gcc.dg/vect/vect-77.c scan-tree-dump-times vectorized 1 loops 1
FAIL: gcc.dg/vect/vect-77.c scan-tree-dump-times Vectorizing an unaligned access 1
FAIL: gcc.dg/vect/vect-78.c scan-tree-dump-times vectorized 1 loops 1
FAIL: gcc.dg/vect/vect-78.c scan-tree-dump-times Vectorizing an unaligned access 1

For these two regressions, the problem is the same: we end with an
evolution: ib_16 + (aint *) ((long unsigned int) {off_11, +, 1}_1 * 4)
in which the casts cannot be removed because the offset is not known,
and even if the number of iterations is known, chrec_convert cannot
prove that it does not overflow.  I propose to propagate the offset
by hand, or to wait for ipcp ;-)

FAIL: gcc.dg/vect/vect-87.c scan-tree-dump-times vectorized 1 loops 1
FAIL: gcc.dg/vect/vect-87.c scan-tree-dump-times Alignment of access forced using peeling 1
FAIL: gcc.dg/vect/vect-88.c scan-tree-dump-times vectorized 1 loops 1
FAIL: gcc.dg/vect/vect-88.c scan-tree-dump-times Alignment of access forced using peeling 1

For these two testcases we'll need IP-value range propagation.  I
think that we'll have to modify these testcases by inlining the code.
Dorit, could you look at vect-{77,78,87,88}.c testcases?  Thanks.

	* tree-cfg.c (print_succ_bbs): Correctly print successors.
	* tree-chrec.c (chrec_convert): Call scev_probably_wraps_p for checking
	that the iv does not wrap before converting the iv.
	* tree-ssa-loop-ivcanon.c: Correct typo in comment.
	* tree-ssa-loop-ivopts.c (idx_find_step): Add a fixme note.
	* tree-ssa-loop-niter.c (scev_probably_wraps_p): Check that AT_STMT is
	not null.
	(convert_step): Add a comment.

Index: tree-cfg.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-cfg.c,v
retrieving revision 2.211
diff -d -u -p -r2.211 tree-cfg.c
--- tree-cfg.c	12 Jul 2005 13:20:28 -0000	2.211
+++ tree-cfg.c	26 Jul 2005 09:59:38 -0000
@@ -4454,7 +4454,7 @@ static void print_pred_bbs (FILE *, basi
 static void print_succ_bbs (FILE *, basic_block bb);
 
 
-/* Print the predecessors indexes of edge E on FILE.  */
+/* Print on FILE the indexes for the predecessors of basic_block BB.  */
 
 static void
 print_pred_bbs (FILE *file, basic_block bb)
@@ -4463,11 +4463,11 @@ print_pred_bbs (FILE *file, basic_block 
   edge_iterator ei;
 
   FOR_EACH_EDGE (e, ei, bb->preds)
-    fprintf (file, "bb_%d", e->src->index);
+    fprintf (file, "bb_%d ", e->src->index);
 }
 
 
-/* Print the successors indexes of edge E on FILE.  */
+/* Print on FILE the indexes for the successors of basic_block BB.  */
 
 static void
 print_succ_bbs (FILE *file, basic_block bb)
@@ -4476,7 +4476,7 @@ print_succ_bbs (FILE *file, basic_block 
   edge_iterator ei;
 
   FOR_EACH_EDGE (e, ei, bb->succs)
-    fprintf (file, "bb_%d", e->src->index);
+    fprintf (file, "bb_%d ", e->dest->index);
 }
 
 
Index: tree-chrec.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-chrec.c,v
retrieving revision 2.22
diff -d -u -p -r2.22 tree-chrec.c
--- tree-chrec.c	13 Jul 2005 10:08:36 -0000	2.22
+++ tree-chrec.c	26 Jul 2005 09:59:38 -0000
@@ -1110,9 +1110,24 @@ chrec_convert (tree type, tree chrec, tr
 
   if (evolution_function_is_affine_p (chrec))
     {
-      tree step = convert_step (current_loops->parray[CHREC_VARIABLE (chrec)],
- 				type, CHREC_LEFT (chrec), CHREC_RIGHT (chrec),
- 				at_stmt);
+      tree step;
+      bool dummy;
+
+      /* Avoid conversion of (signed char) {(uchar)1, +, (uchar)1}_x
+	 when it is not possible to prove that the scev does not wrap.
+	 See PR22236, where a sequence 1, 2, ..., 255 has to be
+	 converted to signed char, but this would wrap: 1, 2, ...,
+	 127, -128, ...  The result should not be {(schar)1, +,
+	 (schar)1}_x, but instead, we should keep the conversion:
+	 (schar) {(uchar)1, +, (uchar)1}_x.  */
+      if (scev_probably_wraps_p (type, CHREC_LEFT (chrec), CHREC_RIGHT (chrec),
+				 at_stmt,
+				 current_loops->parray[CHREC_VARIABLE (chrec)],
+				 &dummy))
+	return fold_convert (type, chrec);
+
+      step = convert_step (current_loops->parray[CHREC_VARIABLE (chrec)], type,
+			   CHREC_LEFT (chrec), CHREC_RIGHT (chrec), at_stmt);
       if (!step)
  	return fold_convert (type, chrec);
 
Index: tree-ssa-loop-ivcanon.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-loop-ivcanon.c,v
retrieving revision 2.18
diff -d -u -p -r2.18 tree-ssa-loop-ivcanon.c
--- tree-ssa-loop-ivcanon.c	21 Jul 2005 07:24:10 -0000	2.18
+++ tree-ssa-loop-ivcanon.c	26 Jul 2005 09:59:38 -0000
@@ -252,7 +252,7 @@ try_unroll_loop_completely (struct loops
 }
 
 /* Adds a canonical induction variable to LOOP if suitable.  LOOPS is the loops
-   tree.  CREATE_IV is true if we may create a new iv.  UL determines what
+   tree.  CREATE_IV is true if we may create a new iv.  UL determines 
    which loops we are allowed to completely unroll.  If TRY_EVAL is true, we try
    to determine the number of iterations of a loop by direct evaluation. 
    Returns true if cfg is changed.  */
Index: tree-ssa-loop-ivopts.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-loop-ivopts.c,v
retrieving revision 2.85
diff -d -u -p -r2.85 tree-ssa-loop-ivopts.c
--- tree-ssa-loop-ivopts.c	21 Jul 2005 07:24:10 -0000	2.85
+++ tree-ssa-loop-ivopts.c	26 Jul 2005 09:59:38 -0000
@@ -1443,6 +1443,8 @@ idx_find_step (tree base, tree *idx, voi
     /* The step for pointer arithmetics already is 1 byte.  */
     step = build_int_cst (sizetype, 1);
 
+  /* FIXME: convert_step should not be used outside chrec_convert: fix
+     this by calling chrec_convert.  */
   iv_step = convert_step (dta->ivopts_data->current_loop,
 			  sizetype, iv->base, iv->step, dta->stmt);
 
Index: tree-ssa-loop-niter.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-loop-niter.c,v
retrieving revision 2.33
diff -d -u -p -r2.33 tree-ssa-loop-niter.c
--- tree-ssa-loop-niter.c	21 Jul 2005 07:24:12 -0000	2.33
+++ tree-ssa-loop-niter.c	26 Jul 2005 09:59:38 -0000
@@ -1707,7 +1707,7 @@ scev_probably_wraps_p (tree type, tree b
      i_2 to wrap around, but not i.0_6, because it is of a signed
      type.  This causes VRP to erroneously fold the predicate above
      because it thinks that i.0_6 cannot be negative.  */
-  if (TREE_CODE (at_stmt) == MODIFY_EXPR)
+  if (at_stmt && TREE_CODE (at_stmt) == MODIFY_EXPR)
     {
       tree rhs = TREE_OPERAND (at_stmt, 1);
       tree outer_t = TREE_TYPE (rhs);
@@ -1748,7 +1748,8 @@ scev_probably_wraps_p (tree type, tree b
 }
 
 /* Return the conversion to NEW_TYPE of the STEP of an induction
-   variable BASE + STEP * I at AT_STMT.  */
+   variable BASE + STEP * I at AT_STMT.  When it fails, return
+   NULL_TREE.  */
 
 tree
 convert_step (struct loop *loop, tree new_type, tree base, tree step,
Index: testsuite/gcc.dg/vect/vect-46.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.dg/vect/vect-46.c,v
retrieving revision 1.7
diff -d -u -p -r1.7 vect-46.c
--- testsuite/gcc.dg/vect/vect-46.c	31 Mar 2005 18:34:18 -0000	1.7
+++ testsuite/gcc.dg/vect/vect-46.c	26 Jul 2005 09:59:52 -0000
@@ -23,11 +23,11 @@ void bar (afloat *pa, afloat *pb, afloat
 
 
 int
-main1 (int n , afloat * __restrict__ pa, afloat * __restrict__ pb, afloat * __restrict__ pc)
+main1 (afloat * __restrict__ pa, afloat * __restrict__ pb, afloat * __restrict__ pc)
 {
   int i;
 
-  for (i = 0; i < n; i++)
+  for (i = 0; i < N; i++)
     {
       pa[i] = pb[i] * pc[i];
     }
@@ -38,14 +38,13 @@ main1 (int n , afloat * __restrict__ pa,
 int main (void)
 {
   int i;
-  int n=N;
   afloat a[N];
   afloat b[N] = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57};
   afloat c[N] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
 
   check_vect ();
 
-  main1 (n,a,b,c);
+  main1 (a,b,c);
   bar (a,b,c);
   return 0;
 }
Index: testsuite/gcc.dg/vect/vect-50.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.dg/vect/vect-50.c,v
retrieving revision 1.9
diff -d -u -p -r1.9 vect-50.c
--- testsuite/gcc.dg/vect/vect-50.c	31 Mar 2005 18:34:18 -0000	1.9
+++ testsuite/gcc.dg/vect/vect-50.c	26 Jul 2005 09:59:52 -0000
@@ -22,11 +22,11 @@ void bar (float *pa, float *pb, float *p
 
 
 int
-main1 (int n, float * __restrict__ pa, float * __restrict__ pb, float * __restrict__ pc)
+main1 (float * __restrict__ pa, float * __restrict__ pb, float * __restrict__ pc)
 {
   int i;
 
-  for (i = 0; i < n; i++)
+  for (i = 0; i < N; i++)
     {
       pa[i] = pb[i] * pc[i];
     }
@@ -45,7 +45,7 @@ int main (void)
 
   check_vect ();
 
-  main1 (N,a,b,c);
+  main1 (a,b,c);
   return 0;
 }
 
Index: testsuite/gcc.dg/vect/vect-52.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.dg/vect/vect-52.c,v
retrieving revision 1.9
diff -d -u -p -r1.9 vect-52.c
--- testsuite/gcc.dg/vect/vect-52.c	31 Mar 2005 18:34:18 -0000	1.9
+++ testsuite/gcc.dg/vect/vect-52.c	26 Jul 2005 09:59:52 -0000
@@ -23,11 +23,11 @@ void bar (float *pa, float *pb, float *p
 
 
 int
-main1 (int n, afloat * __restrict__ pa, float * __restrict__ pb, float * __restrict__ pc)
+main1 (afloat * __restrict__ pa, float * __restrict__ pb, float * __restrict__ pc)
 {
   int i;
 
-  for (i = 0; i < n; i++)
+  for (i = 0; i < N; i++)
     {
       pa[i] = pb[i] * pc[i];
     }
@@ -46,8 +46,8 @@ int main (void)
 
   check_vect ();
 
-  main1 (N,a,&b[1],c);
-  main1 (N,a,&b[1],&c[1]);
+  main1 (a,&b[1],c);
+  main1 (a,&b[1],&c[1]);
   return 0;
 }
 
Index: testsuite/gcc.dg/vect/vect-58.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.dg/vect/vect-58.c,v
retrieving revision 1.10
diff -d -u -p -r1.10 vect-58.c
--- testsuite/gcc.dg/vect/vect-58.c	31 Mar 2005 18:34:18 -0000	1.10
+++ testsuite/gcc.dg/vect/vect-58.c	26 Jul 2005 09:59:52 -0000
@@ -23,11 +23,11 @@ void bar (afloat *pa, afloat *pb, afloat
 
 
 int
-main1 (int n , afloat * __restrict__ pa, afloat * __restrict__ pb, afloat * __restrict__ pc)
+main1 (afloat * __restrict__ pa, afloat * __restrict__ pb, afloat * __restrict__ pc)
 {
   int i;
 
-  for (i = 0; i < n/2; i++)
+  for (i = 0; i < N/2; i++)
     {
       pa[i+1] = pb[i+1] * pc[i+1];
     }
@@ -40,14 +40,13 @@ main1 (int n , afloat * __restrict__ pa,
 int main (void)
 {
   int i;
-  int n=N;
   afloat a[N];
   afloat b[N] = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57};
   afloat c[N] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
 
   check_vect ();
 
-  main1 (n,a,b,c);
+  main1 (a,b,c);
   return 0;
 }
 
Index: testsuite/gcc.dg/vect/vect-60.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.dg/vect/vect-60.c,v
retrieving revision 1.9
diff -d -u -p -r1.9 vect-60.c
--- testsuite/gcc.dg/vect/vect-60.c	31 Mar 2005 18:34:18 -0000	1.9
+++ testsuite/gcc.dg/vect/vect-60.c	26 Jul 2005 09:59:52 -0000
@@ -23,11 +23,11 @@ void bar (afloat *pa, afloat *pb, afloat
 
 
 int
-main1 (int n , afloat * __restrict__ pa, afloat * __restrict__ pb, afloat * __restrict__ pc)
+main1 (afloat * __restrict__ pa, afloat * __restrict__ pb, afloat * __restrict__ pc)
 {
   int i;
 
-  for (i = 0; i < n/2; i++)
+  for (i = 0; i < N/2; i++)
     {
       pa[i] = pb[i+1] * pc[i+1];
     }
@@ -40,14 +40,13 @@ main1 (int n , afloat * __restrict__ pa,
 int main (void)
 {
   int i;
-  int n=N;
   afloat a[N];
   afloat b[N] = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57};
   afloat c[N] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
 
   check_vect ();
 
-  main1 (n,a,b,c);
+  main1 (a,b,c);
   return 0;
 }
 
Index: testsuite/gcc.dg/vect/vect-77.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.dg/vect/vect-77.c,v
retrieving revision 1.11
diff -d -u -p -r1.11 vect-77.c
--- testsuite/gcc.dg/vect/vect-77.c	7 Jun 2005 19:51:25 -0000	1.11
+++ testsuite/gcc.dg/vect/vect-77.c	26 Jul 2005 09:59:52 -0000
@@ -20,7 +20,6 @@ int main1 (aint *ib, int off)
       ia[i] = ib[i+off];
     }
 
-
   /* check results:  */
   for (i = 0; i < N; i++)
     {
Index: testsuite/gcc.dg/vect/vect-92.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.dg/vect/vect-92.c,v
retrieving revision 1.4
diff -d -u -p -r1.4 vect-92.c
--- testsuite/gcc.dg/vect/vect-92.c	16 Jul 2005 18:56:53 -0000	1.4
+++ testsuite/gcc.dg/vect/vect-92.c	26 Jul 2005 09:59:52 -0000
@@ -50,17 +50,17 @@ main2 (afloat * __restrict__ pa, afloat 
 }
 
 int
-main3 (afloat * __restrict__ pa, afloat * __restrict__ pb, afloat * __restrict__ pc, int n)
+main3 (afloat * __restrict__ pa, afloat * __restrict__ pb, afloat * __restrict__ pc)
 {
   int i;
 
-  for (i = 0; i < n; i++)
+  for (i = 0; i < N-1; i++)
     {
       pa[i+1] = pb[i+1] * pc[i+1];
     }
 
   /* check results:  */
-  for (i = 0; i < n; i++)
+  for (i = 0; i < N-1; i++)
     {
       if (pa[i+1] != (pb[i+1] * pc[i+1]))
 	abort ();
@@ -80,7 +80,7 @@ int main (void)
 
   main1 (a,b,c);
   main2 (a,b,c);
-  main3 (a,b,c,N-1);
+  main3 (a,b,c);
 
   return 0;
 }



More information about the Gcc-patches mailing list