mirror of git://gcc.gnu.org/git/gcc.git
ddg.c (walk_mems_2): Moved from alias.c, use may_alias_p instead of alias_sets_conflict_p.
2010-08-09 Bingfeng Mei <bmei@broadcom.com> * ddg.c (walk_mems_2): Moved from alias.c, use may_alias_p instead of alias_sets_conflict_p. (walk_mems_1): Moved from alias.c. (insns_may_alias_p): New function, originally insn_alias_sets_conflict_p in alias.c. (add_inter_loop_mem_dep): Use insns_may_alias_p now. * cse.c (cse_insn): New argument in calling nonoverlapping_memrefs_p. * alias.c (walk_mems_2): Moved to ddg.c. (walk_mems_1): Ditto. (insn_alias_sets_conflict_p): Renamed to insns_may_alias_p and moved to ddg.c. (nonoverlapping_memrefs_p): Add flag to guard offset-based memory disambiguation. *(may_alias_p): New function to check whether two memory expression may alias or not. Currently used in buidling inter-iteration memory dependence. *alias.h (nonoverlapping_memrefs_p): New flag as third argument. (insn_alias_sets_conflict_p): Removed *rtl.h (may_alias_p): New function prototype. From-SVN: r163037
This commit is contained in:
parent
72ac05b04e
commit
c6ea834c83
|
@ -1,3 +1,25 @@
|
||||||
|
2010-08-09 Bingfeng Mei <bmei@broadcom.com>
|
||||||
|
|
||||||
|
* ddg.c (walk_mems_2): Moved from alias.c, use may_alias_p instead of
|
||||||
|
alias_sets_conflict_p.
|
||||||
|
(walk_mems_1): Moved from alias.c.
|
||||||
|
(insns_may_alias_p): New function, originally insn_alias_sets_conflict_p
|
||||||
|
in alias.c.
|
||||||
|
(add_inter_loop_mem_dep): Use insns_may_alias_p now.
|
||||||
|
* cse.c (cse_insn): New argument in calling nonoverlapping_memrefs_p.
|
||||||
|
* alias.c (walk_mems_2): Moved to ddg.c.
|
||||||
|
(walk_mems_1): Ditto.
|
||||||
|
(insn_alias_sets_conflict_p): Renamed to insns_may_alias_p and moved
|
||||||
|
to ddg.c.
|
||||||
|
(nonoverlapping_memrefs_p): Add flag to guard offset-based memory
|
||||||
|
disambiguation.
|
||||||
|
*(may_alias_p): New function to check whether two memory expression
|
||||||
|
may alias or not. Currently used in buidling inter-iteration memory
|
||||||
|
dependence.
|
||||||
|
*alias.h (nonoverlapping_memrefs_p): New flag as third argument.
|
||||||
|
(insn_alias_sets_conflict_p): Removed
|
||||||
|
*rtl.h (may_alias_p): New function prototype.
|
||||||
|
|
||||||
2010-08-09 Nathan Froyd <froydnj@codesourcery.com>
|
2010-08-09 Nathan Froyd <froydnj@codesourcery.com>
|
||||||
|
|
||||||
* tree.c (nreverse): Assert that we don't have a BLOCK.
|
* tree.c (nreverse): Assert that we don't have a BLOCK.
|
||||||
|
|
120
gcc/alias.c
120
gcc/alias.c
|
@ -452,43 +452,6 @@ alias_sets_conflict_p (alias_set_type set1, alias_set_type set2)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
walk_mems_2 (rtx *x, rtx mem)
|
|
||||||
{
|
|
||||||
if (MEM_P (*x))
|
|
||||||
{
|
|
||||||
if (alias_sets_conflict_p (MEM_ALIAS_SET(*x), MEM_ALIAS_SET(mem)))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
walk_mems_1 (rtx *x, rtx *pat)
|
|
||||||
{
|
|
||||||
if (MEM_P (*x))
|
|
||||||
{
|
|
||||||
/* Visit all MEMs in *PAT and check indepedence. */
|
|
||||||
if (for_each_rtx (pat, (rtx_function) walk_mems_2, *x))
|
|
||||||
/* Indicate that dependence was determined and stop traversal. */
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return 1 if two specified instructions have mem expr with conflict alias sets*/
|
|
||||||
bool
|
|
||||||
insn_alias_sets_conflict_p (rtx insn1, rtx insn2)
|
|
||||||
{
|
|
||||||
/* For each pair of MEMs in INSN1 and INSN2 check their independence. */
|
|
||||||
return for_each_rtx (&PATTERN (insn1), (rtx_function) walk_mems_1,
|
|
||||||
&PATTERN (insn2));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return 1 if the two specified alias sets will always conflict. */
|
/* Return 1 if the two specified alias sets will always conflict. */
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -2187,10 +2150,11 @@ adjust_offset_for_component_ref (tree x, rtx offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return nonzero if we can determine the exprs corresponding to memrefs
|
/* Return nonzero if we can determine the exprs corresponding to memrefs
|
||||||
X and Y and they do not overlap. */
|
X and Y and they do not overlap.
|
||||||
|
If LOOP_VARIANT is set, skip offset-based disambiguation */
|
||||||
|
|
||||||
int
|
int
|
||||||
nonoverlapping_memrefs_p (const_rtx x, const_rtx y)
|
nonoverlapping_memrefs_p (const_rtx x, const_rtx y, bool loop_invariant)
|
||||||
{
|
{
|
||||||
tree exprx = MEM_EXPR (x), expry = MEM_EXPR (y);
|
tree exprx = MEM_EXPR (x), expry = MEM_EXPR (y);
|
||||||
rtx rtlx, rtly;
|
rtx rtlx, rtly;
|
||||||
|
@ -2287,6 +2251,10 @@ nonoverlapping_memrefs_p (const_rtx x, const_rtx y)
|
||||||
|| (CONSTANT_P (basey) && REG_P (basex)
|
|| (CONSTANT_P (basey) && REG_P (basex)
|
||||||
&& REGNO_PTR_FRAME_P (REGNO (basex))));
|
&& REGNO_PTR_FRAME_P (REGNO (basex))));
|
||||||
|
|
||||||
|
/* Offset based disambiguation not appropriate for loop invariant */
|
||||||
|
if (loop_invariant)
|
||||||
|
return 0;
|
||||||
|
|
||||||
sizex = (!MEM_P (rtlx) ? (int) GET_MODE_SIZE (GET_MODE (rtlx))
|
sizex = (!MEM_P (rtlx) ? (int) GET_MODE_SIZE (GET_MODE (rtlx))
|
||||||
: MEM_SIZE (rtlx) ? INTVAL (MEM_SIZE (rtlx))
|
: MEM_SIZE (rtlx) ? INTVAL (MEM_SIZE (rtlx))
|
||||||
: -1);
|
: -1);
|
||||||
|
@ -2413,7 +2381,7 @@ true_dependence_1 (const_rtx mem, enum machine_mode mem_mode, rtx mem_addr,
|
||||||
if (DIFFERENT_ALIAS_SETS_P (x, mem))
|
if (DIFFERENT_ALIAS_SETS_P (x, mem))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (nonoverlapping_memrefs_p (mem, x))
|
if (nonoverlapping_memrefs_p (mem, x, false))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (aliases_everything_p (x))
|
if (aliases_everything_p (x))
|
||||||
|
@ -2528,7 +2496,7 @@ write_dependence_p (const_rtx mem, const_rtx x, int writep)
|
||||||
SIZE_FOR_MODE (x), x_addr, 0)) != -1)
|
SIZE_FOR_MODE (x), x_addr, 0)) != -1)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (nonoverlapping_memrefs_p (x, mem))
|
if (nonoverlapping_memrefs_p (x, mem, false))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fixed_scalar
|
fixed_scalar
|
||||||
|
@ -2559,6 +2527,76 @@ output_dependence (const_rtx mem, const_rtx x)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Check whether X may be aliased with MEM. Don't do offset-based
|
||||||
|
memory disambiguation & TBAA. */
|
||||||
|
int
|
||||||
|
may_alias_p (const_rtx mem, const_rtx x)
|
||||||
|
{
|
||||||
|
rtx x_addr, mem_addr;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (MEM_VOLATILE_P (x) && MEM_VOLATILE_P (mem))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* ??? In true_dependence we also allow BLKmode to alias anything. */
|
||||||
|
if (GET_MODE (mem) == BLKmode || GET_MODE (x) == BLKmode)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (MEM_ALIAS_SET (x) == ALIAS_SET_MEMORY_BARRIER
|
||||||
|
|| MEM_ALIAS_SET (mem) == ALIAS_SET_MEMORY_BARRIER)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* Read-only memory is by definition never modified, and therefore can't
|
||||||
|
conflict with anything. We don't expect to find read-only set on MEM,
|
||||||
|
but stupid user tricks can produce them, so don't die. */
|
||||||
|
if (MEM_READONLY_P (x))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* If we have MEMs refering to different address spaces (which can
|
||||||
|
potentially overlap), we cannot easily tell from the addresses
|
||||||
|
whether the references overlap. */
|
||||||
|
if (MEM_ADDR_SPACE (mem) != MEM_ADDR_SPACE (x))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
x_addr = XEXP (x, 0);
|
||||||
|
mem_addr = XEXP (mem, 0);
|
||||||
|
if (!((GET_CODE (x_addr) == VALUE
|
||||||
|
&& GET_CODE (mem_addr) != VALUE
|
||||||
|
&& reg_mentioned_p (x_addr, mem_addr))
|
||||||
|
|| (GET_CODE (x_addr) != VALUE
|
||||||
|
&& GET_CODE (mem_addr) == VALUE
|
||||||
|
&& reg_mentioned_p (mem_addr, x_addr))))
|
||||||
|
{
|
||||||
|
x_addr = get_addr (x_addr);
|
||||||
|
mem_addr = get_addr (mem_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! base_alias_check (x_addr, mem_addr, GET_MODE (x), GET_MODE (mem_addr)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
x_addr = canon_rtx (x_addr);
|
||||||
|
mem_addr = canon_rtx (mem_addr);
|
||||||
|
|
||||||
|
if (nonoverlapping_memrefs_p (mem, x, true))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (aliases_everything_p (x))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* We cannot use aliases_everything_p to test MEM, since we must look
|
||||||
|
at MEM_ADDR, rather than XEXP (mem, 0). */
|
||||||
|
if (GET_MODE (mem) == QImode || GET_CODE (mem_addr) == AND)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (fixed_scalar_and_varying_struct_p (mem, x, mem_addr, x_addr,
|
||||||
|
rtx_addr_varies_p))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* TBAA not valid for loop_invarint */
|
||||||
|
return rtx_refs_may_alias_p (x, mem, false);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
init_alias_target (void)
|
init_alias_target (void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -42,8 +42,7 @@ extern void record_component_aliases (tree);
|
||||||
extern int alias_sets_conflict_p (alias_set_type, alias_set_type);
|
extern int alias_sets_conflict_p (alias_set_type, alias_set_type);
|
||||||
extern int alias_sets_must_conflict_p (alias_set_type, alias_set_type);
|
extern int alias_sets_must_conflict_p (alias_set_type, alias_set_type);
|
||||||
extern int objects_must_conflict_p (tree, tree);
|
extern int objects_must_conflict_p (tree, tree);
|
||||||
extern int nonoverlapping_memrefs_p (const_rtx, const_rtx);
|
extern int nonoverlapping_memrefs_p (const_rtx, const_rtx, bool);
|
||||||
extern bool insn_alias_sets_conflict_p (rtx, rtx);
|
|
||||||
|
|
||||||
/* This alias set can be used to force a memory to conflict with all
|
/* This alias set can be used to force a memory to conflict with all
|
||||||
other memories, creating a barrier across which no memory reference
|
other memories, creating a barrier across which no memory reference
|
||||||
|
|
|
@ -5015,7 +5015,7 @@ cse_insn (rtx insn)
|
||||||
dest = canon_rtx (SET_DEST (sets[i].rtl));
|
dest = canon_rtx (SET_DEST (sets[i].rtl));
|
||||||
|
|
||||||
if (!MEM_P (src) || !MEM_P (dest)
|
if (!MEM_P (src) || !MEM_P (dest)
|
||||||
|| !nonoverlapping_memrefs_p (src, dest))
|
|| !nonoverlapping_memrefs_p (src, dest, false))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
39
gcc/ddg.c
39
gcc/ddg.c
|
@ -348,12 +348,49 @@ build_inter_loop_deps (ddg_ptr g)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
walk_mems_2 (rtx *x, rtx mem)
|
||||||
|
{
|
||||||
|
if (MEM_P (*x))
|
||||||
|
{
|
||||||
|
if (may_alias_p (*x, mem))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
walk_mems_1 (rtx *x, rtx *pat)
|
||||||
|
{
|
||||||
|
if (MEM_P (*x))
|
||||||
|
{
|
||||||
|
/* Visit all MEMs in *PAT and check indepedence. */
|
||||||
|
if (for_each_rtx (pat, (rtx_function) walk_mems_2, *x))
|
||||||
|
/* Indicate that dependence was determined and stop traversal. */
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return 1 if two specified instructions have mem expr with conflict alias sets*/
|
||||||
|
static int
|
||||||
|
insns_may_alias_p (rtx insn1, rtx insn2)
|
||||||
|
{
|
||||||
|
/* For each pair of MEMs in INSN1 and INSN2 check their independence. */
|
||||||
|
return for_each_rtx (&PATTERN (insn1), (rtx_function) walk_mems_1,
|
||||||
|
&PATTERN (insn2));
|
||||||
|
}
|
||||||
|
|
||||||
/* Given two nodes, analyze their RTL insns and add inter-loop mem deps
|
/* Given two nodes, analyze their RTL insns and add inter-loop mem deps
|
||||||
to ddg G. */
|
to ddg G. */
|
||||||
static void
|
static void
|
||||||
add_inter_loop_mem_dep (ddg_ptr g, ddg_node_ptr from, ddg_node_ptr to)
|
add_inter_loop_mem_dep (ddg_ptr g, ddg_node_ptr from, ddg_node_ptr to)
|
||||||
{
|
{
|
||||||
if (!insn_alias_sets_conflict_p (from->insn, to->insn))
|
if (!insns_may_alias_p (from->insn, to->insn))
|
||||||
/* Do not create edge if memory references have disjoint alias sets. */
|
/* Do not create edge if memory references have disjoint alias sets. */
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -2424,6 +2424,7 @@ extern int canon_true_dependence (const_rtx, enum machine_mode, rtx, const_rtx,
|
||||||
extern int read_dependence (const_rtx, const_rtx);
|
extern int read_dependence (const_rtx, const_rtx);
|
||||||
extern int anti_dependence (const_rtx, const_rtx);
|
extern int anti_dependence (const_rtx, const_rtx);
|
||||||
extern int output_dependence (const_rtx, const_rtx);
|
extern int output_dependence (const_rtx, const_rtx);
|
||||||
|
extern int may_alias_p (const_rtx, const_rtx);
|
||||||
extern void init_alias_target (void);
|
extern void init_alias_target (void);
|
||||||
extern void init_alias_analysis (void);
|
extern void init_alias_analysis (void);
|
||||||
extern void end_alias_analysis (void);
|
extern void end_alias_analysis (void);
|
||||||
|
|
Loading…
Reference in New Issue