diff options
author | Bingfeng Mei <bmei@broadcom.com> | 2010-08-09 14:44:03 +0000 |
---|---|---|
committer | Bingfeng Mei <meibf@gcc.gnu.org> | 2010-08-09 14:44:03 +0000 |
commit | c6ea834c83126f1a249525715f677ccf9969c30b (patch) | |
tree | e1019cb9c50fe10a946e21114e247d48c6ccc78a /gcc | |
parent | 72ac05b04e2baf2ff9eebd42e6ff5f22fd3b1546 (diff) | |
download | gcc-c6ea834c83126f1a249525715f677ccf9969c30b.tar.gz |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 22 | ||||
-rw-r--r-- | gcc/alias.c | 120 | ||||
-rw-r--r-- | gcc/alias.h | 3 | ||||
-rw-r--r-- | gcc/cse.c | 2 | ||||
-rw-r--r-- | gcc/ddg.c | 39 | ||||
-rw-r--r-- | gcc/rtl.h | 1 |
6 files changed, 142 insertions, 45 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6c73664e85d..ddae0798b46 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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> * tree.c (nreverse): Assert that we don't have a BLOCK. diff --git a/gcc/alias.c b/gcc/alias.c index f5de4db9d75..3f5f47a009a 100644 --- a/gcc/alias.c +++ b/gcc/alias.c @@ -452,43 +452,6 @@ alias_sets_conflict_p (alias_set_type set1, alias_set_type set2) 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. */ 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 - 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 -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); rtx rtlx, rtly; @@ -2287,6 +2251,10 @@ nonoverlapping_memrefs_p (const_rtx x, const_rtx y) || (CONSTANT_P (basey) && REG_P (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)) : MEM_SIZE (rtlx) ? INTVAL (MEM_SIZE (rtlx)) : -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)) return 0; - if (nonoverlapping_memrefs_p (mem, x)) + if (nonoverlapping_memrefs_p (mem, x, false)) return 0; 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) return ret; - if (nonoverlapping_memrefs_p (x, mem)) + if (nonoverlapping_memrefs_p (x, mem, false)) return 0; 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 init_alias_target (void) { diff --git a/gcc/alias.h b/gcc/alias.h index 5907215824d..58945524e9a 100644 --- a/gcc/alias.h +++ b/gcc/alias.h @@ -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_must_conflict_p (alias_set_type, alias_set_type); extern int objects_must_conflict_p (tree, tree); -extern int nonoverlapping_memrefs_p (const_rtx, const_rtx); -extern bool insn_alias_sets_conflict_p (rtx, rtx); +extern int nonoverlapping_memrefs_p (const_rtx, const_rtx, bool); /* This alias set can be used to force a memory to conflict with all other memories, creating a barrier across which no memory reference diff --git a/gcc/cse.c b/gcc/cse.c index ae513eb2a16..dcba6bc3bb3 100644 --- a/gcc/cse.c +++ b/gcc/cse.c @@ -5015,7 +5015,7 @@ cse_insn (rtx insn) dest = canon_rtx (SET_DEST (sets[i].rtl)); if (!MEM_P (src) || !MEM_P (dest) - || !nonoverlapping_memrefs_p (src, dest)) + || !nonoverlapping_memrefs_p (src, dest, false)) break; } diff --git a/gcc/ddg.c b/gcc/ddg.c index 0a20ed61291..88aaf9bb2e4 100644 --- a/gcc/ddg.c +++ b/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 to ddg G. */ static void 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. */ return; diff --git a/gcc/rtl.h b/gcc/rtl.h index 710e3caa144..bb873584057 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -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 anti_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_analysis (void); extern void end_alias_analysis (void); |