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

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

Reply via email to