avoid remove&reinsert of call when splitting block for inlining
authorAlexandre Oliva <aoliva@redhat.com>
Wed, 10 May 2017 10:16:54 +0000 (10:16 +0000)
committerAlexandre Oliva <aoliva@gcc.gnu.org>
Wed, 10 May 2017 10:16:54 +0000 (10:16 +0000)
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
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/guality/inline-params-2.c [new file with mode: 0644]
gcc/tree-inline.c

index 1f08f99f01d76042928a56927a3d6c9f3c5d6517..454203cde920d96859e86f8b4986a1794d9d7eb9 100644 (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
index 8ec71d724383a2172b2c9f0e909c852e6e485d21..0fc75a3c1a215ff14a4325ccdac5f28cd29525af 100644 (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
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 (file)
index 0000000..e00188c
--- /dev/null
@@ -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);
+}
index bfaaede0c326cf00e7dea8e22e3f2b55d6d73c59..db3e08fe0b08d41bcecf030623fe456780ff5d30 100644 (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);