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 PRs 44971 and 44988


This fixes the PRs by making sure we handle all uses of MEM_REFs in
the rewriting and the partial-use detection code.  It also makes
sure not to iterate over all referenced vars as that is not stable
wrt -g vs. -g0.

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

Richard.

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

	PR middle-end/44971
	PR middle-end/44988
	* tree-ssa.c (maybe_optimize_var): New function split out from ...
	(execute_update_addresses_taken): ... here.
	(non_rewritable_mem_ref_base): Likewise.
	(execute_update_addresses_taken): Do not iterate over all referenced
	vars but just all local decls and parms.
	Properly check call and asm arguments and rewrite call arguments.

	* gcc.dg/pr44971.c: New testcase.
	* gcc.c-torture/compile/pr44988.c: Likewise.

Index: gcc/tree-ssa.c
===================================================================
*** gcc/tree-ssa.c	(revision 162307)
--- gcc/tree-ssa.c	(working copy)
*************** maybe_rewrite_mem_ref_base (tree *tp)
*** 1835,1852 ****
      }
  }
  
  /* Compute TREE_ADDRESSABLE and DECL_GIMPLE_REG_P for local variables.  */
  
  void
  execute_update_addresses_taken (bool do_optimize)
  {
    tree var;
-   referenced_var_iterator rvi;
    gimple_stmt_iterator gsi;
    basic_block bb;
    bitmap addresses_taken = BITMAP_ALLOC (NULL);
    bitmap not_reg_needs = BITMAP_ALLOC (NULL);
    bool update_vops = false;
  
    /* Collect into ADDRESSES_TAKEN all variables whose address is taken within
       the function body.  */
--- 1835,1937 ----
      }
  }
  
