From ce3fb06e43047b540787319dd59ecd771577218c Mon Sep 17 00:00:00 2001 From: kenner Date: Tue, 27 May 2003 18:44:57 +0000 Subject: [PATCH] * 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@67189 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 21 ++++++++ gcc/builtins.c | 4 +- gcc/calls.c | 3 +- gcc/emit-rtl.c | 6 +-- gcc/explow.c | 3 +- gcc/expr.c | 8 +-- gcc/fold-const.c | 17 ++++--- gcc/function.c | 3 +- gcc/tree.c | 149 +++++++++++++++++++++++++++++++++++++++++++++---------- gcc/tree.h | 14 +++++- 10 files changed, 176 insertions(+), 52 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 82911fa3ad9..d56b572547d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,24 @@ +2003-05027 Richard Kenner + + * 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 * diagnostic.h (output_verbatim, verbatim): Remove printf diff --git a/gcc/builtins.c b/gcc/builtins.c index e2da8b87373..eef1cce496c 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 a3f2de0c880..9d7899c8bce 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 1df50a75fec..f5689919343 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 da7e2b797b9..ec7a69a7833 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 d251a27cc01..770bef4afa2 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 6a4e2290e39..381bc9cb959 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 8177952a13f..64d045b9b13 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 efb4e222d20..51ff3faea10 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 2c5f2d92e10..65b7de27bca 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. */ -- 2.11.0