mirror of git://gcc.gnu.org/git/gcc.git
re PR tree-optimization/58143 (wrong code at -O3)
2013-10-17 Richard Biener <rguenther@suse.de> PR tree-optimization/58143 * tree-ssa-loop-im.c (arith_code_with_undefined_signed_overflow): New function. (rewrite_to_defined_overflow): Likewise. (move_computations_dom_walker::before_dom): Rewrite stmts with undefined signed overflow that are not always executed into unsigned arithmetic. * gcc.dg/torture/pr58143-1.c: New testcase. * gcc.dg/torture/pr58143-2.c: Likewise. * gcc.dg/torture/pr58143-3.c: Likewise. From-SVN: r203745
This commit is contained in:
parent
568a31f2f6
commit
f4bed77be4
|
|
@ -1,3 +1,13 @@
|
||||||
|
2013-10-17 Richard Biener <rguenther@suse.de>
|
||||||
|
|
||||||
|
PR tree-optimization/58143
|
||||||
|
* tree-ssa-loop-im.c (arith_code_with_undefined_signed_overflow):
|
||||||
|
New function.
|
||||||
|
(rewrite_to_defined_overflow): Likewise.
|
||||||
|
(move_computations_dom_walker::before_dom): Rewrite stmts
|
||||||
|
with undefined signed overflow that are not always executed
|
||||||
|
into unsigned arithmetic.
|
||||||
|
|
||||||
2013-10-16 Michael Meissner <meissner@linux.vnet.ibm.com>
|
2013-10-16 Michael Meissner <meissner@linux.vnet.ibm.com>
|
||||||
|
|
||||||
PR target/57756
|
PR target/57756
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,10 @@
|
||||||
|
2013-10-17 Richard Biener <rguenther@suse.de>
|
||||||
|
|
||||||
|
PR tree-optimization/58143
|
||||||
|
* gcc.dg/torture/pr58143-1.c: New testcase.
|
||||||
|
* gcc.dg/torture/pr58143-2.c: Likewise.
|
||||||
|
* gcc.dg/torture/pr58143-3.c: Likewise.
|
||||||
|
|
||||||
2013-10-17 Marek Polacek <polacek@redhat.com>
|
2013-10-17 Marek Polacek <polacek@redhat.com>
|
||||||
|
|
||||||
PR c/58267
|
PR c/58267
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
/* { dg-do run } */
|
||||||
|
/* { dg-additional-options "-fstrict-overflow" } */
|
||||||
|
|
||||||
|
extern void abort (void);
|
||||||
|
|
||||||
|
int a, b, c, d, e, f, g, h = 1, i;
|
||||||
|
|
||||||
|
int foo (int p)
|
||||||
|
{
|
||||||
|
return p < 0 && a < - __INT_MAX__ - 1 - p ? 0 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int *bar ()
|
||||||
|
{
|
||||||
|
int j;
|
||||||
|
i = h ? 0 : 1 % h;
|
||||||
|
for (j = 0; j < 1; j++)
|
||||||
|
for (d = 0; d; d++)
|
||||||
|
for (e = 1; e;)
|
||||||
|
return 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int baz ()
|
||||||
|
{
|
||||||
|
for (; b >= 0; b--)
|
||||||
|
for (c = 1; c >= 0; c--)
|
||||||
|
{
|
||||||
|
int *k = &c;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
for (f = 0; f < 1; f++)
|
||||||
|
{
|
||||||
|
g = foo (*k);
|
||||||
|
bar ();
|
||||||
|
}
|
||||||
|
if (*k)
|
||||||
|
break;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main ()
|
||||||
|
{
|
||||||
|
baz ();
|
||||||
|
if (b != 0)
|
||||||
|
abort ();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
/* { dg-do run } */
|
||||||
|
/* { dg-additional-options "-fstrict-overflow" } */
|
||||||
|
|
||||||
|
int a, b, d, e, f, *g, h, i;
|
||||||
|
volatile int c;
|
||||||
|
|
||||||
|
char foo (unsigned char p)
|
||||||
|
{
|
||||||
|
return p + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bar ()
|
||||||
|
{
|
||||||
|
for (h = 0; h < 3; h = foo (h))
|
||||||
|
{
|
||||||
|
c;
|
||||||
|
for (f = 0; f < 1; f++)
|
||||||
|
{
|
||||||
|
i = a && 0 < -__INT_MAX__ - h ? 0 : 1;
|
||||||
|
if (e)
|
||||||
|
for (; d;)
|
||||||
|
b = 0;
|
||||||
|
else
|
||||||
|
g = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main ()
|
||||||
|
{
|
||||||
|
bar ();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
/* { dg-do run } */
|
||||||
|
/* { dg-additional-options "-fstrict-overflow" } */
|
||||||
|
|
||||||
|
int a, b, c, d, e;
|
||||||
|
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
for (b = 4; b > -30; b--)
|
||||||
|
for (; c;)
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
e = a > __INT_MAX__ - b;
|
||||||
|
if (d)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -1117,6 +1117,67 @@ public:
|
||||||
unsigned int todo_;
|
unsigned int todo_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Return true if CODE is an operation that when operating on signed
|
||||||
|
integer types involves undefined behavior on overflow and the
|
||||||
|
operation can be expressed with unsigned arithmetic. */
|
||||||
|
|
||||||
|
static bool
|
||||||
|
arith_code_with_undefined_signed_overflow (tree_code code)
|
||||||
|
{
|
||||||
|
switch (code)
|
||||||
|
{
|
||||||
|
case PLUS_EXPR:
|
||||||
|
case MINUS_EXPR:
|
||||||
|
case MULT_EXPR:
|
||||||
|
case NEGATE_EXPR:
|
||||||
|
case POINTER_PLUS_EXPR:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Rewrite STMT, an assignment with a signed integer or pointer arithmetic
|
||||||
|
operation that can be transformed to unsigned arithmetic by converting
|
||||||
|
its operand, carrying out the operation in the corresponding unsigned
|
||||||
|
type and converting the result back to the original type.
|
||||||
|
|
||||||
|
Returns a sequence of statements that replace STMT and also contain
|
||||||
|
a modified form of STMT itself. */
|
||||||
|
|
||||||
|
static gimple_seq
|
||||||
|
rewrite_to_defined_overflow (gimple stmt)
|
||||||
|
{
|
||||||
|
if (dump_file && (dump_flags & TDF_DETAILS))
|
||||||
|
{
|
||||||
|
fprintf (dump_file, "rewriting stmt with undefined signed "
|
||||||
|
"overflow ");
|
||||||
|
print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
|
||||||
|
}
|
||||||
|
|
||||||
|
tree lhs = gimple_assign_lhs (stmt);
|
||||||
|
tree type = unsigned_type_for (TREE_TYPE (lhs));
|
||||||
|
gimple_seq stmts = NULL;
|
||||||
|
for (unsigned i = 1; i < gimple_num_ops (stmt); ++i)
|
||||||
|
{
|
||||||
|
gimple_seq stmts2 = NULL;
|
||||||
|
gimple_set_op (stmt, i,
|
||||||
|
force_gimple_operand (fold_convert (type,
|
||||||
|
gimple_op (stmt, i)),
|
||||||
|
&stmts2, true, NULL_TREE));
|
||||||
|
gimple_seq_add_seq (&stmts, stmts2);
|
||||||
|
}
|
||||||
|
gimple_assign_set_lhs (stmt, make_ssa_name (type, stmt));
|
||||||
|
if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR)
|
||||||
|
gimple_assign_set_rhs_code (stmt, PLUS_EXPR);
|
||||||
|
gimple_seq_add_stmt (&stmts, stmt);
|
||||||
|
gimple cvt = gimple_build_assign_with_ops
|
||||||
|
(NOP_EXPR, lhs, gimple_assign_lhs (stmt), NULL_TREE);
|
||||||
|
gimple_seq_add_stmt (&stmts, cvt);
|
||||||
|
|
||||||
|
return stmts;
|
||||||
|
}
|
||||||
|
|
||||||
/* Hoist the statements in basic block BB out of the loops prescribed by
|
/* Hoist the statements in basic block BB out of the loops prescribed by
|
||||||
data stored in LIM_DATA structures associated with each statement. Callback
|
data stored in LIM_DATA structures associated with each statement. Callback
|
||||||
for walk_dominator_tree. */
|
for walk_dominator_tree. */
|
||||||
|
|
@ -1247,7 +1308,21 @@ move_computations_dom_walker::before_dom_children (basic_block bb)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
gsi_remove (&bsi, false);
|
gsi_remove (&bsi, false);
|
||||||
gsi_insert_on_edge (e, stmt);
|
/* In case this is a stmt that is not unconditionally executed
|
||||||
|
when the target loop header is executed and the stmt may
|
||||||
|
invoke undefined integer or pointer overflow rewrite it to
|
||||||
|
unsigned arithmetic. */
|
||||||
|
if (is_gimple_assign (stmt)
|
||||||
|
&& INTEGRAL_TYPE_P (TREE_TYPE (gimple_assign_lhs (stmt)))
|
||||||
|
&& TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (gimple_assign_lhs (stmt)))
|
||||||
|
&& arith_code_with_undefined_signed_overflow
|
||||||
|
(gimple_assign_rhs_code (stmt))
|
||||||
|
&& (!ALWAYS_EXECUTED_IN (bb)
|
||||||
|
|| !(ALWAYS_EXECUTED_IN (bb) == level
|
||||||
|
|| flow_loop_nested_p (ALWAYS_EXECUTED_IN (bb), level))))
|
||||||
|
gsi_insert_seq_on_edge (e, rewrite_to_defined_overflow (stmt));
|
||||||
|
else
|
||||||
|
gsi_insert_on_edge (e, stmt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue