re PR c/35634 (operand of pre-/postin-/decrement not promoted)
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
This commit is contained in:
parent
b1c2b51b66
commit
cc3c4f62f3
|
@ -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>
|
2012-11-28 Steven Bosscher <steven@gcc.gnu.org>
|
||||||
|
|
||||||
PR rtl-optimization/55006
|
PR rtl-optimization/55006
|
||||||
|
|
|
@ -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>
|
2012-11-23 Jakub Jelinek <jakub@redhat.com>
|
||||||
|
|
||||||
PR sanitizer/55435
|
PR sanitizer/55435
|
||||||
|
|
|
@ -172,16 +172,37 @@ c_gimplify_expr (tree *expr_p, gimple_seq *pre_p ATTRIBUTE_UNUSED,
|
||||||
{
|
{
|
||||||
enum tree_code code = TREE_CODE (*expr_p);
|
enum tree_code code = TREE_CODE (*expr_p);
|
||||||
|
|
||||||
/* This is handled mostly by gimplify.c, but we have to deal with
|
switch (code)
|
||||||
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. */
|
case DECL_EXPR:
|
||||||
if (code == DECL_EXPR
|
/* This is handled mostly by gimplify.c, but we have to deal with
|
||||||
&& TREE_CODE (DECL_EXPR_DECL (*expr_p)) == VAR_DECL
|
not warning about int x = x; as it is a GCC extension to turn off
|
||||||
&& !DECL_EXTERNAL (DECL_EXPR_DECL (*expr_p))
|
this warning but only if warn_init_self is zero. */
|
||||||
&& !TREE_STATIC (DECL_EXPR_DECL (*expr_p))
|
if (TREE_CODE (DECL_EXPR_DECL (*expr_p)) == VAR_DECL
|
||||||
&& (DECL_INITIAL (DECL_EXPR_DECL (*expr_p)) == DECL_EXPR_DECL (*expr_p))
|
&& !DECL_EXTERNAL (DECL_EXPR_DECL (*expr_p))
|
||||||
&& !warn_init_self)
|
&& !TREE_STATIC (DECL_EXPR_DECL (*expr_p))
|
||||||
TREE_NO_WARNING (DECL_EXPR_DECL (*expr_p)) = 1;
|
&& (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;
|
return GS_UNHANDLED;
|
||||||
}
|
}
|
||||||
|
|
|
@ -979,6 +979,8 @@ extern enum gimplify_status gimplify_expr (tree *, gimple_seq *, gimple_seq *,
|
||||||
bool (*) (tree), fallback_t);
|
bool (*) (tree), fallback_t);
|
||||||
extern void gimplify_type_sizes (tree, gimple_seq *);
|
extern void gimplify_type_sizes (tree, gimple_seq *);
|
||||||
extern void gimplify_one_sizepos (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 bool gimplify_stmt (tree *, gimple_seq *);
|
||||||
extern gimple gimplify_body (tree, bool);
|
extern gimple gimplify_body (tree, bool);
|
||||||
extern void push_gimplify_context (struct gimplify_ctx *);
|
extern void push_gimplify_context (struct gimplify_ctx *);
|
||||||
|
|
|
@ -2317,11 +2317,13 @@ gimplify_compound_lval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
|
||||||
*EXPR_P should be stored.
|
*EXPR_P should be stored.
|
||||||
|
|
||||||
WANT_VALUE is nonzero iff we want to use the value of this expression
|
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,
|
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;
|
enum tree_code code;
|
||||||
tree lhs, lvalue, rhs, t1;
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (postfix)
|
||||||
|
lhs = get_initialized_tmp_var (lhs, pre_p, NULL);
|
||||||
|
|
||||||
/* For POINTERs increment, use POINTER_PLUS_EXPR. */
|
/* For POINTERs increment, use POINTER_PLUS_EXPR. */
|
||||||
if (POINTER_TYPE_P (TREE_TYPE (lhs)))
|
if (POINTER_TYPE_P (TREE_TYPE (lhs)))
|
||||||
{
|
{
|
||||||
rhs = convert_to_ptrofftype_loc (loc, rhs);
|
rhs = convert_to_ptrofftype_loc (loc, rhs);
|
||||||
if (arith_code == MINUS_EXPR)
|
if (arith_code == MINUS_EXPR)
|
||||||
rhs = fold_build1_loc (loc, NEGATE_EXPR, TREE_TYPE (rhs), rhs);
|
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)
|
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_assign (lvalue, t1, pre_p);
|
||||||
gimplify_seq_add_seq (orig_post_p, post);
|
gimplify_seq_add_seq (orig_post_p, post);
|
||||||
*expr_p = t2;
|
*expr_p = lhs;
|
||||||
return GS_ALL_DONE;
|
return GS_ALL_DONE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
t1 = build2 (arith_code, TREE_TYPE (*expr_p), lhs, rhs);
|
|
||||||
*expr_p = build2 (MODIFY_EXPR, TREE_TYPE (lvalue), lvalue, t1);
|
*expr_p = build2 (MODIFY_EXPR, TREE_TYPE (lvalue), lvalue, t1);
|
||||||
return GS_OK;
|
return GS_OK;
|
||||||
}
|
}
|
||||||
|
@ -7111,7 +7118,8 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
|
||||||
case PREINCREMENT_EXPR:
|
case PREINCREMENT_EXPR:
|
||||||
case PREDECREMENT_EXPR:
|
case PREDECREMENT_EXPR:
|
||||||
ret = gimplify_self_mod_expr (expr_p, pre_p, post_p,
|
ret = gimplify_self_mod_expr (expr_p, pre_p, post_p,
|
||||||
fallback != fb_none);
|
fallback != fb_none,
|
||||||
|
TREE_TYPE (*expr_p));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ARRAY_REF:
|
case ARRAY_REF:
|
||||||
|
|
|
@ -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>
|
2012-11-27 Tobias Burnus <burnus@net-b.de>
|
||||||
|
|
||||||
PR fortran/55476
|
PR fortran/55476
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
#define N 16
|
#define N 16
|
||||||
|
|
||||||
int main1 (short a, short *b)
|
__attribute__ ((noinline)) int main1 (short a, short *b)
|
||||||
{
|
{
|
||||||
while (++a < 4) *b++ = 2;
|
while (++a < 4) *b++ = 2;
|
||||||
|
|
||||||
|
|
|
@ -1727,6 +1727,7 @@ vect_can_advance_ivs_p (loop_vec_info loop_vinfo)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
STRIP_NOPS (access_fn);
|
||||||
if (dump_enabled_p ())
|
if (dump_enabled_p ())
|
||||||
{
|
{
|
||||||
dump_printf_loc (MSG_NOTE, vect_location,
|
dump_printf_loc (MSG_NOTE, vect_location,
|
||||||
|
|
Loading…
Reference in New Issue