Hi,
it has turned out that I was bit too optimistic in my expectations that
improved ipa-inline-analysis on scalar parameters will be enough to solve needs
of tramp3d.  In tramp3d as in many of C++ programs most code is passed by
reference and while I have some patches in this area, the tracking is difficult
by lack of jump functions that is something Martin promise only after GCC 4.7.

This patch makes ipa-inline-analysis to guess again that param->field loads will
be optimized away with 50% probability.  This recovers most of tramp3d 
performance
(not quite all).  While constructin gtestcase for this I also noticed that
we don't really handle returns of structures in the cases NRV is not happening.
This is added as TODO.

Bootstrapped/regtested x86_64-linux, will commit it shortly.

        * 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.
Index: testsuite/gcc.dg/ipa/inline-5.c
===================================================================
--- testsuite/gcc.dg/ipa/inline-5.c     (revision 0)
+++ testsuite/gcc.dg/ipa/inline-5.c     (revision 0)
@@ -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"  } } */
Index: ipa-inline-analysis.c
===================================================================
--- ipa-inline-analysis.c       (revision 179205)
+++ ipa-inline-analysis.c       (working copy)
@@ -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 cgr
              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,

Reply via email to