/* Alias analysis for GNU C
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
- 2007 Free Software Foundation, Inc.
+ 2007, 2008, 2009 Free Software Foundation, Inc.
Contributed by John Carr (jfc@mit.edu).
This file is part of GCC.
However, this is no actual entry for alias set zero. It is an
error to attempt to explicitly construct a subset of zero. */
-struct alias_set_entry GTY(())
-{
+struct GTY(()) alias_set_entry {
/* The alias set number, as stored in MEM_ALIAS_SET. */
alias_set_type alias_set;
static int write_dependence_p (const_rtx, const_rtx, int);
static void memory_modified_1 (rtx, const_rtx, void *);
-static void record_alias_subset (alias_set_type, alias_set_type);
/* Set up all info needed to perform alias analysis on memory references. */
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
if (t == 0 || t == error_mark_node || ! POINTER_TYPE_P (TREE_TYPE (t)))
return 0;
+ if (TREE_CODE (t) == SSA_NAME)
+ t = SSA_NAME_VAR (t);
+
/* If this is a declaration, return it. If T is based on a restrict
qualified decl, return that decl. */
if (DECL_P (t))
}
}
+/* Return the alias set for the memory pointed to by T, which may be
+ either a type or an expression. Return -1 if there is nothing
+ special about dereferencing 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;
+
+ if (! TYPE_P (t))
+ {
+ tree decl = find_base_decl (t);
+
+ if (decl && DECL_POINTER_ALIAS_SET_KNOWN_P (decl))
+ {
+ /* If we haven't computed the actual alias set, do it now. */
+ if (DECL_POINTER_ALIAS_SET (decl) == -2)
+ {
+ tree pointed_to_type = TREE_TYPE (TREE_TYPE (decl));
+
+ /* No two restricted pointers can point at the same thing.
+ However, a restricted pointer can point at the same thing
+ as an unrestricted pointer, if that unrestricted pointer
+ is based on the restricted pointer. So, we make the
+ alias set for the restricted pointer a subset of the
+ alias set for the type pointed to by the type of the
+ decl. */
+ alias_set_type pointed_to_alias_set
+ = get_alias_set (pointed_to_type);
+
+ if (pointed_to_alias_set == 0)
+ /* It's not legal to make a subset of alias set zero. */
+ DECL_POINTER_ALIAS_SET (decl) = 0;
+ else if (AGGREGATE_TYPE_P (pointed_to_type))
+ /* For an aggregate, we must treat the restricted
+ pointer the same as an ordinary pointer. If we
+ were to make the type pointed to by the
+ restricted pointer a subset of the pointed-to
+ type, then we would believe that other subsets
+ of the pointed-to type (such as fields of that
+ type) do not conflict with the type pointed to
+ by the restricted pointer. */
+ DECL_POINTER_ALIAS_SET (decl)
+ = pointed_to_alias_set;
+ else
+ {
+ DECL_POINTER_ALIAS_SET (decl) = new_alias_set ();
+ record_alias_subset (pointed_to_alias_set,
+ DECL_POINTER_ALIAS_SET (decl));
+ }
+ }
+
+ /* We use the alias set indicated in the declaration. */
+ return DECL_POINTER_ALIAS_SET (decl);
+ }
+
+ /* Now all we care about is the type. */
+ t = TREE_TYPE (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))
+ return 0;
+
+ return -1;
+}
+
+/* Return the alias set for the memory pointed to by T, which may be
+ either a type or an expression. */
+
+alias_set_type
+get_deref_alias_set (tree t)
+{
+ alias_set_type set = get_deref_alias_set_1 (t);
+
+ /* Fall back to the alias-set of the pointed-to type. */
+ if (set == -1)
+ {
+ if (! TYPE_P (t))
+ t = TREE_TYPE (t);
+ set = get_alias_set (TREE_TYPE (t));
+ }
+
+ return set;
+}
+
/* Return the alias set for T, which may be either a type or an
expression. Call language-specific routine for help, if needed. */
STRIP_NOPS (inner);
}
- /* Check for accesses through restrict-qualified pointers. */
if (INDIRECT_REF_P (inner))
{
- tree decl;
-
- if (TREE_CODE (TREE_OPERAND (inner, 0)) == SSA_NAME)
- decl = SSA_NAME_VAR (TREE_OPERAND (inner, 0));
- else
- decl = find_base_decl (TREE_OPERAND (inner, 0));
-
- if (decl && DECL_POINTER_ALIAS_SET_KNOWN_P (decl))
- {
- /* If we haven't computed the actual alias set, do it now. */
- if (DECL_POINTER_ALIAS_SET (decl) == -2)
- {
- tree pointed_to_type = TREE_TYPE (TREE_TYPE (decl));
-
- /* No two restricted pointers can point at the same thing.
- However, a restricted pointer can point at the same thing
- as an unrestricted pointer, if that unrestricted pointer
- is based on the restricted pointer. So, we make the
- alias set for the restricted pointer a subset of the
- alias set for the type pointed to by the type of the
- decl. */
- alias_set_type pointed_to_alias_set
- = get_alias_set (pointed_to_type);
-
- if (pointed_to_alias_set == 0)
- /* It's not legal to make a subset of alias set zero. */
- DECL_POINTER_ALIAS_SET (decl) = 0;
- else if (AGGREGATE_TYPE_P (pointed_to_type))
- /* For an aggregate, we must treat the restricted
- pointer the same as an ordinary pointer. If we
- were to make the type pointed to by the
- restricted pointer a subset of the pointed-to
- type, then we would believe that other subsets
- of the pointed-to type (such as fields of that
- type) do not conflict with the type pointed to
- by the restricted pointer. */
- DECL_POINTER_ALIAS_SET (decl)
- = pointed_to_alias_set;
- else
- {
- DECL_POINTER_ALIAS_SET (decl) = new_alias_set ();
- record_alias_subset (pointed_to_alias_set,
- DECL_POINTER_ALIAS_SET (decl));
- }
- }
-
- /* We use the alias set indicated in the declaration. */
- return DECL_POINTER_ALIAS_SET (decl);
- }
-
- /* 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. */
- else if (TREE_CODE (TREE_TYPE (inner)) == VOID_TYPE
- || (TYPE_REF_CAN_ALIAS_ALL
- (TREE_TYPE (TREE_OPERAND (inner, 0)))))
- return 0;
+ set = get_deref_alias_set_1 (TREE_OPERAND (inner, 0));
+ if (set != -1)
+ return set;
}
/* Otherwise, pick up the outermost object that we could have a pointer
It is illegal for SUPERSET to be zero; everything is implicitly a
subset of alias set zero. */
-static void
+void
record_alias_subset (alias_set_type superset, alias_set_type subset)
{
alias_set_entry superset_entry;
return x;
return 0;
+ case LO_SUM:
+ /* The standard form is (lo_sum reg sym) so look only at the
+ second operand. */
+ return find_base_term (XEXP (x, 1));
+
case CONST:
x = XEXP (x, 0);
if (GET_CODE (x) != PLUS && GET_CODE (x) != MINUS)
return 0;
/* Fall through. */
- case LO_SUM:
case PLUS:
case MINUS:
{
if (rtx_equal_p (x_base, y_base))
return 1;
- /* The base addresses of the read and write are different expressions.
- If they are both symbols and they are not accessed via AND, there is
- no conflict. We can bring knowledge of object alignment into play
- here. For example, on alpha, "char a, b;" can alias one another,
- though "char a; long b;" cannot. */
+ /* The base addresses are different expressions. If they are not accessed
+ via AND, there is no conflict. We can bring knowledge of object
+ alignment into play here. For example, on alpha, "char a, b;" can
+ alias one another, though "char a; long b;" cannot. AND addesses may
+ implicitly alias surrounding objects; i.e. unaligned access in DImode
+ via AND address can alias all surrounding object types except those
+ with aligment 8 or higher. */
+ if (GET_CODE (x) == AND && GET_CODE (y) == AND)
+ return 1;
+ if (GET_CODE (x) == AND
+ && (GET_CODE (XEXP (x, 1)) != CONST_INT
+ || (int) GET_MODE_UNIT_SIZE (y_mode) < -INTVAL (XEXP (x, 1))))
+ return 1;
+ if (GET_CODE (y) == AND
+ && (GET_CODE (XEXP (y, 1)) != CONST_INT
+ || (int) GET_MODE_UNIT_SIZE (x_mode) < -INTVAL (XEXP (y, 1))))
+ return 1;
+
+ /* Differing symbols not accessed via AND never alias. */
if (GET_CODE (x_base) != ADDRESS && GET_CODE (y_base) != ADDRESS)
- {
- if (GET_CODE (x) == AND && GET_CODE (y) == AND)
- return 1;
- if (GET_CODE (x) == AND
- && (GET_CODE (XEXP (x, 1)) != CONST_INT
- || (int) GET_MODE_UNIT_SIZE (y_mode) < -INTVAL (XEXP (x, 1))))
- return 1;
- if (GET_CODE (y) == AND
- && (GET_CODE (XEXP (y, 1)) != CONST_INT
- || (int) GET_MODE_UNIT_SIZE (x_mode) < -INTVAL (XEXP (y, 1))))
- return 1;
- /* Differing symbols never alias. */
- return 0;
- }
+ return 0;
/* If one address is a stack reference there can be no alias:
stack references using different base registers do not alias,
Variant of true_dependence which assumes MEM has already been
canonicalized (hence we no longer do that here).
The mem_addr argument has been added, since true_dependence computed
- this value prior to canonicalizing. */
+ this value prior to canonicalizing.
+ If x_addr is non-NULL, it is used in preference of XEXP (x, 0). */
int
canon_true_dependence (const_rtx mem, enum machine_mode mem_mode, rtx mem_addr,
- const_rtx x, bool (*varies) (const_rtx, bool))
+ const_rtx x, rtx x_addr, bool (*varies) (const_rtx, bool))
{
- rtx x_addr;
-
if (MEM_VOLATILE_P (x) && MEM_VOLATILE_P (mem))
return 1;
if (nonoverlapping_memrefs_p (x, mem))
return 0;
- x_addr = get_addr (XEXP (x, 0));
+ if (! x_addr)
+ x_addr = get_addr (XEXP (x, 0));
if (! base_alias_check (x_addr, mem_addr, GET_MODE (x), mem_mode))
return 0;