avoid remove&reinsert of call when splitting block for inlining

We used to split the inlined-into block at (= after) the call, and then
remove the call from the first block to insert it in the second.

The removal may cause unnecessary and unrecoverable resetting of debug
insns: we do not generate debug temps for calls.

Avoid the remove-and-reinsert dance by splitting the block before the
call.

for  gcc/ChangeLog

	* tree-inline.c (expand_call_inline): Split block at stmt
	before the call.

for  gcc/testsuite/ChangeLog

	* gcc.dg/guality/inline-params-2.c: New.

From-SVN: r247830
This commit is contained in:
Alexandre Oliva 2017-05-10 10:16:54 +00:00 committed by Alexandre Oliva
parent f00b411f54
commit e1ad2926a0
4 changed files with 53 additions and 19 deletions

View File

@ -1,3 +1,8 @@
2017-05-10 Alexandre Oliva <aoliva@redhat.com>
* tree-inline.c (expand_call_inline): Split block at stmt
before the call.
2017-05-09 Michael Meissner <meissner@linux.vnet.ibm.com>
PR target/68163

View File

@ -1,3 +1,7 @@
2017-05-10 Alexandre Oliva <aoliva@redhat.com>
* gcc.dg/guality/inline-params-2.c: New.
2017-05-10 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/80145

View File

@ -0,0 +1,38 @@
/* { dg-do run } */
/* tree inline used to split the block for inlining after the call,
then move the call to the after-the-call block. This move
temporarily deletes the assignment to the result, which in turn
resets any debug bind stmts referencing the result. Make sure we
don't do that, verifying that the result is visible after the call,
and when passed to another inline function. */
/* { dg-options "-g" } */
/* { dg-xfail-run-if "" { "*-*-*" } { "-fno-fat-lto-objects" } } */
#define GUALITY_DONT_FORCE_LIVE_AFTER -1
#ifndef STATIC_INLINE
#define STATIC_INLINE /*static*/
#endif
#include "guality.h"
__attribute__ ((always_inline)) static inline int
t1 (int i)
{
GUALCHKVAL (i);
return i;
}
__attribute__ ((always_inline)) static inline int
t2 (int i)
{
GUALCHKVAL (i);
return i - 42;
}
int
main (int argc, char *argv[])
{
int i = t1(42);
GUALCHKVAL (i);
return t2(i);
}

View File

@ -4542,33 +4542,20 @@ expand_call_inline (basic_block bb, gimple *stmt, copy_body_data *id)
DECL_FUNCTION_PERSONALITY (cg_edge->caller->decl)
= DECL_FUNCTION_PERSONALITY (cg_edge->callee->decl);
/* Split the block holding the GIMPLE_CALL. */
e = split_block (bb, stmt);
/* Split the block before the GIMPLE_CALL. */
stmt_gsi = gsi_for_stmt (stmt);
gsi_prev (&stmt_gsi);
e = split_block (bb, gsi_end_p (stmt_gsi) ? NULL : gsi_stmt (stmt_gsi));
bb = e->src;
return_block = e->dest;
remove_edge (e);
/* split_block splits after the statement; work around this by
moving the call into the second block manually. Not pretty,
but seems easier than doing the CFG manipulation by hand
when the GIMPLE_CALL is in the last statement of BB. */
stmt_gsi = gsi_last_bb (bb);
gsi_remove (&stmt_gsi, false);
/* If the GIMPLE_CALL was in the last statement of BB, it may have
been the source of abnormal edges. In this case, schedule
the removal of dead abnormal edges. */
gsi = gsi_start_bb (return_block);
if (gsi_end_p (gsi))
{
gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
purge_dead_abnormal_edges = true;
}
else
{
gsi_insert_before (&gsi, stmt, GSI_NEW_STMT);
purge_dead_abnormal_edges = false;
}
gsi_next (&gsi);
purge_dead_abnormal_edges = gsi_end_p (gsi);
stmt_gsi = gsi_start_bb (return_block);