diff options
Diffstat (limited to 'gcc/alias.c')
-rw-r--r-- | gcc/alias.c | 243 |
1 files changed, 154 insertions, 89 deletions
diff --git a/gcc/alias.c b/gcc/alias.c index 966e9d28d5a..1736169b476 100644 --- a/gcc/alias.c +++ b/gcc/alias.c @@ -40,11 +40,11 @@ along with GCC; see the file COPYING3. If not see #include "timevar.h" #include "dumpfile.h" #include "target.h" -#include "cgraph.h" #include "df.h" #include "tree-ssa-alias.h" #include "pointer-set.h" -#include "tree-ssa.h" +#include "gimple.h" +#include "gimple-ssa.h" /* The aliasing API provided here solves related but different problems: @@ -500,51 +500,70 @@ objects_must_conflict_p (tree t1, tree t2) return alias_sets_must_conflict_p (set1, set2); } -/* Return true if all nested component references handled by - get_inner_reference in T are such that we should use the alias set - provided by the object at the heart of T. - - This is true for non-addressable components (which don't have their - own alias set), as well as components of objects in alias set zero. - This later point is a special case wherein we wish to override the - alias set used by the component, but we don't have per-FIELD_DECL - assignable alias sets. */ - -bool -component_uses_parent_alias_set (const_tree t) +/* Return the outermost parent of component present in the chain of + component references handled by get_inner_reference in T with the + following property: + - the component is non-addressable, or + - the parent has alias set zero, + or NULL_TREE if no such parent exists. In the former cases, the alias + set of this parent is the alias set that must be used for T itself. */ + +tree +component_uses_parent_alias_set_from (const_tree t) { - while (1) - { - /* If we're at the end, it vacuously uses its own alias set. */ - if (!handled_component_p (t)) - return false; + const_tree found = NULL_TREE; + while (handled_component_p (t)) + { switch (TREE_CODE (t)) { case COMPONENT_REF: if (DECL_NONADDRESSABLE_P (TREE_OPERAND (t, 1))) - return true; + found = t; break; case ARRAY_REF: case ARRAY_RANGE_REF: if (TYPE_NONALIASED_COMPONENT (TREE_TYPE (TREE_OPERAND (t, 0)))) - return true; + found = t; break; case REALPART_EXPR: case IMAGPART_EXPR: break; - default: + case BIT_FIELD_REF: + case VIEW_CONVERT_EXPR: /* Bitfields and casts are never addressable. */ - return true; + found = t; + break; + + default: + gcc_unreachable (); } + if (get_alias_set (TREE_TYPE (TREE_OPERAND (t, 0))) == 0) + found = t; + t = TREE_OPERAND (t, 0); - if (get_alias_set (TREE_TYPE (t)) == 0) - return true; } + + if (found) + return TREE_OPERAND (found, 0); + + return NULL_TREE; +} + + +/* Return whether the pointer-type T effective for aliasing may + access everything and thus the reference has to be assigned + alias-set zero. */ + +static bool +ref_all_alias_ptr_type_p (const_tree t) +{ + return (TREE_CODE (TREE_TYPE (t)) == VOID_TYPE + || TYPE_REF_CAN_ALIAS_ALL (t)); } /* Return the alias set for the memory pointed to by T, which may be @@ -554,11 +573,6 @@ component_uses_parent_alias_set (const_tree t) static alias_set_type get_deref_alias_set_1 (tree t) { - /* If we're not doing any alias analysis, just assume everything - aliases everything else. */ - if (!flag_strict_aliasing) - return 0; - /* All we care about is the type. */ if (! TYPE_P (t)) t = TREE_TYPE (t); @@ -566,8 +580,7 @@ get_deref_alias_set_1 (tree t) /* If we have an INDIRECT_REF via a void pointer, we don't know anything about what that might alias. Likewise if the pointer is marked that way. */ - if (TREE_CODE (TREE_TYPE (t)) == VOID_TYPE - || TYPE_REF_CAN_ALIAS_ALL (t)) + if (ref_all_alias_ptr_type_p (t)) return 0; return -1; @@ -579,6 +592,11 @@ get_deref_alias_set_1 (tree t) alias_set_type get_deref_alias_set (tree t) { + /* If we're not doing any alias analysis, just assume everything + aliases everything else. */ + if (!flag_strict_aliasing) + return 0; + alias_set_type set = get_deref_alias_set_1 (t); /* Fall back to the alias-set of the pointed-to type. */ @@ -592,6 +610,98 @@ get_deref_alias_set (tree t) return set; } +/* Return the pointer-type relevant for TBAA purposes from the + memory reference tree *T or NULL_TREE in which case *T is + adjusted to point to the outermost component reference that + can be used for assigning an alias set. */ + +static tree +reference_alias_ptr_type_1 (tree *t) +{ + tree inner; + + /* Get the base object of the reference. */ + inner = *t; + while (handled_component_p (inner)) + { + /* If there is a VIEW_CONVERT_EXPR in the chain we cannot use + the type of any component references that wrap it to + determine the alias-set. */ + if (TREE_CODE (inner) == VIEW_CONVERT_EXPR) + *t = TREE_OPERAND (inner, 0); + inner = TREE_OPERAND (inner, 0); + } + + /* Handle pointer dereferences here, they can override the + alias-set. */ + if (INDIRECT_REF_P (inner) + && ref_all_alias_ptr_type_p (TREE_TYPE (TREE_OPERAND (inner, 0)))) + return TREE_TYPE (TREE_OPERAND (inner, 0)); + else if (TREE_CODE (inner) == TARGET_MEM_REF) + return TREE_TYPE (TMR_OFFSET (inner)); + else if (TREE_CODE (inner) == MEM_REF + && ref_all_alias_ptr_type_p (TREE_TYPE (TREE_OPERAND (inner, 1)))) + return TREE_TYPE (TREE_OPERAND (inner, 1)); + + /* If the innermost reference is a MEM_REF that has a + conversion embedded treat it like a VIEW_CONVERT_EXPR above, + using the memory access type for determining the alias-set. */ + if (TREE_CODE (inner) == MEM_REF + && (TYPE_MAIN_VARIANT (TREE_TYPE (inner)) + != TYPE_MAIN_VARIANT + (TREE_TYPE (TREE_TYPE (TREE_OPERAND (inner, 1)))))) + return TREE_TYPE (TREE_OPERAND (inner, 1)); + + /* Otherwise, pick up the outermost object that we could have + a pointer to. */ + tree tem = component_uses_parent_alias_set_from (*t); + if (tem) + *t = tem; + + return NULL_TREE; +} + +/* Return the pointer-type relevant for TBAA purposes from the + gimple memory reference tree T. This is the type to be used for + the offset operand of MEM_REF or TARGET_MEM_REF replacements of T + and guarantees that get_alias_set will return the same alias + set for T and the replacement. */ + +tree +reference_alias_ptr_type (tree t) +{ + tree ptype = reference_alias_ptr_type_1 (&t); + /* If there is a given pointer type for aliasing purposes, return it. */ + if (ptype != NULL_TREE) + return ptype; + + /* Otherwise build one from the outermost component reference we + may use. */ + if (TREE_CODE (t) == MEM_REF + || TREE_CODE (t) == TARGET_MEM_REF) + return TREE_TYPE (TREE_OPERAND (t, 1)); + else + return build_pointer_type (TYPE_MAIN_VARIANT (TREE_TYPE (t))); +} + +/* Return whether the pointer-types T1 and T2 used to determine + two alias sets of two references will yield the same answer + from get_deref_alias_set. */ + +bool +alias_ptr_types_compatible_p (tree t1, tree t2) +{ + if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2)) + return true; + + if (ref_all_alias_ptr_type_p (t1) + || ref_all_alias_ptr_type_p (t2)) + return false; + + return (TYPE_MAIN_VARIANT (TREE_TYPE (t1)) + == TYPE_MAIN_VARIANT (TREE_TYPE (t2))); +} + /* Return the alias set for T, which may be either a type or an expression. Call language-specific routine for help, if needed. */ @@ -615,8 +725,6 @@ get_alias_set (tree t) aren't types. */ if (! TYPE_P (t)) { - tree inner; - /* Give the language a chance to do something with this tree before we look at it. */ STRIP_NOPS (t); @@ -624,51 +732,11 @@ get_alias_set (tree t) if (set != -1) return set; - /* Get the base object of the reference. */ - inner = t; - while (handled_component_p (inner)) - { - /* If there is a VIEW_CONVERT_EXPR in the chain we cannot use - the type of any component references that wrap it to - determine the alias-set. */ - if (TREE_CODE (inner) == VIEW_CONVERT_EXPR) - t = TREE_OPERAND (inner, 0); - inner = TREE_OPERAND (inner, 0); - } - - /* Handle pointer dereferences here, they can override the - alias-set. */ - if (INDIRECT_REF_P (inner)) - { - set = get_deref_alias_set_1 (TREE_OPERAND (inner, 0)); - if (set != -1) - return set; - } - else if (TREE_CODE (inner) == TARGET_MEM_REF) - return get_deref_alias_set (TMR_OFFSET (inner)); - else if (TREE_CODE (inner) == MEM_REF) - { - set = get_deref_alias_set_1 (TREE_OPERAND (inner, 1)); - if (set != -1) - return set; - } - - /* If the innermost reference is a MEM_REF that has a - conversion embedded treat it like a VIEW_CONVERT_EXPR above, - using the memory access type for determining the alias-set. */ - if (TREE_CODE (inner) == MEM_REF - && TYPE_MAIN_VARIANT (TREE_TYPE (inner)) - != TYPE_MAIN_VARIANT - (TREE_TYPE (TREE_TYPE (TREE_OPERAND (inner, 1))))) - return get_deref_alias_set (TREE_OPERAND (inner, 1)); - - /* Otherwise, pick up the outermost object that we could have a pointer - to, processing conversions as above. */ - while (component_uses_parent_alias_set (t)) - { - t = TREE_OPERAND (t, 0); - STRIP_NOPS (t); - } + /* Get the alias pointer-type to use or the outermost object + that we could have a pointer to. */ + tree ptype = reference_alias_ptr_type_1 (&t); + if (ptype != NULL) + return get_deref_alias_set (ptype); /* If we've already determined the alias set for a decl, just return it. This is necessary for C++ anonymous unions, whose component @@ -2907,16 +2975,13 @@ init_alias_analysis (void) /* Wipe the reg_seen array clean. */ bitmap_clear (reg_seen); - /* Mark all hard registers which may contain an address. - The stack, frame and argument pointers may contain an address. - An argument register which can hold a Pmode value may contain - an address even if it is not in BASE_REGS. - - The address expression is VOIDmode for an argument and - Pmode for other registers. */ - - memcpy (new_reg_base_value, static_reg_base_value, - FIRST_PSEUDO_REGISTER * sizeof (rtx)); + /* Initialize the alias information for this pass. */ + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + if (static_reg_base_value[i]) + { + new_reg_base_value[i] = static_reg_base_value[i]; + bitmap_set_bit (reg_seen, i); + } /* Walk the insns adding values to the new_reg_base_value array. */ for (i = 0; i < rpo_cnt; i++) |