diff options
| author | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-06-22 08:25:43 +0000 |
|---|---|---|
| committer | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-06-22 08:25:43 +0000 |
| commit | e9a597fe457cc2062847d037eff33da8eed5dbc7 (patch) | |
| tree | 44d4b4d401a22261e056fbd78171ceccf1ac25c5 /gcc/tree-ssa-alias.c | |
| parent | e6f9d301a4a6085a086530c7b54414d03ceff5dd (diff) | |
| download | gcc-e9a597fe457cc2062847d037eff33da8eed5dbc7.tar.gz | |
2009-06-22 Basile Starynkevitch <basile@starynkevitch.net>
MELT branch merged with trunk r148777
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/melt-branch@148778 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-ssa-alias.c')
| -rw-r--r-- | gcc/tree-ssa-alias.c | 252 |
1 files changed, 228 insertions, 24 deletions
diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c index 6cbec5de2bf..98955246aea 100644 --- a/gcc/tree-ssa-alias.c +++ b/gcc/tree-ssa-alias.c @@ -168,14 +168,9 @@ ptr_deref_may_alias_decl_p (tree ptr, tree decl) { struct ptr_info_def *pi; - /* ??? During SCCVN/PRE we can end up with *&x during valueizing - operands. Likewise we can end up with dereferencing constant - pointers. Just bail out in these cases for now. */ - if (TREE_CODE (ptr) == ADDR_EXPR - || TREE_CODE (ptr) == INTEGER_CST) - return true; - - gcc_assert (TREE_CODE (ptr) == SSA_NAME + gcc_assert ((TREE_CODE (ptr) == SSA_NAME + || TREE_CODE (ptr) == ADDR_EXPR + || TREE_CODE (ptr) == INTEGER_CST) && (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL || TREE_CODE (decl) == RESULT_DECL)); @@ -184,6 +179,29 @@ ptr_deref_may_alias_decl_p (tree ptr, tree decl) if (!may_be_aliased (decl)) return false; + /* ADDR_EXPR pointers either just offset another pointer or directly + specify the pointed-to set. */ + if (TREE_CODE (ptr) == ADDR_EXPR) + { + tree base = get_base_address (TREE_OPERAND (ptr, 0)); + if (base + && INDIRECT_REF_P (base)) + ptr = TREE_OPERAND (base, 0); + else if (base + && SSA_VAR_P (base)) + return operand_equal_p (base, decl, 0); + else if (base + && CONSTANT_CLASS_P (base)) + return false; + else + return true; + } + + /* We can end up with dereferencing constant pointers. + Just bail out in this case. */ + if (TREE_CODE (ptr) == INTEGER_CST) + return true; + /* If we do not have useful points-to information for this pointer we cannot disambiguate anything else. */ pi = SSA_NAME_PTR_INFO (ptr); @@ -202,18 +220,46 @@ ptr_derefs_may_alias_p (tree ptr1, tree ptr2) { struct ptr_info_def *pi1, *pi2; - /* ??? During SCCVN/PRE we can end up with *&x during valueizing - operands. Likewise we can end up with dereferencing constant - pointers. Just bail out in these cases for now. */ - if (TREE_CODE (ptr1) == ADDR_EXPR - || TREE_CODE (ptr1) == INTEGER_CST - || TREE_CODE (ptr2) == ADDR_EXPR + gcc_assert ((TREE_CODE (ptr1) == SSA_NAME + || TREE_CODE (ptr1) == ADDR_EXPR + || TREE_CODE (ptr1) == INTEGER_CST) + && (TREE_CODE (ptr2) == SSA_NAME + || TREE_CODE (ptr2) == ADDR_EXPR + || TREE_CODE (ptr2) == INTEGER_CST)); + + /* ADDR_EXPR pointers either just offset another pointer or directly + specify the pointed-to set. */ + if (TREE_CODE (ptr1) == ADDR_EXPR) + { + tree base = get_base_address (TREE_OPERAND (ptr1, 0)); + if (base + && INDIRECT_REF_P (base)) + ptr1 = TREE_OPERAND (base, 0); + else if (base + && SSA_VAR_P (base)) + return ptr_deref_may_alias_decl_p (ptr2, base); + else + return true; + } + if (TREE_CODE (ptr2) == ADDR_EXPR) + { + tree base = get_base_address (TREE_OPERAND (ptr2, 0)); + if (base + && INDIRECT_REF_P (base)) + ptr2 = TREE_OPERAND (base, 0); + else if (base + && SSA_VAR_P (base)) + return ptr_deref_may_alias_decl_p (ptr1, base); + else + return true; + } + + /* We can end up with dereferencing constant pointers. + Just bail out in this case. */ + if (TREE_CODE (ptr1) == INTEGER_CST || TREE_CODE (ptr2) == INTEGER_CST) return true; - gcc_assert (TREE_CODE (ptr1) == SSA_NAME - && TREE_CODE (ptr2) == SSA_NAME); - /* We may end up with two empty points-to solutions for two same pointers. In this case we still want to say both pointers alias, so shortcut that here. */ @@ -232,6 +278,31 @@ ptr_derefs_may_alias_p (tree ptr1, tree ptr2) return pt_solutions_intersect (&pi1->pt, &pi2->pt); } +/* Return true if dereferencing PTR may alias *REF. + The caller is responsible for applying TBAA to see if PTR + may access *REF at all. */ + +static bool +ptr_deref_may_alias_ref_p_1 (tree ptr, ao_ref *ref) +{ + tree base = ao_ref_base (ref); + + if (INDIRECT_REF_P (base)) + return ptr_derefs_may_alias_p (ptr, TREE_OPERAND (base, 0)); + else if (SSA_VAR_P (base)) + return ptr_deref_may_alias_decl_p (ptr, base); + + return true; +} + +static bool +ptr_deref_may_alias_ref_p (tree ptr, tree ref) +{ + ao_ref r; + ao_ref_init (&r, ref); + return ptr_deref_may_alias_ref_p_1 (ptr, &r); +} + /* Dump alias information on FILE. */ @@ -778,7 +849,7 @@ refs_output_dependent_p (tree store1, tree store2) static bool ref_maybe_used_by_call_p_1 (gimple call, tree ref) { - tree base; + tree base, callee; unsigned i; int flags = gimple_call_flags (call); @@ -803,13 +874,64 @@ ref_maybe_used_by_call_p_1 (gimple call, tree ref) && !is_global_var (base)) goto process_args; + callee = gimple_call_fndecl (call); + + /* Handle those builtin functions explicitly that do not act as + escape points. See tree-ssa-structalias.c:find_func_aliases + for the list of builtins we might need to handle here. */ + if (callee != NULL_TREE + && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL) + switch (DECL_FUNCTION_CODE (callee)) + { + /* All the following functions clobber memory pointed to by + their first argument. */ + case BUILT_IN_STRCPY: + case BUILT_IN_STRNCPY: + case BUILT_IN_BCOPY: + case BUILT_IN_MEMCPY: + case BUILT_IN_MEMMOVE: + case BUILT_IN_MEMPCPY: + case BUILT_IN_STPCPY: + case BUILT_IN_STPNCPY: + case BUILT_IN_STRCAT: + case BUILT_IN_STRNCAT: + { + tree src = gimple_call_arg (call, 1); + return ptr_deref_may_alias_ref_p (src, ref); + } + /* The following builtins do not read from memory. */ + case BUILT_IN_FREE: + case BUILT_IN_MEMSET: + case BUILT_IN_FREXP: + case BUILT_IN_FREXPF: + case BUILT_IN_FREXPL: + case BUILT_IN_GAMMA_R: + case BUILT_IN_GAMMAF_R: + case BUILT_IN_GAMMAL_R: + case BUILT_IN_LGAMMA_R: + case BUILT_IN_LGAMMAF_R: + case BUILT_IN_LGAMMAL_R: + case BUILT_IN_MODF: + case BUILT_IN_MODFF: + case BUILT_IN_MODFL: + case BUILT_IN_REMQUO: + case BUILT_IN_REMQUOF: + case BUILT_IN_REMQUOL: + case BUILT_IN_SINCOS: + case BUILT_IN_SINCOSF: + case BUILT_IN_SINCOSL: + return false; + + default: + /* Fallthru to general call handling. */; + } + /* Check if base is a global static variable that is not read by the function. */ if (TREE_CODE (base) == VAR_DECL && TREE_STATIC (base) && !TREE_PUBLIC (base)) { - tree callee = gimple_call_fndecl (call); bitmap not_read; if (callee != NULL_TREE @@ -901,6 +1023,7 @@ static bool call_may_clobber_ref_p_1 (gimple call, ao_ref *ref) { tree base; + tree callee; /* If the call is pure or const it cannot clobber anything. */ if (gimple_call_flags (call) @@ -926,18 +1049,99 @@ call_may_clobber_ref_p_1 (gimple call, ao_ref *ref) || !is_global_var (base))) return false; + callee = gimple_call_fndecl (call); + + /* Handle those builtin functions explicitly that do not act as + escape points. See tree-ssa-structalias.c:find_func_aliases + for the list of builtins we might need to handle here. */ + if (callee != NULL_TREE + && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL) + switch (DECL_FUNCTION_CODE (callee)) + { + /* All the following functions clobber memory pointed to by + their first argument. */ + case BUILT_IN_STRCPY: + case BUILT_IN_STRNCPY: + case BUILT_IN_BCOPY: + case BUILT_IN_MEMCPY: + case BUILT_IN_MEMMOVE: + case BUILT_IN_MEMPCPY: + case BUILT_IN_STPCPY: + case BUILT_IN_STPNCPY: + case BUILT_IN_STRCAT: + case BUILT_IN_STRNCAT: + { + tree dest = gimple_call_arg (call, 0); + return ptr_deref_may_alias_ref_p_1 (dest, ref); + } + /* Freeing memory kills the pointed-to memory. More importantly + the call has to serve as a barrier for moving loads and stores + across it. Same is true for memset. */ + case BUILT_IN_FREE: + case BUILT_IN_MEMSET: + { + tree ptr = gimple_call_arg (call, 0); + return ptr_deref_may_alias_ref_p_1 (ptr, ref); + } + case BUILT_IN_GAMMA_R: + case BUILT_IN_GAMMAF_R: + case BUILT_IN_GAMMAL_R: + case BUILT_IN_LGAMMA_R: + case BUILT_IN_LGAMMAF_R: + case BUILT_IN_LGAMMAL_R: + { + tree out = gimple_call_arg (call, 1); + if (ptr_deref_may_alias_ref_p_1 (out, ref)) + return true; + if (flag_errno_math) + break; + return false; + } + case BUILT_IN_FREXP: + case BUILT_IN_FREXPF: + case BUILT_IN_FREXPL: + case BUILT_IN_MODF: + case BUILT_IN_MODFF: + case BUILT_IN_MODFL: + { + tree out = gimple_call_arg (call, 1); + return ptr_deref_may_alias_ref_p_1 (out, ref); + } + case BUILT_IN_REMQUO: + case BUILT_IN_REMQUOF: + case BUILT_IN_REMQUOL: + { + tree out = gimple_call_arg (call, 2); + if (ptr_deref_may_alias_ref_p_1 (out, ref)) + return true; + if (flag_errno_math) + break; + return false; + } + case BUILT_IN_SINCOS: + case BUILT_IN_SINCOSF: + case BUILT_IN_SINCOSL: + { + tree sin = gimple_call_arg (call, 1); + tree cos = gimple_call_arg (call, 2); + return (ptr_deref_may_alias_ref_p_1 (sin, ref) + || ptr_deref_may_alias_ref_p_1 (cos, ref)); + } + default: + /* Fallthru to general call handling. */; + } + /* Check if base is a global static variable that is not written by the function. */ - if (TREE_CODE (base) == VAR_DECL + if (callee != NULL_TREE + && TREE_CODE (base) == VAR_DECL && TREE_STATIC (base) && !TREE_PUBLIC (base)) { - tree callee = gimple_call_fndecl (call); bitmap not_written; - if (callee != NULL_TREE - && (not_written - = ipa_reference_get_not_written_global (cgraph_node (callee))) + if ((not_written + = ipa_reference_get_not_written_global (cgraph_node (callee))) && bitmap_bit_p (not_written, DECL_UID (base))) return false; } |
