X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Falias.c;h=3ac6848378331cb67f9a5cc0dd99cb100e5b9a94;hp=db8555fdc6a3543d92e589ccef66263090f85185;hb=600380f0c4744b85234a0411a3fb842ef0e248df;hpb=8b435339f60a4c904ba9b263b6f3a67ab2fade30 diff --git a/gcc/alias.c b/gcc/alias.c index db8555fdc6a..3ac68483783 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 - 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. @@ -49,7 +49,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA /* 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; @@ -87,7 +87,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 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 @@ -109,11 +109,11 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA `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 @@ -149,7 +149,6 @@ struct alias_set_entry GTY(()) 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, @@ -293,6 +292,26 @@ insert_subset_children (splay_tree_node node, void *data) 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 @@ -730,7 +749,7 @@ record_component_aliases (tree type) { 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, @@ -1023,7 +1042,7 @@ record_set (rtx dest, rtx set, void *data ATTRIBUTE_UNUSED) 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. */ @@ -1091,7 +1110,7 @@ clear_reg_alias_info (rtx reg) /* If a value is known for REGNO, return it. */ -rtx +rtx get_reg_known_value (unsigned int regno) { if (regno >= FIRST_PSEUDO_REGISTER) @@ -1325,39 +1344,6 @@ rtx_equal_for_memref_p (rtx x, rtx y) 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) { @@ -1620,7 +1606,7 @@ addr_side_effect_eval (rtx addr, int size, int n_refs) 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); @@ -1857,13 +1843,15 @@ fixed_scalar_and_varying_struct_p (rtx mem1, rtx mem2, rtx mem1_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. */ @@ -2001,14 +1989,14 @@ nonoverlapping_memrefs_p (rtx x, rtx y) /* 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) @@ -2020,7 +2008,7 @@ nonoverlapping_memrefs_p (rtx x, rtx y) 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); @@ -2048,7 +2036,7 @@ nonoverlapping_memrefs_p (rtx x, rtx y) 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); @@ -2149,7 +2137,7 @@ true_dependence (rtx mem, enum machine_mode mem_mode, rtx x, 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) @@ -2431,9 +2419,7 @@ init_alias_analysis (void) 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); @@ -2506,8 +2492,8 @@ init_alias_analysis (void) #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 @@ -2526,10 +2512,12 @@ init_alias_analysis (void) 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), @@ -2563,8 +2551,8 @@ init_alias_analysis (void) } /* 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] @@ -2584,38 +2572,6 @@ init_alias_analysis (void) 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;