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 PR44831


This fixes PR44831, phiprop needs to be careful about embedded conversions
in MEM_REFs.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied.

Richard.

2010-07-08  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/44831
	* tree-ssa-phiprop.c (phiprop_insert_phi): Properly build
	a MEM_REF preserving TBAA info of the original dereference.
	Dereference the original pointer if the address is not
	invariant.
	(propagate_with_phi): Fixup type checks wrt MEM_REFs.  Require
	at least one invariant address that we are going to dereference.

	* gcc.c-torture/compile/pr44831.c: New testcase.
	* gcc.dg/tree-ssa/pr21463.c: Adjust.

Index: gcc/tree-ssa-phiprop.c
===================================================================
*** gcc/tree-ssa-phiprop.c	(revision 161946)
--- gcc/tree-ssa-phiprop.c	(working copy)
*************** phiprop_insert_phi (basic_block bb, gimp
*** 187,196 ****
  	}
        else
  	{
  	  gcc_assert (TREE_CODE (old_arg) == ADDR_EXPR);
! 	  old_arg = TREE_OPERAND (old_arg, 0);
! 	  new_var = create_tmp_reg (TREE_TYPE (old_arg), NULL);
! 	  tmp = gimple_build_assign (new_var, unshare_expr (old_arg));
  	  gcc_assert (is_gimple_reg (new_var));
  	  add_referenced_var (new_var);
  	  new_var = make_ssa_name (new_var, tmp);
--- 187,203 ----
  	}
        else
  	{
+ 	  tree rhs = gimple_assign_rhs1 (use_stmt);
  	  gcc_assert (TREE_CODE (old_arg) == ADDR_EXPR);
! 	  new_var = create_tmp_reg (TREE_TYPE (rhs), NULL);
! 	  if (!is_gimple_min_invariant (old_arg))
! 	    old_arg = PHI_ARG_DEF_FROM_EDGE (phi, e);
! 	  else
! 	    old_arg = unshare_expr (old_arg);
! 	  tmp = gimple_build_assign (new_var,
! 				     fold_build2 (MEM_REF, TREE_TYPE (rhs),
! 						  old_arg,
! 						  TREE_OPERAND (rhs, 1)));
  	  gcc_assert (is_gimple_reg (new_var));
  	  add_referenced_var (new_var);
  	  new_var = make_ssa_name (new_var, tmp);
*************** propagate_with_phi (basic_block bb, gimp
*** 246,251 ****
--- 253,260 ----
    use_operand_p arg_p, use;
    ssa_op_iter i;
    bool phi_inserted;
+   tree type = NULL_TREE;
+   bool one_invariant = false;
  
    if (!POINTER_TYPE_P (TREE_TYPE (ptr))
        || !is_gimple_reg_type (TREE_TYPE (TREE_TYPE (ptr))))
*************** propagate_with_phi (basic_block bb, gimp
*** 268,283 ****
  	    return false;
  	  arg = gimple_assign_rhs1 (def_stmt);
  	}
!       if ((TREE_CODE (arg) != ADDR_EXPR
! 	   /* Avoid to have to decay *&a to a[0] later.  */
! 	   || !is_gimple_reg_type (TREE_TYPE (TREE_OPERAND (arg, 0))))
  	  && !(TREE_CODE (arg) == SSA_NAME
  	       && SSA_NAME_VERSION (arg) < n
  	       && phivn[SSA_NAME_VERSION (arg)].value != NULL_TREE
  	       && phivn_valid_p (phivn, arg, bb)))
  	return false;
      }
  
    /* Find a dereferencing use.  First follow (single use) ssa
       copy chains for ptr.  */
    while (single_imm_use (ptr, &use, &use_stmt)
--- 277,305 ----
  	    return false;
  	  arg = gimple_assign_rhs1 (def_stmt);
  	}
!       if (TREE_CODE (arg) != ADDR_EXPR
  	  && !(TREE_CODE (arg) == SSA_NAME
  	       && SSA_NAME_VERSION (arg) < n
  	       && phivn[SSA_NAME_VERSION (arg)].value != NULL_TREE
+ 	       && (!type
+ 		   || types_compatible_p
+ 		       (type, TREE_TYPE (phivn[SSA_NAME_VERSION (arg)].value)))
  	       && phivn_valid_p (phivn, arg, bb)))
  	return false;
+       if (!type
+ 	  && TREE_CODE (arg) == SSA_NAME)
+ 	type = TREE_TYPE (phivn[SSA_NAME_VERSION (arg)].value);
+       if (TREE_CODE (arg) == ADDR_EXPR
+ 	  && is_gimple_min_invariant (arg))
+ 	one_invariant = true;
      }
  
