]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
2010-05-19 Martin Jambor <mjambor@suse.cz>
authorjamborm <jamborm@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 19 May 2010 11:49:36 +0000 (11:49 +0000)
committerjamborm <jamborm@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 19 May 2010 11:49:36 +0000 (11:49 +0000)
* ipa-prop.c (ipa_print_node_jump_functions): Print jump functions
also for indirect edges.  Actual printing moved...
(ipa_print_node_jump_functions_for_edge): ...here.
(ipa_compute_jump_functions): Renamed to
ipa_compute_jump_functions_for_edge and made static.
(ipa_compute_jump_functions): New function.
(make_edge_direct_to_target): Check if the number of arguments on
the newly direct edge is the same as the number of parametrs of
the callee.
* ipa-cp.c (ipcp_init_stage): Most functionality moved to new
ipa_compute_jump_functions.  Call ipa_analyze_params_uses.
* ipa-inline.c (inline_indirect_intraprocedural_analysis): Call
analysis functions unconditionally, call the new
ipa_analyze_params_uses on the node instead of every edge.

* testsuite/g++.dg/ipa/ivinline-8.C: New test.
* testsuite/gcc.dg/ipa/iinline-2.c: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@159559 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/ipa-cp.c
gcc/ipa-inline.c
gcc/ipa-prop.c
gcc/ipa-prop.h
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/ipa/ivinline-8.C [new file with mode: 0644]
gcc/testsuite/gcc.dg/ipa/iinline-2.c [new file with mode: 0644]

index 30ed7cb422b1cae41a1ab38ef95f98aa3e3d1969..c725ab9bc9b10d4f844576319ebeca3adcce73ac 100644 (file)
@@ -1,3 +1,20 @@
+2010-05-19  Martin Jambor  <mjambor@suse.cz>
+
+       * ipa-prop.c (ipa_print_node_jump_functions): Print jump functions
+       also for indirect edges.  Actual printing moved...
+       (ipa_print_node_jump_functions_for_edge): ...here.
+       (ipa_compute_jump_functions): Renamed to
+       ipa_compute_jump_functions_for_edge and made static.
+       (ipa_compute_jump_functions): New function.
+       (make_edge_direct_to_target): Check if the number of arguments on
+       the newly direct edge is the same as the number of parametrs of
+       the callee.
+       * ipa-cp.c (ipcp_init_stage): Most functionality moved to new
+       ipa_compute_jump_functions.  Call ipa_analyze_params_uses.
+       * ipa-inline.c (inline_indirect_intraprocedural_analysis): Call
+       analysis functions unconditionally, call the new
+       ipa_analyze_params_uses on the node instead of every edge.
+
 2010-05-19  Christian Borntraeger  <borntraeger@de.ibm.com>
 
         * tree-ssa-loop-prefetch.c (mem_ref_group, ar_data): Change step
index f4aab5d2d8997fb093e9a95c7c2e419650f7a725..a1bfe0e87013e07f5780801886b2503a5e344bcb 100644 (file)
@@ -614,7 +614,6 @@ static void
 ipcp_init_stage (void)
 {
   struct cgraph_node *node;
-  struct cgraph_edge *cs;
 
   for (node = cgraph_nodes; node; node = node->next)
     if (node->analyzed)
@@ -623,19 +622,10 @@ ipcp_init_stage (void)
     {
       if (!node->analyzed)
        continue;
+
+      ipa_analyze_params_uses (node);
       /* building jump functions  */
-      for (cs = node->callees; cs; cs = cs->next_callee)
-       {
-         /* We do not need to bother analyzing calls to unknown
-            functions unless they may become known during lto/whopr.  */
-         if (!cs->callee->analyzed && !flag_lto && !flag_whopr)
-           continue;
-         ipa_count_arguments (cs);
-         if (ipa_get_cs_argument_count (IPA_EDGE_REF (cs))
-             != ipa_get_param_count (IPA_NODE_REF (cs->callee)))
-           ipa_set_called_with_variable_arg (IPA_NODE_REF (cs->callee));
-         ipa_compute_jump_functions (cs);
-       }
+      ipa_compute_jump_functions (node);
     }
 }
 
