aboutsummaryrefslogtreecommitdiff
path: root/gcc/alias.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/alias.c')
-rw-r--r--gcc/alias.c119
1 files changed, 88 insertions, 31 deletions
diff --git a/gcc/alias.c b/gcc/alias.c
index 85bce38c70f..060d1a5e076 100644
--- a/gcc/alias.c
+++ b/gcc/alias.c
@@ -25,7 +25,6 @@ Boston, MA 02111-1307, USA. */
#include "tree.h"
#include "tm_p.h"
#include "function.h"
-#include "insn-flags.h"
#include "expr.h"
#include "regs.h"
#include "hard-reg-set.h"
@@ -95,6 +94,8 @@ static void record_set PARAMS ((rtx, rtx, void *));
static rtx find_base_term PARAMS ((rtx));
static int base_alias_check PARAMS ((rtx, rtx, enum machine_mode,
enum machine_mode));
+static int handled_component_p PARAMS ((tree));
+static int can_address_p PARAMS ((tree));
static rtx find_base_value PARAMS ((rtx));
static int mems_in_disjoint_alias_sets_p PARAMS ((rtx, rtx));
static int insert_subset_children PARAMS ((splay_tree_node, void*));
@@ -309,6 +310,12 @@ int
objects_must_conflict_p (t1, t2)
tree t1, t2;
{
+ /* If neither has a type specified, we don't know if they'll conflict
+ because we may be using them to store objects of various types, for
+ example the argument and local variables areas of inlined functions. */
+ if (t1 == 0 && t2 == 0)
+ return 0;
+
/* If one or the other has readonly fields or is readonly,
then they may not conflict. */
if ((t1 != 0 && readonly_fields_p (t1))
@@ -394,6 +401,58 @@ find_base_decl (t)
}
}
+/* Return 1 if T is an expression that get_inner_reference handles. */
+
+static int
+handled_component_p (t)
+ tree t;
+{
+ switch (TREE_CODE (t))
+ {
+ case BIT_FIELD_REF:
+ case COMPONENT_REF:
+ case ARRAY_REF:
+ case NON_LVALUE_EXPR:
+ return 1;
+
+ case NOP_EXPR:
+ case CONVERT_EXPR:
+ return (TYPE_MODE (TREE_TYPE (t))
+ == TYPE_MODE (TREE_TYPE (TREE_OPERAND (t, 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. */
+
+static int
+can_address_p (t)
+ tree t;
+{
+ /* If we're at the end, it is vacuously addressable. */
+ if (! handled_component_p (t))
+ return 1;
+
+ /* Bitfields are never addressable. */
+ else if (TREE_CODE (t) == BIT_FIELD_REF)
+ return 0;
+
+ else if (TREE_CODE (t) == COMPONENT_REF
+ && ! DECL_NONADDRESSABLE_P (TREE_OPERAND (t, 1))
+ && can_address_p (TREE_OPERAND (t, 0)))
+ return 1;
+
+ else if (TREE_CODE (t) == ARRAY_REF
+ && ! TYPE_NONALIASED_COMPONENT (TREE_TYPE (TREE_OPERAND (t, 0)))
+ && can_address_p (TREE_OPERAND (t, 0)))
+ return 1;
+
+ return 0;
+}
+
/* Return the alias set for T, which may be either a type or an
expression. Call language-specific routine for help, if needed. */
@@ -433,35 +492,9 @@ get_alias_set (t)
/* Now loop the same way as get_inner_reference and get the alias
set to use. Pick up the outermost object that we could have
a pointer to. */
- while (1)
- {
- /* Unnamed bitfields are not an addressable object. */
- if (TREE_CODE (t) == BIT_FIELD_REF)
- ;
- else if (TREE_CODE (t) == COMPONENT_REF)
- {
- if (! DECL_NONADDRESSABLE_P (TREE_OPERAND (t, 1)))
- /* Stop at an adressable decl. */
- break;
- }
- else if (TREE_CODE (t) == ARRAY_REF)
- {
- if (! TYPE_NONALIASED_COMPONENT
- (TREE_TYPE (TREE_OPERAND (t, 0))))
- /* Stop at an addresssable array element. */
- break;
- }
- else if (TREE_CODE (t) != NON_LVALUE_EXPR
- && ! ((TREE_CODE (t) == NOP_EXPR
- || TREE_CODE (t) == CONVERT_EXPR)
- && (TYPE_MODE (TREE_TYPE (t))
- == TYPE_MODE (TREE_TYPE (TREE_OPERAND (t, 0))))))
- /* Stop if not one of above and not mode-preserving conversion. */
- break;
+ while (handled_component_p (t) && ! can_address_p (t))
+ t = TREE_OPERAND (t, 0);
- t = TREE_OPERAND (t, 0);
- }
-
if (TREE_CODE (t) == INDIRECT_REF)
{
/* Check for accesses through restrict-qualified pointers. */
@@ -904,6 +937,21 @@ record_base_value (regno, val, invariant)
reg_base_value[regno] = find_base_value (val);
}
+/* Clear alias info for a register. This is used if an RTL transformation
+ changes the value of a register. This is used in flow by AUTO_INC_DEC
+ optimizations. We don't need to clear reg_base_value, since flow only
+ changes the offset. */
+
+void
+clear_reg_alias_info (reg)
+ rtx reg;
+{
+ unsigned int regno = REGNO (reg);
+
+ if (regno < reg_known_value_size && regno >= FIRST_PSEUDO_REGISTER)
+ reg_known_value[regno] = reg;
+}
+
/* Returns a canonical version of X, from the point of view alias
analysis. (For example, if X is a MEM whose address is a register,
and the register has a known value (say a SYMBOL_REF), then a MEM
@@ -993,6 +1041,9 @@ rtx_equal_for_memref_p (x, y)
/* Some RTL can be compared without a recursive examination. */
switch (code)
{
+ case VALUE:
+ return CSELIB_VAL_PTR (x) == CSELIB_VAL_PTR (y);
+
case REG:
return REGNO (x) == REGNO (y);
@@ -1062,6 +1113,12 @@ rtx_equal_for_memref_p (x, y)
return 0;
break;
+ /* This can happen for asm operands. */
+ case 's':
+ if (strcmp (XSTR (x, i), XSTR (y, i)))
+ return 0;
+ break;
+
/* This can happen for an asm which clobbers memory. */
case '0':
break;
@@ -2242,6 +2299,7 @@ init_alias_analysis ()
&& REG_N_SETS (regno) == 1)
|| (note = find_reg_note (insn, REG_EQUIV, NULL_RTX)) != 0)
&& GET_CODE (XEXP (note, 0)) != EXPR_LIST
+ && ! rtx_varies_p (XEXP (note, 0), 1)
&& ! reg_overlap_mentioned_p (SET_DEST (set), XEXP (note, 0)))
{
reg_known_value[regno] = XEXP (note, 0);
@@ -2255,8 +2313,7 @@ init_alias_analysis ()
&& GET_CODE (XEXP (src, 1)) == CONST_INT)
{
rtx op0 = XEXP (src, 0);
- if (reg_known_value[REGNO (op0)])
- op0 = reg_known_value[REGNO (op0)];
+ op0 = reg_known_value[REGNO (op0)];
reg_known_value[regno]
= plus_constant_for_output (op0,
INTVAL (XEXP (src, 1)));