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] Make IVOPTs create MEM_REFs instead of TARGET_MEM_REFs when possible


This avoids generating pointless TARGET_MEM_REFs with just a base
or symbol and a constant offset.  TARGET_MEM_REFs do not preserve
type-based alias information properly (yet) while MEM_REFs do,
a MEM_REF is also smaller.  I still plan to adjust TARGET_MEM_REF
to use an unified base and a pointer typed constant offset operand
so it will behave as a MEM_REF with extra index and step operands,
but that is for a later patch which should also get rid of TMR_ORIGINAL.

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

Richard.

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

	* tree.c (reference_alias_ptr_type): New function.
	* tree.h (reference_alias_ptr_type): Declare.
	* tree-ssa-loop-ivopts.c (copy_ref_info): Restructure to
	allow non-TARGET_MEM_REF new refs.
	(rewrite_use_address): Pass old alias pointer type to
	create_mem_ref.
	* tree-ssa-address.c (create_mem_ref_raw): Get alias pointer type.
	Build a MEM_REF instead of a TARGET_MEM_REF if possible.
	(create_mem_ref): Get alias pointer type.  Adjust calls to
	create_mem_ref_raw.
	(maybe_fold_tmr): Likewise.
	* tree-flow.h (create_mem_ref): Adjust prototype.

Index: gcc/tree.c
===================================================================
*** gcc/tree.c	(revision 161837)
--- gcc/tree.c	(working copy)
*************** mem_ref_offset (const_tree t)
*** 3913,3918 ****
--- 3913,3937 ----
  			  TYPE_PRECISION (TREE_TYPE (toff)));
  }
  
+ /* Return the pointer-type relevant for TBAA purposes from the
+    gimple memory reference tree T.  This is the type to be used for
+    the offset operand of MEM_REF or TARGET_MEM_REF replacements of T.  */
+ 
+ tree
+ reference_alias_ptr_type (const_tree t)
+ {
+   const_tree base = t;
+   while (handled_component_p (base))
+     base = TREE_OPERAND (base, 0);
+   if (TREE_CODE (base) == MEM_REF)
+     return TREE_TYPE (TREE_OPERAND (base, 1));
+   else if (TREE_CODE (base) == TARGET_MEM_REF
+ 	   || TREE_CODE (base) == MISALIGNED_INDIRECT_REF)
+     return NULL_TREE;
+   else
+     return build_pointer_type (TYPE_MAIN_VARIANT (TREE_TYPE (base)));
+ }
+ 
  /* Similar except don't specify the TREE_TYPE
     and leave the TREE_SIDE_EFFECTS as 0.
     It is permissible for arguments to be null,
Index: gcc/tree.h
===================================================================
*** gcc/tree.h	(revision 161837)
--- gcc/tree.h	(working copy)
*************** extern tree build_simple_mem_ref_loc (lo
*** 4965,4970 ****
--- 4965,4971 ----
  #define build_simple_mem_ref(T)\
  	build_simple_mem_ref_loc (UNKNOWN_LOCATION, T)
  extern double_int mem_ref_offset (const_tree);
+ extern tree reference_alias_ptr_type (const_tree);
  extern tree constant_boolean_node (int, tree);
  extern tree div_if_zero_remainder (enum tree_code, const_tree, const_tree);
  
Index: gcc/tree-ssa-loop-ivopts.c
===================================================================
*** gcc/tree-ssa-loop-ivopts.c	(revision 161837)
--- gcc/tree-ssa-loop-ivopts.c	(working copy)
*************** unshare_and_remove_ssa_names (tree ref)
*** 5547,5579 ****
  static void
  copy_ref_info (tree new_ref, tree old_ref)
  {
!   if (TREE_CODE (old_ref) == TARGET_MEM_REF)
!     copy_mem_ref_info (new_ref, old_ref);
!   else
      {
!       TMR_ORIGINAL (new_ref) = unshare_and_remove_ssa_names (old_ref);
!       TREE_SIDE_EFFECTS (new_ref) = TREE_SIDE_EFFECTS (old_ref);
!       TREE_THIS_VOLATILE (new_ref) = TREE_THIS_VOLATILE (old_ref);
!       /* We can transfer points-to information from an old pointer
!          or decl base to the new one.  */
!       if (TMR_BASE (new_ref)
! 	  && TREE_CODE (TMR_BASE (new_ref)) == SSA_NAME
! 	  && POINTER_TYPE_P (TREE_TYPE (TMR_BASE (new_ref)))
! 	  && !SSA_NAME_PTR_INFO (TMR_BASE (new_ref)))
  	{
! 	  tree base = get_base_address (old_ref);
! 	  if ((INDIRECT_REF_P (base)
! 	       || TREE_CODE (base) == MEM_REF)
! 	      && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
! 	    duplicate_ssa_name_ptr_info
! 	      (TMR_BASE (new_ref), SSA_NAME_PTR_INFO (TREE_OPERAND (base, 0)));
! 	  else if (TREE_CODE (base) == VAR_DECL
! 		   || TREE_CODE (base) == PARM_DECL
! 		   || TREE_CODE (base) == RESULT_DECL)
! 	    {
! 	      struct ptr_info_def *pi = get_ptr_info (TMR_BASE (new_ref));
! 	      pt_solution_set_var (&pi->pt, base);
! 	    }
  	}
      }
  }
