diff mbox

avoid remove&reinsert of call when splitting block for inlining

Message ID or7f1pg56f.fsf@lxoliva.fsfla.org
State New
Headers show

Commit Message

Alexandre Oliva May 9, 2017, 8:12 p.m. UTC
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.

Regstrapped on x86_64-linux-gnu and i686-linux-gnu.  Ok to install?

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.
---
 gcc/testsuite/gcc.dg/guality/inline-params-2.c |   38 ++++++++++++++++++++++++
 gcc/tree-inline.c                              |   25 ++++------------
 2 files changed, 44 insertions(+), 19 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/guality/inline-params-2.c

Comments

Richard Biener May 10, 2017, 8:11 a.m. UTC | #1
On Tue, May 9, 2017 at 10:12 PM, Alexandre Oliva <aoliva@redhat.com> wrote:
> 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.
>
> Regstrapped on x86_64-linux-gnu and i686-linux-gnu.  Ok to install?

Ok if you included Ada in bootstrap / testing.

Thanks,
Richard.

> 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.
> ---
>  gcc/testsuite/gcc.dg/guality/inline-params-2.c |   38 ++++++++++++++++++++++++
>  gcc/tree-inline.c                              |   25 ++++------------
>  2 files changed, 44 insertions(+), 19 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.dg/guality/inline-params-2.c
>
> 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 0000000..e00188ca
> --- /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 bfaaede..db3e08f 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);
>
>
> --
> Alexandre Oliva, freedom fighter    http://FSFLA.org/~lxoliva/
> You must be the change you wish to see in the world. -- Gandhi
> Be Free! -- http://FSFLA.org/   FSF Latin America board member
> Free Software Evangelist|Red Hat Brasil GNU Toolchain Engineer
diff mbox

Patch

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 0000000..e00188ca
--- /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 bfaaede..db3e08f 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);