aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Kenner <kenner@vlsi1.ultra.nyu.edu>2003-05-27 14:44:57 -0400
committerRichard Kenner <kenner@gcc.gnu.org>2003-05-27 14:44:57 -0400
commit7a6cdb44fd51d6036d32a732363f19c8e51f0d89 (patch)
tree6be268fb48b8e0a8cb871503b25decd003ae8522 /gcc
parent86982c71d17f2e9888e649fe5c88b65ff84561d8 (diff)
downloadgcc-7a6cdb44fd51d6036d32a732363f19c8e51f0d89.zip
gcc-7a6cdb44fd51d6036d32a732363f19c8e51f0d89.tar.gz
gcc-7a6cdb44fd51d6036d32a732363f19c8e51f0d89.tar.bz2
tree.h (contains_placeholder_p): Now returns bool.
* 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. From-SVN: r67189
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog21
-rw-r--r--gcc/builtins.c4
-rw-r--r--gcc/calls.c3
-rw-r--r--gcc/emit-rtl.c6
-rw-r--r--gcc/explow.c3
-rw-r--r--gcc/expr.c8
-rw-r--r--gcc/fold-const.c17
-rw-r--r--gcc/function.c3
-rw-r--r--gcc/tree.c149
-rw-r--r--gcc/tree.h14
10 files changed, 176 insertions, 52 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 82911fa..d56b572 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,24 @@
+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
diff --git a/gcc/builtins.c b/gcc/builtins.c
index e2da8b8..eef1cce 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -5242,7 +5242,7 @@ fold_builtin (exp)
/* 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));
@@ -5252,7 +5252,7 @@ fold_builtin (exp)
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,
diff --git a/gcc/calls.c b/gcc/calls.c
index a3f2de0..9d7899c 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -1146,8 +1146,7 @@ initialize_argument_information (num_actuals, args, args_size, n_named_args,
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),
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index 1df50a75..f568991 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -1986,11 +1986,9 @@ set_mem_attributes_minus_bitpos (ref, t, objectp, bitpos)
/* 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);
diff --git a/gcc/explow.c b/gcc/explow.c
index da7e2b7..ec7a69a 100644
--- a/gcc/explow.c
+++ b/gcc/explow.c
@@ -294,8 +294,7 @@ expr_size (exp)
{
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);
diff --git a/gcc/expr.c b/gcc/expr.c
index d251a27..770bef4 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -4982,7 +4982,7 @@ store_constructor (exp, target, cleared, size)
{
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));
@@ -5799,7 +5799,7 @@ get_inner_reference (exp, pbitsize, pbitpos, poffset, pmode,
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);
@@ -5829,9 +5829,9 @@ get_inner_reference (exp, pbitsize, pbitpos, poffset, pmode,
/* 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,
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 6a4e229..381bc9c 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -3470,7 +3470,7 @@ fold_range_test (exp)
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);
@@ -4768,7 +4768,7 @@ fold_mathfn_compare (fcode, code, type, arg0, arg1)
/* 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);
@@ -4788,7 +4788,7 @@ fold_mathfn_compare (fcode, code, type, arg0, arg1)
/* 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,
@@ -4851,7 +4851,7 @@ fold_inf_compare (code, type, arg0, arg1)
/* 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));
@@ -5119,7 +5119,7 @@ fold (expr)
|| 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);
@@ -5133,7 +5133,7 @@ fold (expr)
|| 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);
@@ -5313,7 +5313,8 @@ fold (expr)
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)
@@ -5883,7 +5884,7 @@ fold (expr)
/* 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));
diff --git a/gcc/function.c b/gcc/function.c
index 8177952..64d045b 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -4494,8 +4494,7 @@ assign_parms (fndecl)
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,
diff --git a/gcc/tree.c b/gcc/tree.c
index efb4e22..51ff3fae 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -1390,15 +1390,9 @@ tree
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.
@@ -1745,7 +1739,7 @@ unsafe_for_reeval (expr)
/* 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;
{
@@ -1770,13 +1764,12 @@ contains_placeholder_p (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':
@@ -1786,16 +1779,16 @@ contains_placeholder_p (exp)
{
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
@@ -1804,15 +1797,14 @@ contains_placeholder_p (exp)
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;
@@ -1821,10 +1813,10 @@ contains_placeholder_p (exp)
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;
}
@@ -1835,6 +1827,109 @@ contains_placeholder_p (exp)
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. */
@@ -1960,9 +2055,9 @@ substitute_in_expr (exp, f, r)
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))
@@ -1994,11 +2089,11 @@ substitute_in_expr (exp, f, r)
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)
diff --git a/gcc/tree.h b/gcc/tree.h
index 2c5f2d9..65b7de2 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -2523,7 +2523,19 @@ extern int unsafe_for_reeval PARAMS ((tree));
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. */