summaryrefslogtreecommitdiff
path: root/gcc/c-common.c
diff options
context:
space:
mode:
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>1998-06-25 15:14:41 +0000
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>1998-06-25 15:14:41 +0000
commitb5ba9f3a669e68503666852be6e3158f03526733 (patch)
treeaf8828e1df0f3e051eb29c58c7d958cd177e474d /gcc/c-common.c
parenta85413a6ac28d432734c514cd140ee039daad06b (diff)
downloadgcc-b5ba9f3a669e68503666852be6e3158f03526733.tar.gz
* invoke.texi (-fstrict-aliasing): Document.
* rtl.texi (MEM_ALIAS_SET): Document. * flags.h (flag_strict_aliasing): Declare. * toplev.c (flag_strict_aliasing): Define. (f_options): Add -strict-aliasing. (main): Set flag_strict_aliasing if -O2 or higher. * tree.h (tree_type): Add alias_set field. (TYPE_ALIAS_SET): New macro. (TYPE_ALIAS_SET_KNOWN_P): Likewise. (get_alias_set): Declare. * tree.c (lang_get_alias_set): Define. (make_node): Initialize TYPE_ALIAS_SET. (get_alias_set): New function. * print-tree.c (print_node): Dump the alias set for a type. * c-tree.h (c_get_alias_set): Declare. * c-common.c (c_get_alias_set): New function. * c-decl.c (init_decl_processing): Set lang_get_alias_set. * expr.c (protect_from_queue): Propogage alias sets. (expand_assignment): Calculate alias set for new MEMs. (expand_expr): Likewise. * function.c (put_var_into_stack): Likewise. (put_reg_into_stack): Likewise. (gen_mem_addressof): Likewise. (assign_parms): Likewise. * stmt.c (expand_decl): Likewise. * varasm.c (make_decl_rtl): Eliminate redundant clearing of DECL_RTL. Calculate alias set for new MEMs. * rtl.def (REG): Add dummy operand. (MEM): Add extra operand to store the MEM_ALIAS_SET. * rtl.h (MEM_ALIAS_SET): New macro. (gen_rtx_MEM): Declare. * emit-rtl.c (gen_rtx_MEM): New function. * gengenrtl.c (sepcial_rtx): Make MEMs special. * alias.c (CHECK_ALIAS_SETS_FOR_CONSISTENCY): New macro. (DIFFERENT_ALIAS_SETS_P): Likewise. (canon_rtx): Propogate the alias set to the new MEM. (true_dependence): Check the alias sets. (anti_dependence): Likewise. (output_dependence): Likewise. * explow.c (stabilize): Progoate alias sets. * integrate.c (copy_rtx_and_substitute): Likewise. * final.c (alter_subreg): Make sure not to leave MEM_IN_STRUCT_P in an unpredictable state. Propogate alias sets. * reload1.c (reload): Clear MEM_ALIAS_SET for new MEMs about which we have no alias information. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@20719 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/c-common.c')
-rw-r--r--gcc/c-common.c87
1 files changed, 87 insertions, 0 deletions
diff --git a/gcc/c-common.c b/gcc/c-common.c
index 9a8d0731bdd..245fedb97be 100644
--- a/gcc/c-common.c
+++ b/gcc/c-common.c
@@ -2880,3 +2880,90 @@ c_build_type_variant (type, constp, volatilep)
TYPE_DOMAIN (type));
return build_type_variant (type, constp, volatilep);
}
+
+/* Return the typed-based alias set for T, which may be an expression
+ or a type. */
+
+int
+c_get_alias_set (t)
+ tree t;
+{
+ static int next_set = 0;
+ tree type;
+
+ if (t == error_mark_node)
+ return 0;
+
+ type = (TREE_CODE_CLASS (TREE_CODE (t)) == 't')
+ ? t : TREE_TYPE (t);
+
+ if (type == error_mark_node)
+ return 0;
+
+ if (TYPE_ALIAS_SET_KNOWN_P (type))
+ /* If we've already calculated the value, just return it. */
+ return TYPE_ALIAS_SET (type);
+
+ if (TREE_CODE (t) == BIT_FIELD_REF)
+ /* Perhaps reads and writes to this piece of data alias fields
+ neighboring the bitfield. Perhaps that's impossible. For now,
+ let's just assume that bitfields can alias everything, which is
+ the conservative assumption. */
+ return 0;
+ if (TREE_CODE (t) == COMPONENT_REF
+ && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == UNION_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 through it. Even the type-punning allowed here is a
+ GCC extension, albeit a common and useful one; the C standard
+ says that such accesses have implementation-defined behavior. */
+ return 0;
+ 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));
+ return TYPE_ALIAS_SET (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);
+
+ if (signed_variant != type)
+ {
+ TYPE_ALIAS_SET (type) = c_get_alias_set (signed_variant);
+ return TYPE_ALIAS_SET (type);
+ }
+ else 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 TYPE_ALIAS_SET (type);
+ }
+ }
+ 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;
+ return TYPE_ALIAS_SET (type);
+ }
+
+ /* TYPE is something we haven't seen before. Put it in a new alias
+ set. */
+ TYPE_ALIAS_SET (type) = ++next_set;
+ return TYPE_ALIAS_SET (type);
+}