+ /* For a tree REF return its base if it is the base of a MEM_REF
+    that cannot be rewritten into SSA form.  Otherwise return NULL_TREE.  */
+ 
+ static tree
+ non_rewritable_mem_ref_base (tree ref)
+ {
+   tree base = ref;
+ 
+   /* A plain decl does not need it set.  */
+   if (DECL_P (ref))
+     return NULL_TREE;
+ 
+   while (handled_component_p (base))
+     base = TREE_OPERAND (base, 0);
+ 
+   /* But watch out for MEM_REFs we cannot lower to a
+      VIEW_CONVERT_EXPR.  */
+   if (TREE_CODE (base) == MEM_REF
+       && TREE_CODE (TREE_OPERAND (base, 0)) == ADDR_EXPR)
+     {
+       tree decl = TREE_OPERAND (TREE_OPERAND (base, 0), 0);
+       if (DECL_P (decl)
+ 	  && (!integer_zerop (TREE_OPERAND (base, 1))
+ 	      || (DECL_SIZE (decl)
+ 		  != TYPE_SIZE (TREE_TYPE (base)))))
+ 	return decl;
+     }
+ 
+   return NULL_TREE;
+ }
+ 
+ /* When possible, clear ADDRESSABLE bit or set the REGISTER bit
+    and mark the variable VAR for conversion into SSA.  Returns true
+    when updating stmts is required.  */
+ 
+ static bool
+ maybe_optimize_var (tree var, bitmap addresses_taken, bitmap not_reg_needs)
+ {
+   bool update_vops = false;
+ 
+   /* Global Variables, result decls cannot be changed.  */
+   if (is_global_var (var)
+       || TREE_CODE (var) == RESULT_DECL
+       || bitmap_bit_p (addresses_taken, DECL_UID (var)))
+     return false;
+ 
+   if (TREE_ADDRESSABLE (var)
+       /* Do not change TREE_ADDRESSABLE if we need to preserve var as
+ 	 a non-register.  Otherwise we are confused and forget to
+ 	 add virtual operands for it.  */
+       && (!is_gimple_reg_type (TREE_TYPE (var))
+ 	  || !bitmap_bit_p (not_reg_needs, DECL_UID (var))))
+     {
+       TREE_ADDRESSABLE (var) = 0;
+       if (is_gimple_reg (var))
+ 	mark_sym_for_renaming (var);
+       update_vops = true;
+       if (dump_file)
+ 	{
+ 	  fprintf (dump_file, "No longer having address taken ");
+ 	  print_generic_expr (dump_file, var, 0);
+ 	  fprintf (dump_file, "\n");
+ 	}
+     }
+   if (!DECL_GIMPLE_REG_P (var)
+       && !bitmap_bit_p (not_reg_needs, DECL_UID (var))
+       && (TREE_CODE (TREE_TYPE (var)) == COMPLEX_TYPE
+ 	  || TREE_CODE (TREE_TYPE (var)) == VECTOR_TYPE)
+       && !TREE_THIS_VOLATILE (var)
+       && (TREE_CODE (var) != VAR_DECL || !DECL_HARD_REGISTER (var)))
+     {
+       DECL_GIMPLE_REG_P (var) = 1;
+       mark_sym_for_renaming (var);
+       update_vops = true;
+       if (dump_file)
+ 	{
+ 	  fprintf (dump_file, "Decl is now a gimple register ");
+ 	  print_generic_expr (dump_file, var, 0);
+ 	  fprintf (dump_file, "\n");
+ 	}
+     }
+ 
+   return update_vops;
+ }
+ 
  /* Compute TREE_ADDRESSABLE and DECL_GIMPLE_REG_P for local variables.  */
  
  void
  execute_update_addresses_taken (bool do_optimize)
  {
    tree var;
    gimple_stmt_iterator gsi;
    basic_block bb;
    bitmap addresses_taken = BITMAP_ALLOC (NULL);
    bitmap not_reg_needs = BITMAP_ALLOC (NULL);
    bool update_vops = false;
+   unsigned i;
  
    /* Collect into ADDRESSES_TAKEN all variables whose address is taken within
       the function body.  */
*************** execute_update_addresses_taken (bool do_
*** 1856,1861 ****
--- 1941,1947 ----
  	{
  	  gimple stmt = gsi_stmt (gsi);
  	  enum gimple_code code = gimple_code (stmt);
+ 	  tree decl;
  
  	  /* Note all addresses taken by the stmt.  */
  	  gimple_ior_addresses_taken (addresses_taken, stmt);
*************** execute_update_addresses_taken (bool do_
*** 1877,1883 ****
  		  else if (TREE_CODE (lhs) == MEM_REF
  			   && TREE_CODE (TREE_OPERAND (lhs, 0)) == ADDR_EXPR)
  		    {
! 		      tree decl = TREE_OPERAND (TREE_OPERAND (lhs, 0), 0);
  		      if (DECL_P (decl)
  			  && (!integer_zerop (TREE_OPERAND (lhs, 1))
  			      || (DECL_SIZE (decl)
--- 1963,1969 ----
  		  else if (TREE_CODE (lhs) == MEM_REF
  			   && TREE_CODE (TREE_OPERAND (lhs, 0)) == ADDR_EXPR)
  		    {
! 		      decl = TREE_OPERAND (TREE_OPERAND (lhs, 0), 0);
  		      if (DECL_P (decl)
  			  && (!integer_zerop (TREE_OPERAND (lhs, 1))
  			      || (DECL_SIZE (decl)
*************** execute_update_addresses_taken (bool do_
*** 1890,1916 ****
  	  if (gimple_assign_single_p (stmt))
  	    {
  	      tree rhs = gimple_assign_rhs1 (stmt);
  
!               /* A plain decl does not need it set.  */
!               if (!DECL_P (rhs))
  		{
! 		  tree base = rhs;
! 		  while (handled_component_p (base))
! 		    base = TREE_OPERAND (base, 0);
! 
! 		  /* But watch out for MEM_REFs we cannot lower to a
! 		     VIEW_CONVERT_EXPR.  */
! 		  if (TREE_CODE (base) == MEM_REF
! 		      && TREE_CODE (TREE_OPERAND (base, 0)) == ADDR_EXPR)
! 		    {
! 		      tree decl = TREE_OPERAND (TREE_OPERAND (base, 0), 0);
! 		      if (DECL_P (decl)
! 			  && (!integer_zerop (TREE_OPERAND (base, 1))
! 			      || (DECL_SIZE (decl)
! 				  != TYPE_SIZE (TREE_TYPE (base)))))
! 			bitmap_set_bit (not_reg_needs, DECL_UID (decl));
! 		    }
!                 }
  	    }
  	}
  
--- 1976,2009 ----
  	  if (gimple_assign_single_p (stmt))
  	    {
  	      tree rhs = gimple_assign_rhs1 (stmt);
+ 	      if ((decl = non_rewritable_mem_ref_base (rhs)))
+ 		bitmap_set_bit (not_reg_needs, DECL_UID (decl));
+ 	    }
  
! 	  else if (code == GIMPLE_CALL)
! 	    {
! 	      for (i = 0; i < gimple_call_num_args (stmt); ++i)
  		{
! 		  tree arg = gimple_call_arg (stmt, i);
! 		  if ((decl = non_rewritable_mem_ref_base (arg)))
! 		    bitmap_set_bit (not_reg_needs, DECL_UID (decl));
! 		}
! 	    }
! 
! 	  else if (code == GIMPLE_ASM)
! 	    {
! 	      for (i = 0; i < gimple_asm_noutputs (stmt); ++i)
! 		{
! 		  tree link = gimple_asm_output_op (stmt, i);
! 		  if ((decl = non_rewritable_mem_ref_base (TREE_VALUE (link))))
! 		    bitmap_set_bit (not_reg_needs, DECL_UID (decl));
! 		}
! 	      for (i = 0; i < gimple_asm_ninputs (stmt); ++i)
! 		{
! 		  tree link = gimple_asm_input_op (stmt, i);
! 		  if ((decl = non_rewritable_mem_ref_base (TREE_VALUE (link))))
! 		    bitmap_set_bit (not_reg_needs, DECL_UID (decl));
! 		}
  	    }
  	}
  
*************** execute_update_addresses_taken (bool do_
*** 1933,1982 ****
    /* When possible, clear ADDRESSABLE bit or set the REGISTER bit
       and mark variable for conversion into SSA.  */
    if (optimize && do_optimize)
!     FOR_EACH_REFERENCED_VAR (var, rvi)
!       {
! 	/* Global Variables, result decls cannot be changed.  */
! 	if (is_global_var (var)
! 	    || TREE_CODE (var) == RESULT_DECL
! 	    || bitmap_bit_p (addresses_taken, DECL_UID (var)))
! 	  continue;
! 
! 	if (TREE_ADDRESSABLE (var)
! 	    /* Do not change TREE_ADDRESSABLE if we need to preserve var as
! 	       a non-register.  Otherwise we are confused and forget to
! 	       add virtual operands for it.  */
! 	    && (!is_gimple_reg_type (TREE_TYPE (var))
! 		|| !bitmap_bit_p (not_reg_needs, DECL_UID (var))))
! 	  {
! 	    TREE_ADDRESSABLE (var) = 0;
! 	    if (is_gimple_reg (var))
! 	      mark_sym_for_renaming (var);
! 	    update_vops = true;
! 	    if (dump_file)
! 	      {
! 		fprintf (dump_file, "No longer having address taken ");
! 		print_generic_expr (dump_file, var, 0);
! 		fprintf (dump_file, "\n");
! 	      }
! 	  }
! 	if (!DECL_GIMPLE_REG_P (var)
! 	    && !bitmap_bit_p (not_reg_needs, DECL_UID (var))
! 	    && (TREE_CODE (TREE_TYPE (var)) == COMPLEX_TYPE
! 		|| TREE_CODE (TREE_TYPE (var)) == VECTOR_TYPE)
! 	    && !TREE_THIS_VOLATILE (var)
! 	    && (TREE_CODE (var) != VAR_DECL || !DECL_HARD_REGISTER (var)))
! 	  {
! 	    DECL_GIMPLE_REG_P (var) = 1;
! 	    mark_sym_for_renaming (var);
! 	    update_vops = true;
! 	    if (dump_file)
! 	      {
! 		fprintf (dump_file, "Decl is now a gimple register ");
! 		print_generic_expr (dump_file, var, 0);
! 		fprintf (dump_file, "\n");
! 	      }
! 	  }
!       }
  
    /* Operand caches needs to be recomputed for operands referencing the updated
       variables.  */
--- 2026,2046 ----
    /* When possible, clear ADDRESSABLE bit or set the REGISTER bit
       and mark variable for conversion into SSA.  */
    if (optimize && do_optimize)
!     {
!       /* We cannot iterate over all referenced vars as that can contain
! 	 unused vars from BLOCK trees which cause code generation
! 	 differences for -g vs. -g0.  */
!       for (var = DECL_ARGUMENTS (cfun->decl); var; var = DECL_CHAIN (var))
! 	{
! 	  /* ???  Not all arguments are in referenced vars.  */
! 	  if (!var_ann (var))
! 	    continue;
! 	  update_vops
! 	    |= maybe_optimize_var (var, addresses_taken, not_reg_needs);
! 	}
!       for (i = 0; VEC_iterate (tree, cfun->local_decls, i, var); ++i)
! 	update_vops |= maybe_optimize_var (var, addresses_taken, not_reg_needs);
!     }
  
    /* Operand caches needs to be recomputed for operands referencing the updated
       variables.  */
*************** execute_update_addresses_taken (bool do_
*** 2031,2037 ****
  		  }
  	      }
  
! 	    if (gimple_code (stmt) == GIMPLE_ASM)
  	      {
  		unsigned i;
  		for (i = 0; i < gimple_asm_noutputs (stmt); ++i)
--- 2095,2111 ----
  		  }
  	      }
  
! 	    else if (gimple_code (stmt) == GIMPLE_CALL)
! 	      {
! 		unsigned i;
! 		for (i = 0; i < gimple_call_num_args (stmt); ++i)
! 		  {
! 		    tree *argp = gimple_call_arg_ptr (stmt, i);
! 		    maybe_rewrite_mem_ref_base (argp);
! 		  }
! 	      }
! 
! 	    else if (gimple_code (stmt) == GIMPLE_ASM)
  	      {
  		unsigned i;
  		for (i = 0; i < gimple_asm_noutputs (stmt); ++i)
Index: gcc/testsuite/gcc.c-torture/compile/pr44988.c
===================================================================
*** gcc/testsuite/gcc.c-torture/compile/pr44988.c	(revision 0)
--- gcc/testsuite/gcc.c-torture/compile/pr44988.c	(revision 0)
***************
*** 0 ****
--- 1,13 ----
+ struct S
+ {
+   int i;
+ };
+ 
+ extern void bar (struct S);
+ 
+ void
+ foo (void)
+ {
+   int i = 0;
+   bar (*(struct S *) &i);
+ }
Index: gcc/testsuite/gcc.dg/pr44971.c
===================================================================
*** gcc/testsuite/gcc.dg/pr44971.c	(revision 0)
--- gcc/testsuite/gcc.dg/pr44971.c	(revision 0)
***************
*** 0 ****
--- 1,27 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -fcompare-debug -w" } */
+ 
+ typedef struct
+ {
+   int default_screen;
+ } *_XPrivint;
+ typedef int FcBool;
+ typedef struct
+ {
+   struct _XftintInfo *next;
+ } XftintInfo;
+ int _XftintInfo;
+ 
+ void _XftintInfoGet (int * dpy, FcBool createIfNecessary)
+ {
+   int event_base;
+   &event_base
+    && dpy[createIfNecessary] != 0;
+ }
+ 
+ void _XftCloseint (int dpy, XftintInfo * info,XftintInfo  * *prev)
+ {
+   _XftintInfoGet (dpy, 0);
+   for (prev = &_XftintInfo; info = *prev; prev = &(*prev)->next)
+     ;
+ }


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