--- 5547,5587 ----
  static void
  copy_ref_info (tree new_ref, tree old_ref)
  {
!   tree new_ptr_base = NULL_TREE;
! 
!   if (TREE_CODE (old_ref) == TARGET_MEM_REF
!       && TREE_CODE (new_ref) == TARGET_MEM_REF)
!     TMR_ORIGINAL (new_ref) = TMR_ORIGINAL (old_ref);
!   else if (TREE_CODE (new_ref) == TARGET_MEM_REF)
!     TMR_ORIGINAL (new_ref) = unshare_and_remove_ssa_names (old_ref);
! 
!   TREE_SIDE_EFFECTS (new_ref) = TREE_SIDE_EFFECTS (old_ref);
!   TREE_THIS_VOLATILE (new_ref) = TREE_THIS_VOLATILE (old_ref);
! 
!   if (TREE_CODE (new_ref) == TARGET_MEM_REF)
!     new_ptr_base = TMR_BASE (new_ref);
!   else if (TREE_CODE (new_ref) == MEM_REF)
!     new_ptr_base = TREE_OPERAND (new_ref, 0);
! 
!   /* We can transfer points-to information from an old pointer
!      or decl base to the new one.  */
!   if (new_ptr_base
!       && TREE_CODE (new_ptr_base) == SSA_NAME
!       && POINTER_TYPE_P (TREE_TYPE (new_ptr_base))
!       && !SSA_NAME_PTR_INFO (new_ptr_base))
      {
!       tree base = get_base_address (old_ref);
!       if ((INDIRECT_REF_P (base)
! 	   || TREE_CODE (base) == MEM_REF)
! 	  && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
! 	duplicate_ssa_name_ptr_info
! 	    (new_ptr_base, SSA_NAME_PTR_INFO (TREE_OPERAND (base, 0)));
!       else if (TREE_CODE (base) == VAR_DECL
! 	       || TREE_CODE (base) == PARM_DECL
! 	       || TREE_CODE (base) == RESULT_DECL)
  	{
! 	  struct ptr_info_def *pi = get_ptr_info (new_ptr_base);
! 	  pt_solution_set_var (&pi->pt, base);
  	}
      }
  }
*************** rewrite_use_address (struct ivopts_data
*** 5608,5615 ****
    if (cand->iv->base_object)
      base_hint = var_at_stmt (data->current_loop, cand, use->stmt);
  
!   ref = create_mem_ref (&bsi, TREE_TYPE (*use->op_p), &aff, base_hint,
! 			data->speed);
    copy_ref_info (ref, *use->op_p);
    *use->op_p = ref;
  }
--- 5616,5624 ----
    if (cand->iv->base_object)
      base_hint = var_at_stmt (data->current_loop, cand, use->stmt);
  
!   ref = create_mem_ref (&bsi, TREE_TYPE (*use->op_p),
! 			reference_alias_ptr_type (*use->op_p),
! 			&aff, base_hint, data->speed);
    copy_ref_info (ref, *use->op_p);
    *use->op_p = ref;
  }
