/* Alias analysis for GNU C
- Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
+ Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
Free Software Foundation, Inc.
Contributed by John Carr (jfc@mit.edu).
static int nonlocal_set_p_1 (rtx *, void *);
static int nonlocal_set_p (rtx);
static void memory_modified_1 (rtx, rtx, void *);
+static void record_alias_subset (HOST_WIDE_INT, HOST_WIDE_INT);
/* Set up all info needed to perform alias analysis on memory references. */
static inline int
mems_in_disjoint_alias_sets_p (rtx mem1, rtx mem2)
{
-#ifdef ENABLE_CHECKING
/* Perform a basic sanity check. Namely, that there are no alias sets
if we're not using strict aliasing. This helps to catch bugs
whereby someone uses PUT_CODE, but doesn't clear MEM_ALIAS_SET, or
gen_rtx_MEM, and the MEM_ALIAS_SET is not cleared. If we begin to
use alias sets to indicate that spilled registers cannot alias each
other, we might need to remove this check. */
- if (! flag_strict_aliasing
- && (MEM_ALIAS_SET (mem1) != 0 || MEM_ALIAS_SET (mem2) != 0))
- abort ();
-#endif
+ gcc_assert (flag_strict_aliasing
+ || (!MEM_ALIAS_SET (mem1) && !MEM_ALIAS_SET (mem2)));
return ! alias_sets_conflict_p (MEM_ALIAS_SET (mem1), MEM_ALIAS_SET (mem2));
}
static tree
find_base_decl (tree t)
{
- tree d0, d1, d2;
+ tree d0, d1;
if (t == 0 || t == error_mark_node || ! POINTER_TYPE_P (TREE_TYPE (t)))
return 0;
/* If this is a declaration, return it. */
- if (TREE_CODE_CLASS (TREE_CODE (t)) == 'd')
+ if (DECL_P (t))
return t;
/* Handle general expressions. It would be nice to deal with
same, then `a->f' and `b->f' are also the same. */
switch (TREE_CODE_CLASS (TREE_CODE (t)))
{
- case '1':
+ case tcc_unary:
return find_base_decl (TREE_OPERAND (t, 0));
- case '2':
+ case tcc_binary:
/* Return 0 if found in neither or both are the same. */
d0 = find_base_decl (TREE_OPERAND (t, 0));
d1 = find_base_decl (TREE_OPERAND (t, 1));
else
return 0;
- case '3':
- d0 = find_base_decl (TREE_OPERAND (t, 0));
- d1 = find_base_decl (TREE_OPERAND (t, 1));
- d2 = find_base_decl (TREE_OPERAND (t, 2));
-
- /* Set any nonzero values from the last, then from the first. */
- if (d1 == 0) d1 = d2;
- if (d0 == 0) d0 = d1;
- if (d1 == 0) d1 = d0;
- if (d2 == 0) d2 = d1;
-
- /* At this point all are nonzero or all are zero. If all three are the
- same, return it. Otherwise, return zero. */
- return (d0 == d1 && d1 == d2) ? d0 : 0;
-
default:
return 0;
}
}
-/* Return 1 if all the nested component references handled by
- get_inner_reference in T are such that we can address the object in T. */
+/* 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.
-int
-can_address_p (tree 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 (tree t)
{
- /* If we're at the end, it is vacuously addressable. */
- if (! handled_component_p (t))
- return 1;
+ while (1)
+ {
+ /* If we're at the end, it vacuously uses its own alias set. */
+ if (!handled_component_p (t))
+ return false;
- /* Bitfields are never addressable. */
- else if (TREE_CODE (t) == BIT_FIELD_REF)
- return 0;
+ switch (TREE_CODE (t))
+ {
+ case COMPONENT_REF:
+ if (DECL_NONADDRESSABLE_P (TREE_OPERAND (t, 1)))
+ return true;
+ break;
- /* Fields are addressable unless they are marked as nonaddressable or
- the containing type has alias set 0. */
- else if (TREE_CODE (t) == COMPONENT_REF
- && ! DECL_NONADDRESSABLE_P (TREE_OPERAND (t, 1))
- && get_alias_set (TREE_TYPE (TREE_OPERAND (t, 0))) != 0
- && can_address_p (TREE_OPERAND (t, 0)))
- return 1;
+ case ARRAY_REF:
+ case ARRAY_RANGE_REF:
+ if (TYPE_NONALIASED_COMPONENT (TREE_TYPE (TREE_OPERAND (t, 0))))
+ return true;
+ break;
- /* Likewise for arrays. */
- else if ((TREE_CODE (t) == ARRAY_REF || TREE_CODE (t) == ARRAY_RANGE_REF)
- && ! TYPE_NONALIASED_COMPONENT (TREE_TYPE (TREE_OPERAND (t, 0)))
- && get_alias_set (TREE_TYPE (TREE_OPERAND (t, 0))) != 0
- && can_address_p (TREE_OPERAND (t, 0)))
- return 1;
+ case REALPART_EXPR:
+ case IMAGPART_EXPR:
+ break;
- return 0;
+ default:
+ /* Bitfields and casts are never addressable. */
+ return true;
+ }
+
+ t = TREE_OPERAND (t, 0);
+ if (get_alias_set (TREE_TYPE (t)) == 0)
+ return true;
+ }
}
/* Return the alias set for T, which may be either a type or an
}
/* Check for accesses through restrict-qualified pointers. */
- if (TREE_CODE (inner) == INDIRECT_REF)
+ if (INDIRECT_REF_P (inner))
{
tree decl = find_base_decl (TREE_OPERAND (inner, 0));
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. */
+ by the restricted pointer. */
DECL_POINTER_ALIAS_SET (decl)
= pointed_to_alias_set;
else
/* Otherwise, pick up the outermost object that we could have a pointer
to, processing conversions as above. */
- while (handled_component_p (t) && ! can_address_p (t))
+ while (component_uses_parent_alias_set (t))
{
t = TREE_OPERAND (t, 0);
STRIP_NOPS (t);
It is illegal for SUPERSET to be zero; everything is implicitly a
subset of alias set zero. */
-void
+static void
record_alias_subset (HOST_WIDE_INT superset, HOST_WIDE_INT subset)
{
alias_set_entry superset_entry;
if (superset == subset)
return;
- if (superset == 0)
- abort ();
+ gcc_assert (superset);
superset_entry = get_alias_set_entry (superset);
if (superset_entry == 0)
regno = REGNO (dest);
- if (regno >= VARRAY_SIZE (reg_base_value))
- abort ();
+ gcc_assert (regno < VARRAY_SIZE (reg_base_value));
/* If this spans multiple hard registers, then we must indicate that every
register has an unusable value. */
contain anything but integers and other rtx's,
except for within LABEL_REFs and SYMBOL_REFs. */
default:
- abort ();
+ gcc_unreachable ();
}
}
return 1;
where SIZE is the size in bytes of the memory reference. If ADDR
is not modified by the memory reference then ADDR is returned. */
-rtx
+static rtx
addr_side_effect_eval (rtx addr, int size, int n_refs)
{
int offset = 0;
aliases_everything_p (rtx mem)
{
if (GET_CODE (XEXP (mem, 0)) == AND)
- /* If the address is an AND, its very hard to know at what it is
+ /* If the address is an AND, it's very hard to know at what it is
actually pointing. */
return 1;
moffsetx = adjust_offset_for_component_ref (exprx, moffsetx);
exprx = t;
}
- else if (TREE_CODE (exprx) == INDIRECT_REF)
+ else if (INDIRECT_REF_P (exprx))
{
exprx = TREE_OPERAND (exprx, 0);
if (flag_argument_noalias < 2
moffsety = adjust_offset_for_component_ref (expry, moffsety);
expry = t;
}
- else if (TREE_CODE (expry) == INDIRECT_REF)
+ else if (INDIRECT_REF_P (expry))
{
expry = TREE_OPERAND (expry, 0);
if (flag_argument_noalias < 2
/* 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 abort. */
+ but stupid user tricks can produce them, so don't die. */
if (MEM_READONLY_P (x))
return 0;
/* 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 abort. */
+ but stupid user tricks can produce them, so don't die. */
if (MEM_READONLY_P (x))
return 0;
/* Return true when INSN possibly modify memory contents of MEM
- (ie address can be modified). */
+ (i.e. address can be modified). */
bool
memory_modified_in_insn_p (rtx mem, rtx insn)
{
new_reg_base_value = xmalloc (maxreg * sizeof (rtx));
reg_seen = xmalloc (maxreg);
- if (! reload_completed && flag_old_unroll_loops)
- {
- alias_invariant = ggc_calloc (maxreg, sizeof (rtx));
- alias_invariant_size = maxreg;
- }
/* The basic idea is that each pass through this loop will use the
"constant" information from the previous pass to propagate alias
}
/* Now propagate values from new_reg_base_value to reg_base_value. */
- if (maxreg != (unsigned int) max_reg_num())
- abort ();
+ gcc_assert (maxreg == (unsigned int) max_reg_num());
+
for (ui = 0; ui < maxreg; ui++)
{
if (new_reg_base_value[ui]