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]

Re: [PATCH] Simplified alias-export (final)


Hi Richard,

As we discussed on IRC, this is the patch that tries to save all trees handled by the tree oracle (not stripping array-refs in set_mem_attributes_minus_bitpos) and then using this info on RTL as is for the tree oracle and stripping array-refs on demand for RTL oracle (that is, in nonoverlapping_memrefs_p). I was hoping that this would provide some performance improvements on ia64, but this is not the case at least with SPEC2000. For reference, these are disambiguation numbers I got on SPEC2k/ia64 with the patch:

		old		new	
rtl-component 	3218847		3371435		
rtl-not mem 	136621		136899		
rtl-diff bases	7813751		7836889		
rtl-size offset	3416584		3455505		
ae-not handled	2484337		1271806		
ae-win		2144591		2746011		
all rtl-win	27046845	27946827	

and on tramp3d/x86-64:

		old		new
rtl-component 	124323		124571
rtl-not mem 	13		13
rtl-diff bases	4485		4491
rtl-size offset	48565		47807
ae-not handled	98280		79749
ae-win		395262		413487
all rtl-win	2843184		2857152

After I get back from vacation, I plan to cleanup RTL oracle to remove the parts that are not needed anymore in addition to this patch, which will make more sense then.

Andrey

(only substantial parts (not flags/statistics used for testing) are in changelog)

* emit-rtl.c (set_mem_attributes_minus_bitpos): Save all trees that will be handled by the alias oracle.
* alias.c (strip_array_ref_from_ref): New.
(nonoverlapping_memrefs_p): Use it for adjusting MEM_EXPRs for the RTL oracle.
Index: gcc/alias.c
===================================================================
*** gcc/alias.c	(revision 149907)
--- gcc/alias.c	(working copy)
*************** rtx_refs_may_alias_p (const_rtx x, const
*** 344,352 ****
  
    if (!ao_ref_from_mem (&ref1, x)
        || !ao_ref_from_mem (&ref2, mem))
!     return true;
  
!   return refs_may_alias_p_1 (&ref1, &ref2, tbaa_p);
  }
  
  /* Returns a pointer to the alias set entry for ALIAS_SET, if there is
--- 344,360 ----
  
    if (!ao_ref_from_mem (&ref1, x)
        || !ao_ref_from_mem (&ref2, mem))
!     {
!       statistics_counter_event (cfun, "export-not-handled", 1);
!       return true;
!     }
  
!   if (! refs_may_alias_p_1 (&ref1, &ref2, tbaa_p))
!     {
!       statistics_counter_event (cfun, "alias-export-win", 1);
!       return false;
!     }
!   return true;
  }
  
  /* Returns a pointer to the alias set entry for ALIAS_SET, if there is
*************** adjust_offset_for_component_ref (tree x,
*** 2072,2077 ****
--- 2080,2104 ----
    return GEN_INT (ioffset);
  }
  
+ /* Strip ARRAY_REFs from REF as were done previously while saving MEM_EXPR.  */
+ static tree
+ strip_array_ref_from_ref (tree ref)
+ {
+   tree t = ref;
+   if (TREE_CODE (t) != ARRAY_REF
+       || ! flag_alias_export)
+     return ref;
+   while (TREE_CODE (t) == ARRAY_REF)
+     t = TREE_OPERAND (t, 0);
+   if (DECL_P (t)
+       || TREE_CODE (t) == COMPONENT_REF
+       || (flag_argument_noalias > 1
+           && (INDIRECT_REF_P (t))
+           && TREE_CODE (TREE_OPERAND (t, 0)) == PARM_DECL))
+     return t;
+   return ref;
+ }
+ 
  /* Return nonzero if we can determine the exprs corresponding to memrefs
     X and Y and they do not overlap.  */
  
