re PR c/35634 (operand of pre-/postin-/decrement not promoted)
authorRichard Biener <rguenther@suse.de>
Wed, 28 Nov 2012 09:27:10 +0000 (09:27 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Wed, 28 Nov 2012 09:27:10 +0000 (09:27 +0000)
2012-11-28  Richard Biener  <rguenther@suse.de>

PR c/35634
* gimple.h (gimplify_self_mod_expr): Declare.
* gimplify.c (gimplify_self_mod_expr): Export.  Take a different
type for performing the arithmetic in.
(gimplify_expr): Adjust.
* tree-vect-loop-manip.c (vect_can_advance_ivs_p): Strip
sign conversions we can re-apply after adjusting the IV.

c-family/
* c-gimplify.c (c_gimplify_expr): Gimplify self-modify expressions
here and use a type with proper overflow behavior for types that would
need to be promoted for the arithmetic.

* gcc.dg/torture/pr35634.c: New testcase.
* g++.dg/torture/pr35634.C: Likewise.
* gcc.dg/vect/pr18536.c: Mark worker function noinline.

From-SVN: r193882

gcc/ChangeLog
gcc/c-family/ChangeLog
gcc/c-family/c-gimplify.c
gcc/gimple.h
gcc/gimplify.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/torture/pr35634.C [new file with mode: 0644]
gcc/testsuite/gcc.dg/torture/pr35634.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/pr18536.c
gcc/tree-vect-loop-manip.c

index 8fde718..b1a4afb 100644 (file)
@@ -1,3 +1,13 @@
+2012-11-28  Richard Biener  <rguenther@suse.de>
+
+       PR c/35634
+       * gimple.h (gimplify_self_mod_expr): Declare.
+       * gimplify.c (gimplify_self_mod_expr): Export.  Take a different
+       type for performing the arithmetic in.
+       (gimplify_expr): Adjust.
+       * tree-vect-loop-manip.c (vect_can_advance_ivs_p): Strip
+       sign conversions we can re-apply after adjusting the IV.
+
 2012-11-28  Steven Bosscher  <steven@gcc.gnu.org>
 
        PR rtl-optimization/55006
index ce794a2..ab68f3a 100644 (file)
@@ -1,3 +1,10 @@
+2012-11-28  Richard Biener  <rguenther@suse.de>
+
+       PR c/35634
+       * c-gimplify.c (c_gimplify_expr): Gimplify self-modify expressions
+       here and use a type with proper overflow behavior for types that would
+       need to be promoted for the arithmetic.
+
 2012-11-23  Jakub Jelinek  <jakub@redhat.com>
 
        PR sanitizer/55435
index 27814e1..74c94c1 100644 (file)
@@ -172,16 +172,37 @@ c_gimplify_expr (tree *expr_p, gimple_seq *pre_p ATTRIBUTE_UNUSED,
 {
   enum tree_code code = TREE_CODE (*expr_p);
 
-  /* This is handled mostly by gimplify.c, but we have to deal with
-     not warning about int x = x; as it is a GCC extension to turn off
-     this warning but only if warn_init_self is zero.  */
-  if (code == DECL_EXPR
-      && TREE_CODE (DECL_EXPR_DECL (*expr_p)) == VAR_DECL
-      && !DECL_EXTERNAL (DECL_EXPR_DECL (*expr_p))
-      && !TREE_STATIC (DECL_EXPR_DECL (*expr_p))
-      && (DECL_INITIAL (DECL_EXPR_DECL (*expr_p)) == DECL_EXPR_DECL (*expr_p))
-      && !warn_init_self)
-    TREE_NO_WARNING (DECL_EXPR_DECL (*expr_p)) = 1;
+  switch (code)
+    {
+    case DECL_EXPR:
+      /* This is handled mostly by gimplify.c, but we have to deal with
+        not warning about int x = x; as it is a GCC extension to turn off
+        this warning but only if warn_init_self is zero.  */
+      if (TREE_CODE (DECL_EXPR_DECL (*expr_p)) == VAR_DECL
+         && !DECL_EXTERNAL (DECL_EXPR_DECL (*expr_p))
+         && !TREE_STATIC (DECL_EXPR_DECL (*expr_p))
+         && (DECL_INITIAL (DECL_EXPR_DECL (*expr_p)) == DECL_EXPR_DECL (*expr_p))
+         && !warn_init_self)
+       TREE_NO_WARNING (DECL_EXPR_DECL (*expr_p)) = 1;
+      break;
+
+    case PREINCREMENT_EXPR:
+    case PREDECREMENT_EXPR:
+    case POSTINCREMENT_EXPR:
+    case POSTDECREMENT_EXPR:
+      {
+       tree type = TREE_TYPE (TREE_OPERAND (*expr_p, 0));
+       if (INTEGRAL_TYPE_P (type) && c_promoting_integer_type_p (type))
+         {
+           if (TYPE_OVERFLOW_UNDEFINED (type))
+             type = unsigned_type_for (type);
+           return gimplify_self_mod_expr (expr_p, pre_p, post_p, 1, type);
+         }
+       break;
+      }
+
+    default:;
+    }
 
   return GS_UNHANDLED;
 }
index 2d6cef4..5fcaac6 100644 (file)
@@ -979,6 +979,8 @@ extern enum gimplify_status gimplify_expr (tree *, gimple_seq *, gimple_seq *,
                                           bool (*) (tree), fallback_t);
 extern void gimplify_type_sizes (tree, gimple_seq *);
 extern void gimplify_one_sizepos (tree *, gimple_seq *);
+enum gimplify_status gimplify_self_mod_expr (tree *, gimple_seq *, gimple_seq *,
+                                            bool, tree);
 extern bool gimplify_stmt (tree *, gimple_seq *);
 extern gimple gimplify_body (tree, bool);
 extern void push_gimplify_context (struct gimplify_ctx *);
index 8d555f8..384adb2 100644 (file)
@@ -2317,11 +2317,13 @@ gimplify_compound_lval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
        *EXPR_P should be stored.
 
     WANT_VALUE is nonzero iff we want to use the value of this expression
-       in another expression.  */
+       in another expression.
 
-static enum gimplify_status
+    ARITH_TYPE is the type the computation should be performed in.  */
+
+enum gimplify_status
 gimplify_self_mod_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
-                       bool want_value)
+                       bool want_value, tree arith_type)
 {
   enum tree_code code;
   tree lhs, lvalue, rhs, t1;
@@ -2382,27 +2384,32 @@ gimplify_self_mod_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
        return ret;
     }
 
