aboutsummaryrefslogtreecommitdiff
path: root/gcc/alias.c
diff options
context:
space:
mode:
authorRichard Kenner <kenner@vlsi1.ultra.nyu.edu>2000-12-30 13:10:51 +0000
committerRichard Kenner <kenner@gcc.gnu.org>2000-12-30 08:10:51 -0500
commit1da68f560dd41ef12f15138fb1b1aff06067f4b7 (patch)
tree23f23dc6bdc5d0a2afd4675766fb43eb2ef34bc3 /gcc/alias.c
parent2e9ab75de463a34abe8d5d0749999195d6e62942 (diff)
downloadgcc-1da68f560dd41ef12f15138fb1b1aff06067f4b7.zip
gcc-1da68f560dd41ef12f15138fb1b1aff06067f4b7.tar.gz
gcc-1da68f560dd41ef12f15138fb1b1aff06067f4b7.tar.bz2
alias.c (alias_sets_conflict_p): New function.
* alias.c (alias_sets_conflict_p): New function. (mems_in_disjoint_alias_sets_p): Use it. (readonly_fields_p): Moved from expr.c; check for record type. (objects_must_conflict_p): New function. * calls.c (expand_call): Use assign_temp as much as possible, use readonly variant if assigned once, and don't set memory attributes. (emit_library_call_value_1, store_one_arg): Likewise. * integrate.c (expand_inline_function): Likewise. * stmt.c (expand_asm_operands, expand_return): Likewise. * expr.c (copy_blkmode_from_reg, store_constructor): Likewise. (store_field, save_noncopied_parts, expand_expr): Likewise. (expand_expr_unaligned): Likewise. (readonly_fields_p): Moved to alias.c. (safe_from_p): Rework handling of SAVE_EXPR. MEMs ony conflict if alias sets conflict; likewise for INDIRECT_REF. * function.c (struct temp_slot): Delete field ALIAS_SET; add TYPE. (assign_stack_for_temp): Use objects_must_confict_p. Set all memory attributes from type, if specified. (mark_temp_slot): Mark TYPE field. * tree.h (alias_sets_conflict_p, readonly_fields_p): New decls. (objects_must_conflict_p): Likewise. * stmt.c (expand_decl): Don't use assign_stack_temp in error case. (add_case_node): No need to copy nodes anymore. From-SVN: r38559
Diffstat (limited to 'gcc/alias.c')
-rw-r--r--gcc/alias.c111
1 files changed, 86 insertions, 25 deletions
diff --git a/gcc/alias.c b/gcc/alias.c
index d11d1b3..41cf596 100644
--- a/gcc/alias.c
+++ b/gcc/alias.c
@@ -211,8 +211,6 @@ mems_in_disjoint_alias_sets_p (mem1, mem2)
rtx mem1;
rtx mem2;
{
- alias_set_entry ase;
-
#ifdef ENABLE_CHECKING
/* Perform a basic sanity check. Namely, that there are no alias sets
if we're not using strict aliasing. This helps to catch bugs
@@ -226,49 +224,112 @@ mems_in_disjoint_alias_sets_p (mem1, mem2)
abort ();
#endif
- /* If have no alias set information for one of the MEMs, we have to assume
- it can alias anything. */
- if (MEM_ALIAS_SET (mem1) == 0 || MEM_ALIAS_SET (mem2) == 0)
- return 0;
+ return ! alias_sets_conflict_p (MEM_ALIAS_SET (mem1), MEM_ALIAS_SET (mem2));
+}
- /* If the two alias sets are the same, they may alias. */
- if (MEM_ALIAS_SET (mem1) == MEM_ALIAS_SET (mem2))
- return 0;
+/* Insert the NODE into the splay tree given by DATA. Used by
+ record_alias_subset via splay_tree_foreach. */
+
+static int
+insert_subset_children (node, data)
+ splay_tree_node node;
+ void *data;
+{
+ splay_tree_insert ((splay_tree) data, node->key, node->value);
+
+ return 0;
+}
+
+/* Return 1 if the two specified alias sets may conflict. */
+
+int
+alias_sets_conflict_p (set1, set2)
+ HOST_WIDE_INT set1, set2;
+{
+ alias_set_entry ase;
+
+ /* If have no alias set information for one of the operands, we have
+ to assume it can alias anything. */
+ if (set1 == 0 || set2 == 0
+ /* If the two alias sets are the same, they may alias. */
+ || set1 == set2)
+ return 1;
/* See if the first alias set is a subset of the second. */
- ase = get_alias_set_entry (MEM_ALIAS_SET (mem1));
+ ase = get_alias_set_entry (set1);
if (ase != 0
&& (ase->has_zero_child
|| splay_tree_lookup (ase->children,
- (splay_tree_key) MEM_ALIAS_SET (mem2))))
- return 0;
+ (splay_tree_key) set2)))
+ return 1;
/* Now do the same, but with the alias sets reversed. */
- ase = get_alias_set_entry (MEM_ALIAS_SET (mem2));
+ ase = get_alias_set_entry (set2);
if (ase != 0
&& (ase->has_zero_child
|| splay_tree_lookup (ase->children,
- (splay_tree_key) MEM_ALIAS_SET (mem1))))
- return 0;
+ (splay_tree_key) set1)))
+ return 1;
- /* The two MEMs are in distinct alias sets, and neither one is the
+ /* The two alias sets are distinct and neither one is the
child of the other. Therefore, they cannot alias. */
- return 1;
+ return 0;
}
+
+/* Return 1 if TYPE is a RECORD_TYPE, UNION_TYPE, or QUAL_UNION_TYPE and has
+ has any readonly fields. If any of the fields have types that
+ contain readonly fields, return true as well. */
-/* Insert the NODE into the splay tree given by DATA. Used by
- record_alias_subset via splay_tree_foreach. */
-
-static int
-insert_subset_children (node, data)
- splay_tree_node node;
- void *data;
+int
+readonly_fields_p (type)
+ tree type;
{
- splay_tree_insert ((splay_tree) data, node->key, node->value);
+ tree field;
+
+ if (TREE_CODE (type) != RECORD_TYPE && TREE_CODE (type) != UNION_TYPE
+ && TREE_CODE (type) != QUAL_UNION_TYPE)
+ return 0;
+
+ for (field = TYPE_FIELDS (type); field != 0; field = TREE_CHAIN (field))
+ if (TREE_CODE (field) == FIELD_DECL
+ && (TREE_READONLY (field)
+ || readonly_fields_p (TREE_TYPE (field))))
+ return 1;
return 0;
}
+/* Return 1 if any MEM object of type T1 will always conflict (using the
+ dependency routines in this file) with any MEM object of type T2.
+ This is used when allocating temporary storage. If T1 and/or T2 are
+ NULL_TREE, it means we know nothing about the storage. */
+
+int
+objects_must_conflict_p (t1, t2)
+ tree t1, t2;
+{
+ /* If they are the same type, they must conflict. */
+ if (t1 == t2
+ /* Likewise if both are volatile. */
+ || (t1 != 0 && TYPE_VOLATILE (t1) && t2 != 0 && TYPE_VOLATILE (t2)))
+ return 1;
+
+ /* We now know they are different types. If one or both has readonly fields
+ or if one is readonly and the other not, they may not conflict.
+ Likewise if one is aggregate and the other is scalar. */
+ if ((t1 != 0 && readonly_fields_p (t1))
+ || (t2 != 0 && readonly_fields_p (t2))
+ || ((t1 != 0 && TYPE_READONLY (t1))
+ != (t2 != 0 && TYPE_READONLY (t2)))
+ || ((t1 != 0 && AGGREGATE_TYPE_P (t1))
+ != (t2 != 0 && AGGREGATE_TYPE_P (t2))))
+ return 0;
+
+ /* Otherwise they conflict only if the alias sets conflict. */
+ return alias_sets_conflict_p (t1 ? get_alias_set (t1) : 0,
+ t2 ? get_alias_set (t2) : 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,