This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix PR40022


This fixes PR40022, a tuplification error in the phiprop pass.  While
fixing it I took the opportunity to clean it up somewhat and add
some dumping to it for the 4.5 variant of the patch.

Bootstrapped and tested on x86_64-unknown-linux-gnu, the 4.4 variant
is still testing.  Will apply after both have succeeded.

Richard.

2009-05-05  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/40022
	* tree-ssa-phiprop.c (struct phiprop_d): Exchange vop_stmt for
	the only vuse.
	(phivn_valid_p): Fix tuplification error, simplify.
	(phiprop_insert_phi): Add dumps.
	(propagate_with_phi): Simplify.

	* gcc.c-torture/execute/pr40022.c: New testcase.

Index: gcc/testsuite/gcc.c-torture/execute/pr40022.c
===================================================================
*** gcc/testsuite/gcc.c-torture/execute/pr40022.c	(revision 0)
--- gcc/testsuite/gcc.c-torture/execute/pr40022.c	(revision 0)
***************
*** 0 ****
--- 1,51 ----
+ extern void abort (void);
+ 
+ struct A
+ {
+   struct A *a;
+ };
+ 
+ struct B
+ {
+   struct A *b;
+ };
+ 
+ __attribute__((noinline))
+ struct A *
+ foo (struct A *x)
+ {
+   asm volatile ("" : : "g" (x) : "memory");
+   return x;
+ }
+ 
+ __attribute__((noinline))
+ void
+ bar (struct B *w, struct A *x, struct A *y, struct A *z)
+ {
+   struct A **c;
+   c = &w->b;
+   *c = foo (x);
+   while (*c)
+     c = &(*c)->a;
+   *c = foo (y);
+   while (*c)
+     c = &(*c)->a;
+   *c = foo (z);
+ }
+ 
+ struct B d;
+ struct A e, f, g;
+ 
+ int
+ main (void)
+ {
+   f.a = &g;
+   bar (&d, &e, &f, 0);
+   if (d.b == 0
+       || d.b->a == 0
+       || d.b->a->a == 0
+       || d.b->a->a->a != 0)
+     abort ();
+   return 0;
+ }
+ 
Index: gcc/tree-ssa-phiprop.c
===================================================================
*** gcc/tree-ssa-phiprop.c	(revision 147093)
--- gcc/tree-ssa-phiprop.c	(working copy)
*************** along with GCC; see the file COPYING3.
*** 90,101 ****
  
  
  /* Structure to keep track of the value of a dereferenced PHI result
!    and the set of virtual operands used for that dereference.  */
  
  struct phiprop_d
  {
    tree value;
!   gimple vop_stmt;
  };
  
  /* Verify if the value recorded for NAME in PHIVN is still valid at
--- 90,101 ----
  
  
  /* Structure to keep track of the value of a dereferenced PHI result
!    and the virtual operand used for that dereference.  */
  
  struct phiprop_d
  {
    tree value;
!   tree vuse;
  };
  
  /* Verify if the value recorded for NAME in PHIVN is still valid at
*************** struct phiprop_d
*** 104,137 ****
  static bool
  phivn_valid_p (struct phiprop_d *phivn, tree name, basic_block bb)
  {
!   gimple vop_stmt = phivn[SSA_NAME_VERSION (name)].vop_stmt;
!   tree vuse;
  
!   /* The def stmts of all virtual uses need to be post-dominated
!      by bb.  */
!   if ((vuse = gimple_vuse (vop_stmt)))
      {
!       gimple use_stmt;
!       imm_use_iterator ui2;
!       bool ok = true;
! 
!       FOR_EACH_IMM_USE_STMT (use_stmt, ui2, vuse)
! 	{
! 	  /* If BB does not dominate a VDEF, the value is invalid.  */
! 	  if (((is_gimple_assign (use_stmt)
! 	        && gimple_vdef (use_stmt))
! 	       || gimple_code (use_stmt) == GIMPLE_PHI)
! 	      && !dominated_by_p (CDI_DOMINATORS, gimple_bb (use_stmt), bb))
! 	    {
! 	      ok = false;
! 	      BREAK_FROM_IMM_USE_STMT (ui2);
! 	    }
  	}
-       if (!ok)
- 	return false;
      }
  
!   return true;
  }
  
  /* Insert a new phi node for the dereference of PHI at basic_block
--- 104,130 ----
  static bool
  phivn_valid_p (struct phiprop_d *phivn, tree name, basic_block bb)
  {
!   tree vuse = phivn[SSA_NAME_VERSION (name)].vuse;
!   gimple use_stmt;
!   imm_use_iterator ui2;
!   bool ok = true;
  
!   /* The def stmts of the virtual uses need to be dominated by bb.  */
!   gcc_assert (vuse != NULL_TREE);
! 
!   FOR_EACH_IMM_USE_STMT (use_stmt, ui2, vuse)
      {
!       /* If BB does not dominate a VDEF, the value is invalid.  */
!       if ((gimple_vdef (use_stmt) != NULL_TREE
! 	   || gimple_code (use_stmt) == GIMPLE_PHI)
! 	  && !dominated_by_p (CDI_DOMINATORS, gimple_bb (use_stmt), bb))
! 	{
! 	  ok = false;
! 	  BREAK_FROM_IMM_USE_STMT (ui2);
  	}
      }
  
