mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-01-11 09:54:51 +08:00
re PR middle-end/17075 (miscompilation with tail calls in cfgexpand)
PR 17075 * cfgexpand.c (expand_gimple_tailcall): Detect when we can both create new blocks and fall through. (expand_gimple_basic_block): Update to match. From-SVN: r86389
This commit is contained in:
parent
0b540f12b0
commit
cea4955090
@ -1,3 +1,10 @@
|
||||
2004-08-22 Richard Henderson <rth@redhat.com>
|
||||
|
||||
PR 17075
|
||||
* cfgexpand.c (expand_gimple_tailcall): Detect when we can both
|
||||
create new blocks and fall through.
|
||||
(expand_gimple_basic_block): Update to match.
|
||||
|
||||
2004-08-22 Ulrich Weigand <uweigand@de.ibm.com>
|
||||
|
||||
* reload.c (find_reloads_address): Make return value tri-state.
|
||||
|
@ -129,10 +129,15 @@ expand_gimple_cond_expr (basic_block bb, tree stmt)
|
||||
/* A subroutine of expand_gimple_basic_block. Expand one CALL_EXPR
|
||||
that has CALL_EXPR_TAILCALL set. Returns non-null if we actually
|
||||
generated a tail call (something that might be denied by the ABI
|
||||
rules governing the call; see calls.c). */
|
||||
rules governing the call; see calls.c).
|
||||
|
||||
Sets CAN_FALLTHRU if we generated a *conditional* tail call, and
|
||||
can still reach the rest of BB. The case here is __builtin_sqrt,
|
||||
where the NaN result goes through the external function (with a
|
||||
tailcall) and the normal result happens via a sqrt instruction. */
|
||||
|
||||
static basic_block
|
||||
expand_gimple_tailcall (basic_block bb, tree stmt)
|
||||
expand_gimple_tailcall (basic_block bb, tree stmt, bool *can_fallthru)
|
||||
{
|
||||
rtx last = get_last_insn ();
|
||||
edge e;
|
||||
@ -145,6 +150,7 @@ expand_gimple_tailcall (basic_block bb, tree stmt)
|
||||
if (CALL_P (last) && SIBLING_CALL_P (last))
|
||||
goto found;
|
||||
|
||||
*can_fallthru = true;
|
||||
return NULL;
|
||||
|
||||
found:
|
||||
@ -191,12 +197,17 @@ expand_gimple_tailcall (basic_block bb, tree stmt)
|
||||
last = NEXT_INSN (last);
|
||||
if (!BARRIER_P (last))
|
||||
abort ();
|
||||
|
||||
*can_fallthru = false;
|
||||
while (NEXT_INSN (last))
|
||||
{
|
||||
/* For instance an sqrt builtin expander expands if with
|
||||
sibcall in the then and label for `else`. */
|
||||
if (LABEL_P (NEXT_INSN (last)))
|
||||
break;
|
||||
{
|
||||
*can_fallthru = true;
|
||||
break;
|
||||
}
|
||||
delete_insn (NEXT_INSN (last));
|
||||
}
|
||||
|
||||
@ -277,7 +288,7 @@ expand_gimple_basic_block (basic_block bb, FILE * dump_file)
|
||||
for (; !bsi_end_p (bsi); bsi_next (&bsi))
|
||||
{
|
||||
tree stmt = bsi_stmt (bsi);
|
||||
basic_block new_bb = NULL;
|
||||
basic_block new_bb;
|
||||
|
||||
if (!stmt)
|
||||
continue;
|
||||
@ -285,18 +296,29 @@ expand_gimple_basic_block (basic_block bb, FILE * dump_file)
|
||||
/* Expand this statement, then evaluate the resulting RTL and
|
||||
fixup the CFG accordingly. */
|
||||
if (TREE_CODE (stmt) == COND_EXPR)
|
||||
new_bb = expand_gimple_cond_expr (bb, stmt);
|
||||
{
|
||||
new_bb = expand_gimple_cond_expr (bb, stmt);
|
||||
if (new_bb)
|
||||
return new_bb;
|
||||
}
|
||||
else
|
||||
{
|
||||
tree call = get_call_expr_in (stmt);
|
||||
if (call && CALL_EXPR_TAILCALL (call))
|
||||
new_bb = expand_gimple_tailcall (bb, stmt);
|
||||
{
|
||||
bool can_fallthru;
|
||||
new_bb = expand_gimple_tailcall (bb, stmt, &can_fallthru);
|
||||
if (new_bb)
|
||||
{
|
||||
if (can_fallthru)
|
||||
bb = new_bb;
|
||||
else
|
||||
return new_bb;
|
||||
}
|
||||
}
|
||||
else
|
||||
expand_expr_stmt (stmt);
|
||||
}
|
||||
|
||||
if (new_bb)
|
||||
return new_bb;
|
||||
}
|
||||
|
||||
do_pending_stack_adjust ();
|
||||
|
Loading…
Reference in New Issue
Block a user