re PR tree-optimization/58946 (internal compiler error: in operator[], at vec.h:722)

PR tree-optimization/58946
	* tree-ssa-reassoc.c (maybe_optimize_range_tests): Update all
	bbs with bbinfo[idx].op != NULL before all blocks with
	bbinfo[idx].op == NULL.

	* gcc.c-torture/compile/pr58946.c: New test.

From-SVN: r204348
This commit is contained in:
Jakub Jelinek 2013-11-04 11:29:42 +01:00 committed by Jakub Jelinek
parent 2546da0b1d
commit 96f9e25a4b
4 changed files with 74 additions and 29 deletions

View File

@ -1,3 +1,10 @@
2013-11-04 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/58946
* tree-ssa-reassoc.c (maybe_optimize_range_tests): Update all
bbs with bbinfo[idx].op != NULL before all blocks with
bbinfo[idx].op == NULL.
2013-11-04 Richard Sandiford <rdsandiford@googlemail.com>
* config/avr/avr-log.c (avr_double_int_pop_digit): Delete.

View File

@ -1,3 +1,8 @@
2013-11-04 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/58946
* gcc.c-torture/compile/pr58946.c: New test.
2013-11-03 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/52071

View File

@ -0,0 +1,20 @@
/* PR tree-optimization/58946 */
int
foo (unsigned int c)
{
unsigned int d, e, f;
if ((int) c < 0)
d = 0;
else
d = c;
if (d == 0)
e = __INT_MAX__ + 1U;
else
e = d;
if ((int) e < 0)
f = 0;
else
f = e;
return f;
}

View File

@ -2657,6 +2657,7 @@ maybe_optimize_range_tests (gimple stmt)
edge e;
vec<operand_entry_t> ops = vNULL;
vec<inter_bb_range_test_entry> bbinfo = vNULL;
bool any_changes = false;
/* Consider only basic blocks that end with GIMPLE_COND or
a cast statement satisfying final_range_test_p. All
@ -2870,41 +2871,31 @@ maybe_optimize_range_tests (gimple stmt)
break;
}
if (ops.length () > 1)
any_changes = optimize_range_tests (ERROR_MARK, &ops);
if (any_changes)
{
unsigned int idx;
bool any_changes = optimize_range_tests (ERROR_MARK, &ops);
for (bb = last_bb, idx = 0; any_changes; bb = single_pred (bb), idx++)
/* update_ops relies on has_single_use predicates returning the
same values as it did during get_ops earlier. Additionally it
never removes statements, only adds new ones and it should walk
from the single imm use and check the predicate already before
making those changes.
On the other side, the handling of GIMPLE_COND directly can turn
previously multiply used SSA_NAMEs into single use SSA_NAMEs, so
it needs to be done in a separate loop afterwards. */
for (bb = last_bb, idx = 0; ; bb = single_pred (bb), idx++)
{
if (bbinfo[idx].first_idx < bbinfo[idx].last_idx)
if (bbinfo[idx].first_idx < bbinfo[idx].last_idx
&& bbinfo[idx].op != NULL_TREE)
{
gimple stmt = last_stmt (bb);
tree new_op;
if (bbinfo[idx].op == NULL_TREE)
{
if (ops[bbinfo[idx].first_idx]->op != NULL_TREE)
{
if (integer_zerop (ops[bbinfo[idx].first_idx]->op))
gimple_cond_make_false (stmt);
else if (integer_onep (ops[bbinfo[idx].first_idx]->op))
gimple_cond_make_true (stmt);
else
{
gimple_cond_set_code (stmt, NE_EXPR);
gimple_cond_set_lhs (stmt,
ops[bbinfo[idx].first_idx]->op);
gimple_cond_set_rhs (stmt, boolean_false_node);
}
update_stmt (stmt);
}
bbinfo[idx].op = new_op = boolean_false_node;
}
else
new_op = update_ops (bbinfo[idx].op,
(enum tree_code)
ops[bbinfo[idx].first_idx]->rank,
ops, &bbinfo[idx].first_idx,
loop_containing_stmt (stmt));
stmt = last_stmt (bb);
new_op = update_ops (bbinfo[idx].op,
(enum tree_code)
ops[bbinfo[idx].first_idx]->rank,
ops, &bbinfo[idx].first_idx,
loop_containing_stmt (stmt));
if (new_op == NULL_TREE)
{
gcc_assert (bb == last_bb);
@ -2956,6 +2947,28 @@ maybe_optimize_range_tests (gimple stmt)
if (bb == first_bb)
break;
}
for (bb = last_bb, idx = 0; ; bb = single_pred (bb), idx++)
{
if (bbinfo[idx].first_idx < bbinfo[idx].last_idx
&& bbinfo[idx].op == NULL_TREE
&& ops[bbinfo[idx].first_idx]->op != NULL_TREE)
{
stmt = last_stmt (bb);
if (integer_zerop (ops[bbinfo[idx].first_idx]->op))
gimple_cond_make_false (stmt);
else if (integer_onep (ops[bbinfo[idx].first_idx]->op))
gimple_cond_make_true (stmt);
else
{
gimple_cond_set_code (stmt, NE_EXPR);
gimple_cond_set_lhs (stmt, ops[bbinfo[idx].first_idx]->op);
gimple_cond_set_rhs (stmt, boolean_false_node);
}
update_stmt (stmt);
}
if (bb == first_bb)
break;
}
}
bbinfo.release ();
ops.release ();