!   return ok;
  }
  
  /* Insert a new phi node for the dereference of PHI at basic_block
*************** phiprop_insert_phi (basic_block bb, gimp
*** 154,159 ****
--- 147,158 ----
    res = gimple_assign_lhs (use_stmt);
    SSA_NAME_DEF_STMT (res) = new_phi = create_phi_node (res, bb);
  
+   if (dump_file && (dump_flags & TDF_DETAILS))
+     {
+       fprintf (dump_file, "Inserting PHI for result of load ");
+       print_gimple_stmt (dump_file, use_stmt, 0, 0);
+     }
+ 
    /* Add PHI arguments for each edge inserting loads of the
       addressable operands.  */
    FOR_EACH_EDGE (e, ei, bb->preds)
*************** phiprop_insert_phi (basic_block bb, gimp
*** 171,178 ****
  	}
  
        if (TREE_CODE (old_arg) == SSA_NAME)
! 	/* Reuse a formerly created dereference.  */
! 	new_var = phivn[SSA_NAME_VERSION (old_arg)].value;
        else
  	{
  	  gcc_assert (TREE_CODE (old_arg) == ADDR_EXPR);
--- 170,188 ----
  	}
  
        if (TREE_CODE (old_arg) == SSA_NAME)
! 	{
! 	  if (dump_file && (dump_flags & TDF_DETAILS))
! 	    {
! 	      fprintf (dump_file, "  for edge defining ");
! 	      print_generic_expr (dump_file, PHI_ARG_DEF_FROM_EDGE (phi, e), 0);
! 	      fprintf (dump_file, " reusing PHI result ");
! 	      print_generic_expr (dump_file,
! 				  phivn[SSA_NAME_VERSION (old_arg)].value, 0);
! 	      fprintf (dump_file, "\n");
! 	    }
! 	  /* Reuse a formerly created dereference.  */
! 	  new_var = phivn[SSA_NAME_VERSION (old_arg)].value;
! 	}
        else
  	{
  	  gcc_assert (TREE_CODE (old_arg) == ADDR_EXPR);
*************** phiprop_insert_phi (basic_block bb, gimp
*** 188,196 ****
  	  gimple_assign_set_lhs (tmp, new_var);
  
  	  gsi_insert_on_edge (e, tmp);
- 
  	  update_stmt (tmp);
! 	  mark_symbols_for_renaming (tmp);
  	}
  
        add_phi_arg (new_phi, new_var, e);
--- 198,212 ----
  	  gimple_assign_set_lhs (tmp, new_var);
  
  	  gsi_insert_on_edge (e, tmp);
  	  update_stmt (tmp);
! 
! 	  if (dump_file && (dump_flags & TDF_DETAILS))
! 	    {
! 	      fprintf (dump_file, "  for edge defining ");
! 	      print_generic_expr (dump_file, PHI_ARG_DEF_FROM_EDGE (phi, e), 0);
! 	      fprintf (dump_file, " inserting load ");
! 	      print_gimple_stmt (dump_file, tmp, 0, 0);
! 	    }
  	}
  
        add_phi_arg (new_phi, new_var, e);
*************** phiprop_insert_phi (basic_block bb, gimp
*** 198,203 ****
--- 214,222 ----
  
    update_stmt (new_phi);
  
+   if (dump_file && (dump_flags & TDF_DETAILS))
+     print_gimple_stmt (dump_file, new_phi, 0, 0);
+ 
    return res;
  }
  
*************** propagate_with_phi (basic_block bb, gimp
*** 270,275 ****
--- 289,295 ----
    phi_inserted = false;
    FOR_EACH_IMM_USE_STMT (use_stmt, ui, ptr)
      {
+       gimple def_stmt;
        tree vuse;
  
        /* Check whether this is a load of *ptr.  */
*************** propagate_with_phi (basic_block bb, gimp
*** 281,297 ****
  	    && !stmt_can_throw_internal (use_stmt)))
  	continue;
  
!       /* Check if we can move the loads.  The def stmts of all virtual uses
! 	 need to be post-dominated by bb.  */
!       if ((vuse = gimple_vuse (use_stmt)) != NULL_TREE)
! 	{
! 	  gimple def_stmt = SSA_NAME_DEF_STMT (vuse);
! 	  if (!SSA_NAME_IS_DEFAULT_DEF (vuse)
! 	      && (gimple_bb (def_stmt) == bb
! 		  || !dominated_by_p (CDI_DOMINATORS,
! 				      bb, gimple_bb (def_stmt))))
! 	    goto next;
! 	}
  
        /* Found a proper dereference.  Insert a phi node if this
  	 is the first load transformation.  */
--- 301,315 ----
  	    && !stmt_can_throw_internal (use_stmt)))
  	continue;
  
