re PR tree-optimization/80153 (ivopt generate wrong code)
authorBin Cheng <amker@gcc.gnu.org>
Mon, 10 Apr 2017 16:51:44 +0000 (16:51 +0000)
committerBin Cheng <amker@gcc.gnu.org>
Mon, 10 Apr 2017 16:51:44 +0000 (16:51 +0000)
PR tree-optimization/80153
* tree-affine.c (aff_combination_to_tree): Get base pointer from
the first element of pointer type aff_tree.  Build result expr in
aff_tree's type.
(add_elt_to_tree): Convert to type unconditionally.  Remove other
fold_convert calls.
* tree-ssa-loop-ivopts.c (alloc_iv): Pass in consistent types.
(rewrite_use_nonlinear_expr): Check invariant using iv information.
gcc/testsuite
PR tree-optimization/80153
* gcc.c-torture/execute/pr80153.c: New.

From-SVN: r246810

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/pr80153.c [new file with mode: 0644]
gcc/tree-affine.c
gcc/tree-ssa-loop-ivopts.c

index b6d385b357979b24bd6f341c4765361e5b9b2574..3bd0951bb62a66ca26d72b4a9dde869b693d8382 100644 (file)
@@ -1,3 +1,15 @@
+2017-04-10  Richard Biener  <rguenther@suse.de>
+           Bin Cheng  <bin.cheng@arm.com>
+
+       PR tree-optimization/80153
+       * tree-affine.c (aff_combination_to_tree): Get base pointer from
+       the first element of pointer type aff_tree.  Build result expr in
+       aff_tree's type.
+       (add_elt_to_tree): Convert to type unconditionally.  Remove other
+       fold_convert calls.
+       * tree-ssa-loop-ivopts.c (alloc_iv): Pass in consistent types.
+       (rewrite_use_nonlinear_expr): Check invariant using iv information.
+
 2017-04-10  Richard Biener  <rguenther@suse.de>
 
        * tree-ssa-structalias.c (find_func_aliases): Properly handle
index f71cb1a30aa70388f8a035ee18f7a62a07cdb8e1..1c5d5baba7e6b1316715e3d22c5926a0ed98d100 100644 (file)
@@ -1,3 +1,8 @@
+2017-04-10  Bin Cheng  <bin.cheng@arm.com>
+
+       PR tree-optimization/80153
+       * gcc.c-torture/execute/pr80153.c: New.
+
 2017-04-10  Richard Biener  <rguenther@suse.de>
 
        PR middle-end/80362
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr80153.c b/gcc/testsuite/gcc.c-torture/execute/pr80153.c
new file mode 100644 (file)
index 0000000..3eed578
--- /dev/null
@@ -0,0 +1,48 @@
+/* PR tree-optimization/80153 */
+
+void check (int, int, int) __attribute__((noinline));
+void check (int c, int c2, int val)
+{
+  if (!val) {
+    __builtin_abort();
+  }
+}
+
+static const char *buf;
+static int l, i;
+
+void _fputs(const char *str)  __attribute__((noinline));
+void _fputs(const char *str)
+{
+  buf = str;
+  i = 0;
+  l = __builtin_strlen(buf);
+}
+
+char _fgetc() __attribute__((noinline));
+char _fgetc()
+{
+  char val = buf[i];
+  i++;
+  if (i > l)
+    return -1;
+  else
+    return val;
+}
+
+static const char *string = "oops!\n";
+
+int main(void)
+{
+  int i;
+  int c;
+
+  _fputs(string);
+
+  for (i = 0; i < __builtin_strlen(string); i++) {
+    c = _fgetc();
+    check(c, string[i], c == string[i]);
+  }
+
+  return 0;
+}
index 30fff67b0054eb8ddbfc4c19f5425f5264cb7855..13c477dc7d6dcfebdea9c852d1266726be01250c 100644 (file)
@@ -377,58 +377,28 @@ static tree
 add_elt_to_tree (tree expr, tree type, tree elt, const widest_int &scale_in)
 {
   enum tree_code code;
-  tree type1 = type;
-  if (POINTER_TYPE_P (type))
-    type1 = sizetype;
 
   widest_int scale = wide_int_ext_for_comb (scale_in, type);
 
-  if (scale == -1
-      && POINTER_TYPE_P (TREE_TYPE (elt)))
-    {
-      elt = convert_to_ptrofftype (elt);
-      elt = fold_build1 (NEGATE_EXPR, TREE_TYPE (elt), elt);
-      scale = 1;
-    }
-
+  elt = fold_convert (type, elt);
   if (scale == 1)
     {
       if (!expr)
-       {
-         if (POINTER_TYPE_P (TREE_TYPE (elt)))
-           return elt;
-         else
-           return fold_convert (type1, elt);
-       }
+       return elt;
 
-      if (POINTER_TYPE_P (TREE_TYPE (expr)))
-       return fold_build_pointer_plus (expr, elt);
-      if (POINTER_TYPE_P (TREE_TYPE (elt)))
-       return fold_build_pointer_plus (elt, expr);
-      return fold_build2 (PLUS_EXPR, type1,
-                         expr, fold_convert (type1, elt));
+      return fold_build2 (PLUS_EXPR, type, expr, elt);
     }
 
   if (scale == -1)
     {
       if (!expr)
-       return fold_build1 (NEGATE_EXPR, type1,
-                           fold_convert (type1, elt));
+       return fold_build1 (NEGATE_EXPR, type, elt);
 
-      if (POINTER_TYPE_P (TREE_TYPE (expr)))
-       {
-         elt = convert_to_ptrofftype (elt);
-         elt = fold_build1 (NEGATE_EXPR, TREE_TYPE (elt), elt);
-         return fold_build_pointer_plus (expr, elt);
-       }
-      return fold_build2 (MINUS_EXPR, type1,
-                         expr, fold_convert (type1, elt));
+      return fold_build2 (MINUS_EXPR, type, expr, elt);
     }
 
-  elt = fold_convert (type1, elt);
   if (!expr)
-    return fold_build2 (MULT_EXPR, type1, elt,
-                       wide_int_to_tree (type1, scale));
+    return fold_build2 (MULT_EXPR, type, elt, wide_int_to_tree (type, scale));
 
   if (wi::neg_p (scale))
     {
@@ -438,15 +408,8 @@ add_elt_to_tree (tree expr, tree type, tree elt, const widest_int &scale_in)
   else
     code = PLUS_EXPR;
 
-  elt = fold_build2 (MULT_EXPR, type1, elt,
-                    wide_int_to_tree (type1, scale));
-  if (POINTER_TYPE_P (TREE_TYPE (expr)))
-    {
-      if (code == MINUS_EXPR)
-        elt = fold_build1 (NEGATE_EXPR, type1, elt);
-      return fold_build_pointer_plus (expr, elt);
-    }
-  return fold_build2 (code, type1, expr, elt);
+  elt = fold_build2 (MULT_EXPR, type, elt, wide_int_to_tree (type, scale));
+  return fold_build2 (code, type, expr, elt);
 }
 
 /* Makes tree from the affine combination COMB.  */
@@ -454,17 +417,25 @@ add_elt_to_tree (tree expr, tree type, tree elt, const widest_int &scale_in)
 tree
 aff_combination_to_tree (aff_tree *comb)
 {
-  tree type = comb->type;
-  tree expr = NULL_TREE;
+  tree type = comb->type, base = NULL_TREE, expr = NULL_TREE;
   unsigned i;
   widest_int off, sgn;
-  tree type1 = type;
-  if (POINTER_TYPE_P (type))
-    type1 = sizetype;
 
   gcc_assert (comb->n == MAX_AFF_ELTS || comb->rest == NULL_TREE);
 
-  for (i = 0; i < comb->n; i++)
+  i = 0;
+  if (POINTER_TYPE_P (type))
+    {
+      type = sizetype;
+      if (comb->n > 0 && comb->elts[0].coef == 1
+         && POINTER_TYPE_P (TREE_TYPE (comb->elts[0].val)))
+       {
+         base = comb->elts[0].val;
+         ++i;
+       }
+    }
+
+  for (; i < comb->n; i++)
     expr = add_elt_to_tree (expr, type, comb->elts[i].val, comb->elts[i].coef);
 
   if (comb->rest)
@@ -482,7 +453,12 @@ aff_combination_to_tree (aff_tree *comb)
       off = comb->offset;
       sgn = 1;
     }
-  return add_elt_to_tree (expr, type, wide_int_to_tree (type1, off), sgn);
+  expr = add_elt_to_tree (expr, type, wide_int_to_tree (type, off), sgn);
+
+  if (base)
+    return fold_build_pointer_plus (base, expr);
+  else
+    return fold_convert (comb->type, expr);
 }
 
 /* Copies the tree elements of COMB to ensure that they are not shared.  */