index e1de7ce25cc8a579dc11ae2c6d6a49f92564ac25..12757f7a2a3940012f272a38383cbed7c898b46d 100644 (file)
@@ -1971,21 +1971,10 @@ struct gimple_opt_pass pass_inline_parameters =
 static void
 inline_indirect_intraprocedural_analysis (struct cgraph_node *node)
 {
-  struct cgraph_edge *cs;
-
-  if (!flag_ipa_cp)
-    {
-      ipa_initialize_node_params (node);
-      ipa_detect_param_modifications (node);
-    }
+  ipa_initialize_node_params (node);
+  ipa_detect_param_modifications (node);
   ipa_analyze_params_uses (node);
-
-  if (!flag_ipa_cp)
-    for (cs = node->callees; cs; cs = cs->next_callee)
-      {
-       ipa_count_arguments (cs);
-       ipa_compute_jump_functions (cs);
-      }
+  ipa_compute_jump_functions (node);
 
   if (dump_file)
     {
index 6437389876e0f8bc0eda6e4473982b5542b53af4..d977242b5f0d2d32b625aa717115ae4b63f5e013 100644 (file)
@@ -304,16 +304,87 @@ ipa_count_arguments (struct cgraph_edge *cs)
   ipa_set_cs_argument_count (IPA_EDGE_REF (cs), arg_num);
 }
 
+/* Print the jump functions associated with call graph edge CS to file F.  */
+
+static void
+ipa_print_node_jump_functions_for_edge (FILE *f, struct cgraph_edge *cs)
+{
+  int i, count;
+
+  count = ipa_get_cs_argument_count (IPA_EDGE_REF (cs));
+  for (i = 0; i < count; i++)
+    {
+      struct ipa_jump_func *jump_func;
+      enum jump_func_type type;
+
+      jump_func = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i);
+      type = jump_func->type;
+
+      fprintf (f, "       param %d: ", i);
+      if (type == IPA_JF_UNKNOWN)
+       fprintf (f, "UNKNOWN\n");
+      else if (type == IPA_JF_KNOWN_TYPE)
+       {
+         tree binfo_type = TREE_TYPE (jump_func->value.base_binfo);
+         fprintf (f, "KNOWN TYPE, type in binfo is: ");
+         print_generic_expr (f, binfo_type, 0);
+         fprintf (f, " (%u)\n", TYPE_UID (binfo_type));
+       }
+      else if (type == IPA_JF_CONST)
+       {
+         tree val = jump_func->value.constant;
+         fprintf (f, "CONST: ");
+         print_generic_expr (f, val, 0);
+         if (TREE_CODE (val) == ADDR_EXPR
+             && TREE_CODE (TREE_OPERAND (val, 0)) == CONST_DECL)
+           {
+             fprintf (f, " -> ");
+             print_generic_expr (f, DECL_INITIAL (TREE_OPERAND (val, 0)),
+                                 0);
+           }
+         fprintf (f, "\n");
+       }
+      else if (type == IPA_JF_CONST_MEMBER_PTR)
+       {
+         fprintf (f, "CONST MEMBER PTR: ");
+         print_generic_expr (f, jump_func->value.member_cst.pfn, 0);
+         fprintf (f, ", ");
+         print_generic_expr (f, jump_func->value.member_cst.delta, 0);
+         fprintf (f, "\n");
+       }
+      else if (type == IPA_JF_PASS_THROUGH)
+       {
+         fprintf (f, "PASS THROUGH: ");
+         fprintf (f, "%d, op %s ",
+                  jump_func->value.pass_through.formal_id,
+                  tree_code_name[(int)
+                                 jump_func->value.pass_through.operation]);
+         if (jump_func->value.pass_through.operation != NOP_EXPR)
+           print_generic_expr (dump_file,
+                               jump_func->value.pass_through.operand, 0);
+         fprintf (dump_file, "\n");
+       }
+      else if (type == IPA_JF_ANCESTOR)
+       {
+         fprintf (f, "ANCESTOR: ");
+         fprintf (f, "%d, offset "HOST_WIDE_INT_PRINT_DEC", ",
+                  jump_func->value.ancestor.formal_id,
+                  jump_func->value.ancestor.offset);
+         print_generic_expr (f, jump_func->value.ancestor.type, 0);
+         fprintf (dump_file, "\n");
+       }
+    }
+}
+
+
 /* Print the jump functions of all arguments on all call graph edges going from
    NODE to file F.  */
 
 void
 ipa_print_node_jump_functions (FILE *f, struct cgraph_node *node)
 {
-  int i, count;
   struct cgraph_edge *cs;
-  struct ipa_jump_func *jump_func;
-  enum jump_func_type type;
+  int i;
 
   fprintf (f, "  Jump functions of caller  %s:\n", cgraph_node_name (node));
   for (cs = node->callees; cs; cs = cs->next_callee)
@@ -321,69 +392,26 @@ ipa_print_node_jump_functions (FILE *f, struct cgraph_node *node)
       if (!ipa_edge_args_info_available_for_edge_p (cs))
        continue;
 
-      fprintf (f, "    callsite  %s ", cgraph_node_name (node));
-      fprintf (f, "-> %s :: \n", cgraph_node_name (cs->callee));
+      fprintf (f, "    callsite  %s/%i -> %s/%i : \n",
+              cgraph_node_name (node), node->uid,
+              cgraph_node_name (cs->callee), cs->callee->uid);
+      ipa_print_node_jump_functions_for_edge (f, cs);
+    }
 
