The following patch fixes PR66375, SCEV computing a wrong evolution
for the loop PHI node defining 'c', ignoring the conversion to/from char.

The issue here is, I believe, that we first follow the SSA edge but
only then add to the evolution, so the SSA edge following transfers
the initial condition (a constant) while it really should transfer
the evolution { init, +, step }.

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

Richard.

2015-06-03  Richard Biener  <rguent...@suse.de>

        PR tree-optimization/66375
        * tree-scalar-evolution.c (follow_ssa_edge_binary): First
        add to the evolution before following SSA edges.

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

Index: gcc/tree-scalar-evolution.c
===================================================================
--- gcc/tree-scalar-evolution.c (revision 224028)
+++ gcc/tree-scalar-evolution.c (working copy)
@@ -958,27 +958,25 @@ follow_ssa_edge_binary (struct loop *loo
              limit++;
 
              evol = *evolution_of_loop;
-             res = follow_ssa_edge
-               (loop, SSA_NAME_DEF_STMT (rhs0), halting_phi, &evol, limit);
-
-             if (res == t_true)
-               *evolution_of_loop = add_to_evolution
+             evol = add_to_evolution
                  (loop->num,
                   chrec_convert (type, evol, at_stmt),
                   code, rhs1, at_stmt);
-
+             res = follow_ssa_edge
+               (loop, SSA_NAME_DEF_STMT (rhs0), halting_phi, &evol, limit);
+             if (res == t_true)
+               *evolution_of_loop = evol;
              else if (res == t_false)
                {
+                 *evolution_of_loop = add_to_evolution
+                     (loop->num,
+                      chrec_convert (type, *evolution_of_loop, at_stmt),
+                      code, rhs0, at_stmt);
                  res = follow_ssa_edge
                    (loop, SSA_NAME_DEF_STMT (rhs1), halting_phi,
                     evolution_of_loop, limit);
-
                  if (res == t_true)
-                   *evolution_of_loop = add_to_evolution
-                     (loop->num,
-                      chrec_convert (type, *evolution_of_loop, at_stmt),
-                      code, rhs0, at_stmt);
-
+                   ;
                  else if (res == t_dont_know)
                    *evolution_of_loop = chrec_dont_know;
                }
@@ -991,15 +989,15 @@ follow_ssa_edge_binary (struct loop *loo
            {
              /* Match an assignment under the form:
                 "a = b + ...".  */
+             *evolution_of_loop = add_to_evolution
+                 (loop->num, chrec_convert (type, *evolution_of_loop,
+                                            at_stmt),
+                  code, rhs1, at_stmt);
              res = follow_ssa_edge
                (loop, SSA_NAME_DEF_STMT (rhs0), halting_phi,
                 evolution_of_loop, limit);
              if (res == t_true)
-               *evolution_of_loop = add_to_evolution
-                 (loop->num, chrec_convert (type, *evolution_of_loop,
-                                            at_stmt),
-                  code, rhs1, at_stmt);
-
+               ;       
              else if (res == t_dont_know)
                *evolution_of_loop = chrec_dont_know;
            }
@@ -1009,15 +1007,15 @@ follow_ssa_edge_binary (struct loop *loo
        {
          /* Match an assignment under the form:
             "a = ... + c".  */
+         *evolution_of_loop = add_to_evolution
+             (loop->num, chrec_convert (type, *evolution_of_loop,
+                                        at_stmt),
+              code, rhs0, at_stmt);
          res = follow_ssa_edge
            (loop, SSA_NAME_DEF_STMT (rhs1), halting_phi,
             evolution_of_loop, limit);
          if (res == t_true)
-           *evolution_of_loop = add_to_evolution
-             (loop->num, chrec_convert (type, *evolution_of_loop,
-                                        at_stmt),
-              code, rhs0, at_stmt);
-
+           ;
          else if (res == t_dont_know)
            *evolution_of_loop = chrec_dont_know;
        }
@@ -1042,13 +1040,13 @@ follow_ssa_edge_binary (struct loop *loo
          if (TREE_CODE (rhs1) == SSA_NAME)
            limit++;
 
+         *evolution_of_loop = add_to_evolution
+             (loop->num, chrec_convert (type, *evolution_of_loop, at_stmt),
+              MINUS_EXPR, rhs1, at_stmt);
          res = follow_ssa_edge (loop, SSA_NAME_DEF_STMT (rhs0), halting_phi,
                                 evolution_of_loop, limit);
          if (res == t_true)
-           *evolution_of_loop = add_to_evolution
-             (loop->num, chrec_convert (type, *evolution_of_loop, at_stmt),
-              MINUS_EXPR, rhs1, at_stmt);
-
+           ;
          else if (res == t_dont_know)
            *evolution_of_loop = chrec_dont_know;
        }
Index: gcc/testsuite/gcc.dg/torture/pr66375.c
===================================================================
--- gcc/testsuite/gcc.dg/torture/pr66375.c      (revision 0)
+++ gcc/testsuite/gcc.dg/torture/pr66375.c      (working copy)
@@ -0,0 +1,13 @@
+/* { dg-do run } */
+
+int a;
+extern void abort (void);
+int main ()
+{
+  int c = 0;
+  for (; a < 13; ++a)
+    c = (signed char)c - 11;
+  if (c != 113)
+    abort ();
+  return 0;
+}

Reply via email to