/* Alias analysis for GNU C
- Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
- Free Software Foundation, Inc.
+ Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+ 2007 Free Software Foundation, Inc.
Contributed by John Carr (jfc@mit.edu).
This file is part of GCC.
/* The aliasing API provided here solves related but different problems:
- Say there exists (in c)
+ Say there exists (in c)
struct X {
struct Y y1;
this may be too conservative for some C++ types.
The pass ipa-type-escape does this analysis for the types whose
- instances do not escape across the compilation boundary.
+ instances do not escape across the compilation boundary.
Historically in GCC, these two problems were combined and a single
data structure was used to represent the solution to these
`double'. (However, a store to an `int' cannot alias a `double'
and vice versa.) We indicate this via a tree structure that looks
like:
- struct S
- / \
+ struct S
+ / \
/ \
- |/_ _\|
- int double
+ |/_ _\|
+ int double
(The arrows are directed and point downwards.)
In this situation we say the alias set for `struct S' is the
typedef struct alias_set_entry *alias_set_entry;
static int rtx_equal_for_memref_p (rtx, rtx);
-static rtx find_symbolic_term (rtx);
static int memrefs_conflict_p (int, rtx, int, rtx, HOST_WIDE_INT);
static void record_set (rtx, rtx, void *);
static int base_alias_check (rtx, rtx, enum machine_mode,
return 0;
}
+/* Return true if the first alias set is a subset of the second. */
+
+bool
+alias_set_subset_of (HOST_WIDE_INT set1, HOST_WIDE_INT set2)
+{
+ alias_set_entry ase;
+
+ /* Everything is a subset of the "aliases everything" set. */
+ if (set2 == 0)
+ return true;
+
+ /* Otherwise, check if set1 is a subset of set2. */
+ ase = get_alias_set_entry (set2);
+ if (ase != 0
+ && (splay_tree_lookup (ase->children,
+ (splay_tree_key) set1)))
+ return true;
+ return false;
+}
+
/* Return 1 if the two specified alias sets may conflict. */
int
{
int i;
tree binfo, base_binfo;
-
+
for (binfo = TYPE_BINFO (type), i = 0;
BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
record_alias_subset (superset,
If neither case holds, reject the original base value as invalid.
Note that the following situation is not detected:
- extern int x, y; int *p = &x; p += (&y-&x);
+ extern int x, y; int *p = &x; p += (&y-&x);
ANSI C does not allow computing the difference of addresses
of distinct top level objects. */
/* If a value is known for REGNO, return it. */
-rtx
+rtx
get_reg_known_value (unsigned int regno)
{
if (regno >= FIRST_PSEUDO_REGISTER)
return 1;
}
-/* Given an rtx X, find a SYMBOL_REF or LABEL_REF within
- X and return it, or return 0 if none found. */
-
-static rtx
-find_symbolic_term (rtx x)
-{
- int i;
- enum rtx_code code;
- const char *fmt;
-
- code = GET_CODE (x);
- if (code == SYMBOL_REF || code == LABEL_REF)
- return x;
- if (OBJECT_P (x))
- return 0;
-
- fmt = GET_RTX_FORMAT (code);
- for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
- {
- rtx t;
-
- if (fmt[i] == 'e')
- {
- t = find_symbolic_term (XEXP (x, i));
- if (t != 0)
- return t;
- }
- else if (fmt[i] == 'E')
- break;
- }
- return 0;
-}
-
rtx
find_base_term (rtx x)
{
if (offset)
addr = gen_rtx_PLUS (GET_MODE (addr), XEXP (addr, 0),
- GEN_INT (offset));
+ GEN_INT (offset));
else
addr = XEXP (addr, 0);
addr = canon_rtx (addr);
if (! flag_strict_aliasing)
return NULL_RTX;
- if (MEM_SCALAR_P (mem1) && MEM_IN_STRUCT_P (mem2)
+ if (MEM_ALIAS_SET (mem2)
+ && MEM_SCALAR_P (mem1) && MEM_IN_STRUCT_P (mem2)
&& !varies_p (mem1_addr, 1) && varies_p (mem2_addr, 1))
/* MEM1 is a scalar at a fixed address; MEM2 is a struct at a
varying address. */
return mem1;
- if (MEM_IN_STRUCT_P (mem1) && MEM_SCALAR_P (mem2)
+ if (MEM_ALIAS_SET (mem1)
+ && MEM_IN_STRUCT_P (mem1) && MEM_SCALAR_P (mem2)
&& varies_p (mem1_addr, 1) && !varies_p (mem2_addr, 1))
/* MEM2 is a scalar at a fixed address; MEM1 is a struct at a
varying address. */
/* Unless both have exprs, we can't tell anything. */
if (exprx == 0 || expry == 0)
return 0;
-
+
/* If both are field references, we may be able to determine something. */
if (TREE_CODE (exprx) == COMPONENT_REF
&& TREE_CODE (expry) == COMPONENT_REF
&& nonoverlapping_component_refs_p (exprx, expry))
return 1;
-
+
/* If the field reference test failed, look at the DECLs involved. */
moffsetx = MEM_OFFSET (x);
if (TREE_CODE (exprx) == COMPONENT_REF)
tree fieldcontext = DECL_FIELD_CONTEXT (field);
if (ipa_type_escape_field_does_not_clobber_p (fieldcontext,
TREE_TYPE (field)))
- return 1;
+ return 1;
}
{
tree t = decl_for_component_ref (exprx);
tree fieldcontext = DECL_FIELD_CONTEXT (field);
if (ipa_type_escape_field_does_not_clobber_p (fieldcontext,
TREE_TYPE (field)))
- return 1;
+ return 1;
}
{
tree t = decl_for_component_ref (expry);
return 1;
/* (mem:BLK (scratch)) is a special mechanism to conflict with everything.
- This is used in epilogue deallocation functions. */
+ This is used in epilogue deallocation functions, and in cselib. */
if (GET_MODE (x) == BLKmode && GET_CODE (XEXP (x, 0)) == SCRATCH)
return 1;
if (GET_MODE (mem) == BLKmode && GET_CODE (XEXP (mem, 0)) == SCRATCH)
if (reg_base_value)
VEC_truncate (rtx, reg_base_value, 0);
- VEC_safe_grow (rtx, gc, reg_base_value, maxreg);
- memset (VEC_address (rtx, reg_base_value), 0,
- sizeof (rtx) * VEC_length (rtx, reg_base_value));
+ VEC_safe_grow_cleared (rtx, gc, reg_base_value, maxreg);
new_reg_base_value = XNEWVEC (rtx, maxreg);
reg_seen = XNEWVEC (char, maxreg);
#endif
/* If this insn has a noalias note, process it, Otherwise,
- scan for sets. A simple set will have no side effects
- which could change the base value of any other register. */
+ scan for sets. A simple set will have no side effects
+ which could change the base value of any other register. */
if (GET_CODE (PATTERN (insn)) == SET
&& REG_NOTES (insn) != 0
rtx src = SET_SRC (set);
rtx t;
- if (REG_NOTES (insn) != 0
- && (((note = find_reg_note (insn, REG_EQUAL, 0)) != 0
- && REG_N_SETS (regno) == 1)
- || (note = find_reg_note (insn, REG_EQUIV, NULL_RTX)) != 0)
+ note = find_reg_equal_equiv_note (insn);
+ if (note && REG_NOTE_KIND (note) == REG_EQUAL
+ && REG_N_SETS (regno) != 1)
+ note = NULL_RTX;
+
+ if (note != NULL_RTX
&& GET_CODE (XEXP (note, 0)) != EXPR_LIST
&& ! rtx_varies_p (XEXP (note, 0), 1)
&& ! reg_overlap_mentioned_p (SET_DEST (set),
}
/* Now propagate values from new_reg_base_value to reg_base_value. */
- gcc_assert (maxreg == (unsigned int) max_reg_num());
-
+ gcc_assert (maxreg == (unsigned int) max_reg_num ());
+
for (ui = 0; ui < maxreg; ui++)
{
if (new_reg_base_value[ui]
if (reg_known_value[i] == 0)
reg_known_value[i] = regno_reg_rtx[i + FIRST_PSEUDO_REGISTER];
- /* Simplify the reg_base_value array so that no register refers to
- another register, except to special registers indirectly through
- ADDRESS expressions.
-
- In theory this loop can take as long as O(registers^2), but unless
- there are very long dependency chains it will run in close to linear
- time.
-
- This loop may not be needed any longer now that the main loop does
- a better job at propagating alias information. */
- pass = 0;
- do
- {
- changed = 0;
- pass++;
- for (ui = 0; ui < maxreg; ui++)
- {
- rtx base = VEC_index (rtx, reg_base_value, ui);
- if (base && REG_P (base))
- {
- unsigned int base_regno = REGNO (base);
- if (base_regno == ui) /* register set from itself */
- VEC_replace (rtx, reg_base_value, ui, 0);
- else
- VEC_replace (rtx, reg_base_value, ui,
- VEC_index (rtx, reg_base_value, base_regno));
- changed = 1;
- }
- }
- }
- while (changed && pass < MAX_ALIAS_LOOP_PASSES);
-
/* Clean up. */
free (new_reg_base_value);
new_reg_base_value = 0;