diff mbox

[4.4] Backport of the fix for PR 49886 (again)

Message ID 20110916104518.GA12695@virgil.arch.suse.de
State New
Headers show

Commit Message

Martin Jambor Sept. 16, 2011, 10:45 a.m. UTC
Hi,

the patch below is a backport of the fix for PR 49886 as it is now in
trunk except that we check for type attributes in ipa-split instead of
in ipa-inline-analysis which does not exist in the 4.6 branch.  The
fix is almost the same as the one I have previously reverted but the
!is_gimple_reg path was added to address the fallout of the first
patch.

I have checked that the testcase from PR 50295 does not trigger with
this patch and added the testcase from PR 50287 (which is essentially
the same bug but the testcase is simpler).  Also bootstrapped and
tested on x86_64-linux.

Since the difference from the previously approved patch is exactly
what has been approved for trunk (and finally seems to work), I will
commit this on Monday unless someone objects.

Thanks,

Martin


2011-09-15  Martin Jambor  <mjambor@suse.cz>

	PR middle-end/49886
	* ipa-split.c (split_function): Do not change signature if it is
	not possible or there are attribute types.

	* testsuite/gcc.dg/torture/pr49886.c: Remove XFAILs.
	* testsuite/gcc.dg/torture/pr50287.c: New test.
diff mbox

Patch

Index: gcc/testsuite/gcc.dg/torture/pr49886.c
===================================================================
--- gcc/testsuite/gcc.dg/torture/pr49886.c	(revision 178885)
+++ gcc/testsuite/gcc.dg/torture/pr49886.c	(working copy)
@@ -1,5 +1,4 @@ 
 /* { dg-do run } */
-/* { dg-xfail-run-if "" { "*-*-*" } { "-O2" "-O3" "-Os" } } */
 
 struct PMC {
     unsigned flags;
Index: gcc/testsuite/gcc.dg/torture/pr50287.c
===================================================================
--- gcc/testsuite/gcc.dg/torture/pr50287.c	(revision 0)
+++ gcc/testsuite/gcc.dg/torture/pr50287.c	(revision 0)
@@ -0,0 +1,109 @@ 
+/* { dg-do compile } */
+
+struct PMC {
+    unsigned flags;
+};
+
+struct PVC {
+  unsigned flags, other_stuff;
+};
+
+
+typedef struct Pcc_cell
+{
+    struct PMC *p;
+    long bla;
+    long type;
+} Pcc_cell;
+
+int gi;
+int cond;
+
+struct PVC g_pvc;
+
+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, struct PVC pvc)
+  __attribute__((__nonnull__(1)));
+
+static void
+mark_cell(int * interp, Pcc_cell *c, struct PVC pvc)
+{
+  if (!cond)
+    return;
+
+  if (c && c->type == 4 && c->p
+      && !(c->p->flags & (1<<8)))
+    never_ever(gi + 1, c->p);
+  if (c && c->type == 4 && c->p
+      && !(c->p->flags & (1<<7)))
+    never_ever(gi + 2, c->p);
+  if (c && c->type == 4 && c->p
+      && !(c->p->flags & (1<<6)))
+    never_ever(gi + 3, c->p);
+  if (c && c->type == 4 && c->p
+      && !(c->p->flags & (1<<5)))
+    never_ever(gi + 4, c->p);
+  if (c && c->type == 4 && c->p
+      && !(c->p->flags & (1<<4)))
+    never_ever(gi + 5, c->p);
+  if (c && c->type == 4 && c->p
+      && !(c->p->flags & (1<<3)))
+    never_ever(gi + 6, c->p);
+  if (c && c->type == 4 && c->p
+      && !(c->p->flags & (1<<2)))
+    never_ever(gi + 7, c->p);
+  if (c && c->type == 4 && c->p
+      && !(c->p->flags & (1<<1)))
+    never_ever(gi + 8, c->p);
+  if (c && c->type == 4 && c->p
+      && !(c->p->flags & (1<<9)))
+    never_ever(gi + 9, c->p);
+}
+
+static void
+foo(int * interp, Pcc_cell *c)
+{
+  mark_cell(interp, c, g_pvc);
+}
+
+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, g_pvc);
+}
+
+void
+bar_2 (int * interp, Pcc_cell *c, struct PVC pvc)
+{
+  c->bla += 2;
+  mark_cell(interp, c, pvc);
+}
+
Index: gcc/ipa-split.c
===================================================================
--- gcc/ipa-split.c	(revision 178885)
+++ gcc/ipa-split.c	(working copy)
@@ -946,7 +946,7 @@  split_function (struct split_point *spli
   bitmap args_to_skip = BITMAP_ALLOC (NULL);
   tree parm;
   int num = 0;
-  struct cgraph_node *node;
+  struct cgraph_node *node, *cur_node = cgraph_node (current_function_decl);
   basic_block return_bb = find_return_bb ();
   basic_block call_bb;
   gimple_stmt_iterator gsi;
@@ -966,17 +966,39 @@  split_function (struct split_point *spli
       dump_split_point (dump_file, split_point);
     }
 
+  if (cur_node->local.can_change_signature
+      && !TYPE_ATTRIBUTES (TREE_TYPE (cur_node->decl)))
+    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);
+	/* This parm might not have been used up to now, but is going to be
+	   used, hence register it.  */
+	add_referenced_var (parm);
+	if (is_gimple_reg (parm))
+	  {
+	    arg = gimple_default_def (cfun, parm);
+	    if (!arg)
+	      {
+		arg = make_ssa_name (parm, gimple_build_nop ());
+		set_default_def (parm, arg);
+	      }
+	  }
+	else
+	  arg = parm;
+
 	if (TYPE_MAIN_VARIANT (DECL_ARG_TYPE (parm))
 	    != TYPE_MAIN_VARIANT (TREE_TYPE (arg)))
 	  {
@@ -1057,9 +1079,7 @@  split_function (struct split_point *spli
 
   /* Now create the actual clone.  */
   rebuild_cgraph_edges ();
-  node = cgraph_function_versioning (cgraph_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
@@ -1070,7 +1090,7 @@  split_function (struct split_point *spli
       DECL_BUILT_IN_CLASS (node->decl) = NOT_BUILT_IN;
       DECL_FUNCTION_CODE (node->decl) = (enum built_in_function) 0;
     }
-  cgraph_node_remove_callees (cgraph_node (current_function_decl));
+  cgraph_node_remove_callees (cur_node);
   if (!split_part_return_p)
     TREE_THIS_VOLATILE (node->decl) = 1;
   if (dump_file)