+2003-05027 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+
+ * tree.h (contains_placeholder_p): Now returns bool.
+ (CONTAINS_PLACEHOLDER_P): New macro.
+ (type_contains_placeholder_p): New function.
+ * tree.c (save_expr): Remove code avoiding folding COMPONENT_REF.
+ (contains_placeholder_p): Now returns bool.
+ Rework to use CONTAINS_PLACEHOLDER_P macro.
+ (type_contains_placeholder_p): New function.
+ * fold-const.c (fold, case COMPONENT_REF): Don't fold if
+ type_contains_placeholder_p.
+ (fold_range_test, fold_mathfn_compare, fold_inf_compare, fold):
+ Use CONTAINS_PLACEHOLDER_P macro.
+ * builtins.c (fold_builtin): Likewise.
+ * calls.c (initialize_argument_information): Likewise.
+ * emit-rtl.c (set_mem_attributes_minus_bitpos): Likewise.
+ * explow.c (expr_size): Likewise.
+ * expr.c (store_constructor, get_inner_reference): Likewise.
+ * function.c (assign_parms): Likewise.
+ * stor-layout.c (variable_size): Likewise.
+
2003-05-25 Gabriel Dos Reis <gdr@integrable-solutions.net>
* diagnostic.h (output_verbatim, verbatim): Remove printf
/* Optimize pow(x,2.0) = x*x. */
if (REAL_VALUES_EQUAL (c, dconst2)
&& (*lang_hooks.decls.global_bindings_p) () == 0
- && ! contains_placeholder_p (arg0))
+ && ! CONTAINS_PLACEHOLDER_P (arg0))
{
arg0 = save_expr (arg0);
return fold (build (MULT_EXPR, type, arg0, arg0));
if (flag_unsafe_math_optimizations
&& REAL_VALUES_EQUAL (c, dconstm2)
&& (*lang_hooks.decls.global_bindings_p) () == 0
- && ! contains_placeholder_p (arg0))
+ && ! CONTAINS_PLACEHOLDER_P (arg0))
{
arg0 = save_expr (arg0);
return fold (build (RDIV_EXPR, type,
with those made by function.c. */
/* See if this argument should be passed by invisible reference. */
- if ((TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST
- && contains_placeholder_p (TYPE_SIZE (type)))
+ if (CONTAINS_PLACEHOLDER_P (TYPE_SIZE (type))
|| TREE_ADDRESSABLE (type)
#ifdef FUNCTION_ARG_PASS_BY_REFERENCE
|| FUNCTION_ARG_PASS_BY_REFERENCE (*args_so_far, TYPE_MODE (type),
/* If the index has a self-referential type, pass it to a
WITH_RECORD_EXPR; if the component size is, pass our
component to one. */
- if (! TREE_CONSTANT (index)
- && contains_placeholder_p (index))
+ if (CONTAINS_PLACEHOLDER_P (index))
index = build (WITH_RECORD_EXPR, TREE_TYPE (index), index, t);
- if (! TREE_CONSTANT (unit_size)
- && contains_placeholder_p (unit_size))
+ if (CONTAINS_PLACEHOLDER_P (unit_size))
unit_size = build (WITH_RECORD_EXPR, sizetype,
unit_size, array);
{
tree size = (*lang_hooks.expr_size) (exp);
- if (TREE_CODE (size) != INTEGER_CST
- && contains_placeholder_p (size))
+ if (CONTAINS_PLACEHOLDER_P (size))
size = build (WITH_RECORD_EXPR, sizetype, size, exp);
return expand_expr (size, NULL_RTX, TYPE_MODE (sizetype), 0);
{
rtx offset_rtx;
- if (contains_placeholder_p (offset))
+ if (CONTAINS_PLACEHOLDER_P (offset))
offset = build (WITH_RECORD_EXPR, sizetype,
offset, make_tree (TREE_TYPE (exp), target));
made during type construction. */
if (this_offset == 0)
break;
- else if (contains_placeholder_p (this_offset))
+ else if (CONTAINS_PLACEHOLDER_P (this_offset))
this_offset = build (WITH_RECORD_EXPR, sizetype, this_offset, exp);
offset = size_binop (PLUS_EXPR, offset, this_offset);
/* If the index has a self-referential type, pass it to a
WITH_RECORD_EXPR; if the component size is, pass our
component to one. */
- if (contains_placeholder_p (index))
+ if (CONTAINS_PLACEHOLDER_P (index))
index = build (WITH_RECORD_EXPR, TREE_TYPE (index), index, exp);
- if (contains_placeholder_p (unit_size))
+ if (CONTAINS_PLACEHOLDER_P (unit_size))
unit_size = build (WITH_RECORD_EXPR, sizetype, unit_size, array);
offset = size_binop (PLUS_EXPR, offset,
TREE_OPERAND (exp, 1));
else if ((*lang_hooks.decls.global_bindings_p) () == 0
- && ! contains_placeholder_p (lhs))
+ && ! CONTAINS_PLACEHOLDER_P (lhs))
{
tree common = save_expr (lhs);
/* sqrt(x) < y is x >= 0 && x != +Inf, when y is large. */
if ((*lang_hooks.decls.global_bindings_p) () != 0
- || contains_placeholder_p (arg))
+ || CONTAINS_PLACEHOLDER_P (arg))
return NULL_TREE;
arg = save_expr (arg);
/* sqrt(x) < c is the same as x >= 0 && x < c*c. */
if ((*lang_hooks.decls.global_bindings_p) () == 0
- && ! contains_placeholder_p (arg))
+ && ! CONTAINS_PLACEHOLDER_P (arg))
{
arg = save_expr (arg);
return fold (build (TRUTH_ANDIF_EXPR, type,
/* x <= +Inf is the same as x == x, i.e. isfinite(x). */
if ((*lang_hooks.decls.global_bindings_p) () == 0
- && ! contains_placeholder_p (arg0))
+ && ! CONTAINS_PLACEHOLDER_P (arg0))
{
arg0 = save_expr (arg0);
return fold (build (EQ_EXPR, type, arg0, arg0));
|| count_cond (arg0, 25) + count_cond (arg1, 25) <= 25)
&& (! TREE_SIDE_EFFECTS (arg0)
|| ((*lang_hooks.decls.global_bindings_p) () == 0
- && ! contains_placeholder_p (arg0))))
+ && ! CONTAINS_PLACEHOLDER_P (arg0))))
return
fold_binary_op_with_conditional_arg (code, type, arg1, arg0,
/*cond_first_p=*/0);
|| count_cond (arg0, 25) + count_cond (arg1, 25) <= 25)
&& (! TREE_SIDE_EFFECTS (arg1)
|| ((*lang_hooks.decls.global_bindings_p) () == 0
- && ! contains_placeholder_p (arg1))))
+ && ! CONTAINS_PLACEHOLDER_P (arg1))))
return
fold_binary_op_with_conditional_arg (code, type, arg0, arg1,
/*cond_first_p=*/1);
return t;
case COMPONENT_REF:
- if (TREE_CODE (arg0) == CONSTRUCTOR)
+ if (TREE_CODE (arg0) == CONSTRUCTOR
+ && ! type_contains_placeholder_p (TREE_TYPE (arg0)))
{
tree m = purpose_member (arg1, CONSTRUCTOR_ELTS (arg0));
if (m)
/* x*2 is x+x */
if (! wins && real_twop (arg1)
&& (*lang_hooks.decls.global_bindings_p) () == 0
- && ! contains_placeholder_p (arg0))
+ && ! CONTAINS_PLACEHOLDER_P (arg0))
{
tree arg = save_expr (arg0);
return fold (build (PLUS_EXPR, type, arg, arg));
object itself or if the machine requires these objects be passed
that way. */
- if ((TREE_CODE (TYPE_SIZE (passed_type)) != INTEGER_CST
- && contains_placeholder_p (TYPE_SIZE (passed_type)))
+ if (CONTAINS_PLACEHOLDER_P (TYPE_SIZE (passed_type))
|| TREE_ADDRESSABLE (passed_type)
#ifdef FUNCTION_ARG_PASS_BY_REFERENCE
|| FUNCTION_ARG_PASS_BY_REFERENCE (args_so_far, passed_mode,
save_expr (expr)
tree expr;
{
- tree t = expr;
+ tree t = fold (expr);
tree inner;
- /* Don't fold a COMPONENT_EXPR: if the operand was a CONSTRUCTOR (the
- only time it will fold), it can cause problems with PLACEHOLDER_EXPRs
- in Ada. Moreover, it isn't at all clear why we fold here at all. */
- if (TREE_CODE (t) != COMPONENT_REF)
- t = fold (t);
-
/* If the tree evaluates to a constant, then we don't want to hide that
fact (i.e. this allows further folding, and direct checks for constants).
However, a read-only object that has side effects cannot be bypassed.
/* Return 1 if EXP contains a PLACEHOLDER_EXPR; i.e., if it represents a size
or offset that depends on a field within a record. */
-int
+bool
contains_placeholder_p (exp)
tree exp;
{
position computations since they will be converted into a
WITH_RECORD_EXPR involving the reference, which will assume
here will be valid. */
- return contains_placeholder_p (TREE_OPERAND (exp, 0));
+ return CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 0));
case 'x':
if (code == TREE_LIST)
- return (contains_placeholder_p (TREE_VALUE (exp))
- || (TREE_CHAIN (exp) != 0
- && contains_placeholder_p (TREE_CHAIN (exp))));
+ return (CONTAINS_PLACEHOLDER_P (TREE_VALUE (exp))
+ || CONTAINS_PLACEHOLDER_P (TREE_CHAIN (exp)));
break;
case '1':
{
case COMPOUND_EXPR:
/* Ignoring the first operand isn't quite right, but works best. */
- return contains_placeholder_p (TREE_OPERAND (exp, 1));
+ return CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 1));
case RTL_EXPR:
case CONSTRUCTOR:
return 0;
case COND_EXPR:
- return (contains_placeholder_p (TREE_OPERAND (exp, 0))
- || contains_placeholder_p (TREE_OPERAND (exp, 1))
- || contains_placeholder_p (TREE_OPERAND (exp, 2)));
+ return (CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 0))
+ || CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 1))
+ || CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 2)));
case SAVE_EXPR:
/* If we already know this doesn't have a placeholder, don't
return 0;
SAVE_EXPR_NOPLACEHOLDER (exp) = 1;
- result = contains_placeholder_p (TREE_OPERAND (exp, 0));
+ result = CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 0));
if (result)
SAVE_EXPR_NOPLACEHOLDER (exp) = 0;
return result;
case CALL_EXPR:
- return (TREE_OPERAND (exp, 1) != 0
- && contains_placeholder_p (TREE_OPERAND (exp, 1)));
+ return CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 1));
default:
break;
switch (TREE_CODE_LENGTH (code))
{
case 1:
- return contains_placeholder_p (TREE_OPERAND (exp, 0));
+ return CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 0));
case 2:
- return (contains_placeholder_p (TREE_OPERAND (exp, 0))
- || contains_placeholder_p (TREE_OPERAND (exp, 1)));
+ return (CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 0))
+ || CONTAINS_PLACEHOLDER_P (TREE_OPERAND (exp, 1)));
default:
return 0;
}
return 0;
}
+/* Return 1 if any part of the computation of TYPE involves a PLACEHOLDER_EXPR.
+ This includes size, bounds, qualifiers (for QUAL_UNION_TYPE) and field
+ positions. */
+
+bool
+type_contains_placeholder_p (type)
+ tree type;
+{
+ /* If the size contains a placeholder or the parent type (component type in
+ the case of arrays) type involves a placeholder, this type does. */
+ if (CONTAINS_PLACEHOLDER_P (TYPE_SIZE (type))
+ || CONTAINS_PLACEHOLDER_P (TYPE_SIZE_UNIT (type))
+ || (TREE_TYPE (type) != 0
+ && type_contains_placeholder_p (TREE_TYPE (type))))
+ return 1;
+
+ /* Now do type-specific checks. Note that the last part of the check above
+ greatly limits what we have to do below. */
+ switch (TREE_CODE (type))
+ {
+ case VOID_TYPE:
+ case COMPLEX_TYPE:
+ case VECTOR_TYPE:
+ case ENUMERAL_TYPE:
+ case BOOLEAN_TYPE:
+ case CHAR_TYPE:
+ case POINTER_TYPE:
+ case OFFSET_TYPE:
+ case REFERENCE_TYPE:
+ case METHOD_TYPE:
+ case FILE_TYPE:
+ case FUNCTION_TYPE:
+ return 0;
+
+ case INTEGER_TYPE:
+ case REAL_TYPE:
+ /* Here we just check the bounds. */
+ return (CONTAINS_PLACEHOLDER_P (TYPE_MIN_VALUE (type))
+ || CONTAINS_PLACEHOLDER_P (TYPE_MAX_VALUE (type)));
+
+ case ARRAY_TYPE:
+ case SET_TYPE:
+ /* We're already checked the component type (TREE_TYPE), so just check
+ the index type. */
+ return type_contains_placeholder_p (TYPE_DOMAIN (type));
+
+ case RECORD_TYPE:
+ case UNION_TYPE:
+ case QUAL_UNION_TYPE:
+ {
+ static tree seen_types = 0;
+ tree field;
+ bool ret = 0;
+
+ /* We have to be careful here that we don't end up in infinite
+ recursions due to a field of a type being a pointer to that type
+ or to a mutually-recursive type. So we store a list of record
+ types that we've seen and see if this type is in them. To save
+ memory, we don't use a list for just one type. Here we check
+ whether we've seen this type before and store it if not. */
+ if (seen_types == 0)
+ seen_types = type;
+ else if (TREE_CODE (seen_types) != TREE_LIST)
+ {
+ if (seen_types == type)
+ return 0;
+
+ seen_types = tree_cons (NULL_TREE, type,
+ build_tree_list (NULL_TREE, seen_types));
+ }
+ else
+ {
+ if (value_member (type, seen_types) != 0)
+ return 0;
+
+ seen_types = tree_cons (NULL_TREE, type, seen_types);
+ }
+
+ for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+ if (TREE_CODE (field) == FIELD_DECL
+ && (CONTAINS_PLACEHOLDER_P (DECL_FIELD_OFFSET (field))
+ || (TREE_CODE (type) == QUAL_UNION_TYPE
+ && CONTAINS_PLACEHOLDER_P (DECL_QUALIFIER (field)))
+ || type_contains_placeholder_p (TREE_TYPE (field))))
+ {
+ ret = true;
+ break;
+ }
+
+ /* Now remove us from seen_types and return the result. */
+ if (seen_types == type)
+ seen_types = 0;
+ else
+ seen_types = TREE_CHAIN (seen_types);
+
+ return ret;
+ }
+
+ default:
+ abort ();
+ }
+}
+
/* Return 1 if EXP contains any expressions that produce cleanups for an
outer scope to deal with. Used by fold. */
op0 = TREE_OPERAND (exp, 0);
op1 = TREE_OPERAND (exp, 1);
- if (contains_placeholder_p (op0))
+ if (CONTAINS_PLACEHOLDER_P (op0))
op0 = substitute_in_expr (op0, f, r);
- if (contains_placeholder_p (op1))
+ if (CONTAINS_PLACEHOLDER_P (op1))
op1 = substitute_in_expr (op1, f, r);
if (op0 == TREE_OPERAND (exp, 0) && op1 == TREE_OPERAND (exp, 1))
op1 = TREE_OPERAND (exp, 1);
op2 = TREE_OPERAND (exp, 2);
- if (contains_placeholder_p (op0))
+ if (CONTAINS_PLACEHOLDER_P (op0))
op0 = substitute_in_expr (op0, f, r);
- if (contains_placeholder_p (op1))
+ if (CONTAINS_PLACEHOLDER_P (op1))
op1 = substitute_in_expr (op1, f, r);
- if (contains_placeholder_p (op2))
+ if (CONTAINS_PLACEHOLDER_P (op2))
op2 = substitute_in_expr (op2, f, r);
if (op0 == TREE_OPERAND (exp, 0) && op1 == TREE_OPERAND (exp, 1)
Note that we only allow such expressions within simple arithmetic
or a COND_EXPR. */
-extern int contains_placeholder_p PARAMS ((tree));
+extern bool contains_placeholder_p PARAMS ((tree));
+
+/* This macro calls the above function but short-circuits the common
+ case of a constant to save time. Also check for null. */
+
+#define CONTAINS_PLACEHOLDER_P(EXP) \
+ ((EXP) != 0 && ! TREE_CONSTANT (EXP) && contains_placeholder_p (EXP))
+
+/* Return 1 if any part of the computation of TYPE involves a PLACEHOLDER_EXPR.
+ This includes size, bounds, qualifiers (for QUAL_UNION_TYPE) and field
+ positions. */
+
+extern bool type_contains_placeholder_p PARAMS ((tree));
/* Return 1 if EXP contains any expressions that produce cleanups for an
outer scope to deal with. Used by fold. */