+   /* If we neither have an address of a decl nor can reuse a previously
+      inserted load, do not hoist anything.  */
+   if (!one_invariant
+       && !type)
+     return false;
+ 
    /* Find a dereferencing use.  First follow (single use) ssa
       copy chains for ptr.  */
    while (single_imm_use (ptr, &use, &use_stmt)
*************** propagate_with_phi (basic_block bb, gimp
*** 298,305 ****
  	    && gimple_assign_rhs_code (use_stmt) == MEM_REF
  	    && TREE_OPERAND (gimple_assign_rhs1 (use_stmt), 0) == ptr
  	    && integer_zerop (TREE_OPERAND (gimple_assign_rhs1 (use_stmt), 1))
! 	    && types_compatible_p (TREE_TYPE (gimple_assign_rhs1 (use_stmt)),
! 				   TREE_TYPE (TREE_TYPE (ptr)))
  	    /* We cannot replace a load that may throw or is volatile.  */
  	    && !stmt_can_throw_internal (use_stmt)))
  	continue;
--- 320,328 ----
  	    && gimple_assign_rhs_code (use_stmt) == MEM_REF
  	    && TREE_OPERAND (gimple_assign_rhs1 (use_stmt), 0) == ptr
  	    && integer_zerop (TREE_OPERAND (gimple_assign_rhs1 (use_stmt), 1))
! 	    && (!type
! 		|| types_compatible_p
! 		     (TREE_TYPE (gimple_assign_lhs (use_stmt)), type))
  	    /* We cannot replace a load that may throw or is volatile.  */
  	    && !stmt_can_throw_internal (use_stmt)))
  	continue;
*************** propagate_with_phi (basic_block bb, gimp
*** 319,324 ****
--- 342,348 ----
        if (!phi_inserted)
  	{
  	  res = phiprop_insert_phi (bb, phi, use_stmt, phivn, n);
+ 	  type = TREE_TYPE (res);
  
  	  /* Remember the value we created for *ptr.  */
  	  phivn[SSA_NAME_VERSION (ptr)].value = res;
Index: gcc/testsuite/gcc.c-torture/compile/pr44831.c
===================================================================
*** gcc/testsuite/gcc.c-torture/compile/pr44831.c	(revision 0)
--- gcc/testsuite/gcc.c-torture/compile/pr44831.c	(revision 0)
***************
*** 0 ****
--- 1,15 ----
+ typedef unsigned char UCHAR, *PUCHAR;
+ typedef void *HANDLE;
+ typedef struct _NCB {
+     UCHAR ncb_reserve[10];
+ } NCB, *PNCB;
+ struct NBCmdQueue {
+     PNCB head;
+ };
+ PNCB *NBCmdQueueFindNBC(struct NBCmdQueue *queue, PNCB ncb)
+ {
+   PNCB *ret = &queue->head;
+   while (ret && *ret != ncb)
+     ret = (PNCB *)((*ret)->ncb_reserve + sizeof(HANDLE));
+ }
+ 
Index: gcc/testsuite/gcc.dg/tree-ssa/pr21463.c
===================================================================
*** gcc/testsuite/gcc.dg/tree-ssa/pr21463.c	(revision 161946)
--- gcc/testsuite/gcc.dg/tree-ssa/pr21463.c	(working copy)
***************
*** 1,5 ****
  /* { dg-do compile } */
! /* { dg-options "-O -fdump-tree-phiprop" } */
  
  struct f
  {
--- 1,5 ----
  /* { dg-do compile } */
! /* { dg-options "-O -fdump-tree-phiprop-details" } */
  
  struct f
  {
*************** int g(int i, int c, struct f *ff, int g)
*** 16,20 ****
    return *t;
  }
  
! /* { dg-final { scan-tree-dump-not "\\*t" "phiprop" } } */
  /* { dg-final { cleanup-tree-dump "phiprop" } } */
--- 16,20 ----
    return *t;
  }
  
! /* { dg-final { scan-tree-dump-times "Inserting PHI for result of load" 1 "phiprop" } } */
  /* { dg-final { cleanup-tree-dump "phiprop" } } */


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