!       /* Check if we can move the loads.  The def stmt of the virtual use
! 	 needs to be in a different basic block post-dominated by bb
! 	 (which it is if the def stmt is not a PHI node).  */
!       vuse = gimple_vuse (use_stmt);
!       def_stmt = SSA_NAME_DEF_STMT (vuse);
!       if (!SSA_NAME_IS_DEFAULT_DEF (vuse)
! 	  && (gimple_code (def_stmt) == GIMPLE_PHI
! 	      || gimple_bb (def_stmt) == bb))
! 	goto next;
  
        /* Found a proper dereference.  Insert a phi node if this
  	 is the first load transformation.  */
*************** propagate_with_phi (basic_block bb, gimp
*** 301,307 ****
  
  	  /* Remember the value we created for *ptr.  */
  	  phivn[SSA_NAME_VERSION (ptr)].value = res;
! 	  phivn[SSA_NAME_VERSION (ptr)].vop_stmt = use_stmt;
  
  	  /* Remove old stmt.  The phi is taken care of by DCE, if we
  	     want to delete it here we also have to delete all intermediate
--- 319,325 ----
  
  	  /* Remember the value we created for *ptr.  */
  	  phivn[SSA_NAME_VERSION (ptr)].value = res;
! 	  phivn[SSA_NAME_VERSION (ptr)].vuse = vuse;
  
  	  /* Remove old stmt.  The phi is taken care of by DCE, if we
  	     want to delete it here we also have to delete all intermediate



2009-05-05  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/40022
	* tree-ssa-phiprop.c (phivn_valid_p): Fix tuplification error.

	* gcc.c-torture/execute/pr40022.c: New testcase.

Index: gcc/tree-ssa-phiprop.c
===================================================================
*** gcc/tree-ssa-phiprop.c	(revision 147123)
--- gcc/tree-ssa-phiprop.c	(working copy)
*************** phivn_valid_p (struct phiprop_d *phivn,
*** 119,126 ****
        FOR_EACH_IMM_USE_STMT (use_stmt, ui2, vuse)
  	{
  	  /* If BB does not dominate a VDEF, the value is invalid.  */
! 	  if (((is_gimple_assign (use_stmt)
! 	        && !ZERO_SSA_OPERANDS (use_stmt, SSA_OP_VDEF))
  	       || gimple_code (use_stmt) == GIMPLE_PHI)
  	      && !dominated_by_p (CDI_DOMINATORS, gimple_bb (use_stmt), bb))
  	    {
--- 119,125 ----
        FOR_EACH_IMM_USE_STMT (use_stmt, ui2, vuse)
  	{
  	  /* If BB does not dominate a VDEF, the value is invalid.  */
! 	  if ((!ZERO_SSA_OPERANDS (use_stmt, SSA_OP_VDEF)
  	       || gimple_code (use_stmt) == GIMPLE_PHI)
  	      && !dominated_by_p (CDI_DOMINATORS, gimple_bb (use_stmt), bb))
  	    {
Index: gcc/testsuite/gcc.c-torture/execute/pr40022.c
===================================================================
*** gcc/testsuite/gcc.c-torture/execute/pr40022.c	(revision 0)
--- gcc/testsuite/gcc.c-torture/execute/pr40022.c	(revision 0)
***************
*** 0 ****
--- 1,51 ----
+ extern void abort (void);
+ 
+ struct A
+ {
+   struct A *a;
+ };
+ 
+ struct B
+ {
+   struct A *b;
+ };
+ 
+ __attribute__((noinline))
+ struct A *
+ foo (struct A *x)
+ {
+   asm volatile ("" : : "g" (x) : "memory");
+   return x;
+ }
+ 
+ __attribute__((noinline))
+ void
+ bar (struct B *w, struct A *x, struct A *y, struct A *z)
+ {
+   struct A **c;
+   c = &w->b;
+   *c = foo (x);
+   while (*c)
+     c = &(*c)->a;
+   *c = foo (y);
+   while (*c)
+     c = &(*c)->a;
+   *c = foo (z);
+ }
+ 
+ struct B d;
+ struct A e, f, g;
+ 
+ int
+ main (void)
+ {
+   f.a = &g;
+   bar (&d, &e, &f, 0);
+   if (d.b == 0
+       || d.b->a == 0
+       || d.b->a->a == 0
+       || d.b->a->a->a != 0)
+     abort ();
+   return 0;
+ }
+ 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]