This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Enable setting MEM alias checking
- To: gcc-patches at gcc dot gnu dot org
- Subject: Enable setting MEM alias checking
- From: kenner at vlsi1 dot ultra dot nyu dot edu (Richard Kenner)
- Date: Mon, 1 Oct 01 19:29:28 EDT
This enables the test that the new and old alias sets conflict and fixes
a number of bugs uncovered with that test, mostly in Ada code (GNAT itself).
Tested on alphaev56.
Mon Oct 1 19:20:57 2001 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
* alias.c (get_alias_set): Try to replace PLACEHOLDER_EXPR.
Loop through NOPs, placeholders, and components.
Don't go through NOPs if change mode.
(record_alias_subset): Do nothing if SUBSET and SET are the same.
* emit-rtl.c (set_mem_alias_set): Enable check.
* expr.c (find_placeholder): New function.
(expand_expr, case PLACEHOLDER_EXPR): Use it.
(expand_expr, case COMPONENT_EXPR): Always copy OP0 when we need
to modify it and avoid unneeded copies.
* expr.h (expand_expr): Always define.
(find_placeholder): New declaration.
*** alias.c 2001/10/01 11:00:45 1.143
--- alias.c 2001/10/01 19:22:59
*************** get_alias_set (t)
*** 471,484 ****
/* 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.
! First handle things that aren't types and start by removing nops
! since we care only about the actual object. */
if (! TYPE_P (t))
{
! 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 but record what we
--- 471,500 ----
/* 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. First handle things that
! aren't types and start by removing nops since we care only about the
! actual object. Also replace PLACEHOLDER_EXPRs and pick up the outermost
! object that we could have a pointer to. */
if (! TYPE_P (t))
{
! /* Remove any NOPs and see what any PLACEHOLD_EXPRs will expand to. */
! while (((TREE_CODE (t) == NOP_EXPR || TREE_CODE (t) == CONVERT_EXPR)
! && (TYPE_MODE (TREE_TYPE (t))
! == TYPE_MODE (TREE_TYPE (TREE_OPERAND (t, 0)))))
! || TREE_CODE (t) == NON_LVALUE_EXPR
! || TREE_CODE (t) == PLACEHOLDER_EXPR
! || (handled_component_p (t) && ! can_address_p (t)))
! {
! /* Give the language a chance to do something with this tree
! before we go inside it. */
! if ((set = lang_get_alias_set (t)) != -1)
! return set;
!
! if (TREE_CODE (t) == PLACEHOLDER_EXPR)
! t = find_placeholder (t, 0);
! else
! t = TREE_OPERAND (t, 0);
! }
/* Now give the language a chance to do something but record what we
*************** get_alias_set (t)
*** 488,500 ****
return set;
! /* Now loop the same way as get_inner_reference and get the alias
! set to use. Pick up the outermost object that we could have
! a pointer to. */
! while (handled_component_p (t) && ! can_address_p (t))
! t = TREE_OPERAND (t, 0);
!
if (TREE_CODE (t) == INDIRECT_REF)
{
- /* Check for accesses through restrict-qualified pointers. */
tree decl = find_base_decl (TREE_OPERAND (t, 0));
--- 504,510 ----
return set;
! /* Check for accesses through restrict-qualified pointers. */
if (TREE_CODE (t) == INDIRECT_REF)
{
tree decl = find_base_decl (TREE_OPERAND (t, 0));
*************** record_alias_subset (superset, subset)
*** 587,590 ****
--- 597,605 ----
alias_set_entry superset_entry;
alias_set_entry subset_entry;
+
+ /* It is possible in complex type situations for both sets to be the same,
+ in which case we can ignore this operation. */
+ if (superset == subset)
+ return;
if (superset == 0)
*** emit-rtl.c 2001/10/01 11:00:45 1.207
--- emit-rtl.c 2001/10/01 19:23:23
*************** set_mem_alias_set (mem, set)
*** 1717,1726 ****
{
/* It would be nice to enable this check, but we can't quite yet. */
- #if 0
#ifdef ENABLE_CHECKING
/* If the new and old alias sets don't conflict, something is wrong. */
if (!alias_sets_conflict_p (set, MEM_ALIAS_SET (mem)))
abort ();
- #endif
#endif
--- 1717,1724 ----
*** expr.c 2001/09/21 16:58:18 1.353
--- expr.c 2001/10/01 19:24:29
*************** check_max_integer_computation_mode (exp)
*** 5956,5959 ****
--- 5956,6022 ----
#endif
+ /* Return an object on the placeholder list that matches EXP, a
+ PLACEHOLDER_EXPR. An object "matches" if it is of the type of the
+ PLACEHOLDER_EXPR or a pointer type to it. For further information,
+ see tree.def. If no such object is found, abort. If PLIST is nonzero,
+ it is a location into which a pointer into the placeholder list at
+ which the object is found is placed. */
+
+ tree
+ find_placeholder (exp, plist)
+ tree exp;
+ tree *plist;
+ {
+ tree type = TREE_TYPE (exp);
+ tree placeholder_expr;
+
+ for (placeholder_expr = placeholder_list; placeholder_expr != 0;
+ placeholder_expr = TREE_CHAIN (placeholder_expr))
+ {
+ tree need_type = TYPE_MAIN_VARIANT (type);
+ tree elt;
+
+ /* Find the outermost reference that is of the type we want. If none,
+ see if any object has a type that is a pointer to the type we
+ want. */
+ for (elt = TREE_PURPOSE (placeholder_expr); elt != 0;
+ elt = ((TREE_CODE (elt) == COMPOUND_EXPR
+ || TREE_CODE (elt) == COND_EXPR)
+ ? TREE_OPERAND (elt, 1)
+ : (TREE_CODE_CLASS (TREE_CODE (elt)) == 'r'
+ || TREE_CODE_CLASS (TREE_CODE (elt)) == '1'
+ || TREE_CODE_CLASS (TREE_CODE (elt)) == '2'
+ || TREE_CODE_CLASS (TREE_CODE (elt)) == 'e')
+ ? TREE_OPERAND (elt, 0) : 0))
+ if (TYPE_MAIN_VARIANT (TREE_TYPE (elt)) == need_type)
+ {
+ if (plist)
+ *plist = placeholder_expr;
+ return elt;
+ }
+
+ for (elt = TREE_PURPOSE (placeholder_expr); elt != 0;
+ elt
+ = ((TREE_CODE (elt) == COMPOUND_EXPR
+ || TREE_CODE (elt) == COND_EXPR)
+ ? TREE_OPERAND (elt, 1)
+ : (TREE_CODE_CLASS (TREE_CODE (elt)) == 'r'
+ || TREE_CODE_CLASS (TREE_CODE (elt)) == '1'
+ || TREE_CODE_CLASS (TREE_CODE (elt)) == '2'
+ || TREE_CODE_CLASS (TREE_CODE (elt)) == 'e')
+ ? TREE_OPERAND (elt, 0) : 0))
+ if (POINTER_TYPE_P (TREE_TYPE (elt))
+ && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (elt)))
+ == need_type))
+ {
+ if (plist)
+ *plist = placeholder_expr;
+ return build1 (INDIRECT_REF, need_type, elt);
+ }
+ }
+
+ abort ();
+ }
+
/* expand_expr: generate code for computing expression EXP.
An rtx for the computed value is returned. The value is never null.
*************** expand_expr (exp, target, tmode, modifie
*** 6483,6546 ****
case PLACEHOLDER_EXPR:
{
tree placeholder_expr;
! /* If there is an object on the head of the placeholder list,
! see if some object in it of type TYPE or a pointer to it. For
! further information, see tree.def. */
! for (placeholder_expr = placeholder_list;
! placeholder_expr != 0;
! placeholder_expr = TREE_CHAIN (placeholder_expr))
! {
! tree need_type = TYPE_MAIN_VARIANT (type);
! tree object = 0;
! tree old_list = placeholder_list;
! tree elt;
!
! /* Find the outermost reference that is of the type we want.
! If none, see if any object has a type that is a pointer to
! the type we want. */
! for (elt = TREE_PURPOSE (placeholder_expr);
! elt != 0 && object == 0;
! elt
! = ((TREE_CODE (elt) == COMPOUND_EXPR
! || TREE_CODE (elt) == COND_EXPR)
! ? TREE_OPERAND (elt, 1)
! : (TREE_CODE_CLASS (TREE_CODE (elt)) == 'r'
! || TREE_CODE_CLASS (TREE_CODE (elt)) == '1'
! || TREE_CODE_CLASS (TREE_CODE (elt)) == '2'
! || TREE_CODE_CLASS (TREE_CODE (elt)) == 'e')
! ? TREE_OPERAND (elt, 0) : 0))
! if (TYPE_MAIN_VARIANT (TREE_TYPE (elt)) == need_type)
! object = elt;
!
! for (elt = TREE_PURPOSE (placeholder_expr);
! elt != 0 && object == 0;
! elt
! = ((TREE_CODE (elt) == COMPOUND_EXPR
! || TREE_CODE (elt) == COND_EXPR)
! ? TREE_OPERAND (elt, 1)
! : (TREE_CODE_CLASS (TREE_CODE (elt)) == 'r'
! || TREE_CODE_CLASS (TREE_CODE (elt)) == '1'
! || TREE_CODE_CLASS (TREE_CODE (elt)) == '2'
! || TREE_CODE_CLASS (TREE_CODE (elt)) == 'e')
! ? TREE_OPERAND (elt, 0) : 0))
! if (POINTER_TYPE_P (TREE_TYPE (elt))
! && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (elt)))
! == need_type))
! object = build1 (INDIRECT_REF, need_type, elt);
!
! if (object != 0)
! {
! /* Expand this object skipping the list entries before
! it was found in case it is also a PLACEHOLDER_EXPR.
! In that case, we want to translate it using subsequent
! entries. */
! placeholder_list = TREE_CHAIN (placeholder_expr);
! temp = expand_expr (object, original_target, tmode,
! ro_modifier);
! placeholder_list = old_list;
! return temp;
! }
! }
}
--- 6546,6557 ----
case PLACEHOLDER_EXPR:
{
+ tree old_list = placeholder_list;
tree placeholder_expr;
! exp = find_placeholder (exp, &placeholder_expr);
! placeholder_list = TREE_CHAIN (placeholder_expr);
! temp = expand_expr (exp, original_target, tmode, ro_modifier);
! placeholder_list = old_list;
! return temp;
}
*************** expand_expr (exp, target, tmode, modifie
*** 6924,6927 ****
--- 6935,6939 ----
&mode1, &unsignedp, &volatilep,
&alignment);
+ rtx orig_op0;
/* If we got back the original object, something is wrong. Perhaps
*************** expand_expr (exp, target, tmode, modifie
*** 6935,6947 ****
to have to do. This occurs in unchecked conversion in Ada. */
! op0 = expand_expr (tem,
! (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE
! && (TREE_CODE (TYPE_SIZE (TREE_TYPE (tem)))
! != INTEGER_CST)
! ? target : NULL_RTX),
! VOIDmode,
! (modifier == EXPAND_INITIALIZER
! || modifier == EXPAND_CONST_ADDRESS)
! ? modifier : EXPAND_NORMAL);
/* If this is a constant, put it into a register if it is a
--- 6947,6960 ----
to have to do. This occurs in unchecked conversion in Ada. */
! orig_op0 = op0
! = expand_expr (tem,
! (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE
! && (TREE_CODE (TYPE_SIZE (TREE_TYPE (tem)))
! != INTEGER_CST)
! ? target : NULL_RTX),
! VOIDmode,
! (modifier == EXPAND_INITIALIZER
! || modifier == EXPAND_CONST_ADDRESS)
! ? modifier : EXPAND_NORMAL);
/* If this is a constant, put it into a register if it is a
*************** expand_expr (exp, target, tmode, modifie
*** 7032,7036 ****
if (GET_CODE (op0) == MEM && volatilep && ! MEM_VOLATILE_P (op0))
{
! op0 = copy_rtx (op0);
MEM_VOLATILE_P (op0) = 1;
}
--- 7045,7051 ----
if (GET_CODE (op0) == MEM && volatilep && ! MEM_VOLATILE_P (op0))
{
! if (op0 == orig_op0)
! op0 = copy_rtx (op0);
!
MEM_VOLATILE_P (op0) = 1;
}
*************** expand_expr (exp, target, tmode, modifie
*** 7173,7176 ****
--- 7188,7194 ----
else
op0 = adjust_address (op0, mode1, bitpos / BITS_PER_UNIT);
+
+ if (op0 == orig_op0)
+ op0 = copy_rtx (op0);
set_mem_attributes (op0, exp, 0);
*** expr.h 2001/10/01 11:00:44 1.93
--- expr.h 2001/10/01 19:24:37
*************** extern rtx store_expr PARAMS ((tree, rtx
*** 499,503 ****
extern rtx force_operand PARAMS ((rtx, rtx));
! #ifdef TREE_CODE
/* Generate code for computing expression EXP.
An rtx for the computed value is returned. The value is never null.
--- 499,510 ----
extern rtx force_operand PARAMS ((rtx, rtx));
! /* Return an object on the placeholder list that matches EXP, a
! PLACEHOLDER_EXPR. An object "matches" if it is of the type of the
! PLACEHOLDER_EXPR or a pointer type to it. For further information,
! see tree.def. If no such object is found, abort. If PLIST is nonzero,
! it is a location into which a pointer into the placeholder list at
! which the object is found is placed. */
! extern tree find_placeholder PARAMS ((tree, tree *));
!
/* Generate code for computing expression EXP.
An rtx for the computed value is returned. The value is never null.
*************** extern rtx force_operand PARAMS ((rtx, r
*** 505,509 ****
extern rtx expand_expr PARAMS ((tree, rtx, enum machine_mode,
enum expand_modifier));
- #endif
/* At the start of a function, record that we have no previously-pushed
--- 512,515 ----