diff options
author | kenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4> | 2000-05-31 18:37:31 +0000 |
---|---|---|
committer | kenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4> | 2000-05-31 18:37:31 +0000 |
commit | f7c44134031628fa9dd82ae7920772ea4efbe3f4 (patch) | |
tree | b0b7fe92ad1922c85f0e4c70693ee5b33b128261 /gcc/alias.c | |
parent | 1101b60ee4e306784bdd2c3ecba9a4460078c1d8 (diff) | |
download | gcc-f7c44134031628fa9dd82ae7920772ea4efbe3f4.tar.gz |
* Makefile.in (c-decl.o): Depend on rtl.h and expr.h.
* alias.c (struct alias_entry): alias_set is HOST_WIDE_INT.
(REG_BASE_VALUE): Remove unneeded cast to unsigned.
(get_alias_set_entry): ALIAS_SET arg is HOST_WIDE_INT.
(find_base_decl): New function, from c_find_base_decl in c-common.c.
(new_alias_set): Moved from tree.c; return is HOST_WIDE_INT.
(get_alias_set): Likewise.
Major rework to do more things and allow language-specific code
to just handle special-cases.
(record_alias_subset): Args are HOST_WIDE_INT.
(record_component_alias): Local vars are HOST_WIDE_INT.
Don't handle COMPLEX_EXPR.
(get_varargs_alias_set): Moved from builtins.c.
(get_frame_alias_set): New function.
* builtins.c (expand_builtin_return_address): Use frame alias set.
(expand_builtin_setjmp, expand_builtin_longjmp): Use alias set
for setjmp buffer.
(get_memory_rtx): Rework to use set_mem_attributes.
(get_varargs_alias_set): Deleted from here.
* c-common.c (c_apply_type_quals_to_decl): Alias sets now HOST_WIDE_INT.
(c_find_base_decl): Deleted from here.
(c_get_alias_set): Remove many cases and rework to just handle
C-specific cases.
* c-common.h (c_get_alias_set): Returns HOST_WIDE_INT.
* c-decl.c (rtl.h, expr.h): Now included.
(init_decl_processing): Call record_component_aliases on array types.
(grokdeclarator): Likewise.
Set TREE_ADDRESSABLE for all fields that are not bitfields.
* c-typeck.c (common_type): Call record_component_aliases for array.
* caller-save.c (setup_save_areas): Rework register loop for unsigned.
Set all save areas to the frame alias set.
* calls.c (initialie_argument_information): Call set_mem_attributes.
(compute_argument_addresses, expand_call): Likewise.
* explow.c (set_mem_attributes): New function.
(stabilize): Use MEM_COPY_ATTRIBUTES and force_reg.
* expr.c (struct move_by_pieces): Remove {to,from}_{struct,readonly}.
LEN and OFFSET now HOST_WIDE_INT.
(clear_by_pieces): Similar changes.
(move_by_pieces): LEN now HOST_WIDE_INT; don't set deleted fields.
(move_by_pieces_ninsns): Now returns unsigned HOST_WIDE_INT.
(move_by_pieces_1): Don't use deleted fields, use MEM_COPY_ATTRIBUTES.
(clear_by_pieces_1): Likewise.
(emit_push_insn): Call set_mem_attributes.
(expand_expr, case INDIRECT_REF): Likewise.
(expand_expr, case VAR_DECL): Call change_address.
* expr.h (ADD_PARM_SIZE, SUB_PARM_SIZE): Use host_integerp and
tree_low_cst.
(get_varargs_alias_set, get_frame_alias_set): New decls.
(record_base_value, record_alias_subset, lang_get_alias_set): Likewise.
(new_alias_set, set_mem_attributes): Likewse.
* function.c (struct temp_slot): ALIAS_SET is HOST_WIDE_INT.
(assign_stack_temp_for_type): Likewise.
Can split slot even if alias set since can copy.
Set MEM_ALIAS_SET and MEM_SET_IN_STRUCT_P.
(assign_temp): Use host_integerp and tree_low_cst.
(put_var_into_stack): Properly handle SAVE_EXPR.
(put_addressof_into_stack): Likewise.
(assign_parms): Call set_mem_attributes.
Delete #if 0 code.
(fix_lexical_address): Put reference to chain into frame alias set.
(expand_function_start): Call set_mem_attributes.
* integrate.c (expand_inline_function): Likewise.
* recog.c (adj_offsettable_operand): Use MEM_COPY_ATTRIBUTES.
* regmove.c (try_apply_stack_adjustment): Likewise.
* reload.c (push_reload, make_memloc): Likewise.
* reload1.c (alter_reg): Make alias sets for spilled pseudos.
* rtl.def (MEM): Update comment.
* rtl.h (MEM_ALIAS_SET): Now uses XCWINT.
(move_by_pieces): Change length to HOST_WIDE_INT.
(record_base_value, record_alias_subset): Delete from here.
* stmt.c (expand_decl): Call set_mem_attributes.
* stor-layout.c (finish_record_layout): Call record_component_aliases.i
* toplev.c (compile_file): Call init_alias_once earlier.
* tree.c (lang_get_alias_set, get_alias_set, new_alias_set): Deleted
from here: now in alias.c.
* tree.h (struct tree_type): alias_set is HOST_WIDE_INT.
(struct tree_decl): Likewise.
(get_alias_set, new_alias_set, lang_get_alias_set): Deleted from here.
* varasm.c (make_function_rtl, make_decl_rtl): Call set_mem_attributes.
(output_constant_def, force_const_mem): Likewise.
* cp/Makefile.in (decl.o): Include ../expr.h.
* cp/decl.c (expr.h): Include.
(init_decl_processing): Call record_component_aliases for arrays.
(grokdeclarator): Likewise.
Set TREE_ADDRESSABLE for fields that aren't bitfields.
* cp/tree.c (build_cplus_array_type_1): Call record_component_aliases.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@34305 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/alias.c')
-rw-r--r-- | gcc/alias.c | 226 |
1 files changed, 210 insertions, 16 deletions
diff --git a/gcc/alias.c b/gcc/alias.c index 9d3ff8bca0e..feed5415ad8 100644 --- a/gcc/alias.c +++ b/gcc/alias.c @@ -57,10 +57,10 @@ Boston, MA 02111-1307, USA. */ In this situation we say the alias set for `struct S' is the `superset' and that those for `int' and `double' are `subsets'. - To see whether two alias sets can point to the same memory, we must go - down the list of decendents of each and see if there is some alias set - in common. We need not trace past immediate decendents, however, since - we propagate all grandchildren up one level. + To see whether two alias sets can point to the same memory, we must + see if either alias set is a subset of the other. We need not trace + past immediate decendents, however, since we propagate all + grandchildren up one level. Alias set zero is implicitly a superset of all other alias sets. However, this is no actual entry for alias set zero. It is an @@ -69,7 +69,7 @@ Boston, MA 02111-1307, USA. */ typedef struct alias_set_entry { /* The alias set number, as stored in MEM_ALIAS_SET. */ - int alias_set; + HOST_WIDE_INT alias_set; /* The children of the alias set. These are not just the immediate children, but, in fact, all decendents. So, if we have: @@ -81,6 +81,10 @@ typedef struct alias_set_entry splay_tree children; } *alias_set_entry; +/* The language-specific function for alias analysis. If NULL, the + language does not do any special alias analysis. */ +HOST_WIDE_INT (*lang_get_alias_set) PARAMS ((tree)); + static int rtx_equal_for_memref_p PARAMS ((rtx, rtx)); static rtx find_symbolic_term PARAMS ((rtx)); static rtx get_addr PARAMS ((rtx)); @@ -93,9 +97,10 @@ static int base_alias_check PARAMS ((rtx, rtx, enum machine_mode, 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*)); -static alias_set_entry get_alias_set_entry PARAMS ((int)); +static tree find_base_decl PARAMS ((tree)); +static alias_set_entry get_alias_set_entry PARAMS ((HOST_WIDE_INT)); static rtx fixed_scalar_and_varying_struct_p PARAMS ((rtx, rtx, rtx, rtx, - int (*)(rtx))); + int (*) (rtx))); static int aliases_everything_p PARAMS ((rtx)); static int write_dependence_p PARAMS ((rtx, rtx, int)); static int nonlocal_reference_p PARAMS ((rtx)); @@ -140,7 +145,7 @@ static rtx *new_reg_base_value; static unsigned int reg_base_value_size; /* size of reg_base_value array */ #define REG_BASE_VALUE(X) \ - ((unsigned) REGNO (X) < reg_base_value_size ? reg_base_value[REGNO (X)] : 0) + (REGNO (X) < reg_base_value_size ? reg_base_value[REGNO (X)] : 0) /* Vector of known invariant relationships between registers. Set in loop unrolling. Indexed by register number, if nonzero the value @@ -187,7 +192,7 @@ static splay_tree alias_sets; static alias_set_entry get_alias_set_entry (alias_set) - int alias_set; + HOST_WIDE_INT alias_set; { splay_tree_node sn = splay_tree_lookup (alias_sets, (splay_tree_key) alias_set); @@ -236,8 +241,7 @@ mems_in_disjoint_alias_sets_p (mem1, mem2) if (MEM_ALIAS_SET (mem1) == MEM_ALIAS_SET (mem2)) return 0; - /* Iterate through each of the children of the first alias set, - comparing it with the second alias set. */ + /* See if the first alias set is a subset of the second. */ ase = get_alias_set_entry (MEM_ALIAS_SET (mem1)); if (ase != 0 && splay_tree_lookup (ase->children, (splay_tree_key) MEM_ALIAS_SET (mem2))) @@ -266,6 +270,168 @@ insert_subset_children (node, data) return 0; } + +/* T is an expression with pointer type. Find the DECL on which this + expression is based. (For example, in `a[i]' this would be `a'.) + If there is no such DECL, or a unique decl cannot be determined, + NULL_TREE is retured. */ + +static tree +find_base_decl (t) + tree t; +{ + tree d0, d1, d2; + + if (t == 0 || t == error_mark_node || ! POINTER_TYPE_P (TREE_TYPE (t))) + return 0; + + /* If this is a declaration, return it. */ + if (TREE_CODE_CLASS (TREE_CODE (t)) == 'd') + return t; + + /* Handle general expressions. It would be nice to deal with + COMPONENT_REFs here. If we could tell that `a' and `b' were the + same, then `a->f' and `b->f' are also the same. */ + switch (TREE_CODE_CLASS (TREE_CODE (t))) + { + case '1': + return find_base_decl (TREE_OPERAND (t, 0)); + + case '2': + /* Return 0 if found in neither or both are the same. */ + d0 = find_base_decl (TREE_OPERAND (t, 0)); + d1 = find_base_decl (TREE_OPERAND (t, 1)); + if (d0 == d1) + return d0; + else if (d0 == 0) + return d1; + else if (d1 == 0) + return d0; + else + return 0; + + case '3': + d0 = find_base_decl (TREE_OPERAND (t, 0)); + d1 = find_base_decl (TREE_OPERAND (t, 1)); + d0 = find_base_decl (TREE_OPERAND (t, 0)); + d2 = find_base_decl (TREE_OPERAND (t, 2)); + + /* Set any nonzero values from the last, then from the first. */ + if (d1 == 0) d1 = d2; + if (d0 == 0) d0 = d1; + if (d1 == 0) d1 = d0; + if (d2 == 0) d2 = d1; + + /* At this point all are nonzero or all are zero. If all three are the + same, return it. Otherwise, return zero. */ + return (d0 == d1 && d1 == d2) ? d0 : 0; + + default: + 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. */ + +HOST_WIDE_INT +get_alias_set (t) + tree t; +{ + HOST_WIDE_INT set; + HOST_WIDE_INT bitsize, bitpos; + tree offset; + enum machine_mode mode; + int volatilep, unsignedp; + unsigned int alignment; + + /* If we're not doing any alias analysis, just assume everything + aliases everything else. Also return 0 if this or its type is + an error. */ + if (! flag_strict_aliasing || t == error_mark_node + || (! TYPE_P (t) + && (TREE_TYPE (t) == 0 || TREE_TYPE (t) == error_mark_node))) + return 0; + + /* We can be passed either an expression or a type. This and the + language-specific routine may make mutually-recursive calls to + each other to figure out what to do. At each juncture, we see if + this is a tree that the language may need to handle specially. + But first remove nops since we care only about the actual object. */ + while (TREE_CODE (t) == NOP_EXPR || TREE_CODE (t) == CONVERT_EXPR + || TREE_CODE (t) == NON_LVALUE_EXPR) + t = TREE_OPERAND (t, 0); + + /* Now give the language a chance to do something. */ + if (lang_get_alias_set != 0 + && (set = (*lang_get_alias_set) (t)) != -1) + return set; + + /* If this is a reference, go inside it and use the underlying object. */ + if (TREE_CODE_CLASS (TREE_CODE (t)) == 'r') + t = get_inner_reference (t, &bitsize, &bitpos, &offset, &mode, + &unsignedp, &volatilep, &alignment); + + if (TREE_CODE (t) == INDIRECT_REF) + { + /* Check for accesses through restrict-qualified pointers. */ + tree decl = find_base_decl (TREE_OPERAND (t, 0)); + + if (decl && DECL_POINTER_ALIAS_SET_KNOWN_P (decl)) + /* We use the alias set indicated in the declaration. */ + return DECL_POINTER_ALIAS_SET (decl); + + /* If we have an INDIRECT_REF via a void pointer, we don't know anything + about what that might alias. */ + if (TREE_CODE (TREE_TYPE (t)) == VOID_TYPE) + return 0; + } + + /* Give the language another chance to do something special. */ + if (lang_get_alias_set != 0 + && (set = (*lang_get_alias_set) (t)) != -1) + return set; + + /* Now we are done with expressions, so get the type if this isn't + a type. */ + if (! TYPE_P (t)) + t = TREE_TYPE (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. */ + t = TYPE_MAIN_VARIANT (t); + if (TYPE_P (t) && TYPE_ALIAS_SET_KNOWN_P (t)) + return TYPE_ALIAS_SET (t); + + /* See if the language has special handling for this type. */ + if (lang_get_alias_set != 0 + && (set = (*lang_get_alias_set) (t)) != -1) + ; + /* There are no objects of FUNCTION_TYPE, so there's no point in + using up an alias set for them. (There are, of course, pointers + and references to functions, but that's different.) */ + else if (TREE_CODE (t) == FUNCTION_TYPE) + set = 0; + else + /* Otherwise make a new alias set for this type. */ + set = new_alias_set (); + + TYPE_ALIAS_SET (t) = set; + return set; +} + +/* Return a brand-new alias set. */ + +HOST_WIDE_INT +new_alias_set () +{ + static HOST_WIDE_INT last_alias_set; + + if (flag_strict_aliasing) + return ++last_alias_set; + else + return 0; +} /* Indicate that things in SUBSET can alias things in SUPERSET, but not vice versa. For example, in C, a store to an `int' can alias a @@ -278,8 +444,8 @@ insert_subset_children (node, data) void record_alias_subset (superset, subset) - int superset; - int subset; + HOST_WIDE_INT superset; + HOST_WIDE_INT subset; { alias_set_entry superset_entry; alias_set_entry subset_entry; @@ -326,8 +492,8 @@ void record_component_aliases (type) tree type; { - int superset = get_alias_set (type); - int subset; + HOST_WIDE_INT superset = get_alias_set (type); + HOST_WIDE_INT subset; tree field; if (superset == 0) @@ -336,7 +502,6 @@ record_component_aliases (type) switch (TREE_CODE (type)) { case ARRAY_TYPE: - case COMPLEX_TYPE: subset = get_alias_set (TREE_TYPE (type)); if (subset != 0) record_alias_subset (superset, subset); @@ -358,6 +523,34 @@ record_component_aliases (type) } } +/* Allocate an alias set for use in storing and reading from the varargs + spill area. */ + +HOST_WIDE_INT +get_varargs_alias_set () +{ + static HOST_WIDE_INT set = -1; + + if (set == -1) + set = new_alias_set (); + + return set; +} + +/* Likewise, but used for the fixed portions of the frame, e.g., register + save areas. */ + +HOST_WIDE_INT +get_frame_alias_set () +{ + static HOST_WIDE_INT set = -1; + + if (set == -1) + set = new_alias_set (); + + return set; +} + /* Inside SRC, the source of a SET, find a base address. */ static rtx @@ -975,6 +1168,7 @@ base_alias_check (x, y, x_mode, y_mode) /* Convert the address X into something we can use. This is done by returning it unchanged unless it is a value; in the latter case we call cselib to get a more useful rtx. */ + static rtx get_addr (x) rtx x; |