From 3bdf5ad13852aaa871ab41a6e8f509809c8c104d Mon Sep 17 00:00:00 2001 From: Richard Kenner Date: Wed, 31 May 2000 18:37:31 +0000 Subject: [PATCH] Makefile.in (c-decl.o): Depend on rtl.h and expr.h. * 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. From-SVN: r34305 --- gcc/ChangeLog | 81 +++++++++++++++++++ gcc/Makefile.in | 9 ++- gcc/alias.c | 226 +++++++++++++++++++++++++++++++++++++++++++++++++---- gcc/builtins.c | 118 +++++++++++++--------------- gcc/c-common.c | 184 +++++++------------------------------------ gcc/c-common.h | 2 +- gcc/c-typeck.c | 1 + gcc/caller-save.c | 26 +++--- gcc/calls.c | 42 +++++----- gcc/cp/ChangeLog | 9 +++ gcc/cp/Makefile.in | 2 +- gcc/cp/decl.c | 7 ++ gcc/cp/tree.c | 5 +- gcc/explow.c | 71 ++++++++++++++--- gcc/expr.c | 175 +++++++++++++++++++++-------------------- gcc/expr.h | 47 ++++++++--- gcc/function.c | 125 ++++++++++------------------- gcc/recog.c | 13 ++- gcc/regmove.c | 7 +- gcc/reload.c | 16 +++- gcc/reload1.c | 32 +++++--- gcc/rtl.def | 2 +- gcc/rtl.h | 36 +++++---- gcc/stmt.c | 32 ++------ gcc/stor-layout.c | 3 + gcc/toplev.c | 2 +- gcc/tree.c | 36 --------- gcc/tree.h | 7 +- 28 files changed, 739 insertions(+), 577 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9f9c79b..62555cb 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -32,6 +32,87 @@ Wed May 31 13:17:20 2000 Philippe De Muyter Wed May 31 08:07:52 2000 Richard Kenner + * 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. + * flow.c (propagate_block): If block has no successors, stores to frame are dead if not used. diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 8640756..f131dab 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1092,12 +1092,13 @@ $(srcdir)/c-gperf.h: c-parse.gperf exit 1 ) $(SHELL) $(srcdir)/move-if-change tmp-gperf.h $(srcdir)/c-gperf.h -c-decl.o : c-decl.c $(CONFIG_H) system.h $(TREE_H) c-tree.h c-common.h $(GGC_H) \ - c-lex.h flags.h function.h output.h toplev.h defaults.h +c-decl.o : c-decl.c $(CONFIG_H) system.h $(TREE_H) $(RTL_H) c-tree.h \ + c-common.h $(GGC_H) c-lex.h flags.h function.h output.h expr.h toplev.h \ + defaults.h c-typeck.o : c-typeck.c $(CONFIG_H) system.h $(TREE_H) c-tree.h c-common.h \ flags.h intl.h output.h $(EXPR_H) $(RTL_H) toplev.h -c-lang.o : c-lang.c $(CONFIG_H) system.h $(TREE_H) c-tree.h c-common.h $(GGC_H) \ - c-lex.h toplev.h output.h function.h +c-lang.o : c-lang.c $(CONFIG_H) system.h $(TREE_H) c-tree.h c-common.h \ + $(GGC_H) c-lex.h toplev.h output.h function.h c-lex.o : c-lex.c $(CONFIG_H) system.h $(TREE_H) $(RTL_H) c-lex.h c-tree.h \ c-common.h $(srcdir)/c-parse.h $(srcdir)/c-gperf.h c-pragma.h input.h \ intl.h flags.h toplev.h output.h mbchar.h $(GGC_H) diff --git a/gcc/alias.c b/gcc/alias.c index 9d3ff8b..feed541 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; diff --git a/gcc/builtins.c b/gcc/builtins.c index 1094e30..0e89481 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -288,6 +288,7 @@ expand_builtin_return_addr (fndecl_code, count, tem) #endif tem = memory_address (Pmode, tem); tem = copy_to_reg (gen_rtx_MEM (Pmode, tem)); + MEM_ALIAS_SET (tem) = get_frame_alias_set (); } /* For __builtin_frame_address, return what we've got. */ @@ -302,10 +303,14 @@ expand_builtin_return_addr (fndecl_code, count, tem) tem = memory_address (Pmode, plus_constant (tem, GET_MODE_SIZE (Pmode))); tem = gen_rtx_MEM (Pmode, tem); + MEM_ALIAS_SET (tem) = get_frame_alias_set (); #endif return tem; } +/* Alias set used for setjmp buffer. */ +static HOST_WIDE_INT setjmp_alias_set = -1; + /* __builtin_setjmp is passed a pointer to an array of five words (not all will be used on all machines). It operates similarly to the C library function of the same name, but is more efficient. Much of @@ -326,9 +331,13 @@ expand_builtin_setjmp (buf_addr, target, first_label, next_label) enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL); enum machine_mode value_mode; rtx stack_save; + rtx mem; value_mode = TYPE_MODE (integer_type_node); + if (setjmp_alias_set == -1) + setjmp_alias_set = new_alias_set (); + #ifdef POINTERS_EXTEND_UNSIGNED buf_addr = convert_memory_address (Pmode, buf_addr); #endif @@ -349,17 +358,20 @@ expand_builtin_setjmp (buf_addr, target, first_label, next_label) #define BUILTIN_SETJMP_FRAME_VALUE virtual_stack_vars_rtx #endif - emit_move_insn (gen_rtx_MEM (Pmode, buf_addr), - BUILTIN_SETJMP_FRAME_VALUE); - emit_move_insn (validize_mem - (gen_rtx_MEM (Pmode, - plus_constant (buf_addr, - GET_MODE_SIZE (Pmode)))), + mem = gen_rtx_MEM (Pmode, buf_addr); + MEM_ALIAS_SET (mem) = setjmp_alias_set; + emit_move_insn (mem, BUILTIN_SETJMP_FRAME_VALUE); + + mem = gen_rtx_MEM (Pmode, plus_constant (buf_addr, GET_MODE_SIZE (Pmode))), + MEM_ALIAS_SET (mem) = setjmp_alias_set; + + emit_move_insn (validize_mem (mem), force_reg (Pmode, gen_rtx_LABEL_REF (Pmode, lab1))); stack_save = gen_rtx_MEM (sa_mode, plus_constant (buf_addr, 2 * GET_MODE_SIZE (Pmode))); + MEM_ALIAS_SET (stack_save) = setjmp_alias_set; emit_stack_save (SAVE_NONLOCAL, &stack_save, NULL_RTX); /* If there is further processing to do, do it. */ @@ -464,6 +476,9 @@ expand_builtin_longjmp (buf_addr, value) rtx fp, lab, stack; enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL); + if (setjmp_alias_set == -1) + setjmp_alias_set = new_alias_set (); + #ifdef POINTERS_EXTEND_UNSIGNED buf_addr = convert_memory_address (Pmode, buf_addr); #endif @@ -489,6 +504,8 @@ expand_builtin_longjmp (buf_addr, value) stack = gen_rtx_MEM (sa_mode, plus_constant (buf_addr, 2 * GET_MODE_SIZE (Pmode))); + MEM_ALIAS_SET (fp) = MEM_ALIAS_SET (lab) = MEM_ALIAS_SET (stack) + = setjmp_alias_set; /* Pick up FP, label, and SP from the block and jump. This code is from expand_goto in stmt.c; see there for detailed comments. */ @@ -513,53 +530,34 @@ expand_builtin_longjmp (buf_addr, value) } } -/* Get a MEM rtx for expression EXP which can be used in a string instruction - (cmpstrsi, movstrsi, ..). */ +/* Get a MEM rtx for expression EXP which is the address of an operand + to be used to be used in a string instruction (cmpstrsi, movstrsi, ..). */ + static rtx get_memory_rtx (exp) tree exp; { - rtx mem; - int is_aggregate; - - mem = gen_rtx_MEM (BLKmode, - memory_address (BLKmode, - expand_expr (exp, NULL_RTX, - ptr_mode, EXPAND_SUM))); - - RTX_UNCHANGING_P (mem) = TREE_READONLY (exp); - - /* Figure out the type of the object pointed to. Set MEM_IN_STRUCT_P - if the value is the address of a structure or if the expression is - cast to a pointer to structure type. */ - is_aggregate = 0; - - while (TREE_CODE (exp) == NOP_EXPR) - { - tree cast_type = TREE_TYPE (exp); - if (TREE_CODE (cast_type) == POINTER_TYPE - && AGGREGATE_TYPE_P (TREE_TYPE (cast_type))) - { - is_aggregate = 1; - break; - } - exp = TREE_OPERAND (exp, 0); - } - - if (is_aggregate == 0) - { - tree type; - - if (TREE_CODE (exp) == ADDR_EXPR) - /* If this is the address of an object, check whether the - object is an array. */ - type = TREE_TYPE (TREE_OPERAND (exp, 0)); - else - type = TREE_TYPE (TREE_TYPE (exp)); - is_aggregate = AGGREGATE_TYPE_P (type); - } + rtx mem = gen_rtx_MEM (BLKmode, + memory_address (BLKmode, + expand_expr (exp, NULL_RTX, + ptr_mode, EXPAND_SUM))); + + /* Get an expression we can use to find the attributes to assign to MEM. + If it is an ADDR_EXPR, use the operand. Otherwise, dereference it if + we can. First remove any nops. */ + while ((TREE_CODE (exp) == NOP_EXPR || TREE_CODE (exp) == CONVERT_EXPR + || TREE_CODE (exp) == NON_LVALUE_EXPR) + && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (exp, 0)))) + exp = TREE_OPERAND (exp, 0); + + if (TREE_CODE (exp) == ADDR_EXPR) + exp = TREE_OPERAND (exp, 0); + else if (POINTER_TYPE_P (TREE_TYPE (exp))) + exp = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (exp)), exp); + else + return mem; - MEM_SET_IN_STRUCT_P (mem, is_aggregate); + set_mem_attributes (mem, exp, 0); return mem; } @@ -1306,6 +1304,7 @@ expand_builtin_mathfn (exp, target, subtarget) if we failed the caller should emit a normal call, otherwise try to get the result in TARGET, if convenient (and in mode MODE if that's convenient). */ + static rtx expand_builtin_strlen (exp, target, mode) tree exp; @@ -1377,8 +1376,9 @@ expand_builtin_strlen (exp, target, mode) TYPE_MODE (integer_type_node)); char_rtx = const0_rtx; - char_mode = insn_data[(int)icode].operand[2].mode; - if (! (*insn_data[(int)icode].operand[2].predicate) (char_rtx, char_mode)) + char_mode = insn_data[(int) icode].operand[2].mode; + if (! (*insn_data[(int) icode].operand[2].predicate) (char_rtx, + char_mode)) char_rtx = copy_to_mode_reg (char_mode, char_rtx); pat = GEN_FCN (icode) (result, gen_rtx_MEM (BLKmode, src_reg), @@ -1390,7 +1390,7 @@ expand_builtin_strlen (exp, target, mode) /* Now that we are assured of success, expand the source. */ start_sequence (); pat = memory_address (BLKmode, - expand_expr (src, src_reg, ptr_mode, EXPAND_SUM)); + expand_expr (src, src_reg, ptr_mode, EXPAND_SUM)); if (pat != src_reg) emit_move_insn (src_reg, pat); pat = gen_sequence (); @@ -1814,6 +1814,7 @@ expand_builtin_saveregs () /* __builtin_args_info (N) returns word N of the arg space info for the current function. The number and meanings of words is controlled by the definition of CUMULATIVE_ARGS. */ + static rtx expand_builtin_args_info (exp) tree exp; @@ -2007,19 +2008,9 @@ expand_builtin_va_start (stdarg_p, arglist) return const0_rtx; } -/* Allocate an alias set for use in storing and reading from the varargs - spill area. */ -int -get_varargs_alias_set () -{ - static int set = -1; - if (set == -1) - set = new_alias_set (); - return set; -} - /* The "standard" implementation of va_arg: read the value from the current (padded) address and increment by the (padded) size. */ + rtx std_expand_builtin_va_arg (valist, type) tree valist, type; @@ -2063,6 +2054,7 @@ std_expand_builtin_va_arg (valist, type) /* Expand __builtin_va_arg, which is not really a builtin function, but a very special sort of operator. */ + rtx expand_builtin_va_arg (valist, type) tree valist, type; @@ -2146,6 +2138,7 @@ expand_builtin_va_arg (valist, type) } /* Expand ARGLIST, from a call to __builtin_va_end. */ + static rtx expand_builtin_va_end (arglist) tree arglist; @@ -2168,6 +2161,7 @@ expand_builtin_va_end (arglist) /* Expand ARGLIST, from a call to __builtin_va_copy. We do this as a builtin rather than just as an assignment in stdarg.h because of the nastiness of array-type va_list types. */ + static rtx expand_builtin_va_copy (arglist) tree arglist; diff --git a/gcc/c-common.c b/gcc/c-common.c index 6989d40..5cc34c9 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -156,7 +156,6 @@ static void init_attributes PARAMS ((void)); static void record_function_format PARAMS ((tree, tree, enum format_type, int, int)); static void record_international_format PARAMS ((tree, tree, int)); -static tree c_find_base_decl PARAMS ((tree)); static int default_valid_lang_attribute PARAMS ((tree, tree, tree, tree)); /* Keep a stack of if statements. We record the number of compound @@ -3245,10 +3244,10 @@ c_apply_type_quals_to_decl (type_quals, decl) alias set for the type pointed to by the type of the decl. */ - int pointed_to_alias_set + HOST_WIDE_INT pointed_to_alias_set = get_alias_set (TREE_TYPE (TREE_TYPE (decl))); - if (!pointed_to_alias_set) + if (pointed_to_alias_set == 0) /* It's not legal to make a subset of alias set zero. */ ; else @@ -3261,91 +3260,16 @@ c_apply_type_quals_to_decl (type_quals, decl) } } -/* 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 -c_find_base_decl (t) - tree t; -{ - int i; - tree decl; - - if (t == NULL_TREE || t == error_mark_node) - return NULL_TREE; - - if (!POINTER_TYPE_P (TREE_TYPE (t))) - return NULL_TREE; - - decl = NULL_TREE; - - if (TREE_CODE (t) == FIELD_DECL - || TREE_CODE (t) == PARM_DECL - || TREE_CODE (t) == VAR_DECL) - /* Aha, we found a pointer-typed declaration. */ - return t; - - /* 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. */ - - /* Handle general expressions. */ - switch (TREE_CODE_CLASS (TREE_CODE (t))) - { - case '1': - case '2': - case '3': - for (i = TREE_CODE_LENGTH (TREE_CODE (t)); --i >= 0;) - { - tree d = c_find_base_decl (TREE_OPERAND (t, i)); - if (d) - { - if (!decl) - decl = d; - else if (d && d != decl) - /* Two different declarations. That's confusing; let's - just assume we don't know what's going on. */ - decl = NULL_TREE; - } - } - break; - - default: - break; - } - - return decl; -} /* Return the typed-based alias set for T, which may be an expression - or a type. */ + or a type. Return -1 if we don't do anything special. */ -int +HOST_WIDE_INT c_get_alias_set (t) tree t; { - tree type; tree u; - if (t == error_mark_node) - return 0; - - /* For a bit field reference that's not to a specific field, - all we can say is the aliasing information for the underlying object. */ - if (TREE_CODE (t) == BIT_FIELD_REF) - t = TREE_OPERAND (t, 0); - - /* If this is a type, use it, otherwise get the type of the expression. - If the type is an error type, say this may alias anything. */ - type = TYPE_P (t) ? t : TREE_TYPE (t); - if (type == error_mark_node) - return 0; - - /* Deal with special cases first; for certain kinds of references - we're interested in more than just the type. */ - /* Permit type-punning when accessing a union, provided the access is directly through the union. For example, this code does not permit taking the address of a union member and then storing @@ -3359,81 +3283,37 @@ c_get_alias_set (t) && TREE_CODE (TREE_TYPE (TREE_OPERAND (u, 0))) == UNION_TYPE) return 0; - if (TREE_CODE (t) == INDIRECT_REF) - { - /* Check for accesses through restrict-qualified pointers. */ - tree op = TREE_OPERAND (t, 0); - tree decl = c_find_base_decl (op); - - 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 this is a char *, the ANSI C standard says it can alias - anything. */ - if (TREE_CODE (TREE_TYPE (op)) == INTEGER_TYPE - && (TYPE_PRECISION (TREE_TYPE (op)) - == TYPE_PRECISION (char_type_node))) - return 0; - } + /* If this is a char *, the ANSI C standard says it can alias + anything. */ + else if (TREE_CODE (t) == INDIRECT_REF + && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == INTEGER_TYPE + && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (t, 0))) + == TYPE_PRECISION (char_type_node))) + return 0; - /* From here on, only the type matters. */ - - if (TREE_CODE (t) == COMPONENT_REF - && DECL_BIT_FIELD_TYPE (TREE_OPERAND (t, 1))) - /* Since build_modify_expr calls get_unwidened for stores to - component references, the type of a bit field can be changed - from (say) `unsigned int : 16' to `unsigned short' or from - `enum E : 16' to `short'. We want the real type of the - bit-field in this case, not some the integral equivalent. */ - type = DECL_BIT_FIELD_TYPE (TREE_OPERAND (t, 1)); - - if (TYPE_ALIAS_SET_KNOWN_P (type)) - /* If we've already calculated the value, just return it. */ - return TYPE_ALIAS_SET (type); - else if (TYPE_MAIN_VARIANT (type) != type) - /* The C standard specifically allows aliasing between - cv-qualified variants of types. */ - TYPE_ALIAS_SET (type) = c_get_alias_set (TYPE_MAIN_VARIANT (type)); - else if (TREE_CODE (type) == INTEGER_TYPE) - { - tree signed_variant; + /* That's all the expressions we handle specially. */ + if (! TYPE_P (t)) + return -1; + if (TREE_CODE (t) == INTEGER_TYPE) + { /* The C standard specifically allows aliasing between signed and unsigned variants of the same type. We treat the signed variant as canonical. */ - signed_variant = signed_type (type); + tree signed_variant = signed_type (t); - if (signed_variant != type) - TYPE_ALIAS_SET (type) = c_get_alias_set (signed_variant); - else if (signed_variant == signed_char_type_node) + if (signed_variant == signed_char_type_node) /* The C standard guarantess that any object may be accessed via an lvalue that has character type. We don't have to check for unsigned_char_type_node or char_type_node because we are specifically looking at the signed variant. */ - TYPE_ALIAS_SET (type) = 0; + return 0; + else if (signed_variant != t) + return get_alias_set (signed_variant); } - else if (TREE_CODE (type) == ARRAY_TYPE) - /* Anything that can alias one of the array elements can alias - the entire array as well. */ - TYPE_ALIAS_SET (type) = c_get_alias_set (TREE_TYPE (type)); - else if (TREE_CODE (type) == FUNCTION_TYPE) - /* 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.) */ - TYPE_ALIAS_SET (type) = 0; - else if (TREE_CODE (type) == RECORD_TYPE - || TREE_CODE (type) == UNION_TYPE) - /* If TYPE is a struct or union type then we're reading or - writing an entire struct. Thus, we don't know anything about - aliasing. (In theory, such an access can only alias objects - whose type is the same as one of the fields, recursively, but - we don't yet make any use of that information.) */ - TYPE_ALIAS_SET (type) = 0; - else if (POINTER_TYPE_P (type)) + else if (POINTER_TYPE_P (t)) { - tree t; + tree t1; /* Unfortunately, there is no canonical form of a pointer type. In particular, if we have `typedef int I', then `int *', and @@ -3458,19 +3338,14 @@ c_get_alias_set (t) can dereference IPP and CIPP. So, we ignore cv-qualifiers on the pointed-to types. This issue has been reported to the C++ committee. */ - t = TYPE_MAIN_VARIANT (TREE_TYPE (type)); - t = ((TREE_CODE (type) == POINTER_TYPE) - ? build_pointer_type (t) : build_reference_type (t)); - if (t != type) - TYPE_ALIAS_SET (type) = c_get_alias_set (t); + t1 = TYPE_MAIN_VARIANT (TREE_TYPE (t)); + t1 = ((TREE_CODE (t) == POINTER_TYPE) + ? build_pointer_type (t1) : build_reference_type (t1)); + if (t1 != t) + return get_alias_set (t1); } - if (! TYPE_ALIAS_SET_KNOWN_P (type)) - /* TYPE is something we haven't seen before. Put it in a new - alias set. */ - TYPE_ALIAS_SET (type) = new_alias_set (); - - return TYPE_ALIAS_SET (type); + return -1; } /* Build tree nodes and builtin functions common to both C and C++ language @@ -3480,6 +3355,7 @@ c_get_alias_set (t) NO_BUILTINS and NO_NONANSI_BUILTINS contain the respective values of the language frontend flags flag_no_builtin and flag_no_nonansi_builtin. */ + void c_common_nodes_and_builtins (cplus_mode, no_builtins, no_nonansi_builtins) int cplus_mode, no_builtins, no_nonansi_builtins; diff --git a/gcc/c-common.h b/gcc/c-common.h index 0d25b2a..30f58f8 100644 --- a/gcc/c-common.h +++ b/gcc/c-common.h @@ -97,7 +97,7 @@ extern void decl_attributes PARAMS ((tree, tree, tree)); extern void init_function_format_info PARAMS ((void)); extern void check_function_format PARAMS ((tree, tree, tree)); extern void c_apply_type_quals_to_decl PARAMS ((int, tree)); -extern int c_get_alias_set PARAMS ((tree)); +extern HOST_WIDE_INT c_get_alias_set PARAMS ((tree)); /* Print an error message for invalid operands to arith operation CODE. NOP_EXPR is used as a special case (see truthvalue_conversion). */ extern void binary_op_error PARAMS ((enum tree_code)); diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index 0f01c57..1d86242 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -313,6 +313,7 @@ common_type (t1, t2) return build_type_attribute_variant (t2, attributes); /* Merge the element types, and have a size if either arg has one. */ t1 = build_array_type (elt, TYPE_DOMAIN (TYPE_DOMAIN (t1) ? t1 : t2)); + record_component_aliases (t1); return build_type_attribute_variant (t1, attributes); } diff --git a/gcc/caller-save.c b/gcc/caller-save.c index 305894e..f939de7 100644 --- a/gcc/caller-save.c +++ b/gcc/caller-save.c @@ -256,6 +256,7 @@ void setup_save_areas () { int i, j, k; + unsigned int r; HARD_REG_SET hard_regs_used; /* Allocate space in the save area for the largest multi-register @@ -267,16 +268,13 @@ setup_save_areas () for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++) if (reg_renumber[i] >= 0 && REG_N_CALLS_CROSSED (i) > 0) { - int regno = reg_renumber[i]; - int endregno + unsigned int regno = reg_renumber[i]; + unsigned int endregno = regno + HARD_REGNO_NREGS (regno, GET_MODE (regno_reg_rtx[i])); - int nregs = endregno - regno; - for (j = 0; j < nregs; j++) - { - if (call_used_regs[regno+j]) - SET_HARD_REG_BIT (hard_regs_used, regno+j); - } + for (r = regno; r < endregno; r++) + if (call_used_regs[r]) + SET_HARD_REG_BIT (hard_regs_used, r); } /* Now run through all the call-used hard-registers and allocate @@ -322,16 +320,24 @@ setup_save_areas () { /* This should not depend on WORDS_BIG_ENDIAN. The order of words in regs is the same as in memory. */ - rtx temp = gen_rtx_MEM (regno_save_mode[i+k][1], + rtx temp = gen_rtx_MEM (regno_save_mode[i + k][1], XEXP (regno_save_mem[i][j], 0)); - regno_save_mem[i+k][1] + regno_save_mem[i + k][1] = adj_offsettable_operand (temp, k * UNITS_PER_WORD); } } + + /* Now loop again and set the alias set of any save areas we made to + the alias set used to represent frame objects. */ + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + for (j = MOVE_MAX_WORDS; j > 0; j--) + if (regno_save_mem[i][j] != 0) + MEM_ALIAS_SET (regno_save_mem[i][j]) = get_frame_alias_set (); } /* Find the places where hard regs are live across calls and save them. */ + void save_call_clobbered_regs () { diff --git a/gcc/calls.c b/gcc/calls.c index bf33ebd..d59c15b 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -850,6 +850,7 @@ precompute_register_parameters (num_actuals, args, reg_parm_seen) /* The argument list is the property of the called routine and it may clobber it. If the fixed area has been used for previous parameters, we must save and restore it. */ + static rtx save_fixed_argument_area (reg_parm_stack_space, argblock, low_to_save, high_to_save) @@ -891,10 +892,11 @@ save_fixed_argument_area (reg_parm_stack_space, argblock, save_mode = BLKmode; #ifdef ARGS_GROW_DOWNWARD - stack_area = gen_rtx_MEM (save_mode, - memory_address (save_mode, - plus_constant (argblock, - - *high_to_save))); + stack_area + = gen_rtx_MEM (save_mode, + memory_address (save_mode, + plus_constant (argblock, + - *high_to_save))); #else stack_area = gen_rtx_MEM (save_mode, memory_address (save_mode, @@ -1191,17 +1193,12 @@ initialize_argument_information (num_actuals, args, args_size, n_named_args, } copy = gen_rtx_MEM (BLKmode, - allocate_dynamic_stack_space (size_rtx, - NULL_RTX, - TYPE_ALIGN (type))); + allocate_dynamic_stack_space + (size_rtx, NULL_RTX, TYPE_ALIGN (type))); + set_mem_attributes (copy, type, 1); } else - { - int size = int_size_in_bytes (type); - copy = assign_stack_temp (TYPE_MODE (type), size, 0); - } - - MEM_SET_IN_STRUCT_P (copy, AGGREGATE_TYPE_P (type)); + copy = assign_temp (type, 0, 1, 0); store_expr (args[i].tree_value, copy, 0); *ecf_flags &= ~(ECF_CONST | ECF_PURE); @@ -1585,9 +1582,8 @@ compute_argument_addresses (args, argblock, num_actuals) addr = plus_constant (addr, arg_offset); args[i].stack = gen_rtx_MEM (args[i].mode, addr); - MEM_SET_IN_STRUCT_P - (args[i].stack, - AGGREGATE_TYPE_P (TREE_TYPE (args[i].tree_value))); + set_mem_attributes (args[i].stack, + TREE_TYPE (args[i].tree_value), 1); if (GET_CODE (slot_offset) == CONST_INT) addr = plus_constant (arg_reg, INTVAL (slot_offset)); @@ -1596,6 +1592,8 @@ compute_argument_addresses (args, argblock, num_actuals) addr = plus_constant (addr, arg_offset); args[i].stack_slot = gen_rtx_MEM (args[i].mode, addr); + set_mem_attributes (args[i].stack_slot, + TREE_TYPE (args[i].tree_value), 1); } } } @@ -3058,11 +3056,11 @@ expand_call (exp, target, ignore) { if (target == 0 || GET_CODE (target) != MEM) { - target = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (exp)), - memory_address (TYPE_MODE (TREE_TYPE (exp)), - structure_value_addr)); - MEM_SET_IN_STRUCT_P (target, - AGGREGATE_TYPE_P (TREE_TYPE (exp))); + target + = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (exp)), + memory_address (TYPE_MODE (TREE_TYPE (exp)), + structure_value_addr)); + set_mem_attributes (target, exp, 1); } } else if (pcc_struct_value) @@ -3072,7 +3070,7 @@ expand_call (exp, target, ignore) never use this value more than once in one expression. */ target = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (exp)), copy_to_reg (valreg)); - MEM_SET_IN_STRUCT_P (target, AGGREGATE_TYPE_P (TREE_TYPE (exp))); + set_mem_attributes (target, exp, 1); } /* Handle calls that return values in multiple non-contiguous locations. The Irix 6 ABI has examples of this. */ diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 6120852..ffe112a 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,12 @@ +Wed May 31 14:09:00 2000 Richard Kenner + + * Makefile.in (decl.o): Include ../expr.h. + * 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. + * tree.c (build_cplus_array_type_1): Call record_component_aliases. + 2000-05-31 Mark Mitchell * decl.c (build_cp_library_fn): Set DECL_CONTEXT. diff --git a/gcc/cp/Makefile.in b/gcc/cp/Makefile.in index 5284e7d..e162294 100644 --- a/gcc/cp/Makefile.in +++ b/gcc/cp/Makefile.in @@ -256,7 +256,7 @@ lex.o : lex.c $(CXX_TREE_H) \ $(srcdir)/../output.h $(srcdir)/../mbchar.h $(GGC_H) \ $(srcdir)/../input.h operators.def decl.o : decl.c $(CXX_TREE_H) $(srcdir)/../flags.h \ - lex.h decl.h $(srcdir)/../stack.h $(srcdir)/../output.h \ + lex.h decl.h $(srcdir)/../stack.h $(srcdir)/../output.h $(srcdir)/../expr.h \ $(srcdir)/../except.h $(srcdir)/../toplev.h \ $(srcdir)/../hash.h $(GGC_H) $(RTL_H) operators.def decl2.o : decl2.c $(CXX_TREE_H) $(srcdir)/../flags.h \ diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 69f6e74..6640b90 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -32,6 +32,7 @@ Boston, MA 02111-1307, USA. */ #include "system.h" #include "tree.h" #include "rtl.h" +#include "expr.h" #include "flags.h" #include "cp-tree.h" #include "decl.h" @@ -6455,10 +6456,14 @@ init_decl_processing () array type. */ char_array_type_node = build_array_type (char_type_node, array_domain_type); + /* Likewise for arrays of ints. */ int_array_type_node = build_array_type (integer_type_node, array_domain_type); + record_component_aliases (char_array_type_node); + record_component_aliases (int_array_type_node); + if (flag_new_abi) delta_type_node = ptrdiff_type_node; else if (flag_huge_objects) @@ -6522,6 +6527,7 @@ init_decl_processing () /* This is for wide string constants. */ wchar_array_type_node = build_array_type (wchar_type_node, array_domain_type); + record_component_aliases (wchar_array_type_node); if (flag_vtable_thunks) { @@ -11588,6 +11594,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) else { decl = build_decl (FIELD_DECL, declarator, type); + TREE_ADDRESSABLE (decl) = ! bitfield; if (RIDBIT_SETP (RID_MUTABLE, specbits)) { DECL_MUTABLE_P (decl) = 1; diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 382e254..95fafad 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -500,7 +500,10 @@ build_cplus_array_type_1 (elt_type, index_type) TYPE_DOMAIN (t) = index_type; } else - t = build_array_type (elt_type, index_type); + { + t = build_array_type (elt_type, index_type); + record_component_aliases (t); + } /* Push these needs up so that initialization takes place more easily. */ diff --git a/gcc/explow.c b/gcc/explow.c index f689b88..6ca93bc 100644 --- a/gcc/explow.c +++ b/gcc/explow.c @@ -628,6 +628,61 @@ validize_mem (ref) return change_address (ref, GET_MODE (ref), XEXP (ref, 0)); } +/* Given REF, a MEM, and T, either the type of X or the expression + corresponding to REF, set the memory attributes. OBJECTP is nonzero + if we are making a new object of this type. */ + +void +set_mem_attributes (ref, t, objectp) + rtx ref; + tree t; + int objectp; +{ + tree type = TYPE_P (t) ? t : TREE_TYPE (t); + + /* Get the alias set from the expression or type (perhaps using a + front-end routine) and then copy bits from the type. */ + MEM_ALIAS_SET (ref) = get_alias_set (t); + RTX_UNCHANGING_P (ref) = TYPE_READONLY (type); + MEM_VOLATILE_P (ref) = TYPE_VOLATILE (type); + MEM_IN_STRUCT_P (ref) = AGGREGATE_TYPE_P (type); + + /* If we are making an object of this type, we know that it is a scalar if + the type is not an aggregate. */ + if (objectp && ! AGGREGATE_TYPE_P (type)) + MEM_SCALAR_P (ref) = 1; + + /* If T is a type, this is all we can do. Otherwise, we may be able + to deduce some more information about the expression. */ + if (TYPE_P (t)) + return; + + if (TREE_READONLY (t) || TREE_CODE_CLASS (TREE_CODE (t)) == 'c') + RTX_UNCHANGING_P (ref) = 1; + if (TREE_THIS_VOLATILE (t)) + MEM_VOLATILE_P (ref) = 1; + + /* Now see if we can say more about whether it's an aggregate or + scalar. If we already know it's an aggregate, don't bother. */ + if (MEM_IN_STRUCT_P (ref)) + return; + + /* Now remove any NOPs: they don't change what the underlying object is. + Likewise for SAVE_EXPR. */ + while (TREE_CODE (t) == NOP_EXPR || TREE_CODE (t) == CONVERT_EXPR + || TREE_CODE (t) == NON_LVALUE_EXPR || TREE_CODE (t) == SAVE_EXPR) + t = TREE_OPERAND (t, 0); + + /* Since we already know the type isn't an aggregate, if this is a decl, + it must be a scalar. Or if it is a reference into an aggregate, + this is part of an aggregate. Otherwise we don't know. */ + if (DECL_P (t)) + MEM_SCALAR_P (ref) = 1; + else if (TREE_CODE (t) == COMPONENT_REF || TREE_CODE (t) == ARRAY_REF + || TREE_CODE (t) == BIT_FIELD_REF) + MEM_IN_STRUCT_P (ref) = 1; +} + /* Return a modified copy of X with its memory address copied into a temporary register to protect it from side effects. If X is not a MEM, it is returned unchanged (and not copied). @@ -638,25 +693,17 @@ stabilize (x) rtx x; { register rtx addr; + if (GET_CODE (x) != MEM) return x; + addr = XEXP (x, 0); if (rtx_unstable_p (addr)) { - rtx temp = copy_all_regs (addr); - rtx mem; - - if (GET_CODE (temp) != REG) - temp = copy_to_reg (temp); - mem = gen_rtx_MEM (GET_MODE (x), temp); - - /* Mark returned memref with in_struct if it's in an array or - structure. Copy everything else from original memref. */ + rtx temp = force_reg (Pmode, copy_all_regs (addr)); + rtx mem = gen_rtx_MEM (GET_MODE (x), temp); MEM_COPY_ATTRIBUTES (mem, x); - if (GET_CODE (addr) == PLUS) - MEM_SET_IN_STRUCT_P (mem, 1); - return mem; } return x; diff --git a/gcc/expr.c b/gcc/expr.c index 5cef748..cb39728 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -115,16 +115,12 @@ struct move_by_pieces rtx to_addr; int autinc_to; int explicit_inc_to; - int to_struct; - int to_readonly; rtx from; rtx from_addr; int autinc_from; int explicit_inc_from; - int from_struct; - int from_readonly; - int len; - int offset; + unsigned HOST_WIDE_INT len; + HOST_WIDE_INT offset; int reverse; }; @@ -137,9 +133,8 @@ struct clear_by_pieces rtx to_addr; int autinc_to; int explicit_inc_to; - int to_struct; - int len; - int offset; + unsigned HOST_WIDE_INT len; + HOST_WIDE_INT offset; int reverse; }; @@ -148,10 +143,13 @@ extern struct obstack permanent_obstack; static rtx get_push_address PARAMS ((int)); static rtx enqueue_insn PARAMS ((rtx, rtx)); -static int move_by_pieces_ninsns PARAMS ((unsigned int, unsigned int)); +static unsigned HOST_WIDE_INT move_by_pieces_ninsns + PARAMS ((unsigned HOST_WIDE_INT, + unsigned int)); static void move_by_pieces_1 PARAMS ((rtx (*) (rtx, ...), enum machine_mode, struct move_by_pieces *)); -static void clear_by_pieces PARAMS ((rtx, int, unsigned int)); +static void clear_by_pieces PARAMS ((rtx, unsigned HOST_WIDE_INT, + unsigned int)); static void clear_by_pieces_1 PARAMS ((rtx (*) (rtx, ...), enum machine_mode, struct clear_by_pieces *)); @@ -1381,7 +1379,7 @@ convert_modes (mode, oldmode, x, unsignedp) void move_by_pieces (to, from, len, align) rtx to, from; - int len; + unsigned HOST_WIDE_INT len; unsigned int align; { struct move_by_pieces data; @@ -1410,11 +1408,6 @@ move_by_pieces (to, from, len, align) if (data.reverse) data.offset = len; data.len = len; - data.to_struct = MEM_IN_STRUCT_P (to); - data.from_struct = MEM_IN_STRUCT_P (from); - data.to_readonly = RTX_UNCHANGING_P (to); - data.from_readonly = RTX_UNCHANGING_P (from); - /* If copying requires more than two move insns, copy addresses to registers (to make displacements shorter) and use post-increment if available. */ @@ -1489,13 +1482,13 @@ move_by_pieces (to, from, len, align) /* Return number of insns required to move L bytes by pieces. ALIGN (in bytes) is maximum alignment we can assume. */ -static int +static unsigned HOST_WIDE_INT move_by_pieces_ninsns (l, align) - unsigned int l; + unsigned HOST_WIDE_INT l; unsigned int align; { - register int n_insns = 0; - unsigned int max_size = MOVE_MAX + 1; + unsigned HOST_WIDE_INT n_insns = 0; + unsigned HOST_WIDE_INT max_size = MOVE_MAX + 1; if (! SLOW_UNALIGNED_ACCESS (word_mode, align) || align > MOVE_MAX * BITS_PER_UNIT || align >= BIGGEST_ALIGNMENT) @@ -1534,29 +1527,31 @@ move_by_pieces_1 (genfun, mode, data) enum machine_mode mode; struct move_by_pieces *data; { - register int size = GET_MODE_SIZE (mode); - register rtx to1, from1; + unsigned int size = GET_MODE_SIZE (mode); + rtx to1, from1; while (data->len >= size) { - if (data->reverse) data->offset -= size; - - to1 = (data->autinc_to - ? gen_rtx_MEM (mode, data->to_addr) - : copy_rtx (change_address (data->to, mode, - plus_constant (data->to_addr, - data->offset)))); - MEM_IN_STRUCT_P (to1) = data->to_struct; - RTX_UNCHANGING_P (to1) = data->to_readonly; - - from1 - = (data->autinc_from - ? gen_rtx_MEM (mode, data->from_addr) - : copy_rtx (change_address (data->from, mode, - plus_constant (data->from_addr, - data->offset)))); - MEM_IN_STRUCT_P (from1) = data->from_struct; - RTX_UNCHANGING_P (from1) = data->from_readonly; + if (data->reverse) + data->offset -= size; + + if (data->autinc_to) + { + to1 = gen_rtx_MEM (mode, data->to_addr); + MEM_COPY_ATTRIBUTES (to1, data->to); + } + else + to1 = change_address (data->to, mode, + plus_constant (data->to_addr, data->offset)); + + if (data->autinc_from) + { + from1 = gen_rtx_MEM (mode, data->from_addr); + MEM_COPY_ATTRIBUTES (from1, data->from); + } + else + from1 = change_address (data->from, mode, + plus_constant (data->from_addr, data->offset)); if (HAVE_PRE_DECREMENT && data->explicit_inc_to < 0) emit_insn (gen_add2_insn (data->to_addr, GEN_INT (-size))); @@ -1564,12 +1559,14 @@ move_by_pieces_1 (genfun, mode, data) emit_insn (gen_add2_insn (data->from_addr, GEN_INT (-size))); emit_insn ((*genfun) (to1, from1)); + if (HAVE_POST_INCREMENT && data->explicit_inc_to > 0) emit_insn (gen_add2_insn (data->to_addr, GEN_INT (size))); if (HAVE_POST_INCREMENT && data->explicit_inc_from > 0) emit_insn (gen_add2_insn (data->from_addr, GEN_INT (size))); - if (! data->reverse) data->offset += size; + if (! data->reverse) + data->offset += size; data->len -= size; } @@ -2243,12 +2240,12 @@ use_group_regs (call_fusage, regs) static void clear_by_pieces (to, len, align) rtx to; - int len; + unsigned HOST_WIDE_INT len; unsigned int align; { struct clear_by_pieces data; rtx to_addr = XEXP (to, 0); - unsigned int max_size = MOVE_MAX_PIECES + 1; + unsigned HOST_WIDE_INT max_size = MOVE_MAX_PIECES + 1; enum machine_mode mode = VOIDmode, tmode; enum insn_code icode; @@ -2265,8 +2262,6 @@ clear_by_pieces (to, len, align) if (data.reverse) data.offset = len; data.len = len; - data.to_struct = MEM_IN_STRUCT_P (to); - /* If copying requires more than two move insns, copy addresses to registers (to make displacements shorter) and use post-increment if available. */ @@ -2285,13 +2280,16 @@ clear_by_pieces (to, len, align) data.autinc_to = 1; data.explicit_inc_to = -1; } - if (USE_STORE_POST_INCREMENT (mode) && ! data.reverse && ! data.autinc_to) + + if (USE_STORE_POST_INCREMENT (mode) && ! data.reverse + && ! data.autinc_to) { data.to_addr = copy_addr_to_reg (to_addr); data.autinc_to = 1; data.explicit_inc_to = 1; } - if (!data.autinc_to && CONSTANT_P (to_addr)) + + if ( !data.autinc_to && CONSTANT_P (to_addr)) data.to_addr = copy_addr_to_reg (to_addr); } @@ -2334,28 +2332,33 @@ clear_by_pieces_1 (genfun, mode, data) enum machine_mode mode; struct clear_by_pieces *data; { - register int size = GET_MODE_SIZE (mode); - register rtx to1; + unsigned int size = GET_MODE_SIZE (mode); + rtx to1; while (data->len >= size) { - if (data->reverse) data->offset -= size; + if (data->reverse) + data->offset -= size; - to1 = (data->autinc_to - ? gen_rtx_MEM (mode, data->to_addr) - : copy_rtx (change_address (data->to, mode, - plus_constant (data->to_addr, - data->offset)))); - MEM_IN_STRUCT_P (to1) = data->to_struct; + if (data->autinc_to) + { + to1 = gen_rtx_MEM (mode, data->to_addr); + MEM_COPY_ATTRIBUTES (to1, data->to); + } + else + to1 = change_address (data->to, mode, + plus_constant (data->to_addr, data->offset)); if (HAVE_PRE_DECREMENT && data->explicit_inc_to < 0) emit_insn (gen_add2_insn (data->to_addr, GEN_INT (-size))); emit_insn ((*genfun) (to1, const0_rtx)); + if (HAVE_POST_INCREMENT && data->explicit_inc_to > 0) emit_insn (gen_add2_insn (data->to_addr, GEN_INT (size))); - if (! data->reverse) data->offset += size; + if (! data->reverse) + data->offset += size; data->len -= size; } @@ -2627,17 +2630,17 @@ emit_move_insn_1 (x, y) regardless of machine's endianness. */ #ifdef STACK_GROWS_DOWNWARD emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code) - (gen_rtx_MEM (submode, (XEXP (x, 0))), + (gen_rtx_MEM (submode, XEXP (x, 0)), gen_imagpart (submode, y))); emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code) - (gen_rtx_MEM (submode, (XEXP (x, 0))), + (gen_rtx_MEM (submode, XEXP (x, 0)), gen_realpart (submode, y))); #else emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code) - (gen_rtx_MEM (submode, (XEXP (x, 0))), + (gen_rtx_MEM (submode, XEXP (x, 0)), gen_realpart (submode, y))); emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code) - (gen_rtx_MEM (submode, (XEXP (x, 0))), + (gen_rtx_MEM (submode, XEXP (x, 0)), gen_imagpart (submode, y))); #endif } @@ -2866,7 +2869,7 @@ push_block (size, extra, below) - INTVAL (size) - (below ? 0 : extra)); else if (extra != 0 && !below) temp = gen_rtx_PLUS (Pmode, virtual_outgoing_args_rtx, - negate_rtx (Pmode, plus_constant (size, extra))); + negate_rtx (Pmode, plus_constant (size, extra))); else temp = gen_rtx_PLUS (Pmode, virtual_outgoing_args_rtx, negate_rtx (Pmode, size)); @@ -3105,6 +3108,11 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra, if (GET_CODE (size) == CONST_INT && MOVE_BY_PIECES_P ((unsigned) INTVAL (size), align)) { + rtx target = gen_rtx_MEM (BLKmode, temp); + + if (type != 0) + set_mem_attributes (target, type, 1); + move_by_pieces (gen_rtx_MEM (BLKmode, temp), xinner, INTVAL (size), align); goto ret; @@ -3115,6 +3123,9 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra, enum machine_mode mode; rtx target = gen_rtx_MEM (BLKmode, temp); + if (type != 0) + set_mem_attributes (target, type, 1); + for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode; mode = GET_MODE_WIDER_MODE (mode)) @@ -3251,6 +3262,7 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra, { rtx addr; rtx target = NULL_RTX; + rtx dest; /* Push padding now if padding above and stack grows down, or if padding below and stack grows up. @@ -3279,7 +3291,11 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra, target = addr; } - emit_move_insn (gen_rtx_MEM (mode, addr), x); + dest = gen_rtx_MEM (mode, addr); + if (type != 0) + set_mem_attributes (dest, type, 1); + + emit_move_insn (dest, x); if (current_function_check_memory_usage && ! in_check_memory_usage) { @@ -3994,6 +4010,10 @@ store_expr (exp, target, want_value) if (size != const0_rtx) { + rtx dest = gen_rtx_MEM (BLKmode, addr); + + MEM_COPY_ATTRIBUTES (dest, target); + /* Be sure we can write on ADDR. */ in_check_memory_usage = 1; if (current_function_check_memory_usage) @@ -4003,7 +4023,7 @@ store_expr (exp, target, want_value) GEN_INT (MEMORY_USE_WO), TYPE_MODE (integer_type_node)); in_check_memory_usage = 0; - clear_storage (gen_rtx_MEM (BLKmode, addr), size, align); + clear_storage (target, size, align); } if (label) @@ -5980,10 +6000,11 @@ expand_expr (exp, target, tmode, modifier) abort (); addr = XEXP (DECL_RTL (exp), 0); if (GET_CODE (addr) == MEM) - addr = gen_rtx_MEM (Pmode, - fix_lexical_addr (XEXP (addr, 0), exp)); + addr = change_address (addr, Pmode, + fix_lexical_addr (XEXP (addr, 0), exp)); else addr = fix_lexical_addr (addr, exp); + temp = change_address (DECL_RTL (exp), mode, addr); } @@ -6418,7 +6439,6 @@ expand_expr (exp, target, tmode, modifier) case INDIRECT_REF: { tree exp1 = TREE_OPERAND (exp, 0); - tree exp2; tree index; tree string = string_constant (exp1, &index); @@ -6456,19 +6476,7 @@ expand_expr (exp, target, tmode, modifier) } temp = gen_rtx_MEM (mode, op0); - /* If address was computed by addition, - mark this as an element of an aggregate. */ - if (TREE_CODE (exp1) == PLUS_EXPR - || (TREE_CODE (exp1) == SAVE_EXPR - && TREE_CODE (TREE_OPERAND (exp1, 0)) == PLUS_EXPR) - || AGGREGATE_TYPE_P (TREE_TYPE (exp)) - || (TREE_CODE (exp1) == ADDR_EXPR - && (exp2 = TREE_OPERAND (exp1, 0)) - && AGGREGATE_TYPE_P (TREE_TYPE (exp2)))) - MEM_SET_IN_STRUCT_P (temp, 1); - - MEM_VOLATILE_P (temp) = TREE_THIS_VOLATILE (exp) | flag_volatile; - MEM_ALIAS_SET (temp) = get_alias_set (exp); + set_mem_attributes (temp, exp, 0); /* It is incorrect to set RTX_UNCHANGING_P from TREE_READONLY here, because, in C and C++, the fact that a location is accessed @@ -6893,13 +6901,10 @@ expand_expr (exp, target, tmode, modifier) plus_constant (XEXP (op0, 0), (bitpos / BITS_PER_UNIT))); - if (GET_CODE (op0) == MEM) - MEM_ALIAS_SET (op0) = get_alias_set (exp); - + set_mem_attributes (op0, exp, 0); if (GET_CODE (XEXP (op0, 0)) == REG) mark_reg_pointer (XEXP (op0, 0), alignment); - MEM_SET_IN_STRUCT_P (op0, 1); MEM_VOLATILE_P (op0) |= volatilep; if (mode == mode1 || mode1 == BLKmode || mode1 == tmode || modifier == EXPAND_CONST_ADDRESS diff --git a/gcc/expr.h b/gcc/expr.h index 8d7a9d8..ca82ab1 100644 --- a/gcc/expr.h +++ b/gcc/expr.h @@ -94,8 +94,8 @@ struct args_size #define ADD_PARM_SIZE(TO, INC) \ { tree inc = (INC); \ - if (TREE_CODE (inc) == INTEGER_CST) \ - (TO).constant += TREE_INT_CST_LOW (inc); \ + if (host_integerp (inc, 0)) \ + (TO).constant += tree_low_cst (inc, 0); \ else if ((TO).var == 0) \ (TO).var = inc; \ else \ @@ -103,8 +103,8 @@ struct args_size #define SUB_PARM_SIZE(TO, DEC) \ { tree dec = (DEC); \ - if (TREE_CODE (dec) == INTEGER_CST) \ - (TO).constant -= TREE_INT_CST_LOW (dec); \ + if (host_integerp (dec, 0)) \ + (TO).constant -= tree_low_cst (dec, 0); \ else if ((TO).var == 0) \ (TO).var = size_binop (MINUS_EXPR, ssize_int (0), dec); \ else \ @@ -915,7 +915,16 @@ extern rtx expand_builtin_va_arg PARAMS ((tree, tree)); extern rtx expand_builtin_setjmp PARAMS ((rtx, rtx, rtx, rtx)); extern void expand_builtin_longjmp PARAMS ((rtx, rtx)); extern rtx expand_builtin_saveregs PARAMS ((void)); -extern int get_varargs_alias_set PARAMS ((void)); +extern HOST_WIDE_INT get_varargs_alias_set PARAMS ((void)); +extern HOST_WIDE_INT get_frame_alias_set PARAMS ((void)); +extern void record_base_value PARAMS ((unsigned int, rtx, int)); +extern void record_alias_subset PARAMS ((HOST_WIDE_INT, + HOST_WIDE_INT)); +#ifdef TREE_CODE +extern HOST_WIDE_INT get_alias_set PARAMS ((tree)); +extern HOST_WIDE_INT (*lang_get_alias_set) PARAMS ((tree)); +#endif +extern HOST_WIDE_INT new_alias_set PARAMS ((void)); /* Functions from expr.c: */ @@ -1013,10 +1022,9 @@ extern void emit_push_insn PARAMS ((rtx, enum machine_mode, tree, rtx, int, rtx)); /* Emit library call. */ -extern void emit_library_call PARAMS ((rtx orgfun, int no_queue, - enum machine_mode outmode, int nargs, ...)); -extern rtx emit_library_call_value PARAMS ((rtx orgfun, rtx value, int no_queue, - enum machine_mode outmode, int nargs, ...)); +extern void emit_library_call PARAMS ((rtx, int, enum machine_mode, int, ...)); +extern rtx emit_library_call_value PARAMS ((rtx, rtx, int, enum machine_mode, + int, ...)); /* Expand an assignment that stores the value of FROM into TO. */ extern rtx expand_assignment PARAMS ((tree, tree, int, int)); @@ -1100,10 +1108,17 @@ extern rtx prepare_call_address PARAMS ((rtx, tree, rtx *, int)); extern rtx expand_call PARAMS ((tree, rtx, int)); -extern rtx expand_shift PARAMS ((enum tree_code, enum machine_mode, rtx, tree, rtx, int)); -extern rtx expand_divmod PARAMS ((int, enum tree_code, enum machine_mode, rtx, rtx, rtx, int)); -extern void locate_and_pad_parm PARAMS ((enum machine_mode, tree, int, tree, struct args_size *, struct args_size *, struct args_size *, struct args_size *)); +extern rtx expand_shift PARAMS ((enum tree_code, enum machine_mode, rtx, tree, + rtx, int)); +extern rtx expand_divmod PARAMS ((int, enum tree_code, enum machine_mode, rtx, + rtx, rtx, int)); +extern void locate_and_pad_parm PARAMS ((enum machine_mode, tree, int, tree, + struct args_size *, + struct args_size *, + struct args_size *, + struct args_size *)); extern rtx expand_inline_function PARAMS ((tree, tree, rtx, int, tree, rtx)); + /* Return the CODE_LABEL rtx for a LABEL_DECL, creating it if necessary. */ extern rtx label_rtx PARAMS ((tree)); #endif @@ -1132,9 +1147,15 @@ extern rtx change_address PARAMS ((rtx, enum machine_mode, rtx)); /* Return a memory reference like MEMREF, but which is known to have a valid address. */ - extern rtx validize_mem PARAMS ((rtx)); +#ifdef TREE_CODE +/* Given REF, a MEM, and T, either the type of X or the expression + corresponding to REF, set the memory attributes. OBJECTP is nonzero + if we are making a new object of this type. */ +extern void set_mem_attributes PARAMS ((rtx, tree, int)); +#endif + /* Assemble the static constant template for function entry trampolines. */ extern rtx assemble_trampoline_template PARAMS ((void)); diff --git a/gcc/function.c b/gcc/function.c index 1c67eec..978dc81 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -204,7 +204,7 @@ struct temp_slot imposed on the memory. For example, if the stack slot is the call frame for an inline functioned, we have no idea what alias sets will be assigned to various pieces of the call frame. */ - int alias_set; + HOST_WIDE_INT alias_set; /* The value of `sequence_rtl_expr' when this temporary is allocated. */ tree rtl_expr; /* Non-zero if this temporary is currently in use. */ @@ -628,6 +628,7 @@ assign_stack_local_1 (mode, size, align, function) /* Wrapper around assign_stack_local_1; assign a local stack slot for the current function. */ + rtx assign_stack_local (mode, size, align) enum machine_mode mode; @@ -662,7 +663,7 @@ assign_stack_temp_for_type (mode, size, keep, type) tree type; { int align; - int alias_set; + HOST_WIDE_INT alias_set; struct temp_slot *p, *best_p = 0; /* If SIZE is -1 it means that somebody tried to allocate a temporary @@ -684,6 +685,7 @@ assign_stack_temp_for_type (mode, size, keep, type) if (! type) type = type_for_mode (mode, 0); + if (type) align = LOCAL_ALIGNMENT (type, align); @@ -693,7 +695,7 @@ assign_stack_temp_for_type (mode, size, keep, type) for (p = temp_slots; p; p = p->next) if (p->align >= align && p->size >= size && GET_MODE (p->slot) == mode && ! p->in_use - && (!flag_strict_aliasing + && (! flag_strict_aliasing || (alias_set && p->alias_set == alias_set)) && (best_p == 0 || best_p->size > p->size || (best_p->size == p->size && best_p->align > p->align))) @@ -712,11 +714,7 @@ assign_stack_temp_for_type (mode, size, keep, type) /* If there are enough aligned bytes left over, make them into a new temp_slot so that the extra bytes don't get wasted. Do this only for BLKmode slots, so that we can be sure of the alignment. */ - if (GET_MODE (best_p->slot) == BLKmode - /* We can't split slots if -fstrict-aliasing because the - information about the alias set for the new slot will be - lost. */ - && !flag_strict_aliasing) + if (GET_MODE (best_p->slot) == BLKmode) { int alignment = best_p->align / BITS_PER_UNIT; HOST_WIDE_INT rounded_size = CEIL_ROUND (size, alignment); @@ -734,6 +732,7 @@ assign_stack_temp_for_type (mode, size, keep, type) p->align = best_p->align; p->address = 0; p->rtl_expr = 0; + p->alias_set = best_p->alias_set; p->next = temp_slots; temp_slots = p; @@ -824,7 +823,11 @@ assign_stack_temp_for_type (mode, size, keep, type) RTX_UNCHANGING_P (p->slot) = 0; MEM_IN_STRUCT_P (p->slot) = 0; MEM_SCALAR_P (p->slot) = 0; - MEM_ALIAS_SET (p->slot) = 0; + MEM_ALIAS_SET (p->slot) = alias_set; + + if (type != 0) + MEM_SET_IN_STRUCT_P (p->slot, AGGREGATE_TYPE_P (type)); + return p->slot; } @@ -875,11 +878,10 @@ assign_temp (type, keep, memory_required, dont_promote) instead. This is the case for Chill variable-sized strings. */ if (size == -1 && TREE_CODE (type) == ARRAY_TYPE && TYPE_ARRAY_MAX_SIZE (type) != NULL_TREE - && TREE_CODE (TYPE_ARRAY_MAX_SIZE (type)) == INTEGER_CST) - size = TREE_INT_CST_LOW (TYPE_ARRAY_MAX_SIZE (type)); + && host_integerp (TYPE_ARRAY_MAX_SIZE (type), 1)) + size = tree_low_cst (TYPE_ARRAY_MAX_SIZE (type), 1); tmp = assign_stack_temp_for_type (mode, size, keep, type); - MEM_SET_IN_STRUCT_P (tmp, AGGREGATE_TYPE_P (type)); return tmp; } @@ -1397,8 +1399,12 @@ put_var_into_stack (decl) else put_reg_into_stack (function, reg, TREE_TYPE (decl), promoted_mode, decl_mode, - TREE_SIDE_EFFECTS (decl), 0, - TREE_USED (decl) || DECL_INITIAL (decl) != 0, + (TREE_CODE (decl) != SAVE_EXPR + && TREE_THIS_VOLATILE (decl)), + 0, + (TREE_USED (decl) + || (TREE_CODE (decl) != SAVE_EXPR + && DECL_INITIAL (decl) != 0)), 0); } else if (GET_CODE (reg) == CONCAT) @@ -2840,9 +2846,14 @@ put_addressof_into_stack (r, ht) abort (); put_reg_into_stack (0, reg, TREE_TYPE (decl), GET_MODE (reg), - DECL_MODE (decl), TREE_SIDE_EFFECTS (decl), + GET_MODE (reg), + (TREE_CODE (decl) != SAVE_EXPR + && TREE_THIS_VOLATILE (decl)), ADDRESSOF_REGNO (r), - TREE_USED (decl) || DECL_INITIAL (decl) != 0, ht); + (TREE_USED (decl) + || (TREE_CODE (decl) != SAVE_EXPR + && DECL_INITIAL (decl) != 0)), + ht); } /* List of replacements made below in purge_addressof_1 when creating @@ -4168,7 +4179,6 @@ assign_parms (fndecl) for (parm = fnargs; parm; parm = TREE_CHAIN (parm)) { - int aggregate = AGGREGATE_TYPE_P (TREE_TYPE (parm)); struct args_size stack_offset; struct args_size arg_size; int passed_pointer = 0; @@ -4325,12 +4335,7 @@ assign_parms (fndecl) internal_arg_pointer, offset_rtx)); - /* If this is a memory ref that contains aggregate components, - mark it as such for cse and loop optimize. Likewise if it - is readonly. */ - MEM_SET_IN_STRUCT_P (stack_parm, aggregate); - RTX_UNCHANGING_P (stack_parm) = TREE_READONLY (parm); - MEM_ALIAS_SET (stack_parm) = get_alias_set (parm); + set_mem_attributes (stack_parm, parm, 1); } /* If this parameter was passed both in registers and in the stack, @@ -4435,38 +4440,6 @@ assign_parms (fndecl) && nominal_mode != BLKmode && nominal_mode != passed_mode) stack_parm = 0; -#if 0 - /* Now adjust STACK_PARM to the mode and precise location - where this parameter should live during execution, - if we discover that it must live in the stack during execution. - To make debuggers happier on big-endian machines, we store - the value in the last bytes of the space available. */ - - if (nominal_mode != BLKmode && nominal_mode != passed_mode - && stack_parm != 0) - { - rtx offset_rtx; - - if (BYTES_BIG_ENDIAN - && GET_MODE_SIZE (nominal_mode) < UNITS_PER_WORD) - stack_offset.constant += (GET_MODE_SIZE (passed_mode) - - GET_MODE_SIZE (nominal_mode)); - - offset_rtx = ARGS_SIZE_RTX (stack_offset); - if (offset_rtx == const0_rtx) - stack_parm = gen_rtx_MEM (nominal_mode, internal_arg_pointer); - else - stack_parm = gen_rtx_MEM (nominal_mode, - gen_rtx_PLUS (Pmode, - internal_arg_pointer, - offset_rtx)); - - /* If this is a memory ref that contains aggregate components, - mark it as such for cse and loop optimize. */ - MEM_SET_IN_STRUCT_P (stack_parm, aggregate); - } -#endif /* 0 */ - /* ENTRY_PARM is an RTX for the parameter as it arrives, in the mode in which it arrives. STACK_PARM is an RTX for a stack slot where the parameter can live @@ -4506,18 +4479,12 @@ assign_parms (fndecl) stack_parm = assign_stack_local (GET_MODE (entry_parm), size_stored, 0); - - /* If this is a memory ref that contains aggregate - components, mark it as such for cse and loop optimize. */ - MEM_SET_IN_STRUCT_P (stack_parm, aggregate); + set_mem_attributes (stack_parm, parm, 1); } else if (PARM_BOUNDARY % BITS_PER_WORD != 0) abort (); - if (TREE_READONLY (parm)) - RTX_UNCHANGING_P (stack_parm) = 1; - /* Handle calls that pass values in multiple non-contiguous locations. The Irix 6 ABI has examples of this. */ if (GET_CODE (entry_parm) == PARALLEL) @@ -4566,7 +4533,7 @@ assign_parms (fndecl) { DECL_RTL (parm) = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (passed_type)), parmreg); - MEM_SET_IN_STRUCT_P (DECL_RTL (parm), aggregate); + set_mem_attributes (DECL_RTL (parm), parm, 1); } else DECL_RTL (parm) = parmreg; @@ -4672,8 +4639,7 @@ assign_parms (fndecl) else copy = assign_stack_temp (TYPE_MODE (type), int_size_in_bytes (type), 1); - MEM_SET_IN_STRUCT_P (copy, AGGREGATE_TYPE_P (type)); - RTX_UNCHANGING_P (copy) = TREE_READONLY (parm); + set_mem_attributes (copy, parm); store_expr (parm, copy, 0); emit_move_insn (parmreg, XEXP (copy, 0)); @@ -4824,9 +4790,7 @@ assign_parms (fndecl) stack_parm = assign_stack_local (GET_MODE (entry_parm), GET_MODE_SIZE (GET_MODE (entry_parm)), 0); - /* If this is a memory ref that contains aggregate components, - mark it as such for cse and loop optimize. */ - MEM_SET_IN_STRUCT_P (stack_parm, aggregate); + set_mem_attributes (stack_parm, parm, 1); } if (promoted_mode != nominal_mode) @@ -4863,19 +4827,12 @@ assign_parms (fndecl) if (parm == function_result_decl) { tree result = DECL_RESULT (fndecl); - tree restype = TREE_TYPE (result); DECL_RTL (result) = gen_rtx_MEM (DECL_MODE (result), DECL_RTL (parm)); - MEM_SET_IN_STRUCT_P (DECL_RTL (result), - AGGREGATE_TYPE_P (restype)); + set_mem_attributes (DECL_RTL (result), result, 1); } - - if (TREE_THIS_VOLATILE (parm)) - MEM_VOLATILE_P (DECL_RTL (parm)) = 1; - if (TREE_READONLY (parm)) - RTX_UNCHANGING_P (DECL_RTL (parm)) = 1; } /* Output all parameter conversion instructions (possibly including calls) @@ -5398,7 +5355,9 @@ fix_lexical_addr (addr, var) addr = fix_lexical_addr (XEXP (fp->x_arg_pointer_save_area, 0), var); addr = memory_address (Pmode, addr); - base = copy_to_reg (gen_rtx_MEM (Pmode, addr)); + base = gen_rtx_MEM (Pmode, addr); + MEM_ALIAS_SET (base) = get_frame_alias_set (); + base = copy_to_reg (base); #else displacement += (FIRST_PARM_OFFSET (context) - STARTING_FRAME_OFFSET); base = lookup_static_chain (var); @@ -6149,10 +6108,8 @@ expand_function_start (subr, parms_have_cleanups) { DECL_RTL (DECL_RESULT (subr)) = gen_rtx_MEM (DECL_MODE (DECL_RESULT (subr)), value_address); - MEM_SET_IN_STRUCT_P (DECL_RTL (DECL_RESULT (subr)), - AGGREGATE_TYPE_P (TREE_TYPE - (DECL_RESULT - (subr)))); + set_mem_attributes (DECL_RTL (DECL_RESULT (subr)), + DECL_RESULT (subr), 1); } } else if (DECL_MODE (DECL_RESULT (subr)) == VOIDmode) @@ -6247,9 +6204,9 @@ expand_function_start (subr, parms_have_cleanups) #ifdef FRAME_GROWS_DOWNWARD last_ptr = plus_constant (last_ptr, - GET_MODE_SIZE (Pmode)); #endif - last_ptr = copy_to_reg (gen_rtx_MEM (Pmode, - memory_address (Pmode, - last_ptr))); + last_ptr = gen_rtx_MEM (Pmode, memory_address (Pmode, last_ptr)); + MEM_ALIAS_SET (last_ptr) = get_frame_alias_set (); + last_ptr = copy_to_reg (last_ptr); /* If we are not optimizing, ensure that we know that this piece of context is live over the entire function. */ diff --git a/gcc/recog.c b/gcc/recog.c index ed4b135..556f9f9 100644 --- a/gcc/recog.c +++ b/gcc/recog.c @@ -1939,11 +1939,10 @@ mode_independent_operand (op, mode) return 0; } -/* Given an operand OP that is a valid memory reference - which satisfies offsettable_memref_p, - return a new memory reference whose address has been adjusted by OFFSET. - OFFSET should be positive and less than the size of the object referenced. -*/ +/* Given an operand OP that is a valid memory reference which + satisfies offsettable_memref_p, return a new memory reference whose + address has been adjusted by OFFSET. OFFSET should be positive and + less than the size of the object referenced. */ rtx adj_offsettable_operand (op, offset) @@ -1961,7 +1960,7 @@ adj_offsettable_operand (op, offset) { new = gen_rtx_MEM (GET_MODE (op), plus_constant_for_output (y, offset)); - RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (op); + MEM_COPY_ATTRIBUTES (new, op); return new; } @@ -1981,7 +1980,7 @@ adj_offsettable_operand (op, offset) } new = gen_rtx_MEM (GET_MODE (op), plus_constant_for_output (y, offset)); - RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (op); + MEM_COPY_ATTRIBUTES (new, op); return new; } abort (); diff --git a/gcc/regmove.c b/gcc/regmove.c index 5b244a0..44d63e2 100644 --- a/gcc/regmove.c +++ b/gcc/regmove.c @@ -2234,6 +2234,8 @@ try_apply_stack_adjustment (insn, memlist, new_adjust, delta) for (ml = memlist; ml ; ml = ml->next) { HOST_WIDE_INT c = ml->sp_offset - delta; + rtx new = gen_rtx_MEM (GET_MODE (*ml->mem), + plus_constant (stack_pointer_rtx, c)); /* Don't reference memory below the stack pointer. */ if (c < 0) @@ -2242,9 +2244,8 @@ try_apply_stack_adjustment (insn, memlist, new_adjust, delta) return 0; } - validate_change (ml->insn, ml->mem, - gen_rtx_MEM (GET_MODE (*ml->mem), - plus_constant (stack_pointer_rtx, c)), 1); + MEM_COPY_ATTRIBUTES (new, *ml->mem); + validate_change (ml->insn, ml->mem, new, 1); } if (apply_change_group ()) diff --git a/gcc/reload.c b/gcc/reload.c index d19b1d8..0a6d14c 100644 --- a/gcc/reload.c +++ b/gcc/reload.c @@ -860,10 +860,20 @@ push_reload (in, out, inloc, outloc, class, { if (GET_CODE (XEXP (in, 0)) == POST_INC || GET_CODE (XEXP (in, 0)) == POST_DEC) - in = gen_rtx_MEM (GET_MODE (in), XEXP (XEXP (in, 0), 0)); + { + rtx new = gen_rtx_MEM (GET_MODE (in), XEXP (XEXP (in, 0), 0)); + + MEM_COPY_ATTRIBUTES (new, in); + in = new; + } if (GET_CODE (XEXP (in, 0)) == PRE_INC || GET_CODE (XEXP (in, 0)) == PRE_DEC) - out = gen_rtx_MEM (GET_MODE (out), XEXP (XEXP (out, 0), 0)); + { + rtx new = gen_rtx_MEM (GET_MODE (out), XEXP (XEXP (out, 0), 0)); + + MEM_COPY_ATTRIBUTES (new, out); + out = new; + } } /* If we are reloading a (SUBREG constant ...), really reload just the @@ -4344,7 +4354,7 @@ make_memloc (ad, regno) tem = copy_rtx (tem); tem = gen_rtx_MEM (GET_MODE (ad), tem); - RTX_UNCHANGING_P (tem) = RTX_UNCHANGING_P (regno_reg_rtx[regno]); + MEM_COPY_ATTRIBUTES (tem, reg_equiv_memory_loc[regno]); return tem; } diff --git a/gcc/reload1.c b/gcc/reload1.c index c0bf424..3378a68 100644 --- a/gcc/reload1.c +++ b/gcc/reload1.c @@ -1913,13 +1913,18 @@ alter_reg (i, from_reg) adjust = inherent_size - total_size; RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (regno_reg_rtx[i]); + + /* Nothing can alias this slot except this pseudo. */ + MEM_ALIAS_SET (x) = new_alias_set (); } + /* Reuse a stack slot if possible. */ else if (spill_stack_slot[from_reg] != 0 && spill_stack_slot_width[from_reg] >= total_size && (GET_MODE_SIZE (GET_MODE (spill_stack_slot[from_reg])) >= inherent_size)) x = spill_stack_slot[from_reg]; + /* Allocate a bigger slot. */ else { @@ -1927,6 +1932,7 @@ alter_reg (i, from_reg) and for total size. */ enum machine_mode mode = GET_MODE (regno_reg_rtx[i]); rtx stack_slot; + if (spill_stack_slot[from_reg]) { if (GET_MODE_SIZE (GET_MODE (spill_stack_slot[from_reg])) @@ -1935,10 +1941,18 @@ alter_reg (i, from_reg) if (spill_stack_slot_width[from_reg] > total_size) total_size = spill_stack_slot_width[from_reg]; } + /* Make a slot with that size. */ x = assign_stack_local (mode, total_size, inherent_size == total_size ? 0 : -1); stack_slot = x; + + /* All pseudos mapped to this slot can alias each other. */ + if (spill_stack_slot[from_reg]) + MEM_ALIAS_SET (x) = MEM_ALIAS_SET (spill_stack_slot[from_reg]); + else + MEM_ALIAS_SET (x) = new_alias_set (); + if (BYTES_BIG_ENDIAN) { /* Cancel the big-endian correction done in assign_stack_local. @@ -1952,6 +1966,7 @@ alter_reg (i, from_reg) MODE_INT, 1), plus_constant (XEXP (x, 0), adjust)); } + spill_stack_slot[from_reg] = stack_slot; spill_stack_slot_width[from_reg] = total_size; } @@ -1965,16 +1980,11 @@ alter_reg (i, from_reg) wrong mode, make a new stack slot. */ if (adjust != 0 || GET_MODE (x) != GET_MODE (regno_reg_rtx[i])) { - x = gen_rtx_MEM (GET_MODE (regno_reg_rtx[i]), - plus_constant (XEXP (x, 0), adjust)); - - /* If this was shared among registers, must ensure we never - set it readonly since that can cause scheduling - problems. Note we would only have in this adjustment - case in any event, since the code above doesn't set it. */ + rtx new = gen_rtx_MEM (GET_MODE (regno_reg_rtx[i]), + plus_constant (XEXP (x, 0), adjust)); - if (from_reg == -1) - RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (regno_reg_rtx[i]); + MEM_COPY_ATTRIBUTES (new, x); + x = new; } /* Save the stack slot for later. */ @@ -2496,9 +2506,7 @@ eliminate_regs (x, mem_mode, insn) if (new != XEXP (x, 0)) { new = gen_rtx_MEM (GET_MODE (x), new); - new->volatil = x->volatil; - new->unchanging = x->unchanging; - new->in_struct = x->in_struct; + MEM_COPY_ATTRIBUTES (new, x); return new; } else diff --git a/gcc/rtl.def b/gcc/rtl.def index 1f628aa..dc0d95b 100644 --- a/gcc/rtl.def +++ b/gcc/rtl.def @@ -628,7 +628,7 @@ DEF_RTL_EXPR(CONCAT, "concat", "ee", 'o') /* A memory location; operand is the address. Can be nested inside a VOLATILE. The second operand is the alias set to which this MEM - belongs. We use `0' instead of `i' for this field so that the + belongs. We use `0' instead of `w' for this field so that the field need not be specified in machine descriptions. */ DEF_RTL_EXPR(MEM, "mem", "e0", 'o') diff --git a/gcc/rtl.h b/gcc/rtl.h index de0c37d..cca5d52 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -746,8 +746,10 @@ extern const char * const note_insn_name[NOTE_INSN_MAX - NOTE_INSN_BIAS]; #define ASM_OPERANDS_INPUT_CONSTRAINT_VEC(RTX) XCVEC ((RTX), 4, ASM_OPERANDS) #define ASM_OPERANDS_INPUT(RTX, N) XCVECEXP ((RTX), 3, (N), ASM_OPERANDS) #define ASM_OPERANDS_INPUT_LENGTH(RTX) XCVECLEN ((RTX), 3, ASM_OPERANDS) -#define ASM_OPERANDS_INPUT_CONSTRAINT(RTX, N) XSTR (XCVECEXP ((RTX), 4, (N), ASM_OPERANDS), 0) -#define ASM_OPERANDS_INPUT_MODE(RTX, N) GET_MODE (XCVECEXP ((RTX), 4, (N), ASM_OPERANDS)) +#define ASM_OPERANDS_INPUT_CONSTRAINT(RTX, N) \ + XSTR (XCVECEXP ((RTX), 4, (N), ASM_OPERANDS), 0) +#define ASM_OPERANDS_INPUT_MODE(RTX, N) \ + GET_MODE (XCVECEXP ((RTX), 4, (N), ASM_OPERANDS)) #define ASM_OPERANDS_SOURCE_FILE(RTX) XCSTR ((RTX), 5, ASM_OPERANDS) #define ASM_OPERANDS_SOURCE_LINE(RTX) XCINT ((RTX), 6, ASM_OPERANDS) @@ -755,22 +757,15 @@ extern const char * const note_insn_name[NOTE_INSN_MAX - NOTE_INSN_BIAS]; Also in an ASM_OPERANDS rtx. */ #define MEM_VOLATILE_P(RTX) ((RTX)->volatil) -/* For a MEM rtx, 1 if it refers to a field of an aggregate. If zero, - RTX may or may not refer to a field of an aggregate. */ +/* For a MEM rtx, 1 if it refers to an aggregate, either to the + aggregate itself of to a field of the aggregate. If zero, RTX may + or may not be such a refrence. */ #define MEM_IN_STRUCT_P(RTX) ((RTX)->in_struct) /* For a MEM rtx, 1 if it refers to a scalar. If zero, RTX may or may not refer to a scalar.*/ #define MEM_SCALAR_P(RTX) ((RTX)->frame_related) -/* Copy the attributes that apply to memory locations from RHS to LHS. */ -#define MEM_COPY_ATTRIBUTES(LHS, RHS) \ - (MEM_VOLATILE_P (LHS) = MEM_VOLATILE_P (RHS), \ - MEM_IN_STRUCT_P (LHS) = MEM_IN_STRUCT_P (RHS), \ - MEM_SCALAR_P (LHS) = MEM_SCALAR_P (RHS), \ - MEM_ALIAS_SET (LHS) = MEM_ALIAS_SET (RHS), \ - RTX_UNCHANGING_P (LHS) = RTX_UNCHANGING_P (RHS)) - /* If VAL is non-zero, set MEM_IN_STRUCT_P and clear MEM_SCALAR_P in RTX. Otherwise, vice versa. Use this macro only when you are *sure* that you know that the MEM is in a structure, or is a @@ -797,7 +792,15 @@ extern const char * const note_insn_name[NOTE_INSN_MAX - NOTE_INSN_BIAS]; some front-ends, these numbers may correspond in some way to types, or other language-level entities, but they need not, and the back-end makes no such assumptions. */ -#define MEM_ALIAS_SET(RTX) XCINT(RTX, 1, MEM) +#define MEM_ALIAS_SET(RTX) XCWINT(RTX, 1, MEM) + +/* Copy the attributes that apply to memory locations from RHS to LHS. */ +#define MEM_COPY_ATTRIBUTES(LHS, RHS) \ + (MEM_VOLATILE_P (LHS) = MEM_VOLATILE_P (RHS), \ + MEM_IN_STRUCT_P (LHS) = MEM_IN_STRUCT_P (RHS), \ + MEM_SCALAR_P (LHS) = MEM_SCALAR_P (RHS), \ + MEM_ALIAS_SET (LHS) = MEM_ALIAS_SET (RHS), \ + RTX_UNCHANGING_P (LHS) = RTX_UNCHANGING_P (RHS)) /* For a LABEL_REF, 1 means that this reference is to a label outside the loop containing the reference. */ @@ -1645,7 +1648,9 @@ extern int preserve_subexpressions_p PARAMS ((void)); /* In expr.c */ extern void init_expr_once PARAMS ((void)); -extern void move_by_pieces PARAMS ((rtx, rtx, int, unsigned int)); +extern void move_by_pieces PARAMS ((rtx, rtx, + unsigned HOST_WIDE_INT, + unsigned int)); /* In flow.c */ extern void allocate_bb_life_data PARAMS ((void)); @@ -1821,9 +1826,6 @@ extern void mark_constant_function PARAMS ((void)); extern void init_alias_once PARAMS ((void)); extern void init_alias_analysis PARAMS ((void)); extern void end_alias_analysis PARAMS ((void)); - -extern void record_base_value PARAMS ((unsigned int, rtx, int)); -extern void record_alias_subset PARAMS ((int, int)); extern rtx addr_side_effect_eval PARAMS ((rtx, int, int)); /* In sibcall.c */ diff --git a/gcc/stmt.c b/gcc/stmt.c index 3d26748..f134de1 100644 --- a/gcc/stmt.c +++ b/gcc/stmt.c @@ -3792,7 +3792,8 @@ expand_decl (decl) /* An initializer is going to decide the size of this array. Until we know the size, represent its address with a reg. */ DECL_RTL (decl) = gen_rtx_MEM (BLKmode, gen_reg_rtx (Pmode)); - MEM_SET_IN_STRUCT_P (DECL_RTL (decl), AGGREGATE_TYPE_P (type)); + + set_mem_attributes (DECL_RTL (decl), decl, 1); } else if (DECL_MODE (decl) != BLKmode /* If -ffloat-store, don't put explicit float vars @@ -3817,6 +3818,8 @@ expand_decl (decl) mark_reg_pointer (DECL_RTL (decl), TYPE_ALIGN (TREE_TYPE (TREE_TYPE (decl)))); + if (TREE_READONLY (decl)) + RTX_UNCHANGING_P (DECL_RTL (decl)) = 1; } else if (TREE_CODE (DECL_SIZE_UNIT (decl)) == INTEGER_CST @@ -3841,8 +3844,6 @@ expand_decl (decl) } DECL_RTL (decl) = assign_temp (TREE_TYPE (decl), 1, 1, 1); - MEM_SET_IN_STRUCT_P (DECL_RTL (decl), - AGGREGATE_TYPE_P (TREE_TYPE (decl))); /* Set alignment we actually gave this decl. */ DECL_ALIGN (decl) = (DECL_MODE (decl) == BLKmode ? BIGGEST_ALIGNMENT @@ -3854,20 +3855,6 @@ expand_decl (decl) if (addr != oldaddr) emit_move_insn (oldaddr, addr); } - - /* If this is a memory ref that contains aggregate components, - mark it as such for cse and loop optimize. */ - MEM_SET_IN_STRUCT_P (DECL_RTL (decl), - AGGREGATE_TYPE_P (TREE_TYPE (decl))); -#if 0 - /* If this is in memory because of -ffloat-store, - set the volatile bit, to prevent optimizations from - undoing the effects. */ - if (flag_float_store && TREE_CODE (type) == REAL_TYPE) - MEM_VOLATILE_P (DECL_RTL (decl)) = 1; -#endif - - MEM_ALIAS_SET (DECL_RTL (decl)) = get_alias_set (decl); } else /* Dynamic-size object: must push space on the stack. */ @@ -3905,10 +3892,7 @@ expand_decl (decl) /* Reference the variable indirect through that rtx. */ DECL_RTL (decl) = gen_rtx_MEM (DECL_MODE (decl), address); - /* If this is a memory ref that contains aggregate components, - mark it as such for cse and loop optimize. */ - MEM_SET_IN_STRUCT_P (DECL_RTL (decl), - AGGREGATE_TYPE_P (TREE_TYPE (decl))); + set_mem_attributes (DECL_RTL (decl), decl, 1); /* Indicate the alignment we actually gave this variable. */ #ifdef STACK_BOUNDARY @@ -3917,12 +3901,6 @@ expand_decl (decl) DECL_ALIGN (decl) = BIGGEST_ALIGNMENT; #endif } - - if (TREE_THIS_VOLATILE (decl)) - MEM_VOLATILE_P (DECL_RTL (decl)) = 1; - - if (TREE_READONLY (decl)) - RTX_UNCHANGING_P (DECL_RTL (decl)) = 1; } /* Emit code to perform the initialization of a declaration DECL. */ diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c index b28432b..a581d1f 100644 --- a/gcc/stor-layout.c +++ b/gcc/stor-layout.c @@ -1173,6 +1173,9 @@ finish_record_layout (rli) rli->pending_statics = TREE_CHAIN (rli->pending_statics); } + /* Show any alias subsetting we need. */ + record_component_aliases (rli->t); + /* Clean up. */ free (rli); } diff --git a/gcc/toplev.c b/gcc/toplev.c index ef26426..5fa9851 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -2090,13 +2090,13 @@ compile_file (name) || flag_test_coverage || warn_notreached); init_regs (); + init_alias_once (); init_decl_processing (); init_optabs (); init_stmt (); init_eh (); init_loop (); init_reload (); - init_alias_once (); init_function_once (); init_stor_layout_once (); init_varasm_once (); diff --git a/gcc/tree.c b/gcc/tree.c index c2bfab8..2a356ed 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -246,10 +246,6 @@ static int next_decl_uid; /* Unique id for next type created. */ static int next_type_uid = 1; -/* The language-specific function for alias analysis. If NULL, the - language does not do any special alias analysis. */ -int (*lang_get_alias_set) PARAMS ((tree)); - /* Here is how primitive or already-canonicalized types' hash codes are made. */ #define TYPE_HASH(TYPE) ((unsigned long) (TYPE) & 0777777) @@ -5614,38 +5610,6 @@ tree_class_check_failed (node, cl, file, line, function) #endif /* ENABLE_TREE_CHECKING */ -/* Return the alias set for T, which may be either a type or an - expression. */ - -int -get_alias_set (t) - tree t; -{ - /* If we're not doing any lanaguage-specific alias analysis, just - assume everything aliases everything else. */ - if (! flag_strict_aliasing || lang_get_alias_set == 0) - return 0; - - /* If this is a type with a known alias set, return it since this must - be the correct thing to do. */ - else if (TYPE_P (t) && TYPE_ALIAS_SET_KNOWN_P (t)) - return TYPE_ALIAS_SET (t); - else - return (*lang_get_alias_set) (t); -} - -/* Return a brand-new alias set. */ - -int -new_alias_set () -{ - static int last_alias_set; - - if (flag_strict_aliasing) - return ++last_alias_set; - else - return 0; -} #ifndef CHAR_TYPE_SIZE #define CHAR_TYPE_SIZE BITS_PER_UNIT diff --git a/gcc/tree.h b/gcc/tree.h index 13d079a..09758cb 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -1114,7 +1114,7 @@ struct tree_type union tree_node *noncopied_parts; union tree_node *context; struct obstack *obstack; - int alias_set; + HOST_WIDE_INT alias_set; /* Points to a structure whose details depend on the language in use. */ struct lang_type *lang_specific; }; @@ -1620,7 +1620,7 @@ struct tree_decl } u2; union tree_node *vindex; - int pointer_alias_set; + HOST_WIDE_INT pointer_alias_set; /* Points to a structure whose details depend on the language in use. */ struct lang_decl *lang_specific; }; @@ -2373,9 +2373,6 @@ extern tree get_file_function_name_long PARAMS ((const char *)); extern tree get_set_constructor_bits PARAMS ((tree, char *, int)); extern tree get_set_constructor_bytes PARAMS ((tree, unsigned char *, int)); -extern int get_alias_set PARAMS ((tree)); -extern int new_alias_set PARAMS ((void)); -extern int (*lang_get_alias_set) PARAMS ((tree)); extern tree get_callee_fndecl PARAMS ((tree)); /* In stmt.c */ -- 2.7.4