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 + + 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 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 + + 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 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 + + 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 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,