alias.c (get_alias_set): Try to replace PLACEHOLDER_EXPR.
* 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. From-SVN: r45931
This commit is contained in:
parent
477946a63d
commit
f47e9b4ebf
|
@ -1,3 +1,17 @@
|
|||
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.
|
||||
|
||||
2001-10-01 Stephane Carrez <Stephane.Carrez@worldnet.fr>
|
||||
|
||||
* config/m68hc11/m68hc11.md ("add-split"): Fix add split when
|
||||
|
|
45
gcc/alias.c
45
gcc/alias.c
|
@ -470,16 +470,32 @@ get_alias_set (t)
|
|||
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.
|
||||
First handle things that aren't types and start by removing nops
|
||||
since we care only about the actual object. */
|
||||
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))
|
||||
{
|
||||
while (TREE_CODE (t) == NOP_EXPR || TREE_CODE (t) == CONVERT_EXPR
|
||||
|| TREE_CODE (t) == NON_LVALUE_EXPR)
|
||||
t = TREE_OPERAND (t, 0);
|
||||
/* 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
|
||||
gave it this time. */
|
||||
|
@ -487,15 +503,9 @@ get_alias_set (t)
|
|||
if ((set = lang_get_alias_set (t)) != -1)
|
||||
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);
|
||||
|
||||
/* Check for accesses through restrict-qualified pointers. */
|
||||
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))
|
||||
|
@ -587,6 +597,11 @@ record_alias_subset (superset, subset)
|
|||
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)
|
||||
abort ();
|
||||
|
||||
|
|
|
@ -1716,12 +1716,10 @@ set_mem_alias_set (mem, set)
|
|||
HOST_WIDE_INT set;
|
||||
{
|
||||
/* 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
|
||||
|
||||
MEM_ATTRS (mem) = get_mem_attrs (set, MEM_DECL (mem), MEM_OFFSET (mem),
|
||||
|
|
154
gcc/expr.c
154
gcc/expr.c
|
@ -5955,6 +5955,69 @@ check_max_integer_computation_mode (exp)
|
|||
}
|
||||
#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.
|
||||
In the case of a void EXP, const0_rtx is returned.
|
||||
|
@ -6482,66 +6545,14 @@ expand_expr (exp, target, tmode, modifier)
|
|||
|
||||
case PLACEHOLDER_EXPR:
|
||||
{
|
||||
tree old_list = placeholder_list;
|
||||
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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
/* We can't find the object or there was a missing WITH_RECORD_EXPR. */
|
||||
|
@ -6923,6 +6934,7 @@ expand_expr (exp, target, tmode, modifier)
|
|||
tree tem = get_inner_reference (exp, &bitsize, &bitpos, &offset,
|
||||
&mode1, &unsignedp, &volatilep,
|
||||
&alignment);
|
||||
rtx orig_op0;
|
||||
|
||||
/* If we got back the original object, something is wrong. Perhaps
|
||||
we are evaluating an expression too early. In any event, don't
|
||||
|
@ -6934,15 +6946,16 @@ expand_expr (exp, target, tmode, modifier)
|
|||
computation, since it will need a temporary and TARGET is known
|
||||
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);
|
||||
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
|
||||
legitimate constant and OFFSET is 0 and memory if it isn't. */
|
||||
|
@ -7031,7 +7044,9 @@ expand_expr (exp, target, tmode, modifier)
|
|||
/* Don't forget about volatility even if this is a bitfield. */
|
||||
if (GET_CODE (op0) == MEM && volatilep && ! MEM_VOLATILE_P (op0))
|
||||
{
|
||||
op0 = copy_rtx (op0);
|
||||
if (op0 == orig_op0)
|
||||
op0 = copy_rtx (op0);
|
||||
|
||||
MEM_VOLATILE_P (op0) = 1;
|
||||
}
|
||||
|
||||
|
@ -7173,6 +7188,9 @@ expand_expr (exp, target, tmode, modifier)
|
|||
else
|
||||
op0 = adjust_address (op0, mode1, bitpos / BITS_PER_UNIT);
|
||||
|
||||
if (op0 == orig_op0)
|
||||
op0 = copy_rtx (op0);
|
||||
|
||||
set_mem_attributes (op0, exp, 0);
|
||||
if (GET_CODE (XEXP (op0, 0)) == REG)
|
||||
mark_reg_pointer (XEXP (op0, 0), alignment);
|
||||
|
|
10
gcc/expr.h
10
gcc/expr.h
|
@ -498,13 +498,19 @@ extern rtx store_expr PARAMS ((tree, rtx, int));
|
|||
Useful after calling expand_expr with 1 as sum_ok. */
|
||||
extern rtx force_operand PARAMS ((rtx, rtx));
|
||||
|
||||
#ifdef TREE_CODE
|
||||
/* 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.
|
||||
In the case of a void EXP, const0_rtx is returned. */
|
||||
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
|
||||
arguments waiting to be popped. */
|
||||
|
|
Loading…
Reference in New Issue