]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR middle-end/49886 (pass_split_functions cannot deal with function type attributes)
authorMartin Jambor <mjambor@suse.cz>
Wed, 31 Aug 2011 17:17:19 +0000 (19:17 +0200)
committerMartin Jambor <jamborm@gcc.gnu.org>
Wed, 31 Aug 2011 17:17:19 +0000 (19:17 +0200)
2011-08-31  Martin Jambor  <mjambor@suse.cz>

PR middle-end/49886
* ipa-inline-analysis.c (compute_inline_parameters): Set
can_change_signature of noes with typde attributes.
* ipa-split.c (split_function): Do not skip any arguments if
can_change_signature is set.

* testsuite/gcc.c-torture/execute/pr49886.c: New testcase.

From-SVN: r178386

gcc/ChangeLog
gcc/ipa-inline-analysis.c
gcc/ipa-split.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/pr49886.c [new file with mode: 0644]

index 60bb4b5304745a53c9732037964e79be64766f71..afb213b586b3d09cb0c302861e981f73dd7d53c8 100644 (file)
@@ -1,3 +1,11 @@
+2011-08-31  Martin Jambor  <mjambor@suse.cz>
+
+       PR middle-end/49886
+       * ipa-inline-analysis.c (compute_inline_parameters): Set
+       can_change_signature of noes with typde attributes.
+       * ipa-split.c (split_function): Do not skip any arguments if
+       can_change_signature is set.
+
 2011-08-31  Martin Jambor  <mjambor@suse.cz>
 
        * cgraphunit.c (cgraph_redirect_edge_call_stmt_to_callee): Alias
index c0eacbb62fde50b7a32e8e3054b2a823084e2ef0..b56c66944e53db749081871403dc5803b774c892 100644 (file)
@@ -1660,18 +1660,28 @@ compute_inline_parameters (struct cgraph_node *node, bool early)
   /* Can this function be inlined at all?  */
   info->inlinable = tree_inlinable_function_p (node->decl);
 
-  /* Inlinable functions always can change signature.  */
-  if (info->inlinable)
-    node->local.can_change_signature = true;
+  /* Type attributes can use parameter indices to describe them.  */
+  if (TYPE_ATTRIBUTES (TREE_TYPE (node->decl)))
+    node->local.can_change_signature = false;
   else
     {
-      /* Functions calling builtin_apply can not change signature.  */
-      for (e = node->callees; e; e = e->next_callee)
-       if (DECL_BUILT_IN (e->callee->decl)
-           && DECL_BUILT_IN_CLASS (e->callee->decl) == BUILT_IN_NORMAL
-           && DECL_FUNCTION_CODE (e->callee->decl) == BUILT_IN_APPLY_ARGS)
-         break;
-      node->local.can_change_signature = !e;
+      /* Otherwise, inlinable functions always can change signature.  */
+      if (info->inlinable)
+       node->local.can_change_signature = true;
+      else
+       {
+         /* Functions calling builtin_apply can not change signature.  */
+         for (e = node->callees; e; e = e->next_callee)
+           {
+             tree cdecl = e->callee->decl;
+             if (DECL_BUILT_IN (cdecl)
+                 && DECL_BUILT_IN_CLASS (cdecl) == BUILT_IN_NORMAL
+                 && (DECL_FUNCTION_CODE (cdecl) == BUILT_IN_APPLY_ARGS
+                     || DECL_FUNCTION_CODE (cdecl) == BUILT_IN_VA_START))
+               break;
+           }
+         node->local.can_change_signature = !e;
+       }
     }
   estimate_function_body_sizes (node, early);
 
index 7413d81aeeeb3b2e882ec5480178f5fbe5e7acc9..4373a1b423e122af077f584b27f1218e1e1e60ee 100644 (file)
@@ -945,10 +945,10 @@ static void
 split_function (struct split_point *split_point)
 {
   VEC (tree, heap) *args_to_pass = NULL;
-  bitmap args_to_skip = BITMAP_ALLOC (NULL);
+  bitmap args_to_skip;
   tree parm;
   int num = 0;
-  struct cgraph_node *node;
+  struct cgraph_node *node, *cur_node = cgraph_get_node (current_function_decl);
   basic_block return_bb = find_return_bb ();
   basic_block call_bb;
   gimple_stmt_iterator gsi;
@@ -968,17 +968,30 @@ split_function (struct split_point *split_point)
       dump_split_point (dump_file, split_point);
     }
 
+  if (cur_node->local.can_change_signature)
+    args_to_skip = BITMAP_ALLOC (NULL);
+  else
+    args_to_skip = NULL;
+
   /* Collect the parameters of new function and args_to_skip bitmap.  */
   for (parm = DECL_ARGUMENTS (current_function_decl);
        parm; parm = DECL_CHAIN (parm), num++)