*************** nonoverlapping_memrefs_p (const_rtx x, c
*** 2088,2098 ****
    if (exprx == 0 || expry == 0)
      return 0;
  
    /* If both are field references, we may be able to determine something.  */
    if (TREE_CODE (exprx) == COMPONENT_REF
        && TREE_CODE (expry) == COMPONENT_REF
        && nonoverlapping_component_refs_p (exprx, expry))
!     return 1;
  
  
    /* If the field reference test failed, look at the DECLs involved.  */
--- 2115,2131 ----
    if (exprx == 0 || expry == 0)
      return 0;
  
+   exprx = strip_array_ref_from_ref (exprx);
+   expry = strip_array_ref_from_ref (expry);
+ 
    /* If both are field references, we may be able to determine something.  */
    if (TREE_CODE (exprx) == COMPONENT_REF
        && TREE_CODE (expry) == COMPONENT_REF
        && nonoverlapping_component_refs_p (exprx, expry))
!     {
!       statistics_counter_event (cfun, "rtl-oracle-component-ref", 1);
!       return 1;
!     }
  
  
    /* If the field reference test failed, look at the DECLs involved.  */
*************** nonoverlapping_memrefs_p (const_rtx x, c
*** 2106,2112 ****
  	 tree fieldcontext = DECL_FIELD_CONTEXT (field);
  	 if (ipa_type_escape_field_does_not_clobber_p (fieldcontext,
  						       TREE_TYPE (field)))
! 	   return 1;
  	}
        {
  	tree t = decl_for_component_ref (exprx);
--- 2139,2148 ----
  	 tree fieldcontext = DECL_FIELD_CONTEXT (field);
  	 if (ipa_type_escape_field_does_not_clobber_p (fieldcontext,
  						       TREE_TYPE (field)))
!            {
!              statistics_counter_event (cfun, "rtl-oracle-ipa-type-escape", 1);
!              return 1;
!            }
  	}
        {
  	tree t = decl_for_component_ref (exprx);
*************** nonoverlapping_memrefs_p (const_rtx x, c
*** 2134,2140 ****
  	 tree fieldcontext = DECL_FIELD_CONTEXT (field);
  	 if (ipa_type_escape_field_does_not_clobber_p (fieldcontext,
  						       TREE_TYPE (field)))
! 	   return 1;
  	}
        {
  	tree t = decl_for_component_ref (expry);
--- 2170,2179 ----
  	 tree fieldcontext = DECL_FIELD_CONTEXT (field);
  	 if (ipa_type_escape_field_does_not_clobber_p (fieldcontext,
  						       TREE_TYPE (field)))
!            {
!              statistics_counter_event (cfun, "rtl-oracle-ipa-type-escape", 1);
!              return 1;
!            }
  	}
        {
  	tree t = decl_for_component_ref (expry);
*************** nonoverlapping_memrefs_p (const_rtx x, c
*** 2163,2169 ****
       of the stack frame used for locals for spilled pseudos.  */
    if ((!MEM_P (rtlx) || !MEM_P (rtly))
        && ! rtx_equal_p (rtlx, rtly))
!     return 1;
  
    /* Get the base and offsets of both decls.  If either is a register, we
       know both are and are the same, so use that as the base.  The only
--- 2202,2211 ----
       of the stack frame used for locals for spilled pseudos.  */
    if ((!MEM_P (rtlx) || !MEM_P (rtly))
        && ! rtx_equal_p (rtlx, rtly))
!     {
!       statistics_counter_event (cfun, "rtl-oracle-not-mem", 1);
!       return 1;
!     }
  
    /* Get the base and offsets of both decls.  If either is a register, we
       know both are and are the same, so use that as the base.  The only
*************** nonoverlapping_memrefs_p (const_rtx x, c
*** 2182,2192 ****
       stack frame.  Otherwise a different base means we can't tell if they
       overlap or not.  */
    if (! rtx_equal_p (basex, basey))
!     return ((CONSTANT_P (basex) && CONSTANT_P (basey))
! 	    || (CONSTANT_P (basex) && REG_P (basey)
! 		&& REGNO_PTR_FRAME_P (REGNO (basey)))
! 	    || (CONSTANT_P (basey) && REG_P (basex)
! 		&& REGNO_PTR_FRAME_P (REGNO (basex))));
  
    sizex = (!MEM_P (rtlx) ? (int) GET_MODE_SIZE (GET_MODE (rtlx))
  	   : MEM_SIZE (rtlx) ? INTVAL (MEM_SIZE (rtlx))
--- 2224,2239 ----
       stack frame.  Otherwise a different base means we can't tell if they
       overlap or not.  */
    if (! rtx_equal_p (basex, basey))
!     {
!       bool res = ((CONSTANT_P (basex) && CONSTANT_P (basey))
!                   || (CONSTANT_P (basex) && REG_P (basey)
!                       && REGNO_PTR_FRAME_P (REGNO (basey)))
!                   || (CONSTANT_P (basey) && REG_P (basex)
!                       && REGNO_PTR_FRAME_P (REGNO (basex))));
!       if (res)
!         statistics_counter_event (cfun, "rtl-oracle-diff-bases", 1);
!       return res;
!     }
  
    sizex = (!MEM_P (rtlx) ? (int) GET_MODE_SIZE (GET_MODE (rtlx))
  	   : MEM_SIZE (rtlx) ? INTVAL (MEM_SIZE (rtlx))
*************** nonoverlapping_memrefs_p (const_rtx x, c
*** 2219,2231 ****
  
    /* If we don't know the size of the lower-offset value, we can't tell
       if they conflict.  Otherwise, we do the test.  */
!   return sizex >= 0 && offsety >= offsetx + sizex;
  }
  
  /* True dependence: X is read after store in MEM takes place.  */
  
! int
! true_dependence (const_rtx mem, enum machine_mode mem_mode, const_rtx x,
  		 bool (*varies) (const_rtx, bool))
  {
    rtx x_addr, mem_addr;
--- 2266,2283 ----
  
    /* If we don't know the size of the lower-offset value, we can't tell
       if they conflict.  Otherwise, we do the test.  */
!   {
!     bool res = sizex >= 0 && offsety >= offsetx + sizex;
!     if (res)
!       statistics_counter_event (cfun, "rtl-oracle-size-offset", 1);
!     return res;
!   }
  }
  
  /* True dependence: X is read after store in MEM takes place.  */
  
! static int
! true_dependence_1 (const_rtx mem, enum machine_mode mem_mode, const_rtx x,
  		 bool (*varies) (const_rtx, bool))
  {
    rtx x_addr, mem_addr;
*************** true_dependence (const_rtx mem, enum mac
*** 2297,2302 ****
--- 2349,2365 ----
    return rtx_refs_may_alias_p (x, mem, true);
  }
  
+ int
+ true_dependence (const_rtx mem, enum machine_mode mem_mode, const_rtx x,
+ 		 bool (*varies) (const_rtx, bool))
+ {
+   int res = true_dependence_1 (mem, mem_mode, x, varies);
+   if (!res)
+     statistics_counter_event (cfun, "rtl-alias-win", 1);
+   return res;
+ }
+ 
+ 
  /* Canonical true dependence: X is read after store in MEM takes place.
     Variant of true_dependence which assumes MEM has already been
     canonicalized (hence we no longer do that here).
*************** true_dependence (const_rtx mem, enum mac
*** 2304,2311 ****
     this value prior to canonicalizing.
     If x_addr is non-NULL, it is used in preference of XEXP (x, 0).  */
  
! int
! canon_true_dependence (const_rtx mem, enum machine_mode mem_mode, rtx mem_addr,
  		       const_rtx x, rtx x_addr, bool (*varies) (const_rtx, bool))
  {
    if (MEM_VOLATILE_P (x) && MEM_VOLATILE_P (mem))
--- 2367,2374 ----
     this value prior to canonicalizing.
     If x_addr is non-NULL, it is used in preference of XEXP (x, 0).  */
  
! static int
! canon_true_dependence_1 (const_rtx mem, enum machine_mode mem_mode, rtx mem_addr,
  		       const_rtx x, rtx x_addr, bool (*varies) (const_rtx, bool))
  {
    if (MEM_VOLATILE_P (x) && MEM_VOLATILE_P (mem))
*************** canon_true_dependence (const_rtx mem, en
*** 2363,2373 ****
    return rtx_refs_may_alias_p (x, mem, true);
  }
  
  /* Returns nonzero if a write to X might alias a previous read from
     (or, if WRITEP is nonzero, a write to) MEM.  */
  
  static int
! write_dependence_p (const_rtx mem, const_rtx x, int writep)
  {
    rtx x_addr, mem_addr;
    const_rtx fixed_scalar;
--- 2426,2446 ----
    return rtx_refs_may_alias_p (x, mem, true);
  }
  
+ int
+ canon_true_dependence (const_rtx mem, enum machine_mode mem_mode, rtx mem_addr,
+ 		       const_rtx x, rtx x_addr, bool (*varies) (const_rtx, bool))
+ {
+   int res = canon_true_dependence_1 (mem, mem_mode, mem_addr, x, x_addr, varies);
+   if (!res)
+     statistics_counter_event (cfun, "rtl-alias-win", 1);
+   return res;
+ }
+ 
  /* Returns nonzero if a write to X might alias a previous read from
     (or, if WRITEP is nonzero, a write to) MEM.  */
  
  static int
! write_dependence_p_1 (const_rtx mem, const_rtx x, int writep)
  {
    rtx x_addr, mem_addr;
    const_rtx fixed_scalar;
*************** write_dependence_p (const_rtx mem, const
*** 2427,2432 ****
--- 2500,2514 ----
    return rtx_refs_may_alias_p (x, mem, false);
  }
  
+ static int
+ write_dependence_p (const_rtx mem, const_rtx x, int writep)
+ {
+   int res = write_dependence_p_1 (mem, x, writep);
+   if (!res)
+     statistics_counter_event (cfun, "rtl-alias-win", 1);
+   return res;
+ }
+ 
  /* Anti dependence: X is written after read in MEM takes place.  */
  
  int
Index: gcc/emit-rtl.c
===================================================================
*** gcc/emit-rtl.c	(revision 149907)
--- gcc/emit-rtl.c	(working copy)
*************** set_mem_attributes_minus_bitpos (rtx ref
*** 1546,1551 ****
--- 1546,1552 ----
    unsigned int align = MEM_ALIGN (ref);
    HOST_WIDE_INT apply_bitpos = 0;
    tree type;
+   tree full_expr = NULL_TREE;
  
    /* It can happen that type_for_mode was given a mode for which there
       is no language-level type.  In which case it returns NULL, which
*************** set_mem_attributes_minus_bitpos (rtx ref
*** 1616,1621 ****
--- 1617,1628 ----
  	     || TREE_CODE (t) == SAVE_EXPR)
  	t = TREE_OPERAND (t, 0);
  
+       if (handled_component_p (t) 
+           || SSA_VAR_P (t)
+           || INDIRECT_REF_P (t)
+           || TREE_CODE (t) == TARGET_MEM_REF)
+         full_expr = t;
+ 
        /* We may look through structure-like accesses for the purposes of
  	 examining TREE_THIS_NOTRAP, but not array-like accesses.  */
        base = t;
*************** set_mem_attributes_minus_bitpos (rtx ref
*** 1795,1801 ****
  
    /* Now set the attributes we computed above.  */
    MEM_ATTRS (ref)
!     = get_mem_attrs (alias, expr, offset, size, align, GET_MODE (ref));
  
    /* If this is already known to be a scalar or aggregate, we are done.  */
    if (MEM_IN_STRUCT_P (ref) || MEM_SCALAR_P (ref))
--- 1802,1809 ----
  
    /* Now set the attributes we computed above.  */
    MEM_ATTRS (ref)
!     = get_mem_attrs (alias, flag_alias_export ? full_expr : expr, offset, 
!                      size, align, GET_MODE (ref));
  
    /* If this is already known to be a scalar or aggregate, we are done.  */
    if (MEM_IN_STRUCT_P (ref) || MEM_SCALAR_P (ref))
Index: gcc/common.opt
===================================================================
*** gcc/common.opt	(revision 149907)
--- gcc/common.opt	(working copy)
*************** Common Separate
*** 269,274 ****
--- 269,278 ----
  fabi-version=
  Common Joined UInteger Var(flag_abi_version) Init(2)
  
+ falias-export
+ Common Report Var(flag_alias_export) Optimization Init(1)
+ Save alias information on Tree-SSA to be used on RTL
+ 
  falign-functions
  Common Report Var(align_functions,0) Optimization UInteger
  Align the start of functions

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