X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Falias.c;h=2ebde8d73a57f5be383c50a84213394ec346b869;hb=4514949a22403811d4d4de86cd83a29f2e8693db;hp=1ba1ce366d85521e76f40d8bd59d4508e78f7e48;hpb=a80f1c6c4b027d46539739592c836cd13f8193bb;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/alias.c b/gcc/alias.c index 1ba1ce366d8..2ebde8d73a5 100644 --- a/gcc/alias.c +++ b/gcc/alias.c @@ -1,6 +1,6 @@ /* 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. @@ -133,6 +133,10 @@ struct alias_set_entry GTY(()) /* The alias set number, as stored in MEM_ALIAS_SET. */ alias_set_type alias_set; + /* Nonzero if would have a child of zero: this effectively makes this + alias set the same as alias set zero. */ + int has_zero_child; + /* The children of the alias set. These are not just the immediate children, but, in fact, all descendants. So, if we have: @@ -141,10 +145,6 @@ struct alias_set_entry GTY(()) continuing our example above, the children here will be all of `int', `double', `float', and `struct S'. */ splay_tree GTY((param1_is (int), param2_is (int))) children; - - /* Nonzero if would have a child of zero: this effectively makes this - alias set the same as alias set zero. */ - int has_zero_child; }; typedef struct alias_set_entry *alias_set_entry; @@ -164,11 +164,9 @@ static int aliases_everything_p (const_rtx); static bool nonoverlapping_component_refs_p (const_tree, const_tree); static tree decl_for_component_ref (tree); static rtx adjust_offset_for_component_ref (tree, rtx); -static int nonoverlapping_memrefs_p (const_rtx, const_rtx); 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. */ @@ -306,8 +304,9 @@ alias_set_subset_of (alias_set_type set1, alias_set_type set2) /* 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))) + && ((ase->has_zero_child && set1 == 0) + || splay_tree_lookup (ase->children, + (splay_tree_key) set1))) return true; return false; } @@ -344,6 +343,43 @@ alias_sets_conflict_p (alias_set_type set1, alias_set_type set2) 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 @@ -525,7 +561,12 @@ get_alias_set (tree t) /* Check for accesses through restrict-qualified pointers. */ if (INDIRECT_REF_P (inner)) { - tree decl = find_base_decl (TREE_OPERAND (inner, 0)); + 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)) { @@ -579,13 +620,6 @@ get_alias_set (tree t) return 0; } - /* For non-addressable fields we return the alias set of the - outermost object that could have its address taken. If this - is an SFT use the precomputed value. */ - if (TREE_CODE (t) == STRUCT_FIELD_TAG - && SFT_NONADDRESSABLE_P (t)) - return SFT_ALIAS_SET (t); - /* Otherwise, pick up the outermost object that we could have a pointer to, processing conversions as above. */ while (component_uses_parent_alias_set (t)) @@ -606,11 +640,26 @@ get_alias_set (tree t) } /* Variant qualifiers don't affect the alias set, so get the main - variant. If this is a type with a known alias set, return it. */ + variant. Always use the canonical type as well. + If this is a type with a known alias set, return it. */ t = TYPE_MAIN_VARIANT (t); + if (TYPE_CANONICAL (t)) + t = TYPE_CANONICAL (t); if (TYPE_ALIAS_SET_KNOWN_P (t)) return TYPE_ALIAS_SET (t); + /* We don't want to set TYPE_ALIAS_SET for incomplete types. */ + if (!COMPLETE_TYPE_P (t)) + { + /* For arrays with unknown size the conservative answer is the + alias set of the element type. */ + if (TREE_CODE (t) == ARRAY_TYPE) + return get_alias_set (TREE_TYPE (t)); + + /* But return zero as a conservative answer for incomplete types. */ + return 0; + } + /* See if the language has special handling for this type. */ set = lang_hooks.get_alias_set (t); if (set != -1) @@ -630,6 +679,18 @@ get_alias_set (tree t) else if (TREE_CODE (t) == VECTOR_TYPE) set = get_alias_set (TREE_TYPE (t)); + /* Unless the language specifies otherwise, treat array types the + same as their components. This avoids the asymmetry we get + through recording the components. Consider accessing a + character(kind=1) through a reference to a character(kind=1)[1:1]. + Or consider if we want to assign integer(kind=4)[0:D.1387] and + integer(kind=4)[4] the same alias set or not. + Just be pragmatic here and make sure the array and its element + type get the same alias set assigned. */ + else if (TREE_CODE (t) == ARRAY_TYPE + && !TYPE_NONALIASED_COMPONENT (t)) + set = get_alias_set (TREE_TYPE (t)); + else /* Otherwise make a new alias set for this type. */ set = new_alias_set (); @@ -673,7 +734,7 @@ new_alias_set (void) 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; @@ -691,7 +752,7 @@ record_alias_subset (alias_set_type superset, alias_set_type subset) { /* Create an entry for the SUPERSET, so that we have a place to attach the SUBSET. */ - superset_entry = ggc_alloc (sizeof (struct alias_set_entry)); + superset_entry = GGC_NEW (struct alias_set_entry); superset_entry->alias_set = superset; superset_entry->children = splay_tree_new_ggc (splay_tree_compare_ints); @@ -723,9 +784,8 @@ record_alias_subset (alias_set_type superset, alias_set_type subset) /* Record that component types of TYPE, if any, are part of that type for aliasing purposes. For record types, we only record component types - for fields that are marked addressable. For array types, we always - record the component types, so the front end should not call this - function if the individual component aren't addressable. */ + for fields that are not marked non-addressable. For array types, we + only record the component type if it is not marked non-aliased. */ void record_component_aliases (tree type) @@ -738,11 +798,6 @@ record_component_aliases (tree type) switch (TREE_CODE (type)) { - case ARRAY_TYPE: - if (! TYPE_NONALIASED_COMPONENT (type)) - record_alias_subset (superset, get_alias_set (TREE_TYPE (type))); - break; - case RECORD_TYPE: case UNION_TYPE: case QUAL_UNION_TYPE: @@ -758,7 +813,7 @@ record_component_aliases (tree type) get_alias_set (BINFO_TYPE (base_binfo))); } for (field = TYPE_FIELDS (type); field != 0; field = TREE_CHAIN (field)) - if (TREE_CODE (field) == FIELD_DECL && ! DECL_NONADDRESSABLE_P (field)) + if (TREE_CODE (field) == FIELD_DECL && !DECL_NONADDRESSABLE_P (field)) record_alias_subset (superset, get_alias_set (TREE_TYPE (field))); break; @@ -766,6 +821,9 @@ record_component_aliases (tree type) record_alias_subset (superset, get_alias_set (TREE_TYPE (type))); break; + /* VECTOR_TYPE and ARRAY_TYPE share the alias set with their + element type. */ + default: break; } @@ -814,6 +872,11 @@ find_base_value (rtx src) { unsigned int regno; +#if defined (FIND_BASE_TERM) + /* Try machine-dependent ways to find the base term. */ + src = FIND_BASE_TERM (src); +#endif + switch (GET_CODE (src)) { case SYMBOL_REF: @@ -1381,6 +1444,9 @@ find_base_term (rtx x) return 0; /* Fall through. */ 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 PLUS: case MINUS: { @@ -1492,26 +1558,27 @@ base_alias_check (rtx x, rtx y, enum machine_mode x_mode, 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, @@ -1959,7 +2026,7 @@ adjust_offset_for_component_ref (tree x, rtx offset) /* Return nonzero if we can determine the exprs corresponding to memrefs X and Y and they do not overlap. */ -static int +int nonoverlapping_memrefs_p (const_rtx x, const_rtx y) { tree exprx = MEM_EXPR (x), expry = MEM_EXPR (y); @@ -2393,8 +2460,8 @@ init_alias_analysis (void) timevar_push (TV_ALIAS_ANALYSIS); reg_known_value_size = maxreg - FIRST_PSEUDO_REGISTER; - reg_known_value = ggc_calloc (reg_known_value_size, sizeof (rtx)); - reg_known_equiv_p = xcalloc (reg_known_value_size, sizeof (bool)); + reg_known_value = GGC_CNEWVEC (rtx, reg_known_value_size); + reg_known_equiv_p = XCNEWVEC (bool, reg_known_value_size); /* If we have memory allocated from the previous run, use it. */ if (old_reg_base_value)