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>
|
||||
|
||||
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>
|
||||
|
||||
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_;
|
||||
};
|
||||
|
||||
/* 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
|
||||
data stored in LIM_DATA structures associated with each statement. Callback
|
||||
for walk_dominator_tree. */
|
||||
|
|
@ -1247,7 +1308,21 @@ move_computations_dom_walker::before_dom_children (basic_block bb)
|
|||
}
|
||||
}
|
||||
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