From 2ceb2339b1f5519dffb30f777815fa324e519ec6 Mon Sep 17 00:00:00 2001
From: Jan Hubicka <jh@suse.cz>
Date: Tue, 27 Sep 2011 17:08:31 +0200
Subject: [PATCH] inline-5.c: New testcase.

	* gcc.dg/ipa/inline-5.c: New testcase.
	* ipa-inline-analysis.c (eliminated_by_inlining_prob): Handle parameters
	passed by reference; handle loads from non-SSA scalars and update comments.

From-SVN: r179273
---
 gcc/ChangeLog                       |  5 +++
 gcc/ipa-inline-analysis.c           | 65 +++++++++++++++++++++++++----
 gcc/testsuite/ChangeLog             |  4 ++
 gcc/testsuite/gcc.dg/ipa/inline-5.c | 35 ++++++++++++++++
 4 files changed, 100 insertions(+), 9 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/ipa/inline-5.c

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index bc70a4d30df0..cb793d8965ac 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8 @@
+2011-09-27  Jan Hubicka  <jh@suse.cz>
+
+	* ipa-inline-analysis.c (eliminated_by_inlining_prob): Handle parameters
+	passed by reference; handle loads from non-SSA scalars and update comments.
+
 2011-09-27  Bernd Schmidt  <bernds@codesourcery.com>
 
 	PR rtl-optimization/50249
diff --git a/gcc/ipa-inline-analysis.c b/gcc/ipa-inline-analysis.c
index 6d37020d6dd8..76290d0a01cc 100644
--- a/gcc/ipa-inline-analysis.c
+++ b/gcc/ipa-inline-analysis.c
@@ -1290,18 +1290,65 @@ eliminated_by_inlining_prob (gimple stmt)
 	    if (!inner_lhs)
 	      inner_lhs = lhs;
 
+	    /* Reads of parameter are expected to be free.  */
 	    if (unmodified_parm (stmt, inner_rhs))
 	      rhs_free = true;
+
+	    /* When parameter is not SSA register because its address is taken
+	       and it is just copied into one, the statement will be completely
+	       free after inlining (we will copy propagate backward).   */
+	    if (rhs_free && is_gimple_reg (lhs))
+	      return 2;
+
+	    /* Reads of parameters passed by reference
+	       expected to be free (i.e. optimized out after inlining).  */
+	    if (TREE_CODE(inner_rhs) == MEM_REF
+	        && unmodified_parm (stmt, TREE_OPERAND (inner_rhs, 0)))
+	      rhs_free = true;
+
+	    /* Copying parameter passed by reference into gimple register is
+	       probably also going to copy propagate, but we can't be quite
+	       sure.  */
 	    if (rhs_free && is_gimple_reg (lhs))
 	      lhs_free = true;
-	    if (((TREE_CODE (inner_lhs) == PARM_DECL
-	          || (TREE_CODE (inner_lhs) == SSA_NAME
-		      && SSA_NAME_IS_DEFAULT_DEF (inner_lhs)
-		      && TREE_CODE (SSA_NAME_VAR (inner_lhs)) == PARM_DECL))
-		 && inner_lhs != lhs)
-	        || TREE_CODE (inner_lhs) == RESULT_DECL
-	        || (TREE_CODE (inner_lhs) == SSA_NAME
-		    && TREE_CODE (SSA_NAME_VAR (inner_lhs)) == RESULT_DECL))
+	   
+	    /* Writes to parameters, parameters passed by value and return value
+	       (either dirrectly or passed via invisible reference) are free.  
+
+	       TODO: We ought to handle testcase like
+	       struct a {int a,b;};
+	       struct a
+	       retrurnsturct (void)
+		 {
+		   struct a a ={1,2};
+		   return a;
+		 }
+
+	       This translate into:
+
+	       retrurnsturct ()
+		 {
+		   int a$b;
+		   int a$a;
+		   struct a a;
+		   struct a D.2739;
+
+		 <bb 2>:
+		   D.2739.a = 1;
+		   D.2739.b = 2;
+		   return D.2739;
+
+		 }
+	       For that we either need to copy ipa-split logic detecting writes
+	       to return value.  */
+	    if (TREE_CODE (inner_lhs) == PARM_DECL
+		|| TREE_CODE (inner_lhs) == RESULT_DECL
+	        || (TREE_CODE(inner_lhs) == MEM_REF
+		     && (unmodified_parm (stmt, TREE_OPERAND (inner_lhs, 0))
+			 || (TREE_CODE (TREE_OPERAND (inner_lhs, 0)) == SSA_NAME
+			     && TREE_CODE (SSA_NAME_VAR
+					    (TREE_OPERAND (inner_lhs, 0)))
+			     == RESULT_DECL))))
 	      lhs_free = true;
 	    if (lhs_free
 		&& (is_gimple_reg (rhs) || is_gimple_min_invariant (rhs)))
@@ -1919,7 +1966,7 @@ estimate_function_body_sizes (struct cgraph_node *node, bool early)
 	      if (prob == 1 && dump_file && (dump_flags & TDF_DETAILS))
 		fprintf (dump_file, "\t\t50%% will be eliminated by inlining\n");
 	      if (prob == 2 && dump_file && (dump_flags & TDF_DETAILS))
-		fprintf (dump_file, "\t\twill eliminated by inlining\n");
+		fprintf (dump_file, "\t\tWill be eliminated by inlining\n");
 
 	      if (parms_info)
 		p = and_predicates (info->conds, &bb_predicate,
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index a45af3b68c53..31953389dd19 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2011-09-27  Jan Hubicka  <jh@suse.cz>
+
+	* gcc.dg/ipa/inline-5.c: New testcase.
+
 2011-09-27  Ira Rosen  <ira.rosen@linaro.org>
 
 	* gcc.dg/vect/bb-slp-11.c: Expect to get vectorized with 64-bit
diff --git a/gcc/testsuite/gcc.dg/ipa/inline-5.c b/gcc/testsuite/gcc.dg/ipa/inline-5.c
new file mode 100644
index 000000000000..121f7815bcdd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/ipa/inline-5.c
@@ -0,0 +1,35 @@
+/* Check statements that are eliminated by inlining.  */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-ipa-inline-details -fno-early-inlining -fno-partial-inlining -fno-ipa-cp"  } */
+struct a {int a,b,c,d,e;};
+
+void
+accessfield (struct a a)
+{
+  t(a.a);
+    /* Should compile as:
+       tmp = a.a
+	 Will be eliminated by inlining
+       t (tmp);  */
+  t2(&a);
+  t(a.a);
+  return;
+    /* Will be eliminated by inlining */
+}
+void
+accessreference (struct a *a)
+{
+  t(a->a);
+    /* Should compile as:
+       a.0_1 = a;
+	 Will be eliminated by inlining
+       tmp = a.0_1->a;
+	 50% will be eliminated by inlining 
+       t (tmp)  */
+  t2(&a);
+  return;
+    /* Will be eliminated by inlining */
+}
+
+/* { dg-final { scan-ipa-dump-times "Will be eliminated" 4 "inline"  } } */
+/* { dg-final { scan-ipa-dump-times "50. will be eliminated" 1 "inline"  } } */
-- 
GitLab