index d5bd0362f25ad31d8907de186e77f16e7e3d7cc9..036e04161765c8f19bc6f2c8d914ab3bd8ae0e9a 100644 (file)
@@ -1171,7 +1171,7 @@ alloc_iv (struct ivopts_data *data, tree base, tree step,
       || contain_complex_addr_expr (expr))
     {
       aff_tree comb;
-      tree_to_aff_combination (expr, TREE_TYPE (base), &comb);
+      tree_to_aff_combination (expr, TREE_TYPE (expr), &comb);
       base = fold_convert (TREE_TYPE (base), aff_combination_to_tree (&comb));
     }
 
@@ -7183,7 +7183,7 @@ rewrite_use_nonlinear_expr (struct ivopts_data *data,
                            struct iv_use *use, struct iv_cand *cand)
 {
   tree comp;
-  tree op, tgt;
+  tree tgt;
   gassign *ass;
   gimple_stmt_iterator bsi;
 
@@ -7194,6 +7194,7 @@ rewrite_use_nonlinear_expr (struct ivopts_data *data,
   if (cand->pos == IP_ORIGINAL
       && cand->incremented_at == use->stmt)
     {
+      tree op = NULL_TREE;
       enum tree_code stmt_code;
 
       gcc_assert (is_gimple_assign (use->stmt));
@@ -7213,14 +7214,19 @@ rewrite_use_nonlinear_expr (struct ivopts_data *data,
            op = gimple_assign_rhs2 (use->stmt);
          else if (gimple_assign_rhs2 (use->stmt) == cand->var_before)
            op = gimple_assign_rhs1 (use->stmt);
-         else
-           op = NULL_TREE;
        }
-      else
-       op = NULL_TREE;
 
-      if (op && expr_invariant_in_loop_p (data->current_loop, op))
-       return;
+      if (op != NULL_TREE)
+       {
+         if (expr_invariant_in_loop_p (data->current_loop, op))
+           return;
+         if (TREE_CODE (op) == SSA_NAME)
+           {
+             struct iv *iv = get_iv (data, op);
+             if (iv != NULL && integer_zerop (iv->step))
+               return;
+           }
+       }
     }
 
   comp = get_computation (data->current_loop, use, cand);