-    if (!is_gimple_reg (parm)
-       || !gimple_default_def (cfun, parm)
-       || !bitmap_bit_p (split_point->ssa_names_to_pass,
-                         SSA_NAME_VERSION (gimple_default_def (cfun, parm))))
+    if (args_to_skip
+       && (!is_gimple_reg (parm)
+           || !gimple_default_def (cfun, parm)
+           || !bitmap_bit_p (split_point->ssa_names_to_pass,
+                             SSA_NAME_VERSION (gimple_default_def (cfun,
+                                                                   parm)))))
       bitmap_set_bit (args_to_skip, num);
     else
       {
        arg = gimple_default_def (cfun, parm);
+       if (!arg)
+         {
+           arg = make_ssa_name (parm, gimple_build_nop ());
+           set_default_def (parm, arg);
+         }
+
        if (TYPE_MAIN_VARIANT (DECL_ARG_TYPE (parm))
            != TYPE_MAIN_VARIANT (TREE_TYPE (arg)))
          {
@@ -1081,9 +1094,7 @@ split_function (struct split_point *split_point)
 
   /* Now create the actual clone.  */
   rebuild_cgraph_edges ();
-  node = cgraph_function_versioning (cgraph_get_node (current_function_decl),
-                                    NULL, NULL,
-                                    args_to_skip,
+  node = cgraph_function_versioning (cur_node, NULL, NULL, args_to_skip,
                                     split_point->split_bbs,
                                     split_point->entry_bb, "part");
   /* For usual cloning it is enough to clear builtin only when signature
@@ -1094,7 +1105,7 @@ split_function (struct split_point *split_point)
       DECL_BUILT_IN_CLASS (node->decl) = NOT_BUILT_IN;
       DECL_FUNCTION_CODE (node->decl) = (enum built_in_function) 0;
     }
-  cgraph_node_remove_callees (cgraph_get_node (current_function_decl));
+  cgraph_node_remove_callees (cur_node);
   if (!split_part_return_p)
     TREE_THIS_VOLATILE (node->decl) = 1;
   if (dump_file)
index 7fa86ebee80793a1b51bc4cc8ebd7ad7814dce4c..05ee81bc9b1ae7830379c6774a8b99e2f1c918eb 100644 (file)
@@ -1,3 +1,8 @@
+2011-08-31  Martin Jambor  <mjambor@suse.cz>
+
+       PR middle-end/49886
+       * gcc.c-torture/execute/pr49886.c: New testcase.
+
 2011-08-31  Tom de Vries  <tom@codesourcery.com>
 
        PR middle-end/43513
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr49886.c b/gcc/testsuite/gcc.c-torture/execute/pr49886.c
new file mode 100644 (file)
index 0000000..9e9ceb2
--- /dev/null
@@ -0,0 +1,100 @@
+struct PMC {
+    unsigned flags;
+};
+
+typedef struct Pcc_cell
+{
+    struct PMC *p;
+    long bla;
+    long type;
+} Pcc_cell;
+
+int gi;
+int cond;
+
+extern void abort ();
+extern void never_ever(int interp, struct PMC *pmc)
+  __attribute__((noinline,noclone));
+
+void never_ever (int interp, struct PMC *pmc)
+{
+  abort ();
+}
+
+static void mark_cell(int * interp, Pcc_cell *c)
+  __attribute__((__nonnull__(1)));
+
+static void
+mark_cell(int * interp, Pcc_cell *c)
+{
+  if (!cond)
+    return;
+
+  if (c && c->type == 4 && c->p
+      && !(c->p->flags & (1<<18)))
+    never_ever(gi + 1, c->p);
+  if (c && c->type == 4 && c->p
+      && !(c->p->flags & (1<<17)))
+    never_ever(gi + 2, c->p);
+  if (c && c->type == 4 && c->p
+      && !(c->p->flags & (1<<16)))
+    never_ever(gi + 3, c->p);
+  if (c && c->type == 4 && c->p
+      && !(c->p->flags & (1<<15)))
+    never_ever(gi + 4, c->p);
+  if (c && c->type == 4 && c->p
+      && !(c->p->flags & (1<<14)))
+    never_ever(gi + 5, c->p);
+  if (c && c->type == 4 && c->p
+      && !(c->p->flags & (1<<13)))
+    never_ever(gi + 6, c->p);
+  if (c && c->type == 4 && c->p
+      && !(c->p->flags & (1<<12)))
+    never_ever(gi + 7, c->p);
+  if (c && c->type == 4 && c->p
+      && !(c->p->flags & (1<<11)))
+    never_ever(gi + 8, c->p);
+  if (c && c->type == 4 && c->p
+      && !(c->p->flags & (1<<10)))
+    never_ever(gi + 9, c->p);
+}
+
+static void
+foo(int * interp, Pcc_cell *c)
+{
+  mark_cell(interp, c);
+}
+
+static struct Pcc_cell *
+__attribute__((noinline,noclone))
+getnull(void)
+{
+  return (struct Pcc_cell *) 0;
+}
+
+
+int main()
+{
+  int i;
+
+  cond = 1;
+  for (i = 0; i < 100; i++)
+    foo (&gi, getnull ());
+  return 0;
+}
+
+
+void
+bar_1 (int * interp, Pcc_cell *c)
+{
+  c->bla += 1;
+  mark_cell(interp, c);
+}
+
+void
+bar_2 (int * interp, Pcc_cell *c)
+{
+  c->bla += 2;
+  mark_cell(interp, c);
+}
+