-      count = ipa_get_cs_argument_count (IPA_EDGE_REF (cs));
-      for (i = 0; i < count; i++)
-       {
-         jump_func = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i);
-         type = jump_func->type;
+  for (cs = node->indirect_calls, i = 0; cs; cs = cs->next_callee, i++)
+    {
+      if (!ipa_edge_args_info_available_for_edge_p (cs))
+       continue;
 
-         fprintf (f, "       param %d: ", i);
-         if (type == IPA_JF_UNKNOWN)
-           fprintf (f, "UNKNOWN\n");
-         else if (type == IPA_JF_KNOWN_TYPE)
-           {
-             tree binfo_type = TREE_TYPE (jump_func->value.base_binfo);
-             fprintf (f, "KNOWN TYPE, type in binfo is: ");
-             print_generic_expr (f, binfo_type, 0);
-             fprintf (f, " (%u)\n", TYPE_UID (binfo_type));
-           }
-         else if (type == IPA_JF_CONST)
-           {
-             tree val = jump_func->value.constant;
-             fprintf (f, "CONST: ");
-             print_generic_expr (f, val, 0);
-             if (TREE_CODE (val) == ADDR_EXPR
-                 && TREE_CODE (TREE_OPERAND (val, 0)) == CONST_DECL)
-               {
-                 fprintf (f, " -> ");
-                 print_generic_expr (f, DECL_INITIAL (TREE_OPERAND (val, 0)),
-                                                      0);
-               }
-             fprintf (f, "\n");
-           }
-         else if (type == IPA_JF_CONST_MEMBER_PTR)
-           {
-             fprintf (f, "CONST MEMBER PTR: ");
-             print_generic_expr (f, jump_func->value.member_cst.pfn, 0);
-             fprintf (f, ", ");
-             print_generic_expr (f, jump_func->value.member_cst.delta, 0);
-             fprintf (f, "\n");
-           }
-         else if (type == IPA_JF_PASS_THROUGH)
-           {
-             fprintf (f, "PASS THROUGH: ");
-             fprintf (f, "%d, op %s ",
-                      jump_func->value.pass_through.formal_id,
-                      tree_code_name[(int)
-                                     jump_func->value.pass_through.operation]);
-             if (jump_func->value.pass_through.operation != NOP_EXPR)
-               print_generic_expr (dump_file,
-                                   jump_func->value.pass_through.operand, 0);
-             fprintf (dump_file, "\n");
-           }
-         else if (type == IPA_JF_ANCESTOR)
-           {
-             fprintf (f, "ANCESTOR: ");
-             fprintf (f, "%d, offset "HOST_WIDE_INT_PRINT_DEC", ",
-                      jump_func->value.ancestor.formal_id,
-                      jump_func->value.ancestor.offset);
-             print_generic_expr (f, jump_func->value.ancestor.type, 0);
-             fprintf (dump_file, "\n");
-           }
+      if (cs->call_stmt)
+       {
+         fprintf (f, "    indirect callsite %d for stmt ", i);
+         print_gimple_stmt (f, cs->call_stmt, 0, TDF_SLIM);
        }
+      else
+       fprintf (f, "    indirect callsite %d :\n", i);
+      ipa_print_node_jump_functions_for_edge (f, cs);
+
     }
 }
 
