From e1ad2926a08a65efae413d84673e11ba695f2bd4 Mon Sep 17 00:00:00 2001 From: Alexandre Oliva Date: Wed, 10 May 2017 10:16:54 +0000 Subject: [PATCH] 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 --- gcc/ChangeLog | 5 +++ gcc/testsuite/ChangeLog | 4 ++ .../gcc.dg/guality/inline-params-2.c | 38 +++++++++++++++++++ gcc/tree-inline.c | 25 +++--------- 4 files changed, 53 insertions(+), 19 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/guality/inline-params-2.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1f08f99f01d..454203cde92 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2017-05-10 Alexandre Oliva + + * tree-inline.c (expand_call_inline): Split block at stmt + before the call. + 2017-05-09 Michael Meissner PR target/68163 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 8ec71d72438..0fc75a3c1a2 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2017-05-10 Alexandre Oliva + + * gcc.dg/guality/inline-params-2.c: New. + 2017-05-10 Paolo Carlini PR c++/80145 diff --git a/gcc/testsuite/gcc.dg/guality/inline-params-2.c b/gcc/testsuite/gcc.dg/guality/inline-params-2.c new file mode 100644 index 00000000000..e00188ca01d --- /dev/null +++ b/gcc/testsuite/gcc.dg/guality/inline-params-2.c @@ -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); +} diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index bfaaede0c32..db3e08fe0b0 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -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);