summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/c-family/ChangeLog7
-rw-r--r--gcc/c-family/c-gimplify.c41
-rw-r--r--gcc/gimple.h2
-rw-r--r--gcc/gimplify.c26
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/g++.dg/torture/pr35634.C19
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr35634.c19
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr18536.c2
-rw-r--r--gcc/tree-vect-loop-manip.c1
10 files changed, 114 insertions, 20 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 8fde718e02e..b1a4afb0010 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index ce794a29273..ab68f3abd05 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -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
diff --git a/gcc/c-family/c-gimplify.c b/gcc/c-family/c-gimplify.c
index 27814e1a1fb..74c94c140f5 100644
--- a/gcc/c-family/c-gimplify.c
+++ b/gcc/c-family/c-gimplify.c
@@ -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;
}
diff --git a/gcc/gimple.h b/gcc/gimple.h
index 2d6cef4f4d6..5fcaac60d08 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -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 *);
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 8d555f833b9..384adb21c35 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -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:
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 2d8350b2026..e537cdd2372 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 00000000000..00848e35d73
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr35634.C
@@ -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
index 00000000000..32df7d48c28
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr35634.c
@@ -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);
+}
diff --git a/gcc/testsuite/gcc.dg/vect/pr18536.c b/gcc/testsuite/gcc.dg/vect/pr18536.c
index 4bf41bec401..6eac90ff14d 100644
--- a/gcc/testsuite/gcc.dg/vect/pr18536.c
+++ b/gcc/testsuite/gcc.dg/vect/pr18536.c
@@ -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;
diff --git a/gcc/tree-vect-loop-manip.c b/gcc/tree-vect-loop-manip.c
index 34bde34ef25..d3f23c995d6 100644
--- a/gcc/tree-vect-loop-manip.c
+++ b/gcc/tree-vect-loop-manip.c
@@ -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,