diff options
Diffstat (limited to 'gcc/alias.c')
-rw-r--r-- | gcc/alias.c | 119 |
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))); |