From c5ad24334348a54a8378366613d71a095386e5da Mon Sep 17 00:00:00 2001
From: Martin Liska <marxin@gcc.gnu.org>
Date: Tue, 28 Mar 2017 11:37:22 +0000
Subject: [PATCH] Handle PHI nodes w/o a argument (PR ipa/80205).

2017-03-28  Martin Liska  <mliska@suse.cz>

	PR ipa/80205
	* g++.dg/ipa/pr80205.C: New test.
2017-03-28  Richard Biener  <rguenther@suse.de>

	PR ipa/80205
	* tree-inline.c (copy_phis_for_bb): Do not create PHI node
	without arguments, generate default definition of a SSA name.

From-SVN: r246530
---
 gcc/ChangeLog                      |  6 ++
 gcc/testsuite/ChangeLog            |  5 ++
 gcc/testsuite/g++.dg/ipa/pr80205.C | 34 +++++++++++
 gcc/tree-inline.c                  | 92 +++++++++++++++++-------------
 4 files changed, 96 insertions(+), 41 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ipa/pr80205.C

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 7274aa4e7a6e..f15a8a882bb0 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2017-03-28  Richard Biener  <rguenther@suse.de>
+
+	PR ipa/80205
+	* tree-inline.c (copy_phis_for_bb): Do not create PHI node
+	without arguments, generate default definition of a SSA name.
+
 2017-03-28  Richard Biener  <rguenther@suse.de>
 
 	PR middle-end/80222
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index fe42af1b3bbf..b3a54711f240 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2017-03-28  Martin Liska  <mliska@suse.cz>
+
+	PR ipa/80205
+	* g++.dg/ipa/pr80205.C: New test.
+
 2017-03-28  Senthil Kumar Selvaraj  <senthil_kumar.selvaraj@atmel.com>
 
 	* gcc.c-torture/execute/pr79121.c:Use __{U}INT32_TYPE__ for targets
diff --git a/gcc/testsuite/g++.dg/ipa/pr80205.C b/gcc/testsuite/g++.dg/ipa/pr80205.C
new file mode 100644
index 000000000000..460bdcb02ca5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ipa/pr80205.C
@@ -0,0 +1,34 @@
+// PR ipa/80205
+// { dg-options "-fnon-call-exceptions --param early-inlining-insns=100 -O2" }
+
+class a
+{
+public:
+  virtual ~a ();
+};
+class b
+{
+public:
+  template <typename c> b (c);
+  ~b () { delete d; }
+  void
+  operator= (b e)
+  {
+    b (e).f (*this);
+  }
+  void
+  f (b &e)
+  {
+    a g;
+    d = e.d;
+    e.d = &g;
+  }
+  a *d;
+};
+void
+h ()
+{
+  b i = int();
+  void j ();
+  i = j;
+}
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 6b6d489f6ca4..09e80e6a5bcb 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -2344,50 +2344,60 @@ copy_phis_for_bb (basic_block bb, copy_body_data *id)
       if (!virtual_operand_p (res))
 	{
 	  walk_tree (&new_res, copy_tree_body_r, id, NULL);
-	  new_phi = create_phi_node (new_res, new_bb);
-	  FOR_EACH_EDGE (new_edge, ei, new_bb->preds)
+	  if (EDGE_COUNT (new_bb->preds) == 0)
 	    {
-	      edge old_edge = find_edge ((basic_block) new_edge->src->aux, bb);
-	      tree arg;
-	      tree new_arg;
-	      edge_iterator ei2;
-	      location_t locus;
-
-	      /* When doing partial cloning, we allow PHIs on the entry block
-		 as long as all the arguments are the same.  Find any input
-		 edge to see argument to copy.  */
-	      if (!old_edge)
-		FOR_EACH_EDGE (old_edge, ei2, bb->preds)
-		  if (!old_edge->src->aux)
-		    break;
-
-	      arg = PHI_ARG_DEF_FROM_EDGE (phi, old_edge);
-	      new_arg = arg;
-	      walk_tree (&new_arg, copy_tree_body_r, id, NULL);
-	      gcc_assert (new_arg);
-	      /* With return slot optimization we can end up with
-	         non-gimple (foo *)&this->m, fix that here.  */
-	      if (TREE_CODE (new_arg) != SSA_NAME
-		  && TREE_CODE (new_arg) != FUNCTION_DECL
-		  && !is_gimple_val (new_arg))
-		{
-		  gimple_seq stmts = NULL;
-		  new_arg = force_gimple_operand (new_arg, &stmts, true, NULL);
-		  gsi_insert_seq_on_edge (new_edge, stmts);
-		  inserted = true;
-		}
-	      locus = gimple_phi_arg_location_from_edge (phi, old_edge);
-	      if (LOCATION_BLOCK (locus))
+	      /* Technically we'd want a SSA_DEFAULT_DEF here... */
+	      SSA_NAME_DEF_STMT (new_res) = gimple_build_nop ();
+	    }
+	  else
+	    {
+	      new_phi = create_phi_node (new_res, new_bb);
+	      FOR_EACH_EDGE (new_edge, ei, new_bb->preds)
 		{
-		  tree *n;
-		  n = id->decl_map->get (LOCATION_BLOCK (locus));
-		  gcc_assert (n);
-		  locus = set_block (locus, *n);
-		}
-	      else
-		locus = LOCATION_LOCUS (locus);
+		  edge old_edge = find_edge ((basic_block) new_edge->src->aux,
+					     bb);
+		  tree arg;
+		  tree new_arg;
+		  edge_iterator ei2;
+		  location_t locus;
+
+		  /* When doing partial cloning, we allow PHIs on the entry
+		     block as long as all the arguments are the same.
+		     Find any input edge to see argument to copy.  */
+		  if (!old_edge)
+		    FOR_EACH_EDGE (old_edge, ei2, bb->preds)
+		      if (!old_edge->src->aux)
+			break;
+
+		  arg = PHI_ARG_DEF_FROM_EDGE (phi, old_edge);
+		  new_arg = arg;
+		  walk_tree (&new_arg, copy_tree_body_r, id, NULL);
+		  gcc_assert (new_arg);
+		  /* With return slot optimization we can end up with
+		     non-gimple (foo *)&this->m, fix that here.  */
+		  if (TREE_CODE (new_arg) != SSA_NAME
+		      && TREE_CODE (new_arg) != FUNCTION_DECL
+		      && !is_gimple_val (new_arg))
+		    {
+		      gimple_seq stmts = NULL;
+		      new_arg = force_gimple_operand (new_arg, &stmts, true,
+						      NULL);
+		      gsi_insert_seq_on_edge (new_edge, stmts);
+		      inserted = true;
+		    }
+		  locus = gimple_phi_arg_location_from_edge (phi, old_edge);
+		  if (LOCATION_BLOCK (locus))
+		    {
+		      tree *n;
+		      n = id->decl_map->get (LOCATION_BLOCK (locus));
+		      gcc_assert (n);
+		      locus = set_block (locus, *n);
+		    }
+		  else
+		    locus = LOCATION_LOCUS (locus);
 
-	      add_phi_arg (new_phi, new_arg, new_edge, locus);
+		  add_phi_arg (new_phi, new_arg, new_edge, locus);
+		}
 	    }
 	}
     }
-- 
GitLab