This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] Simplified alias-export (final)
- From: Andrey Belevantsev <abel at ispras dot ru>
- To: Richard Guenther <rguenther at suse dot de>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Wed, 22 Jul 2009 14:00:25 +0400
- Subject: Re: [PATCH] Simplified alias-export (final)
- References: <alpine.LNX.2.00.0907131436200.16347@zhemvz.fhfr.qr>
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