+  if (postfix)
+    lhs = get_initialized_tmp_var (lhs, pre_p, NULL);
+
   /* For POINTERs increment, use POINTER_PLUS_EXPR.  */
   if (POINTER_TYPE_P (TREE_TYPE (lhs)))
     {
       rhs = convert_to_ptrofftype_loc (loc, rhs);
       if (arith_code == MINUS_EXPR)
        rhs = fold_build1_loc (loc, NEGATE_EXPR, TREE_TYPE (rhs), rhs);
-      arith_code = POINTER_PLUS_EXPR;
+      t1 = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (*expr_p), lhs, rhs);
     }
+  else
+    t1 = fold_convert (TREE_TYPE (*expr_p),
+                      fold_build2 (arith_code, arith_type,
+                                   fold_convert (arith_type, lhs),
+                                   fold_convert (arith_type, rhs)));
 
   if (postfix)
     {
-      tree t2 = get_initialized_tmp_var (lhs, pre_p, NULL);
-      t1 = build2 (arith_code, TREE_TYPE (*expr_p), t2, rhs);
       gimplify_assign (lvalue, t1, pre_p);
       gimplify_seq_add_seq (orig_post_p, post);
-      *expr_p = t2;
+      *expr_p = lhs;
       return GS_ALL_DONE;
     }
   else
     {
-      t1 = build2 (arith_code, TREE_TYPE (*expr_p), lhs, rhs);
       *expr_p = build2 (MODIFY_EXPR, TREE_TYPE (lvalue), lvalue, t1);
       return GS_OK;
     }
@@ -7111,7 +7118,8 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
        case PREINCREMENT_EXPR:
        case PREDECREMENT_EXPR:
          ret = gimplify_self_mod_expr (expr_p, pre_p, post_p,
-                                       fallback != fb_none);
+                                       fallback != fb_none,
+                                       TREE_TYPE (*expr_p));
          break;
 
        case ARRAY_REF:
index 2d8350b..e537cdd 100644 (file)
@@ -1,3 +1,10 @@
+2012-11-28  Richard Biener  <rguenther@suse.de>
+
+       PR c/35634
+       * gcc.dg/torture/pr35634.c: New testcase.
+       * g++.dg/torture/pr35634.C: Likewise.
+       * gcc.dg/vect/pr18536.c: Mark worker function noinline.
+
 2012-11-27  Tobias Burnus  <burnus@net-b.de>
 
        PR fortran/55476
diff --git a/gcc/testsuite/g++.dg/torture/pr35634.C b/gcc/testsuite/g++.dg/torture/pr35634.C
new file mode 100644 (file)
index 0000000..00848e3
--- /dev/null
@@ -0,0 +1,19 @@
+/* { dg-do run } */
+
+extern "C" void abort (void);
+extern "C" void exit (int);
+
+void foo (int i)
+{
+    static int n;
+    if (i < -128 || i > 127)
+        abort ();
+    if (++n > 1000)
+        exit (0);
+}
+
+int main ()
+{
+    char c;
+    for (c = 0; ; c++) foo (c);
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr35634.c b/gcc/testsuite/gcc.dg/torture/pr35634.c
new file mode 100644 (file)
index 0000000..32df7d4
--- /dev/null
@@ -0,0 +1,19 @@
+/* { dg-do run } */
+
+void abort (void);
+void exit (int);
+
+void foo (int i)
+{
+    static int n;
+    if (i < -128 || i > 127)
+        abort ();
+    if (++n > 1000)
+        exit (0);
+}
+
+int main ()
+{
+    char c;
+    for (c = 0; ; c++) foo (c);
+}
index 4bf41be..6eac90f 100644 (file)
@@ -5,7 +5,7 @@
 
 #define N 16
 
-int main1 (short a, short *b)
+__attribute__ ((noinline)) int main1 (short a, short *b)
 {
   while (++a < 4) *b++ = 2;
 
index 34bde34..d3f23c9 100644 (file)
@@ -1727,6 +1727,7 @@ vect_can_advance_ivs_p (loop_vec_info loop_vinfo)
          return false;
        }
 
+      STRIP_NOPS (access_fn);
       if (dump_enabled_p ())
         {
          dump_printf_loc (MSG_NOTE, vect_location,