Index: gcc/tree-ssa-address.c
===================================================================
*** gcc/tree-ssa-address.c	(revision 161837)
--- gcc/tree-ssa-address.c	(working copy)
*************** valid_mem_ref_p (enum machine_mode mode,
*** 338,344 ****
     TARGET_MEM_REF.  */
  
  static tree
! create_mem_ref_raw (tree type, struct mem_address *addr)
  {
    if (!valid_mem_ref_p (TYPE_MODE (type), TYPE_ADDR_SPACE (type), addr))
      return NULL_TREE;
--- 338,344 ----
     TARGET_MEM_REF.  */
  
  static tree
! create_mem_ref_raw (tree type, tree alias_ptr_type, struct mem_address *addr)
  {
    if (!valid_mem_ref_p (TYPE_MODE (type), TYPE_ADDR_SPACE (type), addr))
      return NULL_TREE;
*************** create_mem_ref_raw (tree type, struct me
*** 349,354 ****
--- 349,372 ----
    if (addr->offset && integer_zerop (addr->offset))
      addr->offset = NULL_TREE;
  
+   /* If possible use a plain MEM_REF instead of a TARGET_MEM_REF.  */
+   if (alias_ptr_type
+       && !addr->index
+       && !addr->step)
+     {
+       tree base, offset;
+       gcc_assert (!addr->symbol ^ !addr->base);
+       if (addr->symbol)
+ 	base = build_fold_addr_expr (addr->symbol);
+       else
+ 	base = addr->base;
+       if (addr->offset)
+ 	offset = fold_convert (alias_ptr_type, addr->offset);
+       else
+ 	offset = build_int_cst (alias_ptr_type, 0);
+       return fold_build2 (MEM_REF, type, base, offset);
+     }
+ 
    return build6 (TARGET_MEM_REF, type,
  		 addr->symbol, addr->base, addr->index,
  		 addr->step, addr->offset, NULL);
*************** gimplify_mem_ref_parts (gimple_stmt_iter
*** 628,635 ****
     of created memory reference.  */
  
  tree
! create_mem_ref (gimple_stmt_iterator *gsi, tree type, aff_tree *addr,
! 		tree base_hint, bool speed)
  {
    tree mem_ref, tmp;
    tree atype;
--- 646,653 ----
     of created memory reference.  */
  
  tree
! create_mem_ref (gimple_stmt_iterator *gsi, tree type, tree alias_ptr_type,
! 		aff_tree *addr, tree base_hint, bool speed)
  {
    tree mem_ref, tmp;
    tree atype;
*************** create_mem_ref (gimple_stmt_iterator *gs
*** 637,643 ****
  
    addr_to_parts (type, addr, base_hint, &parts, speed);
    gimplify_mem_ref_parts (gsi, &parts);
!   mem_ref = create_mem_ref_raw (type, &parts);
    if (mem_ref)
      return mem_ref;
  
--- 655,661 ----
  
    addr_to_parts (type, addr, base_hint, &parts, speed);
    gimplify_mem_ref_parts (gsi, &parts);
!   mem_ref = create_mem_ref_raw (type, alias_ptr_type, &parts);
    if (mem_ref)
      return mem_ref;
  
*************** create_mem_ref (gimple_stmt_iterator *gs
*** 653,659 ****
  				true, NULL_TREE, true, GSI_SAME_STMT);
        parts.step = NULL_TREE;
  
!       mem_ref = create_mem_ref_raw (type, &parts);
        if (mem_ref)
  	return mem_ref;
      }
--- 671,677 ----
  				true, NULL_TREE, true, GSI_SAME_STMT);
        parts.step = NULL_TREE;
  
!       mem_ref = create_mem_ref_raw (type, alias_ptr_type, &parts);
        if (mem_ref)
  	return mem_ref;
      }
*************** create_mem_ref (gimple_stmt_iterator *gs
*** 688,694 ****
  	parts.base = tmp;
        parts.symbol = NULL_TREE;
  
!       mem_ref = create_mem_ref_raw (type, &parts);
        if (mem_ref)
  	return mem_ref;
      }
--- 706,712 ----
  	parts.base = tmp;
        parts.symbol = NULL_TREE;
  
!       mem_ref = create_mem_ref_raw (type, alias_ptr_type, &parts);
        if (mem_ref)
  	return mem_ref;
      }
*************** create_mem_ref (gimple_stmt_iterator *gs
*** 709,715 ****
  	parts.base = parts.index;
        parts.index = NULL_TREE;
  
!       mem_ref = create_mem_ref_raw (type, &parts);
        if (mem_ref)
  	return mem_ref;
      }
--- 727,733 ----
  	parts.base = parts.index;
        parts.index = NULL_TREE;
  
!       mem_ref = create_mem_ref_raw (type, alias_ptr_type, &parts);
        if (mem_ref)
  	return mem_ref;
      }
*************** create_mem_ref (gimple_stmt_iterator *gs
*** 731,737 ****
  
        parts.offset = NULL_TREE;
  
!       mem_ref = create_mem_ref_raw (type, &parts);
        if (mem_ref)
  	return mem_ref;
      }
--- 749,755 ----
  
        parts.offset = NULL_TREE;
  
!       mem_ref = create_mem_ref_raw (type, alias_ptr_type, &parts);
        if (mem_ref)
  	return mem_ref;
      }
*************** maybe_fold_tmr (tree ref)
*** 819,825 ****
    if (!changed)
      return NULL_TREE;
  
!   ret = create_mem_ref_raw (TREE_TYPE (ref), &addr);
    if (!ret)
      return NULL_TREE;
  
--- 837,843 ----
    if (!changed)
      return NULL_TREE;
  
!   ret = create_mem_ref_raw (TREE_TYPE (ref), NULL_TREE, &addr);
    if (!ret)
      return NULL_TREE;
  
Index: gcc/tree-flow.h
===================================================================
*** gcc/tree-flow.h	(revision 161837)
--- gcc/tree-flow.h	(working copy)
*************** struct mem_address
*** 833,839 ****
  };
  
  struct affine_tree_combination;
! tree create_mem_ref (gimple_stmt_iterator *, tree,
  		     struct affine_tree_combination *, tree, bool);
  rtx addr_for_mem_ref (struct mem_address *, addr_space_t, bool);
  void get_address_description (tree, struct mem_address *);
--- 838,844 ----
  };
  
  struct affine_tree_combination;
! tree create_mem_ref (gimple_stmt_iterator *, tree, tree,
  		     struct affine_tree_combination *, tree, bool);
  rtx addr_for_mem_ref (struct mem_address *, addr_space_t, bool);
  void get_address_description (tree, struct mem_address *);


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