summaryrefslogtreecommitdiff
path: root/gcc/alias.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/alias.c')
-rw-r--r--gcc/alias.c243
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++)