@@ -852,8 +880,8 @@ compute_cst_member_ptr_arguments (struct ipa_jump_func *functions,
    information in the jump_functions array in the ipa_edge_args corresponding
    to this callsite.  */
 
-void
-ipa_compute_jump_functions (struct cgraph_edge *cs)
+static void
+ipa_compute_jump_functions_for_edge (struct cgraph_edge *cs)
 {
   struct ipa_node_params *info = IPA_NODE_REF (cs->caller);
   struct ipa_edge_args *arguments = IPA_EDGE_REF (cs);
@@ -880,6 +908,34 @@ ipa_compute_jump_functions (struct cgraph_edge *cs)
   compute_cst_member_ptr_arguments (arguments->jump_functions, call);
 }
 
+/* Compute jump functions for all edges - both direct and indirect - outgoing
+   from NODE.  Also count the actual arguments in the process.  */
+
+void
+ipa_compute_jump_functions (struct cgraph_node *node)
+{
+  struct cgraph_edge *cs;
+
+  for (cs = node->callees; cs; cs = cs->next_callee)
+    {
+      /* We do not need to bother analyzing calls to unknown
+        functions unless they may become known during lto/whopr.  */
+      if (!cs->callee->analyzed && !flag_lto && !flag_whopr)
+       continue;
+      ipa_count_arguments (cs);
+      if (ipa_get_cs_argument_count (IPA_EDGE_REF (cs))
+         != ipa_get_param_count (IPA_NODE_REF (cs->callee)))
+       ipa_set_called_with_variable_arg (IPA_NODE_REF (cs->callee));
+      ipa_compute_jump_functions_for_edge (cs);
+    }
+
+  for (cs = node->indirect_calls; cs; cs = cs->next_callee)
+    {
+      ipa_count_arguments (cs);
+      ipa_compute_jump_functions_for_edge (cs);
+    }
+}
+
 /* If RHS looks like a rhs of a statement loading pfn from a member
    pointer formal parameter, return the parameter, otherwise return
    NULL.  If USE_DELTA, then we look for a use of the delta field
@@ -1345,6 +1401,11 @@ make_edge_direct_to_target (struct cgraph_edge *ie, tree target)
       else
        fprintf (dump_file, "with uid %i\n", ie->lto_stmt_uid);
     }
+
+  if (ipa_get_cs_argument_count (IPA_EDGE_REF (ie))
+      != ipa_get_param_count (IPA_NODE_REF (callee)))
+    ipa_set_called_with_variable_arg (IPA_NODE_REF (callee));
+
   return ie;
 }
 
index c142c03db2859bfd4cd004a936e4272f19f7d458..110044e4da4568c4bcdfe2431712dc9b02a2195c 100644 (file)
@@ -413,7 +413,7 @@ ipa_push_func_to_list (struct ipa_func_list **wl, struct cgraph_node *node)
 }
 
 /* Callsite related calculations.  */
-void ipa_compute_jump_functions (struct cgraph_edge *);
+void ipa_compute_jump_functions (struct cgraph_node *);
 void ipa_count_arguments (struct cgraph_edge *);
 
 /* Function formal parameters related computations.  */
index 135c9b2fc5d947e6ac6e402fa7491879fe72e507..237b3c18be12e89bcee3dd9b8e312b4d5c7f8b1f 100644 (file)
@@ -1,3 +1,8 @@
+2010-05-19  Martin Jambor  <mjambor@suse.cz>
+
+       * g++.dg/ipa/ivinline-8.C: New test.
+       * gcc.dg/ipa/iinline-2.c: Likewise.
+
 2010-05-19  Daniel Franke  <franke.daniel@gmail.com>
 
        PR fortran/34505
diff --git a/gcc/testsuite/g++.dg/ipa/ivinline-8.C b/gcc/testsuite/g++.dg/ipa/ivinline-8.C
new file mode 100644 (file)
index 0000000..3bdf4c1
--- /dev/null
@@ -0,0 +1,77 @@
+/* Verify that virtual calls are inlined (ithout early inlining) even
+   when their caller is itself indirectly inlined.  */
+/* { dg-do run } */
+/* { dg-options "-O3 -fdump-ipa-inline -fno-early-inlining -fno-ipa-cp"  } */
+
+extern "C" void abort (void);
+
+class A
+{
+public:
+  int data;
+  virtual int bar (int i);
+  virtual int foo (int i);
+};
+
+class B : public A
+{
+public:
+  virtual int bar (int i);
+  virtual int foo (int i);
+};
+
+class C : public A
+{
+public:
+  virtual int foo (int i);
+};
+
+int A::bar (int i)
+{
+  return i + 100 * i;
+}
+
+int A::foo (int i)
+{
+  return bar (i) + 1;
+}
+
+int B::bar (int i)
+{
+  return i + 100 * (i + 2);
+}
+
+int B::foo (int i)
+{
+  return bar (i) + 2;
+}
+
+int C::foo (int i)
+{
+  return i + 3;
+}
+
+int middleman (class A *obj, int i)
+{
+  return obj->foo (i);
+}
+
+int __attribute__ ((noinline,noclone)) get_input(void)
+{
+  return 1;
+}
+
+int main (int argc, char *argv[])
+{
+  class B b;
+  int i;
+
+  for (i = 0; i < get_input (); i++)
+    if (middleman (&b, get_input ()) != 303)
+      abort ();
+  return 0;
+}
+
+/* { dg-final { scan-ipa-dump "B::foo\[^\\n\]*inline copy in int main" "inline"  } } */
+/* { dg-final { scan-ipa-dump "B::bar\[^\\n\]*inline copy in int main" "inline"  } } */
+/* { dg-final { cleanup-ipa-dump "inline" } } */
diff --git a/gcc/testsuite/gcc.dg/ipa/iinline-2.c b/gcc/testsuite/gcc.dg/ipa/iinline-2.c
new file mode 100644 (file)
index 0000000..117818d
--- /dev/null
@@ -0,0 +1,41 @@
+/* Verify that simple indirect calls are inlined even without early
+   inlining..  */
+/* { dg-do compile } */
+/* { dg-options "-O3 -c -fdump-ipa-inline -fno-early-inlining -fno-ipa-cp"  } */
+
+extern void non_existent(int);
+
+int __attribute__ ((noinline,noclone)) get_input(void)
+{
+  return 1;
+}
+
+static void hooray ()
+{
+  non_existent (1);
+}
+
+static void hip2 (void (*g)())
+{
+  non_existent (2);
+  g ();
+}
+
+static void hip1 (void (*f)(void (*)()), void (*g)())
+{
+  non_existent (2);
+  f (g);
+}
+
+int main (int argc, int *argv[])
+{
+  int i;
+
+  for (i = 0; i < get_input (); i++)
+    hip1 (hip2, hooray);
+  return 0;
+}
+
+/* { dg-final { scan-ipa-dump "hooray\[^\\n\]*inline copy in main" "inline"  } } */
+/* { dg-final { scan-ipa-dump "hip2\[^\\n\]*inline copy in main" "inline"  } } */
+/* { dg-final { cleanup-ipa-dump "inline" } } */