mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-11-26 21:33:59 +08:00
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
This commit is contained in:
parent
99923eedd0
commit
3bdf5ad138
@ -32,6 +32,87 @@ Wed May 31 13:17:20 2000 Philippe De Muyter <phdm@macqel.be>
|
||||
|
||||
Wed May 31 08:07:52 2000 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
|
||||
|
||||
* 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.
|
||||
|
||||
|
@ -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)
|
||||
|
226
gcc/alias.c
226
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;
|
||||
|
114
gcc/builtins.c
114
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;
|
||||
rtx mem = gen_rtx_MEM (BLKmode,
|
||||
memory_address (BLKmode,
|
||||
expand_expr (exp, NULL_RTX,
|
||||
ptr_mode, EXPAND_SUM)));
|
||||
|
||||
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);
|
||||
|
||||
RTX_UNCHANGING_P (mem) = TREE_READONLY (exp);
|
||||
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;
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
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;
|
||||
|
186
gcc/c-common.c
186
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)
|
||||
/* 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;
|
||||
|
||||
/* That's all the expressions we handle specially. */
|
||||
if (! TYPE_P (t))
|
||||
return -1;
|
||||
|
||||
if (TREE_CODE (t) == INTEGER_TYPE)
|
||||
{
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
/* 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;
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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 ()
|
||||
{
|
||||
|
42
gcc/calls.c
42
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. */
|
||||
|
@ -1,3 +1,12 @@
|
||||
Wed May 31 14:09:00 2000 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
|
||||
|
||||
* 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 <mark@codesourcery.com>
|
||||
|
||||
* decl.c (build_cp_library_fn): Set DECL_CONTEXT.
|
||||
|
@ -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 \
|
||||
|
@ -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;
|
||||
|
@ -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. */
|
||||
|
71
gcc/explow.c
71
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;
|
||||
|
171
gcc/expr.c
171
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;
|
||||
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;
|
||||
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));
|
||||
|
||||
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->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
|
||||
|
47
gcc/expr.h
47
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));
|
||||
|
||||
|
125
gcc/function.c
125
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. */
|
||||
|
13
gcc/recog.c
13
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 ();
|
||||
|
@ -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 ())
|
||||
|
16
gcc/reload.c
16
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;
|
||||
}
|
||||
|
||||
|
@ -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));
|
||||
rtx new = 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. */
|
||||
|
||||
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
|
||||
|
@ -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')
|
||||
|
||||
|
36
gcc/rtl.h
36
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 */
|
||||
|
32
gcc/stmt.c
32
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. */
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 ();
|
||||
|
36
gcc/tree.c
36
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
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user