Message ID | 20221205042109.4144777-1-ppalka@redhat.com |
---|---|
State | New |
Headers | show |
Series | tree, c++: optimize walk_tree_1 and cp_walk_subtrees | expand |
On Mon, 5 Dec 2022 at 09:51, Patrick Palka via Gcc-patches <gcc-patches@gcc.gnu.org> wrote: > > These functions currently repeatedly dereference tp during the subtree > walk, dereferences which the compiler can't CSE because it can't > guarantee that the subtree walking doesn't modify *tp. > > But we already implicitly require that TREE_CODE (*tp) remains the same > throughout the subtree walks, so it doesn't seem to be a huge leap to > strengthen that to requiring *tp remains the same. Hi Patrick, Just wondering in that case, if marking tp with const_tree *, instead of tree *, would perhaps help the compiler for CSEing some of the dereferences to *tp ? Thanks, Prathamesh > > So this patch manually CSEs the dereferences of *tp. This means that > the callback function can no longer replace *tp with another tree (of > the same TREE_CODE) when walking one of its subtrees, but that doesn't > sound like a useful feature anyway. This speeds up the C++ frontend by > about ~1.5% according to my experiments. > > Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for > trunk stage3 or perhaps for stage1? > > gcc/cp/ChangeLog: > > * tree.cc (cp_walk_subtrees): Avoid repeatedly dereferencing tp. > > gcc/ChangeLog: > > * tree.cc (walk_tree_1): Avoid repeatedly dereferencing tp > and type_p. > --- > gcc/cp/tree.cc | 113 +++++++++++++++++++++++++------------------------ > gcc/tree.cc | 103 ++++++++++++++++++++++---------------------- > 2 files changed, 108 insertions(+), 108 deletions(-) > > diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc > index 4066b014f6e..ceb0c75f559 100644 > --- a/gcc/cp/tree.cc > +++ b/gcc/cp/tree.cc > @@ -5441,7 +5441,8 @@ tree > cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, > void *data, hash_set<tree> *pset) > { > - enum tree_code code = TREE_CODE (*tp); > + tree t = *tp; > + enum tree_code code = TREE_CODE (t); > tree result; > > #define WALK_SUBTREE(NODE) \ > @@ -5452,7 +5453,7 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, > } \ > while (0) > > - if (TYPE_P (*tp)) > + if (TYPE_P (t)) > { > /* If *WALK_SUBTREES_P is 1, we're interested in the syntactic form of > the argument, so don't look through typedefs, but do walk into > @@ -5464,15 +5465,15 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, > > See find_abi_tags_r for an example of setting *WALK_SUBTREES_P to 2 > when that's the behavior the walk_tree_fn wants. */ > - if (*walk_subtrees_p == 1 && typedef_variant_p (*tp)) > + if (*walk_subtrees_p == 1 && typedef_variant_p (t)) > { > - if (tree ti = TYPE_ALIAS_TEMPLATE_INFO (*tp)) > + if (tree ti = TYPE_ALIAS_TEMPLATE_INFO (t)) > WALK_SUBTREE (TI_ARGS (ti)); > *walk_subtrees_p = 0; > return NULL_TREE; > } > > - if (tree ti = TYPE_TEMPLATE_INFO (*tp)) > + if (tree ti = TYPE_TEMPLATE_INFO (t)) > WALK_SUBTREE (TI_ARGS (ti)); > } > > @@ -5482,8 +5483,8 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, > switch (code) > { > case TEMPLATE_TYPE_PARM: > - if (template_placeholder_p (*tp)) > - WALK_SUBTREE (CLASS_PLACEHOLDER_TEMPLATE (*tp)); > + if (template_placeholder_p (t)) > + WALK_SUBTREE (CLASS_PLACEHOLDER_TEMPLATE (t)); > /* Fall through. */ > case DEFERRED_PARSE: > case TEMPLATE_TEMPLATE_PARM: > @@ -5497,63 +5498,63 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, > break; > > case TYPENAME_TYPE: > - WALK_SUBTREE (TYPE_CONTEXT (*tp)); > - WALK_SUBTREE (TYPENAME_TYPE_FULLNAME (*tp)); > + WALK_SUBTREE (TYPE_CONTEXT (t)); > + WALK_SUBTREE (TYPENAME_TYPE_FULLNAME (t)); > *walk_subtrees_p = 0; > break; > > case BASELINK: > - if (BASELINK_QUALIFIED_P (*tp)) > - WALK_SUBTREE (BINFO_TYPE (BASELINK_ACCESS_BINFO (*tp))); > - WALK_SUBTREE (BASELINK_FUNCTIONS (*tp)); > + if (BASELINK_QUALIFIED_P (t)) > + WALK_SUBTREE (BINFO_TYPE (BASELINK_ACCESS_BINFO (t))); > + WALK_SUBTREE (BASELINK_FUNCTIONS (t)); > *walk_subtrees_p = 0; > break; > > case PTRMEM_CST: > - WALK_SUBTREE (TREE_TYPE (*tp)); > + WALK_SUBTREE (TREE_TYPE (t)); > *walk_subtrees_p = 0; > break; > > case TREE_LIST: > - WALK_SUBTREE (TREE_PURPOSE (*tp)); > + WALK_SUBTREE (TREE_PURPOSE (t)); > break; > > case OVERLOAD: > - WALK_SUBTREE (OVL_FUNCTION (*tp)); > - WALK_SUBTREE (OVL_CHAIN (*tp)); > + WALK_SUBTREE (OVL_FUNCTION (t)); > + WALK_SUBTREE (OVL_CHAIN (t)); > *walk_subtrees_p = 0; > break; > > case USING_DECL: > - WALK_SUBTREE (DECL_NAME (*tp)); > - WALK_SUBTREE (USING_DECL_SCOPE (*tp)); > - WALK_SUBTREE (USING_DECL_DECLS (*tp)); > + WALK_SUBTREE (DECL_NAME (t)); > + WALK_SUBTREE (USING_DECL_SCOPE (t)); > + WALK_SUBTREE (USING_DECL_DECLS (t)); > *walk_subtrees_p = 0; > break; > > case RECORD_TYPE: > - if (TYPE_PTRMEMFUNC_P (*tp)) > - WALK_SUBTREE (TYPE_PTRMEMFUNC_FN_TYPE_RAW (*tp)); > + if (TYPE_PTRMEMFUNC_P (t)) > + WALK_SUBTREE (TYPE_PTRMEMFUNC_FN_TYPE_RAW (t)); > break; > > case TYPE_ARGUMENT_PACK: > case NONTYPE_ARGUMENT_PACK: > { > - tree args = ARGUMENT_PACK_ARGS (*tp); > + tree args = ARGUMENT_PACK_ARGS (t); > for (tree arg : tree_vec_range (args)) > WALK_SUBTREE (arg); > } > break; > > case TYPE_PACK_EXPANSION: > - WALK_SUBTREE (TREE_TYPE (*tp)); > - WALK_SUBTREE (PACK_EXPANSION_EXTRA_ARGS (*tp)); > + WALK_SUBTREE (TREE_TYPE (t)); > + WALK_SUBTREE (PACK_EXPANSION_EXTRA_ARGS (t)); > *walk_subtrees_p = 0; > break; > > case EXPR_PACK_EXPANSION: > - WALK_SUBTREE (TREE_OPERAND (*tp, 0)); > - WALK_SUBTREE (PACK_EXPANSION_EXTRA_ARGS (*tp)); > + WALK_SUBTREE (TREE_OPERAND (t, 0)); > + WALK_SUBTREE (PACK_EXPANSION_EXTRA_ARGS (t)); > *walk_subtrees_p = 0; > break; > > @@ -5564,31 +5565,31 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, > case DYNAMIC_CAST_EXPR: > case IMPLICIT_CONV_EXPR: > case BIT_CAST_EXPR: > - if (TREE_TYPE (*tp)) > - WALK_SUBTREE (TREE_TYPE (*tp)); > + if (TREE_TYPE (t)) > + WALK_SUBTREE (TREE_TYPE (t)); > break; > > case CONSTRUCTOR: > - if (COMPOUND_LITERAL_P (*tp)) > - WALK_SUBTREE (TREE_TYPE (*tp)); > + if (COMPOUND_LITERAL_P (t)) > + WALK_SUBTREE (TREE_TYPE (t)); > break; > > case TRAIT_EXPR: > - WALK_SUBTREE (TRAIT_EXPR_TYPE1 (*tp)); > - WALK_SUBTREE (TRAIT_EXPR_TYPE2 (*tp)); > + WALK_SUBTREE (TRAIT_EXPR_TYPE1 (t)); > + WALK_SUBTREE (TRAIT_EXPR_TYPE2 (t)); > *walk_subtrees_p = 0; > break; > > case TRAIT_TYPE: > - WALK_SUBTREE (TRAIT_TYPE_TYPE1 (*tp)); > - WALK_SUBTREE (TRAIT_TYPE_TYPE2 (*tp)); > + WALK_SUBTREE (TRAIT_TYPE_TYPE1 (t)); > + WALK_SUBTREE (TRAIT_TYPE_TYPE2 (t)); > *walk_subtrees_p = 0; > break; > > case DECLTYPE_TYPE: > ++cp_unevaluated_operand; > /* We can't use WALK_SUBTREE here because of the goto. */ > - result = cp_walk_tree (&DECLTYPE_TYPE_EXPR (*tp), func, data, pset); > + result = cp_walk_tree (&DECLTYPE_TYPE_EXPR (t), func, data, pset); > --cp_unevaluated_operand; > *walk_subtrees_p = 0; > break; > @@ -5597,7 +5598,7 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, > case SIZEOF_EXPR: > case NOEXCEPT_EXPR: > ++cp_unevaluated_operand; > - result = cp_walk_tree (&TREE_OPERAND (*tp, 0), func, data, pset); > + result = cp_walk_tree (&TREE_OPERAND (t, 0), func, data, pset); > --cp_unevaluated_operand; > *walk_subtrees_p = 0; > break; > @@ -5605,12 +5606,12 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, > case REQUIRES_EXPR: > { > cp_unevaluated u; > - for (tree parm = REQUIRES_EXPR_PARMS (*tp); parm; parm = DECL_CHAIN (parm)) > + for (tree parm = REQUIRES_EXPR_PARMS (t); parm; parm = DECL_CHAIN (parm)) > /* Walk the types of each parameter, but not the parameter itself. > Doing so would cause false positives in the unexpanded parameter > pack checker since an introduced parameter pack looks bare. */ > WALK_SUBTREE (TREE_TYPE (parm)); > - WALK_SUBTREE (REQUIRES_EXPR_REQS (*tp)); > + WALK_SUBTREE (REQUIRES_EXPR_REQS (t)); > *walk_subtrees_p = 0; > break; > } > @@ -5621,12 +5622,12 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, > the containing BIND_EXPR. Compiler temporaries are > handled here. And also normal variables in templates, > since do_poplevel doesn't build a BIND_EXPR then. */ > - if (VAR_P (TREE_OPERAND (*tp, 0)) > + if (VAR_P (TREE_OPERAND (t, 0)) > && (processing_template_decl > - || (DECL_ARTIFICIAL (TREE_OPERAND (*tp, 0)) > - && !TREE_STATIC (TREE_OPERAND (*tp, 0))))) > + || (DECL_ARTIFICIAL (TREE_OPERAND (t, 0)) > + && !TREE_STATIC (TREE_OPERAND (t, 0))))) > { > - tree decl = TREE_OPERAND (*tp, 0); > + tree decl = TREE_OPERAND (t, 0); > WALK_SUBTREE (DECL_INITIAL (decl)); > WALK_SUBTREE (DECL_SIZE (decl)); > WALK_SUBTREE (DECL_SIZE_UNIT (decl)); > @@ -5636,45 +5637,45 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, > case LAMBDA_EXPR: > /* Don't walk into the body of the lambda, but the capture initializers > are part of the enclosing context. */ > - for (tree cap = LAMBDA_EXPR_CAPTURE_LIST (*tp); cap; > + for (tree cap = LAMBDA_EXPR_CAPTURE_LIST (t); cap; > cap = TREE_CHAIN (cap)) > WALK_SUBTREE (TREE_VALUE (cap)); > break; > > case CO_YIELD_EXPR: > - if (TREE_OPERAND (*tp, 1)) > + if (TREE_OPERAND (t, 1)) > /* Operand 1 is the tree for the relevant co_await which has any > interesting sub-trees. */ > - WALK_SUBTREE (TREE_OPERAND (*tp, 1)); > + WALK_SUBTREE (TREE_OPERAND (t, 1)); > break; > > case CO_AWAIT_EXPR: > - if (TREE_OPERAND (*tp, 1)) > + if (TREE_OPERAND (t, 1)) > /* Operand 1 is frame variable. */ > - WALK_SUBTREE (TREE_OPERAND (*tp, 1)); > - if (TREE_OPERAND (*tp, 2)) > + WALK_SUBTREE (TREE_OPERAND (t, 1)); > + if (TREE_OPERAND (t, 2)) > /* Operand 2 has the initialiser, and we need to walk any subtrees > there. */ > - WALK_SUBTREE (TREE_OPERAND (*tp, 2)); > + WALK_SUBTREE (TREE_OPERAND (t, 2)); > break; > > case CO_RETURN_EXPR: > - if (TREE_OPERAND (*tp, 0)) > + if (TREE_OPERAND (t, 0)) > { > - if (VOID_TYPE_P (TREE_OPERAND (*tp, 0))) > + if (VOID_TYPE_P (TREE_OPERAND (t, 0))) > /* For void expressions, operand 1 is a trivial call, and any > interesting subtrees will be part of operand 0. */ > - WALK_SUBTREE (TREE_OPERAND (*tp, 0)); > - else if (TREE_OPERAND (*tp, 1)) > + WALK_SUBTREE (TREE_OPERAND (t, 0)); > + else if (TREE_OPERAND (t, 1)) > /* Interesting sub-trees will be in the return_value () call > arguments. */ > - WALK_SUBTREE (TREE_OPERAND (*tp, 1)); > + WALK_SUBTREE (TREE_OPERAND (t, 1)); > } > break; > > case STATIC_ASSERT: > - WALK_SUBTREE (STATIC_ASSERT_CONDITION (*tp)); > - WALK_SUBTREE (STATIC_ASSERT_MESSAGE (*tp)); > + WALK_SUBTREE (STATIC_ASSERT_CONDITION (t)); > + WALK_SUBTREE (STATIC_ASSERT_MESSAGE (t)); > break; > > default: > diff --git a/gcc/tree.cc b/gcc/tree.cc > index 5eb6a49da31..dfada652570 100644 > --- a/gcc/tree.cc > +++ b/gcc/tree.cc > @@ -11218,10 +11218,6 @@ tree > walk_tree_1 (tree *tp, walk_tree_fn func, void *data, > hash_set<tree> *pset, walk_tree_lh lh) > { > - enum tree_code code; > - int walk_subtrees; > - tree result; > - > #define WALK_SUBTREE_TAIL(NODE) \ > do \ > { \ > @@ -11241,14 +11237,15 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, > return NULL_TREE; > > /* Call the function. */ > - walk_subtrees = 1; > - result = (*func) (tp, &walk_subtrees, data); > + int walk_subtrees = 1; > + tree result = (*func) (tp, &walk_subtrees, data); > > /* If we found something, return it. */ > if (result) > return result; > > - code = TREE_CODE (*tp); > + tree t = *tp; > + tree_code code = TREE_CODE (t); > > /* Even if we didn't, FUNC may have decided that there was nothing > interesting below this point in the tree. */ > @@ -11256,9 +11253,9 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, > { > /* But we still need to check our siblings. */ > if (code == TREE_LIST) > - WALK_SUBTREE_TAIL (TREE_CHAIN (*tp)); > + WALK_SUBTREE_TAIL (TREE_CHAIN (t)); > else if (code == OMP_CLAUSE) > - WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp)); > + WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (t)); > else > return NULL_TREE; > } > @@ -11288,58 +11285,58 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, > break; > > case TREE_LIST: > - WALK_SUBTREE (TREE_VALUE (*tp)); > - WALK_SUBTREE_TAIL (TREE_CHAIN (*tp)); > + WALK_SUBTREE (TREE_VALUE (t)); > + WALK_SUBTREE_TAIL (TREE_CHAIN (t)); > > case TREE_VEC: > { > - int len = TREE_VEC_LENGTH (*tp); > + int len = TREE_VEC_LENGTH (t); > > if (len == 0) > break; > > /* Walk all elements but the first. */ > while (--len) > - WALK_SUBTREE (TREE_VEC_ELT (*tp, len)); > + WALK_SUBTREE (TREE_VEC_ELT (t, len)); > > /* Now walk the first one as a tail call. */ > - WALK_SUBTREE_TAIL (TREE_VEC_ELT (*tp, 0)); > + WALK_SUBTREE_TAIL (TREE_VEC_ELT (t, 0)); > } > > case VECTOR_CST: > { > - unsigned len = vector_cst_encoded_nelts (*tp); > + unsigned len = vector_cst_encoded_nelts (t); > if (len == 0) > break; > /* Walk all elements but the first. */ > while (--len) > - WALK_SUBTREE (VECTOR_CST_ENCODED_ELT (*tp, len)); > + WALK_SUBTREE (VECTOR_CST_ENCODED_ELT (t, len)); > /* Now walk the first one as a tail call. */ > - WALK_SUBTREE_TAIL (VECTOR_CST_ENCODED_ELT (*tp, 0)); > + WALK_SUBTREE_TAIL (VECTOR_CST_ENCODED_ELT (t, 0)); > } > > case COMPLEX_CST: > - WALK_SUBTREE (TREE_REALPART (*tp)); > - WALK_SUBTREE_TAIL (TREE_IMAGPART (*tp)); > + WALK_SUBTREE (TREE_REALPART (t)); > + WALK_SUBTREE_TAIL (TREE_IMAGPART (t)); > > case CONSTRUCTOR: > { > unsigned HOST_WIDE_INT idx; > constructor_elt *ce; > > - for (idx = 0; vec_safe_iterate (CONSTRUCTOR_ELTS (*tp), idx, &ce); > + for (idx = 0; vec_safe_iterate (CONSTRUCTOR_ELTS (t), idx, &ce); > idx++) > WALK_SUBTREE (ce->value); > } > break; > > case SAVE_EXPR: > - WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, 0)); > + WALK_SUBTREE_TAIL (TREE_OPERAND (t, 0)); > > case BIND_EXPR: > { > tree decl; > - for (decl = BIND_EXPR_VARS (*tp); decl; decl = DECL_CHAIN (decl)) > + for (decl = BIND_EXPR_VARS (t); decl; decl = DECL_CHAIN (decl)) > { > /* Walk the DECL_INITIAL and DECL_SIZE. We don't want to walk > into declarations that are just mentioned, rather than > @@ -11350,23 +11347,23 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, > WALK_SUBTREE (DECL_SIZE (decl)); > WALK_SUBTREE (DECL_SIZE_UNIT (decl)); > } > - WALK_SUBTREE_TAIL (BIND_EXPR_BODY (*tp)); > + WALK_SUBTREE_TAIL (BIND_EXPR_BODY (t)); > } > > case STATEMENT_LIST: > { > tree_stmt_iterator i; > - for (i = tsi_start (*tp); !tsi_end_p (i); tsi_next (&i)) > + for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i)) > WALK_SUBTREE (*tsi_stmt_ptr (i)); > } > break; > > case OMP_CLAUSE: > { > - int len = omp_clause_num_ops[OMP_CLAUSE_CODE (*tp)]; > + int len = omp_clause_num_ops[OMP_CLAUSE_CODE (t)]; > for (int i = 0; i < len; i++) > - WALK_SUBTREE (OMP_CLAUSE_OPERAND (*tp, i)); > - WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp)); > + WALK_SUBTREE (OMP_CLAUSE_OPERAND (t, i)); > + WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (t)); > } > > case TARGET_EXPR: > @@ -11375,10 +11372,10 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, > > /* TARGET_EXPRs are peculiar: operands 1 and 3 can be the same. > But, we only want to walk once. */ > - len = (TREE_OPERAND (*tp, 3) == TREE_OPERAND (*tp, 1)) ? 2 : 3; > + len = (TREE_OPERAND (t, 3) == TREE_OPERAND (t, 1)) ? 2 : 3; > for (i = 0; i < len; ++i) > - WALK_SUBTREE (TREE_OPERAND (*tp, i)); > - WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, len)); > + WALK_SUBTREE (TREE_OPERAND (t, i)); > + WALK_SUBTREE_TAIL (TREE_OPERAND (t, len)); > } > > case DECL_EXPR: > @@ -11393,15 +11390,15 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, > variable-sized types. > > Note that DECLs get walked as part of processing the BIND_EXPR. */ > - if (TREE_CODE (DECL_EXPR_DECL (*tp)) == TYPE_DECL) > + if (TREE_CODE (DECL_EXPR_DECL (t)) == TYPE_DECL) > { > /* Call the function for the decl so e.g. copy_tree_body_r can > replace it with the remapped one. */ > - result = (*func) (&DECL_EXPR_DECL (*tp), &walk_subtrees, data); > + result = (*func) (&DECL_EXPR_DECL (t), &walk_subtrees, data); > if (result || !walk_subtrees) > return result; > > - tree *type_p = &TREE_TYPE (DECL_EXPR_DECL (*tp)); > + tree *type_p = &TREE_TYPE (DECL_EXPR_DECL (t)); > if (TREE_CODE (*type_p) == ERROR_MARK) > return NULL_TREE; > > @@ -11412,21 +11409,23 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, > if (result || !walk_subtrees) > return result; > > + tree type = *type_p; > + > /* But do not walk a pointed-to type since it may itself need to > be walked in the declaration case if it isn't anonymous. */ > - if (!POINTER_TYPE_P (*type_p)) > + if (!POINTER_TYPE_P (type)) > { > - result = walk_type_fields (*type_p, func, data, pset, lh); > + result = walk_type_fields (type, func, data, pset, lh); > if (result) > return result; > } > > /* If this is a record type, also walk the fields. */ > - if (RECORD_OR_UNION_TYPE_P (*type_p)) > + if (RECORD_OR_UNION_TYPE_P (type)) > { > tree field; > > - for (field = TYPE_FIELDS (*type_p); field; > + for (field = TYPE_FIELDS (type); field; > field = DECL_CHAIN (field)) > { > /* We'd like to look at the type of the field, but we can > @@ -11439,24 +11438,24 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, > WALK_SUBTREE (DECL_FIELD_OFFSET (field)); > WALK_SUBTREE (DECL_SIZE (field)); > WALK_SUBTREE (DECL_SIZE_UNIT (field)); > - if (TREE_CODE (*type_p) == QUAL_UNION_TYPE) > + if (TREE_CODE (type) == QUAL_UNION_TYPE) > WALK_SUBTREE (DECL_QUALIFIER (field)); > } > } > > /* Same for scalar types. */ > - else if (TREE_CODE (*type_p) == BOOLEAN_TYPE > - || TREE_CODE (*type_p) == ENUMERAL_TYPE > - || TREE_CODE (*type_p) == INTEGER_TYPE > - || TREE_CODE (*type_p) == FIXED_POINT_TYPE > - || TREE_CODE (*type_p) == REAL_TYPE) > + else if (TREE_CODE (type) == BOOLEAN_TYPE > + || TREE_CODE (type) == ENUMERAL_TYPE > + || TREE_CODE (type) == INTEGER_TYPE > + || TREE_CODE (type) == FIXED_POINT_TYPE > + || TREE_CODE (type) == REAL_TYPE) > { > - WALK_SUBTREE (TYPE_MIN_VALUE (*type_p)); > - WALK_SUBTREE (TYPE_MAX_VALUE (*type_p)); > + WALK_SUBTREE (TYPE_MIN_VALUE (type)); > + WALK_SUBTREE (TYPE_MAX_VALUE (type)); > } > > - WALK_SUBTREE (TYPE_SIZE (*type_p)); > - WALK_SUBTREE_TAIL (TYPE_SIZE_UNIT (*type_p)); > + WALK_SUBTREE (TYPE_SIZE (type)); > + WALK_SUBTREE_TAIL (TYPE_SIZE_UNIT (type)); > } > /* FALLTHRU */ > > @@ -11466,20 +11465,20 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, > int i, len; > > /* Walk over all the sub-trees of this operand. */ > - len = TREE_OPERAND_LENGTH (*tp); > + len = TREE_OPERAND_LENGTH (t); > > /* Go through the subtrees. We need to do this in forward order so > that the scope of a FOR_EXPR is handled properly. */ > if (len) > { > for (i = 0; i < len - 1; ++i) > - WALK_SUBTREE (TREE_OPERAND (*tp, i)); > - WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, len - 1)); > + WALK_SUBTREE (TREE_OPERAND (t, i)); > + WALK_SUBTREE_TAIL (TREE_OPERAND (t, len - 1)); > } > } > /* If this is a type, walk the needed fields in the type. */ > - else if (TYPE_P (*tp)) > - return walk_type_fields (*tp, func, data, pset, lh); > + else if (TYPE_P (t)) > + return walk_type_fields (t, func, data, pset, lh); > break; > } > > -- > 2.39.0.rc0.49.g083e01275b >
On Mon, 5 Dec 2022, Prathamesh Kulkarni wrote: > On Mon, 5 Dec 2022 at 09:51, Patrick Palka via Gcc-patches > <gcc-patches@gcc.gnu.org> wrote: > > > > These functions currently repeatedly dereference tp during the subtree > > walk, dereferences which the compiler can't CSE because it can't > > guarantee that the subtree walking doesn't modify *tp. > > > > But we already implicitly require that TREE_CODE (*tp) remains the same > > throughout the subtree walks, so it doesn't seem to be a huge leap to > > strengthen that to requiring *tp remains the same. > Hi Patrick, > Just wondering in that case, if marking tp with const_tree *, instead > of tree *, would perhaps help the compiler > for CSEing some of the dereferences to *tp ? IIUC I don't think using const_tree will help optimization-wise since the main issue is CSEing across calls to the callback fn, and the callback can still potentially modify *tp through some other, non-const pointer to it since it's global memory. > > Thanks, > Prathamesh > > > > So this patch manually CSEs the dereferences of *tp. This means that > > the callback function can no longer replace *tp with another tree (of > > the same TREE_CODE) when walking one of its subtrees, but that doesn't > > sound like a useful feature anyway. This speeds up the C++ frontend by > > about ~1.5% according to my experiments. > > > > Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for > > trunk stage3 or perhaps for stage1? > > > > gcc/cp/ChangeLog: > > > > * tree.cc (cp_walk_subtrees): Avoid repeatedly dereferencing tp. > > > > gcc/ChangeLog: > > > > * tree.cc (walk_tree_1): Avoid repeatedly dereferencing tp > > and type_p. > > --- > > gcc/cp/tree.cc | 113 +++++++++++++++++++++++++------------------------ > > gcc/tree.cc | 103 ++++++++++++++++++++++---------------------- > > 2 files changed, 108 insertions(+), 108 deletions(-) > > > > diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc > > index 4066b014f6e..ceb0c75f559 100644 > > --- a/gcc/cp/tree.cc > > +++ b/gcc/cp/tree.cc > > @@ -5441,7 +5441,8 @@ tree > > cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, > > void *data, hash_set<tree> *pset) > > { > > - enum tree_code code = TREE_CODE (*tp); > > + tree t = *tp; > > + enum tree_code code = TREE_CODE (t); > > tree result; > > > > #define WALK_SUBTREE(NODE) \ > > @@ -5452,7 +5453,7 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, > > } \ > > while (0) > > > > - if (TYPE_P (*tp)) > > + if (TYPE_P (t)) > > { > > /* If *WALK_SUBTREES_P is 1, we're interested in the syntactic form of > > the argument, so don't look through typedefs, but do walk into > > @@ -5464,15 +5465,15 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, > > > > See find_abi_tags_r for an example of setting *WALK_SUBTREES_P to 2 > > when that's the behavior the walk_tree_fn wants. */ > > - if (*walk_subtrees_p == 1 && typedef_variant_p (*tp)) > > + if (*walk_subtrees_p == 1 && typedef_variant_p (t)) > > { > > - if (tree ti = TYPE_ALIAS_TEMPLATE_INFO (*tp)) > > + if (tree ti = TYPE_ALIAS_TEMPLATE_INFO (t)) > > WALK_SUBTREE (TI_ARGS (ti)); > > *walk_subtrees_p = 0; > > return NULL_TREE; > > } > > > > - if (tree ti = TYPE_TEMPLATE_INFO (*tp)) > > + if (tree ti = TYPE_TEMPLATE_INFO (t)) > > WALK_SUBTREE (TI_ARGS (ti)); > > } > > > > @@ -5482,8 +5483,8 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, > > switch (code) > > { > > case TEMPLATE_TYPE_PARM: > > - if (template_placeholder_p (*tp)) > > - WALK_SUBTREE (CLASS_PLACEHOLDER_TEMPLATE (*tp)); > > + if (template_placeholder_p (t)) > > + WALK_SUBTREE (CLASS_PLACEHOLDER_TEMPLATE (t)); > > /* Fall through. */ > > case DEFERRED_PARSE: > > case TEMPLATE_TEMPLATE_PARM: > > @@ -5497,63 +5498,63 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, > > break; > > > > case TYPENAME_TYPE: > > - WALK_SUBTREE (TYPE_CONTEXT (*tp)); > > - WALK_SUBTREE (TYPENAME_TYPE_FULLNAME (*tp)); > > + WALK_SUBTREE (TYPE_CONTEXT (t)); > > + WALK_SUBTREE (TYPENAME_TYPE_FULLNAME (t)); > > *walk_subtrees_p = 0; > > break; > > > > case BASELINK: > > - if (BASELINK_QUALIFIED_P (*tp)) > > - WALK_SUBTREE (BINFO_TYPE (BASELINK_ACCESS_BINFO (*tp))); > > - WALK_SUBTREE (BASELINK_FUNCTIONS (*tp)); > > + if (BASELINK_QUALIFIED_P (t)) > > + WALK_SUBTREE (BINFO_TYPE (BASELINK_ACCESS_BINFO (t))); > > + WALK_SUBTREE (BASELINK_FUNCTIONS (t)); > > *walk_subtrees_p = 0; > > break; > > > > case PTRMEM_CST: > > - WALK_SUBTREE (TREE_TYPE (*tp)); > > + WALK_SUBTREE (TREE_TYPE (t)); > > *walk_subtrees_p = 0; > > break; > > > > case TREE_LIST: > > - WALK_SUBTREE (TREE_PURPOSE (*tp)); > > + WALK_SUBTREE (TREE_PURPOSE (t)); > > break; > > > > case OVERLOAD: > > - WALK_SUBTREE (OVL_FUNCTION (*tp)); > > - WALK_SUBTREE (OVL_CHAIN (*tp)); > > + WALK_SUBTREE (OVL_FUNCTION (t)); > > + WALK_SUBTREE (OVL_CHAIN (t)); > > *walk_subtrees_p = 0; > > break; > > > > case USING_DECL: > > - WALK_SUBTREE (DECL_NAME (*tp)); > > - WALK_SUBTREE (USING_DECL_SCOPE (*tp)); > > - WALK_SUBTREE (USING_DECL_DECLS (*tp)); > > + WALK_SUBTREE (DECL_NAME (t)); > > + WALK_SUBTREE (USING_DECL_SCOPE (t)); > > + WALK_SUBTREE (USING_DECL_DECLS (t)); > > *walk_subtrees_p = 0; > > break; > > > > case RECORD_TYPE: > > - if (TYPE_PTRMEMFUNC_P (*tp)) > > - WALK_SUBTREE (TYPE_PTRMEMFUNC_FN_TYPE_RAW (*tp)); > > + if (TYPE_PTRMEMFUNC_P (t)) > > + WALK_SUBTREE (TYPE_PTRMEMFUNC_FN_TYPE_RAW (t)); > > break; > > > > case TYPE_ARGUMENT_PACK: > > case NONTYPE_ARGUMENT_PACK: > > { > > - tree args = ARGUMENT_PACK_ARGS (*tp); > > + tree args = ARGUMENT_PACK_ARGS (t); > > for (tree arg : tree_vec_range (args)) > > WALK_SUBTREE (arg); > > } > > break; > > > > case TYPE_PACK_EXPANSION: > > - WALK_SUBTREE (TREE_TYPE (*tp)); > > - WALK_SUBTREE (PACK_EXPANSION_EXTRA_ARGS (*tp)); > > + WALK_SUBTREE (TREE_TYPE (t)); > > + WALK_SUBTREE (PACK_EXPANSION_EXTRA_ARGS (t)); > > *walk_subtrees_p = 0; > > break; > > > > case EXPR_PACK_EXPANSION: > > - WALK_SUBTREE (TREE_OPERAND (*tp, 0)); > > - WALK_SUBTREE (PACK_EXPANSION_EXTRA_ARGS (*tp)); > > + WALK_SUBTREE (TREE_OPERAND (t, 0)); > > + WALK_SUBTREE (PACK_EXPANSION_EXTRA_ARGS (t)); > > *walk_subtrees_p = 0; > > break; > > > > @@ -5564,31 +5565,31 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, > > case DYNAMIC_CAST_EXPR: > > case IMPLICIT_CONV_EXPR: > > case BIT_CAST_EXPR: > > - if (TREE_TYPE (*tp)) > > - WALK_SUBTREE (TREE_TYPE (*tp)); > > + if (TREE_TYPE (t)) > > + WALK_SUBTREE (TREE_TYPE (t)); > > break; > > > > case CONSTRUCTOR: > > - if (COMPOUND_LITERAL_P (*tp)) > > - WALK_SUBTREE (TREE_TYPE (*tp)); > > + if (COMPOUND_LITERAL_P (t)) > > + WALK_SUBTREE (TREE_TYPE (t)); > > break; > > > > case TRAIT_EXPR: > > - WALK_SUBTREE (TRAIT_EXPR_TYPE1 (*tp)); > > - WALK_SUBTREE (TRAIT_EXPR_TYPE2 (*tp)); > > + WALK_SUBTREE (TRAIT_EXPR_TYPE1 (t)); > > + WALK_SUBTREE (TRAIT_EXPR_TYPE2 (t)); > > *walk_subtrees_p = 0; > > break; > > > > case TRAIT_TYPE: > > - WALK_SUBTREE (TRAIT_TYPE_TYPE1 (*tp)); > > - WALK_SUBTREE (TRAIT_TYPE_TYPE2 (*tp)); > > + WALK_SUBTREE (TRAIT_TYPE_TYPE1 (t)); > > + WALK_SUBTREE (TRAIT_TYPE_TYPE2 (t)); > > *walk_subtrees_p = 0; > > break; > > > > case DECLTYPE_TYPE: > > ++cp_unevaluated_operand; > > /* We can't use WALK_SUBTREE here because of the goto. */ > > - result = cp_walk_tree (&DECLTYPE_TYPE_EXPR (*tp), func, data, pset); > > + result = cp_walk_tree (&DECLTYPE_TYPE_EXPR (t), func, data, pset); > > --cp_unevaluated_operand; > > *walk_subtrees_p = 0; > > break; > > @@ -5597,7 +5598,7 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, > > case SIZEOF_EXPR: > > case NOEXCEPT_EXPR: > > ++cp_unevaluated_operand; > > - result = cp_walk_tree (&TREE_OPERAND (*tp, 0), func, data, pset); > > + result = cp_walk_tree (&TREE_OPERAND (t, 0), func, data, pset); > > --cp_unevaluated_operand; > > *walk_subtrees_p = 0; > > break; > > @@ -5605,12 +5606,12 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, > > case REQUIRES_EXPR: > > { > > cp_unevaluated u; > > - for (tree parm = REQUIRES_EXPR_PARMS (*tp); parm; parm = DECL_CHAIN (parm)) > > + for (tree parm = REQUIRES_EXPR_PARMS (t); parm; parm = DECL_CHAIN (parm)) > > /* Walk the types of each parameter, but not the parameter itself. > > Doing so would cause false positives in the unexpanded parameter > > pack checker since an introduced parameter pack looks bare. */ > > WALK_SUBTREE (TREE_TYPE (parm)); > > - WALK_SUBTREE (REQUIRES_EXPR_REQS (*tp)); > > + WALK_SUBTREE (REQUIRES_EXPR_REQS (t)); > > *walk_subtrees_p = 0; > > break; > > } > > @@ -5621,12 +5622,12 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, > > the containing BIND_EXPR. Compiler temporaries are > > handled here. And also normal variables in templates, > > since do_poplevel doesn't build a BIND_EXPR then. */ > > - if (VAR_P (TREE_OPERAND (*tp, 0)) > > + if (VAR_P (TREE_OPERAND (t, 0)) > > && (processing_template_decl > > - || (DECL_ARTIFICIAL (TREE_OPERAND (*tp, 0)) > > - && !TREE_STATIC (TREE_OPERAND (*tp, 0))))) > > + || (DECL_ARTIFICIAL (TREE_OPERAND (t, 0)) > > + && !TREE_STATIC (TREE_OPERAND (t, 0))))) > > { > > - tree decl = TREE_OPERAND (*tp, 0); > > + tree decl = TREE_OPERAND (t, 0); > > WALK_SUBTREE (DECL_INITIAL (decl)); > > WALK_SUBTREE (DECL_SIZE (decl)); > > WALK_SUBTREE (DECL_SIZE_UNIT (decl)); > > @@ -5636,45 +5637,45 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, > > case LAMBDA_EXPR: > > /* Don't walk into the body of the lambda, but the capture initializers > > are part of the enclosing context. */ > > - for (tree cap = LAMBDA_EXPR_CAPTURE_LIST (*tp); cap; > > + for (tree cap = LAMBDA_EXPR_CAPTURE_LIST (t); cap; > > cap = TREE_CHAIN (cap)) > > WALK_SUBTREE (TREE_VALUE (cap)); > > break; > > > > case CO_YIELD_EXPR: > > - if (TREE_OPERAND (*tp, 1)) > > + if (TREE_OPERAND (t, 1)) > > /* Operand 1 is the tree for the relevant co_await which has any > > interesting sub-trees. */ > > - WALK_SUBTREE (TREE_OPERAND (*tp, 1)); > > + WALK_SUBTREE (TREE_OPERAND (t, 1)); > > break; > > > > case CO_AWAIT_EXPR: > > - if (TREE_OPERAND (*tp, 1)) > > + if (TREE_OPERAND (t, 1)) > > /* Operand 1 is frame variable. */ > > - WALK_SUBTREE (TREE_OPERAND (*tp, 1)); > > - if (TREE_OPERAND (*tp, 2)) > > + WALK_SUBTREE (TREE_OPERAND (t, 1)); > > + if (TREE_OPERAND (t, 2)) > > /* Operand 2 has the initialiser, and we need to walk any subtrees > > there. */ > > - WALK_SUBTREE (TREE_OPERAND (*tp, 2)); > > + WALK_SUBTREE (TREE_OPERAND (t, 2)); > > break; > > > > case CO_RETURN_EXPR: > > - if (TREE_OPERAND (*tp, 0)) > > + if (TREE_OPERAND (t, 0)) > > { > > - if (VOID_TYPE_P (TREE_OPERAND (*tp, 0))) > > + if (VOID_TYPE_P (TREE_OPERAND (t, 0))) > > /* For void expressions, operand 1 is a trivial call, and any > > interesting subtrees will be part of operand 0. */ > > - WALK_SUBTREE (TREE_OPERAND (*tp, 0)); > > - else if (TREE_OPERAND (*tp, 1)) > > + WALK_SUBTREE (TREE_OPERAND (t, 0)); > > + else if (TREE_OPERAND (t, 1)) > > /* Interesting sub-trees will be in the return_value () call > > arguments. */ > > - WALK_SUBTREE (TREE_OPERAND (*tp, 1)); > > + WALK_SUBTREE (TREE_OPERAND (t, 1)); > > } > > break; > > > > case STATIC_ASSERT: > > - WALK_SUBTREE (STATIC_ASSERT_CONDITION (*tp)); > > - WALK_SUBTREE (STATIC_ASSERT_MESSAGE (*tp)); > > + WALK_SUBTREE (STATIC_ASSERT_CONDITION (t)); > > + WALK_SUBTREE (STATIC_ASSERT_MESSAGE (t)); > > break; > > > > default: > > diff --git a/gcc/tree.cc b/gcc/tree.cc > > index 5eb6a49da31..dfada652570 100644 > > --- a/gcc/tree.cc > > +++ b/gcc/tree.cc > > @@ -11218,10 +11218,6 @@ tree > > walk_tree_1 (tree *tp, walk_tree_fn func, void *data, > > hash_set<tree> *pset, walk_tree_lh lh) > > { > > - enum tree_code code; > > - int walk_subtrees; > > - tree result; > > - > > #define WALK_SUBTREE_TAIL(NODE) \ > > do \ > > { \ > > @@ -11241,14 +11237,15 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, > > return NULL_TREE; > > > > /* Call the function. */ > > - walk_subtrees = 1; > > - result = (*func) (tp, &walk_subtrees, data); > > + int walk_subtrees = 1; > > + tree result = (*func) (tp, &walk_subtrees, data); > > > > /* If we found something, return it. */ > > if (result) > > return result; > > > > - code = TREE_CODE (*tp); > > + tree t = *tp; > > + tree_code code = TREE_CODE (t); > > > > /* Even if we didn't, FUNC may have decided that there was nothing > > interesting below this point in the tree. */ > > @@ -11256,9 +11253,9 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, > > { > > /* But we still need to check our siblings. */ > > if (code == TREE_LIST) > > - WALK_SUBTREE_TAIL (TREE_CHAIN (*tp)); > > + WALK_SUBTREE_TAIL (TREE_CHAIN (t)); > > else if (code == OMP_CLAUSE) > > - WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp)); > > + WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (t)); > > else > > return NULL_TREE; > > } > > @@ -11288,58 +11285,58 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, > > break; > > > > case TREE_LIST: > > - WALK_SUBTREE (TREE_VALUE (*tp)); > > - WALK_SUBTREE_TAIL (TREE_CHAIN (*tp)); > > + WALK_SUBTREE (TREE_VALUE (t)); > > + WALK_SUBTREE_TAIL (TREE_CHAIN (t)); > > > > case TREE_VEC: > > { > > - int len = TREE_VEC_LENGTH (*tp); > > + int len = TREE_VEC_LENGTH (t); > > > > if (len == 0) > > break; > > > > /* Walk all elements but the first. */ > > while (--len) > > - WALK_SUBTREE (TREE_VEC_ELT (*tp, len)); > > + WALK_SUBTREE (TREE_VEC_ELT (t, len)); > > > > /* Now walk the first one as a tail call. */ > > - WALK_SUBTREE_TAIL (TREE_VEC_ELT (*tp, 0)); > > + WALK_SUBTREE_TAIL (TREE_VEC_ELT (t, 0)); > > } > > > > case VECTOR_CST: > > { > > - unsigned len = vector_cst_encoded_nelts (*tp); > > + unsigned len = vector_cst_encoded_nelts (t); > > if (len == 0) > > break; > > /* Walk all elements but the first. */ > > while (--len) > > - WALK_SUBTREE (VECTOR_CST_ENCODED_ELT (*tp, len)); > > + WALK_SUBTREE (VECTOR_CST_ENCODED_ELT (t, len)); > > /* Now walk the first one as a tail call. */ > > - WALK_SUBTREE_TAIL (VECTOR_CST_ENCODED_ELT (*tp, 0)); > > + WALK_SUBTREE_TAIL (VECTOR_CST_ENCODED_ELT (t, 0)); > > } > > > > case COMPLEX_CST: > > - WALK_SUBTREE (TREE_REALPART (*tp)); > > - WALK_SUBTREE_TAIL (TREE_IMAGPART (*tp)); > > + WALK_SUBTREE (TREE_REALPART (t)); > > + WALK_SUBTREE_TAIL (TREE_IMAGPART (t)); > > > > case CONSTRUCTOR: > > { > > unsigned HOST_WIDE_INT idx; > > constructor_elt *ce; > > > > - for (idx = 0; vec_safe_iterate (CONSTRUCTOR_ELTS (*tp), idx, &ce); > > + for (idx = 0; vec_safe_iterate (CONSTRUCTOR_ELTS (t), idx, &ce); > > idx++) > > WALK_SUBTREE (ce->value); > > } > > break; > > > > case SAVE_EXPR: > > - WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, 0)); > > + WALK_SUBTREE_TAIL (TREE_OPERAND (t, 0)); > > > > case BIND_EXPR: > > { > > tree decl; > > - for (decl = BIND_EXPR_VARS (*tp); decl; decl = DECL_CHAIN (decl)) > > + for (decl = BIND_EXPR_VARS (t); decl; decl = DECL_CHAIN (decl)) > > { > > /* Walk the DECL_INITIAL and DECL_SIZE. We don't want to walk > > into declarations that are just mentioned, rather than > > @@ -11350,23 +11347,23 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, > > WALK_SUBTREE (DECL_SIZE (decl)); > > WALK_SUBTREE (DECL_SIZE_UNIT (decl)); > > } > > - WALK_SUBTREE_TAIL (BIND_EXPR_BODY (*tp)); > > + WALK_SUBTREE_TAIL (BIND_EXPR_BODY (t)); > > } > > > > case STATEMENT_LIST: > > { > > tree_stmt_iterator i; > > - for (i = tsi_start (*tp); !tsi_end_p (i); tsi_next (&i)) > > + for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i)) > > WALK_SUBTREE (*tsi_stmt_ptr (i)); > > } > > break; > > > > case OMP_CLAUSE: > > { > > - int len = omp_clause_num_ops[OMP_CLAUSE_CODE (*tp)]; > > + int len = omp_clause_num_ops[OMP_CLAUSE_CODE (t)]; > > for (int i = 0; i < len; i++) > > - WALK_SUBTREE (OMP_CLAUSE_OPERAND (*tp, i)); > > - WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp)); > > + WALK_SUBTREE (OMP_CLAUSE_OPERAND (t, i)); > > + WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (t)); > > } > > > > case TARGET_EXPR: > > @@ -11375,10 +11372,10 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, > > > > /* TARGET_EXPRs are peculiar: operands 1 and 3 can be the same. > > But, we only want to walk once. */ > > - len = (TREE_OPERAND (*tp, 3) == TREE_OPERAND (*tp, 1)) ? 2 : 3; > > + len = (TREE_OPERAND (t, 3) == TREE_OPERAND (t, 1)) ? 2 : 3; > > for (i = 0; i < len; ++i) > > - WALK_SUBTREE (TREE_OPERAND (*tp, i)); > > - WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, len)); > > + WALK_SUBTREE (TREE_OPERAND (t, i)); > > + WALK_SUBTREE_TAIL (TREE_OPERAND (t, len)); > > } > > > > case DECL_EXPR: > > @@ -11393,15 +11390,15 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, > > variable-sized types. > > > > Note that DECLs get walked as part of processing the BIND_EXPR. */ > > - if (TREE_CODE (DECL_EXPR_DECL (*tp)) == TYPE_DECL) > > + if (TREE_CODE (DECL_EXPR_DECL (t)) == TYPE_DECL) > > { > > /* Call the function for the decl so e.g. copy_tree_body_r can > > replace it with the remapped one. */ > > - result = (*func) (&DECL_EXPR_DECL (*tp), &walk_subtrees, data); > > + result = (*func) (&DECL_EXPR_DECL (t), &walk_subtrees, data); > > if (result || !walk_subtrees) > > return result; > > > > - tree *type_p = &TREE_TYPE (DECL_EXPR_DECL (*tp)); > > + tree *type_p = &TREE_TYPE (DECL_EXPR_DECL (t)); > > if (TREE_CODE (*type_p) == ERROR_MARK) > > return NULL_TREE; > > > > @@ -11412,21 +11409,23 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, > > if (result || !walk_subtrees) > > return result; > > > > + tree type = *type_p; > > + > > /* But do not walk a pointed-to type since it may itself need to > > be walked in the declaration case if it isn't anonymous. */ > > - if (!POINTER_TYPE_P (*type_p)) > > + if (!POINTER_TYPE_P (type)) > > { > > - result = walk_type_fields (*type_p, func, data, pset, lh); > > + result = walk_type_fields (type, func, data, pset, lh); > > if (result) > > return result; > > } > > > > /* If this is a record type, also walk the fields. */ > > - if (RECORD_OR_UNION_TYPE_P (*type_p)) > > + if (RECORD_OR_UNION_TYPE_P (type)) > > { > > tree field; > > > > - for (field = TYPE_FIELDS (*type_p); field; > > + for (field = TYPE_FIELDS (type); field; > > field = DECL_CHAIN (field)) > > { > > /* We'd like to look at the type of the field, but we can > > @@ -11439,24 +11438,24 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, > > WALK_SUBTREE (DECL_FIELD_OFFSET (field)); > > WALK_SUBTREE (DECL_SIZE (field)); > > WALK_SUBTREE (DECL_SIZE_UNIT (field)); > > - if (TREE_CODE (*type_p) == QUAL_UNION_TYPE) > > + if (TREE_CODE (type) == QUAL_UNION_TYPE) > > WALK_SUBTREE (DECL_QUALIFIER (field)); > > } > > } > > > > /* Same for scalar types. */ > > - else if (TREE_CODE (*type_p) == BOOLEAN_TYPE > > - || TREE_CODE (*type_p) == ENUMERAL_TYPE > > - || TREE_CODE (*type_p) == INTEGER_TYPE > > - || TREE_CODE (*type_p) == FIXED_POINT_TYPE > > - || TREE_CODE (*type_p) == REAL_TYPE) > > + else if (TREE_CODE (type) == BOOLEAN_TYPE > > + || TREE_CODE (type) == ENUMERAL_TYPE > > + || TREE_CODE (type) == INTEGER_TYPE > > + || TREE_CODE (type) == FIXED_POINT_TYPE > > + || TREE_CODE (type) == REAL_TYPE) > > { > > - WALK_SUBTREE (TYPE_MIN_VALUE (*type_p)); > > - WALK_SUBTREE (TYPE_MAX_VALUE (*type_p)); > > + WALK_SUBTREE (TYPE_MIN_VALUE (type)); > > + WALK_SUBTREE (TYPE_MAX_VALUE (type)); > > } > > > > - WALK_SUBTREE (TYPE_SIZE (*type_p)); > > - WALK_SUBTREE_TAIL (TYPE_SIZE_UNIT (*type_p)); > > + WALK_SUBTREE (TYPE_SIZE (type)); > > + WALK_SUBTREE_TAIL (TYPE_SIZE_UNIT (type)); > > } > > /* FALLTHRU */ > > > > @@ -11466,20 +11465,20 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, > > int i, len; > > > > /* Walk over all the sub-trees of this operand. */ > > - len = TREE_OPERAND_LENGTH (*tp); > > + len = TREE_OPERAND_LENGTH (t); > > > > /* Go through the subtrees. We need to do this in forward order so > > that the scope of a FOR_EXPR is handled properly. */ > > if (len) > > { > > for (i = 0; i < len - 1; ++i) > > - WALK_SUBTREE (TREE_OPERAND (*tp, i)); > > - WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, len - 1)); > > + WALK_SUBTREE (TREE_OPERAND (t, i)); > > + WALK_SUBTREE_TAIL (TREE_OPERAND (t, len - 1)); > > } > > } > > /* If this is a type, walk the needed fields in the type. */ > > - else if (TYPE_P (*tp)) > > - return walk_type_fields (*tp, func, data, pset, lh); > > + else if (TYPE_P (t)) > > + return walk_type_fields (t, func, data, pset, lh); > > break; > > } > > > > -- > > 2.39.0.rc0.49.g083e01275b > > > >
On 12/5/22 06:09, Prathamesh Kulkarni wrote: > On Mon, 5 Dec 2022 at 09:51, Patrick Palka via Gcc-patches > <gcc-patches@gcc.gnu.org> wrote: >> >> These functions currently repeatedly dereference tp during the subtree >> walk, dereferences which the compiler can't CSE because it can't >> guarantee that the subtree walking doesn't modify *tp. >> >> But we already implicitly require that TREE_CODE (*tp) remains the same >> throughout the subtree walks, so it doesn't seem to be a huge leap to >> strengthen that to requiring *tp remains the same. > Hi Patrick, > Just wondering in that case, if marking tp with const_tree *, instead > of tree *, would perhaps help the compiler > for CSEing some of the dereferences to *tp ? That wouldn't make a difference; even if *tp is const, the compiler can't be sure that a call won't change it. And const_tree * doesn't even make *tp const, it makes **tp const. >> So this patch manually CSEs the dereferences of *tp. This means that >> the callback function can no longer replace *tp with another tree (of >> the same TREE_CODE) when walking one of its subtrees, but that doesn't >> sound like a useful feature anyway. This speeds up the C++ frontend by >> about ~1.5% according to my experiments. >> >> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for >> trunk stage3 or perhaps for stage1? OK for stage 1. >> gcc/cp/ChangeLog: >> >> * tree.cc (cp_walk_subtrees): Avoid repeatedly dereferencing tp. >> >> gcc/ChangeLog: >> >> * tree.cc (walk_tree_1): Avoid repeatedly dereferencing tp >> and type_p. >> --- >> gcc/cp/tree.cc | 113 +++++++++++++++++++++++++------------------------ >> gcc/tree.cc | 103 ++++++++++++++++++++++---------------------- >> 2 files changed, 108 insertions(+), 108 deletions(-) >> >> diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc >> index 4066b014f6e..ceb0c75f559 100644 >> --- a/gcc/cp/tree.cc >> +++ b/gcc/cp/tree.cc >> @@ -5441,7 +5441,8 @@ tree >> cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, >> void *data, hash_set<tree> *pset) >> { >> - enum tree_code code = TREE_CODE (*tp); >> + tree t = *tp; >> + enum tree_code code = TREE_CODE (t); >> tree result; >> >> #define WALK_SUBTREE(NODE) \ >> @@ -5452,7 +5453,7 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, >> } \ >> while (0) >> >> - if (TYPE_P (*tp)) >> + if (TYPE_P (t)) >> { >> /* If *WALK_SUBTREES_P is 1, we're interested in the syntactic form of >> the argument, so don't look through typedefs, but do walk into >> @@ -5464,15 +5465,15 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, >> >> See find_abi_tags_r for an example of setting *WALK_SUBTREES_P to 2 >> when that's the behavior the walk_tree_fn wants. */ >> - if (*walk_subtrees_p == 1 && typedef_variant_p (*tp)) >> + if (*walk_subtrees_p == 1 && typedef_variant_p (t)) >> { >> - if (tree ti = TYPE_ALIAS_TEMPLATE_INFO (*tp)) >> + if (tree ti = TYPE_ALIAS_TEMPLATE_INFO (t)) >> WALK_SUBTREE (TI_ARGS (ti)); >> *walk_subtrees_p = 0; >> return NULL_TREE; >> } >> >> - if (tree ti = TYPE_TEMPLATE_INFO (*tp)) >> + if (tree ti = TYPE_TEMPLATE_INFO (t)) >> WALK_SUBTREE (TI_ARGS (ti)); >> } >> >> @@ -5482,8 +5483,8 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, >> switch (code) >> { >> case TEMPLATE_TYPE_PARM: >> - if (template_placeholder_p (*tp)) >> - WALK_SUBTREE (CLASS_PLACEHOLDER_TEMPLATE (*tp)); >> + if (template_placeholder_p (t)) >> + WALK_SUBTREE (CLASS_PLACEHOLDER_TEMPLATE (t)); >> /* Fall through. */ >> case DEFERRED_PARSE: >> case TEMPLATE_TEMPLATE_PARM: >> @@ -5497,63 +5498,63 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, >> break; >> >> case TYPENAME_TYPE: >> - WALK_SUBTREE (TYPE_CONTEXT (*tp)); >> - WALK_SUBTREE (TYPENAME_TYPE_FULLNAME (*tp)); >> + WALK_SUBTREE (TYPE_CONTEXT (t)); >> + WALK_SUBTREE (TYPENAME_TYPE_FULLNAME (t)); >> *walk_subtrees_p = 0; >> break; >> >> case BASELINK: >> - if (BASELINK_QUALIFIED_P (*tp)) >> - WALK_SUBTREE (BINFO_TYPE (BASELINK_ACCESS_BINFO (*tp))); >> - WALK_SUBTREE (BASELINK_FUNCTIONS (*tp)); >> + if (BASELINK_QUALIFIED_P (t)) >> + WALK_SUBTREE (BINFO_TYPE (BASELINK_ACCESS_BINFO (t))); >> + WALK_SUBTREE (BASELINK_FUNCTIONS (t)); >> *walk_subtrees_p = 0; >> break; >> >> case PTRMEM_CST: >> - WALK_SUBTREE (TREE_TYPE (*tp)); >> + WALK_SUBTREE (TREE_TYPE (t)); >> *walk_subtrees_p = 0; >> break; >> >> case TREE_LIST: >> - WALK_SUBTREE (TREE_PURPOSE (*tp)); >> + WALK_SUBTREE (TREE_PURPOSE (t)); >> break; >> >> case OVERLOAD: >> - WALK_SUBTREE (OVL_FUNCTION (*tp)); >> - WALK_SUBTREE (OVL_CHAIN (*tp)); >> + WALK_SUBTREE (OVL_FUNCTION (t)); >> + WALK_SUBTREE (OVL_CHAIN (t)); >> *walk_subtrees_p = 0; >> break; >> >> case USING_DECL: >> - WALK_SUBTREE (DECL_NAME (*tp)); >> - WALK_SUBTREE (USING_DECL_SCOPE (*tp)); >> - WALK_SUBTREE (USING_DECL_DECLS (*tp)); >> + WALK_SUBTREE (DECL_NAME (t)); >> + WALK_SUBTREE (USING_DECL_SCOPE (t)); >> + WALK_SUBTREE (USING_DECL_DECLS (t)); >> *walk_subtrees_p = 0; >> break; >> >> case RECORD_TYPE: >> - if (TYPE_PTRMEMFUNC_P (*tp)) >> - WALK_SUBTREE (TYPE_PTRMEMFUNC_FN_TYPE_RAW (*tp)); >> + if (TYPE_PTRMEMFUNC_P (t)) >> + WALK_SUBTREE (TYPE_PTRMEMFUNC_FN_TYPE_RAW (t)); >> break; >> >> case TYPE_ARGUMENT_PACK: >> case NONTYPE_ARGUMENT_PACK: >> { >> - tree args = ARGUMENT_PACK_ARGS (*tp); >> + tree args = ARGUMENT_PACK_ARGS (t); >> for (tree arg : tree_vec_range (args)) >> WALK_SUBTREE (arg); >> } >> break; >> >> case TYPE_PACK_EXPANSION: >> - WALK_SUBTREE (TREE_TYPE (*tp)); >> - WALK_SUBTREE (PACK_EXPANSION_EXTRA_ARGS (*tp)); >> + WALK_SUBTREE (TREE_TYPE (t)); >> + WALK_SUBTREE (PACK_EXPANSION_EXTRA_ARGS (t)); >> *walk_subtrees_p = 0; >> break; >> >> case EXPR_PACK_EXPANSION: >> - WALK_SUBTREE (TREE_OPERAND (*tp, 0)); >> - WALK_SUBTREE (PACK_EXPANSION_EXTRA_ARGS (*tp)); >> + WALK_SUBTREE (TREE_OPERAND (t, 0)); >> + WALK_SUBTREE (PACK_EXPANSION_EXTRA_ARGS (t)); >> *walk_subtrees_p = 0; >> break; >> >> @@ -5564,31 +5565,31 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, >> case DYNAMIC_CAST_EXPR: >> case IMPLICIT_CONV_EXPR: >> case BIT_CAST_EXPR: >> - if (TREE_TYPE (*tp)) >> - WALK_SUBTREE (TREE_TYPE (*tp)); >> + if (TREE_TYPE (t)) >> + WALK_SUBTREE (TREE_TYPE (t)); >> break; >> >> case CONSTRUCTOR: >> - if (COMPOUND_LITERAL_P (*tp)) >> - WALK_SUBTREE (TREE_TYPE (*tp)); >> + if (COMPOUND_LITERAL_P (t)) >> + WALK_SUBTREE (TREE_TYPE (t)); >> break; >> >> case TRAIT_EXPR: >> - WALK_SUBTREE (TRAIT_EXPR_TYPE1 (*tp)); >> - WALK_SUBTREE (TRAIT_EXPR_TYPE2 (*tp)); >> + WALK_SUBTREE (TRAIT_EXPR_TYPE1 (t)); >> + WALK_SUBTREE (TRAIT_EXPR_TYPE2 (t)); >> *walk_subtrees_p = 0; >> break; >> >> case TRAIT_TYPE: >> - WALK_SUBTREE (TRAIT_TYPE_TYPE1 (*tp)); >> - WALK_SUBTREE (TRAIT_TYPE_TYPE2 (*tp)); >> + WALK_SUBTREE (TRAIT_TYPE_TYPE1 (t)); >> + WALK_SUBTREE (TRAIT_TYPE_TYPE2 (t)); >> *walk_subtrees_p = 0; >> break; >> >> case DECLTYPE_TYPE: >> ++cp_unevaluated_operand; >> /* We can't use WALK_SUBTREE here because of the goto. */ >> - result = cp_walk_tree (&DECLTYPE_TYPE_EXPR (*tp), func, data, pset); >> + result = cp_walk_tree (&DECLTYPE_TYPE_EXPR (t), func, data, pset); >> --cp_unevaluated_operand; >> *walk_subtrees_p = 0; >> break; >> @@ -5597,7 +5598,7 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, >> case SIZEOF_EXPR: >> case NOEXCEPT_EXPR: >> ++cp_unevaluated_operand; >> - result = cp_walk_tree (&TREE_OPERAND (*tp, 0), func, data, pset); >> + result = cp_walk_tree (&TREE_OPERAND (t, 0), func, data, pset); >> --cp_unevaluated_operand; >> *walk_subtrees_p = 0; >> break; >> @@ -5605,12 +5606,12 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, >> case REQUIRES_EXPR: >> { >> cp_unevaluated u; >> - for (tree parm = REQUIRES_EXPR_PARMS (*tp); parm; parm = DECL_CHAIN (parm)) >> + for (tree parm = REQUIRES_EXPR_PARMS (t); parm; parm = DECL_CHAIN (parm)) >> /* Walk the types of each parameter, but not the parameter itself. >> Doing so would cause false positives in the unexpanded parameter >> pack checker since an introduced parameter pack looks bare. */ >> WALK_SUBTREE (TREE_TYPE (parm)); >> - WALK_SUBTREE (REQUIRES_EXPR_REQS (*tp)); >> + WALK_SUBTREE (REQUIRES_EXPR_REQS (t)); >> *walk_subtrees_p = 0; >> break; >> } >> @@ -5621,12 +5622,12 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, >> the containing BIND_EXPR. Compiler temporaries are >> handled here. And also normal variables in templates, >> since do_poplevel doesn't build a BIND_EXPR then. */ >> - if (VAR_P (TREE_OPERAND (*tp, 0)) >> + if (VAR_P (TREE_OPERAND (t, 0)) >> && (processing_template_decl >> - || (DECL_ARTIFICIAL (TREE_OPERAND (*tp, 0)) >> - && !TREE_STATIC (TREE_OPERAND (*tp, 0))))) >> + || (DECL_ARTIFICIAL (TREE_OPERAND (t, 0)) >> + && !TREE_STATIC (TREE_OPERAND (t, 0))))) >> { >> - tree decl = TREE_OPERAND (*tp, 0); >> + tree decl = TREE_OPERAND (t, 0); >> WALK_SUBTREE (DECL_INITIAL (decl)); >> WALK_SUBTREE (DECL_SIZE (decl)); >> WALK_SUBTREE (DECL_SIZE_UNIT (decl)); >> @@ -5636,45 +5637,45 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, >> case LAMBDA_EXPR: >> /* Don't walk into the body of the lambda, but the capture initializers >> are part of the enclosing context. */ >> - for (tree cap = LAMBDA_EXPR_CAPTURE_LIST (*tp); cap; >> + for (tree cap = LAMBDA_EXPR_CAPTURE_LIST (t); cap; >> cap = TREE_CHAIN (cap)) >> WALK_SUBTREE (TREE_VALUE (cap)); >> break; >> >> case CO_YIELD_EXPR: >> - if (TREE_OPERAND (*tp, 1)) >> + if (TREE_OPERAND (t, 1)) >> /* Operand 1 is the tree for the relevant co_await which has any >> interesting sub-trees. */ >> - WALK_SUBTREE (TREE_OPERAND (*tp, 1)); >> + WALK_SUBTREE (TREE_OPERAND (t, 1)); >> break; >> >> case CO_AWAIT_EXPR: >> - if (TREE_OPERAND (*tp, 1)) >> + if (TREE_OPERAND (t, 1)) >> /* Operand 1 is frame variable. */ >> - WALK_SUBTREE (TREE_OPERAND (*tp, 1)); >> - if (TREE_OPERAND (*tp, 2)) >> + WALK_SUBTREE (TREE_OPERAND (t, 1)); >> + if (TREE_OPERAND (t, 2)) >> /* Operand 2 has the initialiser, and we need to walk any subtrees >> there. */ >> - WALK_SUBTREE (TREE_OPERAND (*tp, 2)); >> + WALK_SUBTREE (TREE_OPERAND (t, 2)); >> break; >> >> case CO_RETURN_EXPR: >> - if (TREE_OPERAND (*tp, 0)) >> + if (TREE_OPERAND (t, 0)) >> { >> - if (VOID_TYPE_P (TREE_OPERAND (*tp, 0))) >> + if (VOID_TYPE_P (TREE_OPERAND (t, 0))) >> /* For void expressions, operand 1 is a trivial call, and any >> interesting subtrees will be part of operand 0. */ >> - WALK_SUBTREE (TREE_OPERAND (*tp, 0)); >> - else if (TREE_OPERAND (*tp, 1)) >> + WALK_SUBTREE (TREE_OPERAND (t, 0)); >> + else if (TREE_OPERAND (t, 1)) >> /* Interesting sub-trees will be in the return_value () call >> arguments. */ >> - WALK_SUBTREE (TREE_OPERAND (*tp, 1)); >> + WALK_SUBTREE (TREE_OPERAND (t, 1)); >> } >> break; >> >> case STATIC_ASSERT: >> - WALK_SUBTREE (STATIC_ASSERT_CONDITION (*tp)); >> - WALK_SUBTREE (STATIC_ASSERT_MESSAGE (*tp)); >> + WALK_SUBTREE (STATIC_ASSERT_CONDITION (t)); >> + WALK_SUBTREE (STATIC_ASSERT_MESSAGE (t)); >> break; >> >> default: >> diff --git a/gcc/tree.cc b/gcc/tree.cc >> index 5eb6a49da31..dfada652570 100644 >> --- a/gcc/tree.cc >> +++ b/gcc/tree.cc >> @@ -11218,10 +11218,6 @@ tree >> walk_tree_1 (tree *tp, walk_tree_fn func, void *data, >> hash_set<tree> *pset, walk_tree_lh lh) >> { >> - enum tree_code code; >> - int walk_subtrees; >> - tree result; >> - >> #define WALK_SUBTREE_TAIL(NODE) \ >> do \ >> { \ >> @@ -11241,14 +11237,15 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, >> return NULL_TREE; >> >> /* Call the function. */ >> - walk_subtrees = 1; >> - result = (*func) (tp, &walk_subtrees, data); >> + int walk_subtrees = 1; >> + tree result = (*func) (tp, &walk_subtrees, data); >> >> /* If we found something, return it. */ >> if (result) >> return result; >> >> - code = TREE_CODE (*tp); >> + tree t = *tp; >> + tree_code code = TREE_CODE (t); >> >> /* Even if we didn't, FUNC may have decided that there was nothing >> interesting below this point in the tree. */ >> @@ -11256,9 +11253,9 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, >> { >> /* But we still need to check our siblings. */ >> if (code == TREE_LIST) >> - WALK_SUBTREE_TAIL (TREE_CHAIN (*tp)); >> + WALK_SUBTREE_TAIL (TREE_CHAIN (t)); >> else if (code == OMP_CLAUSE) >> - WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp)); >> + WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (t)); >> else >> return NULL_TREE; >> } >> @@ -11288,58 +11285,58 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, >> break; >> >> case TREE_LIST: >> - WALK_SUBTREE (TREE_VALUE (*tp)); >> - WALK_SUBTREE_TAIL (TREE_CHAIN (*tp)); >> + WALK_SUBTREE (TREE_VALUE (t)); >> + WALK_SUBTREE_TAIL (TREE_CHAIN (t)); >> >> case TREE_VEC: >> { >> - int len = TREE_VEC_LENGTH (*tp); >> + int len = TREE_VEC_LENGTH (t); >> >> if (len == 0) >> break; >> >> /* Walk all elements but the first. */ >> while (--len) >> - WALK_SUBTREE (TREE_VEC_ELT (*tp, len)); >> + WALK_SUBTREE (TREE_VEC_ELT (t, len)); >> >> /* Now walk the first one as a tail call. */ >> - WALK_SUBTREE_TAIL (TREE_VEC_ELT (*tp, 0)); >> + WALK_SUBTREE_TAIL (TREE_VEC_ELT (t, 0)); >> } >> >> case VECTOR_CST: >> { >> - unsigned len = vector_cst_encoded_nelts (*tp); >> + unsigned len = vector_cst_encoded_nelts (t); >> if (len == 0) >> break; >> /* Walk all elements but the first. */ >> while (--len) >> - WALK_SUBTREE (VECTOR_CST_ENCODED_ELT (*tp, len)); >> + WALK_SUBTREE (VECTOR_CST_ENCODED_ELT (t, len)); >> /* Now walk the first one as a tail call. */ >> - WALK_SUBTREE_TAIL (VECTOR_CST_ENCODED_ELT (*tp, 0)); >> + WALK_SUBTREE_TAIL (VECTOR_CST_ENCODED_ELT (t, 0)); >> } >> >> case COMPLEX_CST: >> - WALK_SUBTREE (TREE_REALPART (*tp)); >> - WALK_SUBTREE_TAIL (TREE_IMAGPART (*tp)); >> + WALK_SUBTREE (TREE_REALPART (t)); >> + WALK_SUBTREE_TAIL (TREE_IMAGPART (t)); >> >> case CONSTRUCTOR: >> { >> unsigned HOST_WIDE_INT idx; >> constructor_elt *ce; >> >> - for (idx = 0; vec_safe_iterate (CONSTRUCTOR_ELTS (*tp), idx, &ce); >> + for (idx = 0; vec_safe_iterate (CONSTRUCTOR_ELTS (t), idx, &ce); >> idx++) >> WALK_SUBTREE (ce->value); >> } >> break; >> >> case SAVE_EXPR: >> - WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, 0)); >> + WALK_SUBTREE_TAIL (TREE_OPERAND (t, 0)); >> >> case BIND_EXPR: >> { >> tree decl; >> - for (decl = BIND_EXPR_VARS (*tp); decl; decl = DECL_CHAIN (decl)) >> + for (decl = BIND_EXPR_VARS (t); decl; decl = DECL_CHAIN (decl)) >> { >> /* Walk the DECL_INITIAL and DECL_SIZE. We don't want to walk >> into declarations that are just mentioned, rather than >> @@ -11350,23 +11347,23 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, >> WALK_SUBTREE (DECL_SIZE (decl)); >> WALK_SUBTREE (DECL_SIZE_UNIT (decl)); >> } >> - WALK_SUBTREE_TAIL (BIND_EXPR_BODY (*tp)); >> + WALK_SUBTREE_TAIL (BIND_EXPR_BODY (t)); >> } >> >> case STATEMENT_LIST: >> { >> tree_stmt_iterator i; >> - for (i = tsi_start (*tp); !tsi_end_p (i); tsi_next (&i)) >> + for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i)) >> WALK_SUBTREE (*tsi_stmt_ptr (i)); >> } >> break; >> >> case OMP_CLAUSE: >> { >> - int len = omp_clause_num_ops[OMP_CLAUSE_CODE (*tp)]; >> + int len = omp_clause_num_ops[OMP_CLAUSE_CODE (t)]; >> for (int i = 0; i < len; i++) >> - WALK_SUBTREE (OMP_CLAUSE_OPERAND (*tp, i)); >> - WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp)); >> + WALK_SUBTREE (OMP_CLAUSE_OPERAND (t, i)); >> + WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (t)); >> } >> >> case TARGET_EXPR: >> @@ -11375,10 +11372,10 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, >> >> /* TARGET_EXPRs are peculiar: operands 1 and 3 can be the same. >> But, we only want to walk once. */ >> - len = (TREE_OPERAND (*tp, 3) == TREE_OPERAND (*tp, 1)) ? 2 : 3; >> + len = (TREE_OPERAND (t, 3) == TREE_OPERAND (t, 1)) ? 2 : 3; >> for (i = 0; i < len; ++i) >> - WALK_SUBTREE (TREE_OPERAND (*tp, i)); >> - WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, len)); >> + WALK_SUBTREE (TREE_OPERAND (t, i)); >> + WALK_SUBTREE_TAIL (TREE_OPERAND (t, len)); >> } >> >> case DECL_EXPR: >> @@ -11393,15 +11390,15 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, >> variable-sized types. >> >> Note that DECLs get walked as part of processing the BIND_EXPR. */ >> - if (TREE_CODE (DECL_EXPR_DECL (*tp)) == TYPE_DECL) >> + if (TREE_CODE (DECL_EXPR_DECL (t)) == TYPE_DECL) >> { >> /* Call the function for the decl so e.g. copy_tree_body_r can >> replace it with the remapped one. */ >> - result = (*func) (&DECL_EXPR_DECL (*tp), &walk_subtrees, data); >> + result = (*func) (&DECL_EXPR_DECL (t), &walk_subtrees, data); >> if (result || !walk_subtrees) >> return result; >> >> - tree *type_p = &TREE_TYPE (DECL_EXPR_DECL (*tp)); >> + tree *type_p = &TREE_TYPE (DECL_EXPR_DECL (t)); >> if (TREE_CODE (*type_p) == ERROR_MARK) >> return NULL_TREE; >> >> @@ -11412,21 +11409,23 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, >> if (result || !walk_subtrees) >> return result; >> >> + tree type = *type_p; >> + >> /* But do not walk a pointed-to type since it may itself need to >> be walked in the declaration case if it isn't anonymous. */ >> - if (!POINTER_TYPE_P (*type_p)) >> + if (!POINTER_TYPE_P (type)) >> { >> - result = walk_type_fields (*type_p, func, data, pset, lh); >> + result = walk_type_fields (type, func, data, pset, lh); >> if (result) >> return result; >> } >> >> /* If this is a record type, also walk the fields. */ >> - if (RECORD_OR_UNION_TYPE_P (*type_p)) >> + if (RECORD_OR_UNION_TYPE_P (type)) >> { >> tree field; >> >> - for (field = TYPE_FIELDS (*type_p); field; >> + for (field = TYPE_FIELDS (type); field; >> field = DECL_CHAIN (field)) >> { >> /* We'd like to look at the type of the field, but we can >> @@ -11439,24 +11438,24 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, >> WALK_SUBTREE (DECL_FIELD_OFFSET (field)); >> WALK_SUBTREE (DECL_SIZE (field)); >> WALK_SUBTREE (DECL_SIZE_UNIT (field)); >> - if (TREE_CODE (*type_p) == QUAL_UNION_TYPE) >> + if (TREE_CODE (type) == QUAL_UNION_TYPE) >> WALK_SUBTREE (DECL_QUALIFIER (field)); >> } >> } >> >> /* Same for scalar types. */ >> - else if (TREE_CODE (*type_p) == BOOLEAN_TYPE >> - || TREE_CODE (*type_p) == ENUMERAL_TYPE >> - || TREE_CODE (*type_p) == INTEGER_TYPE >> - || TREE_CODE (*type_p) == FIXED_POINT_TYPE >> - || TREE_CODE (*type_p) == REAL_TYPE) >> + else if (TREE_CODE (type) == BOOLEAN_TYPE >> + || TREE_CODE (type) == ENUMERAL_TYPE >> + || TREE_CODE (type) == INTEGER_TYPE >> + || TREE_CODE (type) == FIXED_POINT_TYPE >> + || TREE_CODE (type) == REAL_TYPE) >> { >> - WALK_SUBTREE (TYPE_MIN_VALUE (*type_p)); >> - WALK_SUBTREE (TYPE_MAX_VALUE (*type_p)); >> + WALK_SUBTREE (TYPE_MIN_VALUE (type)); >> + WALK_SUBTREE (TYPE_MAX_VALUE (type)); >> } >> >> - WALK_SUBTREE (TYPE_SIZE (*type_p)); >> - WALK_SUBTREE_TAIL (TYPE_SIZE_UNIT (*type_p)); >> + WALK_SUBTREE (TYPE_SIZE (type)); >> + WALK_SUBTREE_TAIL (TYPE_SIZE_UNIT (type)); >> } >> /* FALLTHRU */ >> >> @@ -11466,20 +11465,20 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, >> int i, len; >> >> /* Walk over all the sub-trees of this operand. */ >> - len = TREE_OPERAND_LENGTH (*tp); >> + len = TREE_OPERAND_LENGTH (t); >> >> /* Go through the subtrees. We need to do this in forward order so >> that the scope of a FOR_EXPR is handled properly. */ >> if (len) >> { >> for (i = 0; i < len - 1; ++i) >> - WALK_SUBTREE (TREE_OPERAND (*tp, i)); >> - WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, len - 1)); >> + WALK_SUBTREE (TREE_OPERAND (t, i)); >> + WALK_SUBTREE_TAIL (TREE_OPERAND (t, len - 1)); >> } >> } >> /* If this is a type, walk the needed fields in the type. */ >> - else if (TYPE_P (*tp)) >> - return walk_type_fields (*tp, func, data, pset, lh); >> + else if (TYPE_P (t)) >> + return walk_type_fields (t, func, data, pset, lh); >> break; >> } >> >> -- >> 2.39.0.rc0.49.g083e01275b >> >
On Mon, 5 Dec 2022, Jason Merrill wrote: > On 12/5/22 06:09, Prathamesh Kulkarni wrote: > > On Mon, 5 Dec 2022 at 09:51, Patrick Palka via Gcc-patches > > <gcc-patches@gcc.gnu.org> wrote: > > > > > > These functions currently repeatedly dereference tp during the subtree > > > walk, dereferences which the compiler can't CSE because it can't > > > guarantee that the subtree walking doesn't modify *tp. > > > > > > But we already implicitly require that TREE_CODE (*tp) remains the same > > > throughout the subtree walks, so it doesn't seem to be a huge leap to > > > strengthen that to requiring *tp remains the same. > > Hi Patrick, > > Just wondering in that case, if marking tp with const_tree *, instead > > of tree *, would perhaps help the compiler > > for CSEing some of the dereferences to *tp ? > > That wouldn't make a difference; even if *tp is const, the compiler can't be > sure that a call won't change it. And const_tree * doesn't even make *tp > const, it makes **tp const. > > > > So this patch manually CSEs the dereferences of *tp. This means that > > > the callback function can no longer replace *tp with another tree (of > > > the same TREE_CODE) when walking one of its subtrees, but that doesn't > > > sound like a useful feature anyway. This speeds up the C++ frontend by > > > about ~1.5% according to my experiments. > > > > > > Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for > > > trunk stage3 or perhaps for stage1? > > OK for stage 1. Thanks, I just pushed this along with a drive-by change to cp_walk_subtrees <case DECLTYPE_TYPE etc> to use cp_unevaluated instead of incrementing cp_unevaluated_operand directly, which allows us to safely use WALK_SUBTREE in those cases: -- >8 -- Subject: [PATCH] c++, tree: optimize walk_tree_1 and cp_walk_subtrees gcc/cp/ChangeLog: * tree.cc (cp_walk_subtrees): Avoid repeatedly dereferencing tp. <case DECLTYPE_TYPE>: Use cp_unevaluated and WALK_SUBTREE. <case ALIGNOF_EXPR etc>: Likewise. gcc/ChangeLog: * tree.cc (walk_tree_1): Avoid repeatedly dereferencing tp and type_p. --- gcc/cp/tree.cc | 134 +++++++++++++++++++++++++------------------------ gcc/tree.cc | 103 +++++++++++++++++++------------------ 2 files changed, 119 insertions(+), 118 deletions(-) diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc index 69852538894..d35e30faf28 100644 --- a/gcc/cp/tree.cc +++ b/gcc/cp/tree.cc @@ -5445,7 +5445,8 @@ tree cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, void *data, hash_set<tree> *pset) { - enum tree_code code = TREE_CODE (*tp); + tree t = *tp; + enum tree_code code = TREE_CODE (t); tree result; #define WALK_SUBTREE(NODE) \ @@ -5456,7 +5457,7 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, } \ while (0) - if (TYPE_P (*tp)) + if (TYPE_P (t)) { /* If *WALK_SUBTREES_P is 1, we're interested in the syntactic form of the argument, so don't look through typedefs, but do walk into @@ -5468,15 +5469,15 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, See find_abi_tags_r for an example of setting *WALK_SUBTREES_P to 2 when that's the behavior the walk_tree_fn wants. */ - if (*walk_subtrees_p == 1 && typedef_variant_p (*tp)) + if (*walk_subtrees_p == 1 && typedef_variant_p (t)) { - if (tree ti = TYPE_ALIAS_TEMPLATE_INFO (*tp)) + if (tree ti = TYPE_ALIAS_TEMPLATE_INFO (t)) WALK_SUBTREE (TI_ARGS (ti)); *walk_subtrees_p = 0; return NULL_TREE; } - if (tree ti = TYPE_TEMPLATE_INFO (*tp)) + if (tree ti = TYPE_TEMPLATE_INFO (t)) WALK_SUBTREE (TI_ARGS (ti)); } @@ -5486,8 +5487,8 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, switch (code) { case TEMPLATE_TYPE_PARM: - if (template_placeholder_p (*tp)) - WALK_SUBTREE (CLASS_PLACEHOLDER_TEMPLATE (*tp)); + if (template_placeholder_p (t)) + WALK_SUBTREE (CLASS_PLACEHOLDER_TEMPLATE (t)); /* Fall through. */ case DEFERRED_PARSE: case TEMPLATE_TEMPLATE_PARM: @@ -5501,63 +5502,63 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, break; case TYPENAME_TYPE: - WALK_SUBTREE (TYPE_CONTEXT (*tp)); - WALK_SUBTREE (TYPENAME_TYPE_FULLNAME (*tp)); + WALK_SUBTREE (TYPE_CONTEXT (t)); + WALK_SUBTREE (TYPENAME_TYPE_FULLNAME (t)); *walk_subtrees_p = 0; break; case BASELINK: - if (BASELINK_QUALIFIED_P (*tp)) - WALK_SUBTREE (BINFO_TYPE (BASELINK_ACCESS_BINFO (*tp))); - WALK_SUBTREE (BASELINK_FUNCTIONS (*tp)); + if (BASELINK_QUALIFIED_P (t)) + WALK_SUBTREE (BINFO_TYPE (BASELINK_ACCESS_BINFO (t))); + WALK_SUBTREE (BASELINK_FUNCTIONS (t)); *walk_subtrees_p = 0; break; case PTRMEM_CST: - WALK_SUBTREE (TREE_TYPE (*tp)); + WALK_SUBTREE (TREE_TYPE (t)); *walk_subtrees_p = 0; break; case TREE_LIST: - WALK_SUBTREE (TREE_PURPOSE (*tp)); + WALK_SUBTREE (TREE_PURPOSE (t)); break; case OVERLOAD: - WALK_SUBTREE (OVL_FUNCTION (*tp)); - WALK_SUBTREE (OVL_CHAIN (*tp)); + WALK_SUBTREE (OVL_FUNCTION (t)); + WALK_SUBTREE (OVL_CHAIN (t)); *walk_subtrees_p = 0; break; case USING_DECL: - WALK_SUBTREE (DECL_NAME (*tp)); - WALK_SUBTREE (USING_DECL_SCOPE (*tp)); - WALK_SUBTREE (USING_DECL_DECLS (*tp)); + WALK_SUBTREE (DECL_NAME (t)); + WALK_SUBTREE (USING_DECL_SCOPE (t)); + WALK_SUBTREE (USING_DECL_DECLS (t)); *walk_subtrees_p = 0; break; case RECORD_TYPE: - if (TYPE_PTRMEMFUNC_P (*tp)) - WALK_SUBTREE (TYPE_PTRMEMFUNC_FN_TYPE_RAW (*tp)); + if (TYPE_PTRMEMFUNC_P (t)) + WALK_SUBTREE (TYPE_PTRMEMFUNC_FN_TYPE_RAW (t)); break; case TYPE_ARGUMENT_PACK: case NONTYPE_ARGUMENT_PACK: { - tree args = ARGUMENT_PACK_ARGS (*tp); + tree args = ARGUMENT_PACK_ARGS (t); for (tree arg : tree_vec_range (args)) WALK_SUBTREE (arg); } break; case TYPE_PACK_EXPANSION: - WALK_SUBTREE (TREE_TYPE (*tp)); - WALK_SUBTREE (PACK_EXPANSION_EXTRA_ARGS (*tp)); + WALK_SUBTREE (TREE_TYPE (t)); + WALK_SUBTREE (PACK_EXPANSION_EXTRA_ARGS (t)); *walk_subtrees_p = 0; break; case EXPR_PACK_EXPANSION: - WALK_SUBTREE (TREE_OPERAND (*tp, 0)); - WALK_SUBTREE (PACK_EXPANSION_EXTRA_ARGS (*tp)); + WALK_SUBTREE (TREE_OPERAND (t, 0)); + WALK_SUBTREE (PACK_EXPANSION_EXTRA_ARGS (t)); *walk_subtrees_p = 0; break; @@ -5568,54 +5569,55 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, case DYNAMIC_CAST_EXPR: case IMPLICIT_CONV_EXPR: case BIT_CAST_EXPR: - if (TREE_TYPE (*tp)) - WALK_SUBTREE (TREE_TYPE (*tp)); + if (TREE_TYPE (t)) + WALK_SUBTREE (TREE_TYPE (t)); break; case CONSTRUCTOR: - if (COMPOUND_LITERAL_P (*tp)) - WALK_SUBTREE (TREE_TYPE (*tp)); + if (COMPOUND_LITERAL_P (t)) + WALK_SUBTREE (TREE_TYPE (t)); break; case TRAIT_EXPR: - WALK_SUBTREE (TRAIT_EXPR_TYPE1 (*tp)); - WALK_SUBTREE (TRAIT_EXPR_TYPE2 (*tp)); + WALK_SUBTREE (TRAIT_EXPR_TYPE1 (t)); + WALK_SUBTREE (TRAIT_EXPR_TYPE2 (t)); *walk_subtrees_p = 0; break; case TRAIT_TYPE: - WALK_SUBTREE (TRAIT_TYPE_TYPE1 (*tp)); - WALK_SUBTREE (TRAIT_TYPE_TYPE2 (*tp)); + WALK_SUBTREE (TRAIT_TYPE_TYPE1 (t)); + WALK_SUBTREE (TRAIT_TYPE_TYPE2 (t)); *walk_subtrees_p = 0; break; case DECLTYPE_TYPE: - ++cp_unevaluated_operand; - /* We can't use WALK_SUBTREE here because of the goto. */ - result = cp_walk_tree (&DECLTYPE_TYPE_EXPR (*tp), func, data, pset); - --cp_unevaluated_operand; - *walk_subtrees_p = 0; - break; + { + cp_unevaluated u; + WALK_SUBTREE (DECLTYPE_TYPE_EXPR (t)); + *walk_subtrees_p = 0; + break; + } case ALIGNOF_EXPR: case SIZEOF_EXPR: case NOEXCEPT_EXPR: - ++cp_unevaluated_operand; - result = cp_walk_tree (&TREE_OPERAND (*tp, 0), func, data, pset); - --cp_unevaluated_operand; - *walk_subtrees_p = 0; - break; - + { + cp_unevaluated u; + WALK_SUBTREE (TREE_OPERAND (t, 0)); + *walk_subtrees_p = 0; + break; + } + case REQUIRES_EXPR: { cp_unevaluated u; - for (tree parm = REQUIRES_EXPR_PARMS (*tp); parm; parm = DECL_CHAIN (parm)) + for (tree parm = REQUIRES_EXPR_PARMS (t); parm; parm = DECL_CHAIN (parm)) /* Walk the types of each parameter, but not the parameter itself, since doing so would cause false positives in the unexpanded pack checker if the requires-expr introduces a function parameter pack, e.g. requires (Ts... ts) { }. */ WALK_SUBTREE (TREE_TYPE (parm)); - WALK_SUBTREE (REQUIRES_EXPR_REQS (*tp)); + WALK_SUBTREE (REQUIRES_EXPR_REQS (t)); *walk_subtrees_p = 0; break; } @@ -5626,12 +5628,12 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, the containing BIND_EXPR. Compiler temporaries are handled here. And also normal variables in templates, since do_poplevel doesn't build a BIND_EXPR then. */ - if (VAR_P (TREE_OPERAND (*tp, 0)) + if (VAR_P (TREE_OPERAND (t, 0)) && (processing_template_decl - || (DECL_ARTIFICIAL (TREE_OPERAND (*tp, 0)) - && !TREE_STATIC (TREE_OPERAND (*tp, 0))))) + || (DECL_ARTIFICIAL (TREE_OPERAND (t, 0)) + && !TREE_STATIC (TREE_OPERAND (t, 0))))) { - tree decl = TREE_OPERAND (*tp, 0); + tree decl = TREE_OPERAND (t, 0); WALK_SUBTREE (DECL_INITIAL (decl)); WALK_SUBTREE (DECL_SIZE (decl)); WALK_SUBTREE (DECL_SIZE_UNIT (decl)); @@ -5641,45 +5643,45 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, case LAMBDA_EXPR: /* Don't walk into the body of the lambda, but the capture initializers are part of the enclosing context. */ - for (tree cap = LAMBDA_EXPR_CAPTURE_LIST (*tp); cap; + for (tree cap = LAMBDA_EXPR_CAPTURE_LIST (t); cap; cap = TREE_CHAIN (cap)) WALK_SUBTREE (TREE_VALUE (cap)); break; case CO_YIELD_EXPR: - if (TREE_OPERAND (*tp, 1)) + if (TREE_OPERAND (t, 1)) /* Operand 1 is the tree for the relevant co_await which has any interesting sub-trees. */ - WALK_SUBTREE (TREE_OPERAND (*tp, 1)); + WALK_SUBTREE (TREE_OPERAND (t, 1)); break; case CO_AWAIT_EXPR: - if (TREE_OPERAND (*tp, 1)) + if (TREE_OPERAND (t, 1)) /* Operand 1 is frame variable. */ - WALK_SUBTREE (TREE_OPERAND (*tp, 1)); - if (TREE_OPERAND (*tp, 2)) + WALK_SUBTREE (TREE_OPERAND (t, 1)); + if (TREE_OPERAND (t, 2)) /* Operand 2 has the initialiser, and we need to walk any subtrees there. */ - WALK_SUBTREE (TREE_OPERAND (*tp, 2)); + WALK_SUBTREE (TREE_OPERAND (t, 2)); break; case CO_RETURN_EXPR: - if (TREE_OPERAND (*tp, 0)) + if (TREE_OPERAND (t, 0)) { - if (VOID_TYPE_P (TREE_OPERAND (*tp, 0))) + if (VOID_TYPE_P (TREE_OPERAND (t, 0))) /* For void expressions, operand 1 is a trivial call, and any interesting subtrees will be part of operand 0. */ - WALK_SUBTREE (TREE_OPERAND (*tp, 0)); - else if (TREE_OPERAND (*tp, 1)) + WALK_SUBTREE (TREE_OPERAND (t, 0)); + else if (TREE_OPERAND (t, 1)) /* Interesting sub-trees will be in the return_value () call arguments. */ - WALK_SUBTREE (TREE_OPERAND (*tp, 1)); + WALK_SUBTREE (TREE_OPERAND (t, 1)); } break; case STATIC_ASSERT: - WALK_SUBTREE (STATIC_ASSERT_CONDITION (*tp)); - WALK_SUBTREE (STATIC_ASSERT_MESSAGE (*tp)); + WALK_SUBTREE (STATIC_ASSERT_CONDITION (t)); + WALK_SUBTREE (STATIC_ASSERT_MESSAGE (t)); break; default: diff --git a/gcc/tree.cc b/gcc/tree.cc index 207293c48cb..5f2af073af9 100644 --- a/gcc/tree.cc +++ b/gcc/tree.cc @@ -11300,10 +11300,6 @@ tree walk_tree_1 (tree *tp, walk_tree_fn func, void *data, hash_set<tree> *pset, walk_tree_lh lh) { - enum tree_code code; - int walk_subtrees; - tree result; - #define WALK_SUBTREE_TAIL(NODE) \ do \ { \ @@ -11323,14 +11319,15 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, return NULL_TREE; /* Call the function. */ - walk_subtrees = 1; - result = (*func) (tp, &walk_subtrees, data); + int walk_subtrees = 1; + tree result = (*func) (tp, &walk_subtrees, data); /* If we found something, return it. */ if (result) return result; - code = TREE_CODE (*tp); + tree t = *tp; + tree_code code = TREE_CODE (t); /* Even if we didn't, FUNC may have decided that there was nothing interesting below this point in the tree. */ @@ -11338,9 +11335,9 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, { /* But we still need to check our siblings. */ if (code == TREE_LIST) - WALK_SUBTREE_TAIL (TREE_CHAIN (*tp)); + WALK_SUBTREE_TAIL (TREE_CHAIN (t)); else if (code == OMP_CLAUSE) - WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp)); + WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (t)); else return NULL_TREE; } @@ -11370,58 +11367,58 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, break; case TREE_LIST: - WALK_SUBTREE (TREE_VALUE (*tp)); - WALK_SUBTREE_TAIL (TREE_CHAIN (*tp)); + WALK_SUBTREE (TREE_VALUE (t)); + WALK_SUBTREE_TAIL (TREE_CHAIN (t)); case TREE_VEC: { - int len = TREE_VEC_LENGTH (*tp); + int len = TREE_VEC_LENGTH (t); if (len == 0) break; /* Walk all elements but the last. */ for (int i = 0; i < len - 1; ++i) - WALK_SUBTREE (TREE_VEC_ELT (*tp, i)); + WALK_SUBTREE (TREE_VEC_ELT (t, i)); /* Now walk the last one as a tail call. */ - WALK_SUBTREE_TAIL (TREE_VEC_ELT (*tp, len - 1)); + WALK_SUBTREE_TAIL (TREE_VEC_ELT (t, len - 1)); } case VECTOR_CST: { - unsigned len = vector_cst_encoded_nelts (*tp); + unsigned len = vector_cst_encoded_nelts (t); if (len == 0) break; /* Walk all elements but the last. */ for (unsigned i = 0; i < len - 1; ++i) - WALK_SUBTREE (VECTOR_CST_ENCODED_ELT (*tp, i)); + WALK_SUBTREE (VECTOR_CST_ENCODED_ELT (t, i)); /* Now walk the last one as a tail call. */ - WALK_SUBTREE_TAIL (VECTOR_CST_ENCODED_ELT (*tp, len - 1)); + WALK_SUBTREE_TAIL (VECTOR_CST_ENCODED_ELT (t, len - 1)); } case COMPLEX_CST: - WALK_SUBTREE (TREE_REALPART (*tp)); - WALK_SUBTREE_TAIL (TREE_IMAGPART (*tp)); + WALK_SUBTREE (TREE_REALPART (t)); + WALK_SUBTREE_TAIL (TREE_IMAGPART (t)); case CONSTRUCTOR: { unsigned HOST_WIDE_INT idx; constructor_elt *ce; - for (idx = 0; vec_safe_iterate (CONSTRUCTOR_ELTS (*tp), idx, &ce); + for (idx = 0; vec_safe_iterate (CONSTRUCTOR_ELTS (t), idx, &ce); idx++) WALK_SUBTREE (ce->value); } break; case SAVE_EXPR: - WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, 0)); + WALK_SUBTREE_TAIL (TREE_OPERAND (t, 0)); case BIND_EXPR: { tree decl; - for (decl = BIND_EXPR_VARS (*tp); decl; decl = DECL_CHAIN (decl)) + for (decl = BIND_EXPR_VARS (t); decl; decl = DECL_CHAIN (decl)) { /* Walk the DECL_INITIAL and DECL_SIZE. We don't want to walk into declarations that are just mentioned, rather than @@ -11432,23 +11429,23 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, WALK_SUBTREE (DECL_SIZE (decl)); WALK_SUBTREE (DECL_SIZE_UNIT (decl)); } - WALK_SUBTREE_TAIL (BIND_EXPR_BODY (*tp)); + WALK_SUBTREE_TAIL (BIND_EXPR_BODY (t)); } case STATEMENT_LIST: { tree_stmt_iterator i; - for (i = tsi_start (*tp); !tsi_end_p (i); tsi_next (&i)) + for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i)) WALK_SUBTREE (*tsi_stmt_ptr (i)); } break; case OMP_CLAUSE: { - int len = omp_clause_num_ops[OMP_CLAUSE_CODE (*tp)]; + int len = omp_clause_num_ops[OMP_CLAUSE_CODE (t)]; for (int i = 0; i < len; i++) - WALK_SUBTREE (OMP_CLAUSE_OPERAND (*tp, i)); - WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp)); + WALK_SUBTREE (OMP_CLAUSE_OPERAND (t, i)); + WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (t)); } case TARGET_EXPR: @@ -11457,10 +11454,10 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, /* TARGET_EXPRs are peculiar: operands 1 and 3 can be the same. But, we only want to walk once. */ - len = (TREE_OPERAND (*tp, 3) == TREE_OPERAND (*tp, 1)) ? 2 : 3; + len = (TREE_OPERAND (t, 3) == TREE_OPERAND (t, 1)) ? 2 : 3; for (i = 0; i < len; ++i) - WALK_SUBTREE (TREE_OPERAND (*tp, i)); - WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, len)); + WALK_SUBTREE (TREE_OPERAND (t, i)); + WALK_SUBTREE_TAIL (TREE_OPERAND (t, len)); } case DECL_EXPR: @@ -11475,15 +11472,15 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, variable-sized types. Note that DECLs get walked as part of processing the BIND_EXPR. */ - if (TREE_CODE (DECL_EXPR_DECL (*tp)) == TYPE_DECL) + if (TREE_CODE (DECL_EXPR_DECL (t)) == TYPE_DECL) { /* Call the function for the decl so e.g. copy_tree_body_r can replace it with the remapped one. */ - result = (*func) (&DECL_EXPR_DECL (*tp), &walk_subtrees, data); + result = (*func) (&DECL_EXPR_DECL (t), &walk_subtrees, data); if (result || !walk_subtrees) return result; - tree *type_p = &TREE_TYPE (DECL_EXPR_DECL (*tp)); + tree *type_p = &TREE_TYPE (DECL_EXPR_DECL (t)); if (TREE_CODE (*type_p) == ERROR_MARK) return NULL_TREE; @@ -11494,21 +11491,23 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, if (result || !walk_subtrees) return result; + tree type = *type_p; + /* But do not walk a pointed-to type since it may itself need to be walked in the declaration case if it isn't anonymous. */ - if (!POINTER_TYPE_P (*type_p)) + if (!POINTER_TYPE_P (type)) { - result = walk_type_fields (*type_p, func, data, pset, lh); + result = walk_type_fields (type, func, data, pset, lh); if (result) return result; } /* If this is a record type, also walk the fields. */ - if (RECORD_OR_UNION_TYPE_P (*type_p)) + if (RECORD_OR_UNION_TYPE_P (type)) { tree field; - for (field = TYPE_FIELDS (*type_p); field; + for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) { /* We'd like to look at the type of the field, but we can @@ -11521,24 +11520,24 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, WALK_SUBTREE (DECL_FIELD_OFFSET (field)); WALK_SUBTREE (DECL_SIZE (field)); WALK_SUBTREE (DECL_SIZE_UNIT (field)); - if (TREE_CODE (*type_p) == QUAL_UNION_TYPE) + if (TREE_CODE (type) == QUAL_UNION_TYPE) WALK_SUBTREE (DECL_QUALIFIER (field)); } } /* Same for scalar types. */ - else if (TREE_CODE (*type_p) == BOOLEAN_TYPE - || TREE_CODE (*type_p) == ENUMERAL_TYPE - || TREE_CODE (*type_p) == INTEGER_TYPE - || TREE_CODE (*type_p) == FIXED_POINT_TYPE - || TREE_CODE (*type_p) == REAL_TYPE) + else if (TREE_CODE (type) == BOOLEAN_TYPE + || TREE_CODE (type) == ENUMERAL_TYPE + || TREE_CODE (type) == INTEGER_TYPE + || TREE_CODE (type) == FIXED_POINT_TYPE + || TREE_CODE (type) == REAL_TYPE) { - WALK_SUBTREE (TYPE_MIN_VALUE (*type_p)); - WALK_SUBTREE (TYPE_MAX_VALUE (*type_p)); + WALK_SUBTREE (TYPE_MIN_VALUE (type)); + WALK_SUBTREE (TYPE_MAX_VALUE (type)); } - WALK_SUBTREE (TYPE_SIZE (*type_p)); - WALK_SUBTREE_TAIL (TYPE_SIZE_UNIT (*type_p)); + WALK_SUBTREE (TYPE_SIZE (type)); + WALK_SUBTREE_TAIL (TYPE_SIZE_UNIT (type)); } /* FALLTHRU */ @@ -11548,20 +11547,20 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, int i, len; /* Walk over all the sub-trees of this operand. */ - len = TREE_OPERAND_LENGTH (*tp); + len = TREE_OPERAND_LENGTH (t); /* Go through the subtrees. We need to do this in forward order so that the scope of a FOR_EXPR is handled properly. */ if (len) { for (i = 0; i < len - 1; ++i) - WALK_SUBTREE (TREE_OPERAND (*tp, i)); - WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, len - 1)); + WALK_SUBTREE (TREE_OPERAND (t, i)); + WALK_SUBTREE_TAIL (TREE_OPERAND (t, len - 1)); } } /* If this is a type, walk the needed fields in the type. */ - else if (TYPE_P (*tp)) - return walk_type_fields (*tp, func, data, pset, lh); + else if (TYPE_P (t)) + return walk_type_fields (t, func, data, pset, lh); break; }
diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc index 4066b014f6e..ceb0c75f559 100644 --- a/gcc/cp/tree.cc +++ b/gcc/cp/tree.cc @@ -5441,7 +5441,8 @@ tree cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, void *data, hash_set<tree> *pset) { - enum tree_code code = TREE_CODE (*tp); + tree t = *tp; + enum tree_code code = TREE_CODE (t); tree result; #define WALK_SUBTREE(NODE) \ @@ -5452,7 +5453,7 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, } \ while (0) - if (TYPE_P (*tp)) + if (TYPE_P (t)) { /* If *WALK_SUBTREES_P is 1, we're interested in the syntactic form of the argument, so don't look through typedefs, but do walk into @@ -5464,15 +5465,15 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, See find_abi_tags_r for an example of setting *WALK_SUBTREES_P to 2 when that's the behavior the walk_tree_fn wants. */ - if (*walk_subtrees_p == 1 && typedef_variant_p (*tp)) + if (*walk_subtrees_p == 1 && typedef_variant_p (t)) { - if (tree ti = TYPE_ALIAS_TEMPLATE_INFO (*tp)) + if (tree ti = TYPE_ALIAS_TEMPLATE_INFO (t)) WALK_SUBTREE (TI_ARGS (ti)); *walk_subtrees_p = 0; return NULL_TREE; } - if (tree ti = TYPE_TEMPLATE_INFO (*tp)) + if (tree ti = TYPE_TEMPLATE_INFO (t)) WALK_SUBTREE (TI_ARGS (ti)); } @@ -5482,8 +5483,8 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, switch (code) { case TEMPLATE_TYPE_PARM: - if (template_placeholder_p (*tp)) - WALK_SUBTREE (CLASS_PLACEHOLDER_TEMPLATE (*tp)); + if (template_placeholder_p (t)) + WALK_SUBTREE (CLASS_PLACEHOLDER_TEMPLATE (t)); /* Fall through. */ case DEFERRED_PARSE: case TEMPLATE_TEMPLATE_PARM: @@ -5497,63 +5498,63 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, break; case TYPENAME_TYPE: - WALK_SUBTREE (TYPE_CONTEXT (*tp)); - WALK_SUBTREE (TYPENAME_TYPE_FULLNAME (*tp)); + WALK_SUBTREE (TYPE_CONTEXT (t)); + WALK_SUBTREE (TYPENAME_TYPE_FULLNAME (t)); *walk_subtrees_p = 0; break; case BASELINK: - if (BASELINK_QUALIFIED_P (*tp)) - WALK_SUBTREE (BINFO_TYPE (BASELINK_ACCESS_BINFO (*tp))); - WALK_SUBTREE (BASELINK_FUNCTIONS (*tp)); + if (BASELINK_QUALIFIED_P (t)) + WALK_SUBTREE (BINFO_TYPE (BASELINK_ACCESS_BINFO (t))); + WALK_SUBTREE (BASELINK_FUNCTIONS (t)); *walk_subtrees_p = 0; break; case PTRMEM_CST: - WALK_SUBTREE (TREE_TYPE (*tp)); + WALK_SUBTREE (TREE_TYPE (t)); *walk_subtrees_p = 0; break; case TREE_LIST: - WALK_SUBTREE (TREE_PURPOSE (*tp)); + WALK_SUBTREE (TREE_PURPOSE (t)); break; case OVERLOAD: - WALK_SUBTREE (OVL_FUNCTION (*tp)); - WALK_SUBTREE (OVL_CHAIN (*tp)); + WALK_SUBTREE (OVL_FUNCTION (t)); + WALK_SUBTREE (OVL_CHAIN (t)); *walk_subtrees_p = 0; break; case USING_DECL: - WALK_SUBTREE (DECL_NAME (*tp)); - WALK_SUBTREE (USING_DECL_SCOPE (*tp)); - WALK_SUBTREE (USING_DECL_DECLS (*tp)); + WALK_SUBTREE (DECL_NAME (t)); + WALK_SUBTREE (USING_DECL_SCOPE (t)); + WALK_SUBTREE (USING_DECL_DECLS (t)); *walk_subtrees_p = 0; break; case RECORD_TYPE: - if (TYPE_PTRMEMFUNC_P (*tp)) - WALK_SUBTREE (TYPE_PTRMEMFUNC_FN_TYPE_RAW (*tp)); + if (TYPE_PTRMEMFUNC_P (t)) + WALK_SUBTREE (TYPE_PTRMEMFUNC_FN_TYPE_RAW (t)); break; case TYPE_ARGUMENT_PACK: case NONTYPE_ARGUMENT_PACK: { - tree args = ARGUMENT_PACK_ARGS (*tp); + tree args = ARGUMENT_PACK_ARGS (t); for (tree arg : tree_vec_range (args)) WALK_SUBTREE (arg); } break; case TYPE_PACK_EXPANSION: - WALK_SUBTREE (TREE_TYPE (*tp)); - WALK_SUBTREE (PACK_EXPANSION_EXTRA_ARGS (*tp)); + WALK_SUBTREE (TREE_TYPE (t)); + WALK_SUBTREE (PACK_EXPANSION_EXTRA_ARGS (t)); *walk_subtrees_p = 0; break; case EXPR_PACK_EXPANSION: - WALK_SUBTREE (TREE_OPERAND (*tp, 0)); - WALK_SUBTREE (PACK_EXPANSION_EXTRA_ARGS (*tp)); + WALK_SUBTREE (TREE_OPERAND (t, 0)); + WALK_SUBTREE (PACK_EXPANSION_EXTRA_ARGS (t)); *walk_subtrees_p = 0; break; @@ -5564,31 +5565,31 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, case DYNAMIC_CAST_EXPR: case IMPLICIT_CONV_EXPR: case BIT_CAST_EXPR: - if (TREE_TYPE (*tp)) - WALK_SUBTREE (TREE_TYPE (*tp)); + if (TREE_TYPE (t)) + WALK_SUBTREE (TREE_TYPE (t)); break; case CONSTRUCTOR: - if (COMPOUND_LITERAL_P (*tp)) - WALK_SUBTREE (TREE_TYPE (*tp)); + if (COMPOUND_LITERAL_P (t)) + WALK_SUBTREE (TREE_TYPE (t)); break; case TRAIT_EXPR: - WALK_SUBTREE (TRAIT_EXPR_TYPE1 (*tp)); - WALK_SUBTREE (TRAIT_EXPR_TYPE2 (*tp)); + WALK_SUBTREE (TRAIT_EXPR_TYPE1 (t)); + WALK_SUBTREE (TRAIT_EXPR_TYPE2 (t)); *walk_subtrees_p = 0; break; case TRAIT_TYPE: - WALK_SUBTREE (TRAIT_TYPE_TYPE1 (*tp)); - WALK_SUBTREE (TRAIT_TYPE_TYPE2 (*tp)); + WALK_SUBTREE (TRAIT_TYPE_TYPE1 (t)); + WALK_SUBTREE (TRAIT_TYPE_TYPE2 (t)); *walk_subtrees_p = 0; break; case DECLTYPE_TYPE: ++cp_unevaluated_operand; /* We can't use WALK_SUBTREE here because of the goto. */ - result = cp_walk_tree (&DECLTYPE_TYPE_EXPR (*tp), func, data, pset); + result = cp_walk_tree (&DECLTYPE_TYPE_EXPR (t), func, data, pset); --cp_unevaluated_operand; *walk_subtrees_p = 0; break; @@ -5597,7 +5598,7 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, case SIZEOF_EXPR: case NOEXCEPT_EXPR: ++cp_unevaluated_operand; - result = cp_walk_tree (&TREE_OPERAND (*tp, 0), func, data, pset); + result = cp_walk_tree (&TREE_OPERAND (t, 0), func, data, pset); --cp_unevaluated_operand; *walk_subtrees_p = 0; break; @@ -5605,12 +5606,12 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, case REQUIRES_EXPR: { cp_unevaluated u; - for (tree parm = REQUIRES_EXPR_PARMS (*tp); parm; parm = DECL_CHAIN (parm)) + for (tree parm = REQUIRES_EXPR_PARMS (t); parm; parm = DECL_CHAIN (parm)) /* Walk the types of each parameter, but not the parameter itself. Doing so would cause false positives in the unexpanded parameter pack checker since an introduced parameter pack looks bare. */ WALK_SUBTREE (TREE_TYPE (parm)); - WALK_SUBTREE (REQUIRES_EXPR_REQS (*tp)); + WALK_SUBTREE (REQUIRES_EXPR_REQS (t)); *walk_subtrees_p = 0; break; } @@ -5621,12 +5622,12 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, the containing BIND_EXPR. Compiler temporaries are handled here. And also normal variables in templates, since do_poplevel doesn't build a BIND_EXPR then. */ - if (VAR_P (TREE_OPERAND (*tp, 0)) + if (VAR_P (TREE_OPERAND (t, 0)) && (processing_template_decl - || (DECL_ARTIFICIAL (TREE_OPERAND (*tp, 0)) - && !TREE_STATIC (TREE_OPERAND (*tp, 0))))) + || (DECL_ARTIFICIAL (TREE_OPERAND (t, 0)) + && !TREE_STATIC (TREE_OPERAND (t, 0))))) { - tree decl = TREE_OPERAND (*tp, 0); + tree decl = TREE_OPERAND (t, 0); WALK_SUBTREE (DECL_INITIAL (decl)); WALK_SUBTREE (DECL_SIZE (decl)); WALK_SUBTREE (DECL_SIZE_UNIT (decl)); @@ -5636,45 +5637,45 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, case LAMBDA_EXPR: /* Don't walk into the body of the lambda, but the capture initializers are part of the enclosing context. */ - for (tree cap = LAMBDA_EXPR_CAPTURE_LIST (*tp); cap; + for (tree cap = LAMBDA_EXPR_CAPTURE_LIST (t); cap; cap = TREE_CHAIN (cap)) WALK_SUBTREE (TREE_VALUE (cap)); break; case CO_YIELD_EXPR: - if (TREE_OPERAND (*tp, 1)) + if (TREE_OPERAND (t, 1)) /* Operand 1 is the tree for the relevant co_await which has any interesting sub-trees. */ - WALK_SUBTREE (TREE_OPERAND (*tp, 1)); + WALK_SUBTREE (TREE_OPERAND (t, 1)); break; case CO_AWAIT_EXPR: - if (TREE_OPERAND (*tp, 1)) + if (TREE_OPERAND (t, 1)) /* Operand 1 is frame variable. */ - WALK_SUBTREE (TREE_OPERAND (*tp, 1)); - if (TREE_OPERAND (*tp, 2)) + WALK_SUBTREE (TREE_OPERAND (t, 1)); + if (TREE_OPERAND (t, 2)) /* Operand 2 has the initialiser, and we need to walk any subtrees there. */ - WALK_SUBTREE (TREE_OPERAND (*tp, 2)); + WALK_SUBTREE (TREE_OPERAND (t, 2)); break; case CO_RETURN_EXPR: - if (TREE_OPERAND (*tp, 0)) + if (TREE_OPERAND (t, 0)) { - if (VOID_TYPE_P (TREE_OPERAND (*tp, 0))) + if (VOID_TYPE_P (TREE_OPERAND (t, 0))) /* For void expressions, operand 1 is a trivial call, and any interesting subtrees will be part of operand 0. */ - WALK_SUBTREE (TREE_OPERAND (*tp, 0)); - else if (TREE_OPERAND (*tp, 1)) + WALK_SUBTREE (TREE_OPERAND (t, 0)); + else if (TREE_OPERAND (t, 1)) /* Interesting sub-trees will be in the return_value () call arguments. */ - WALK_SUBTREE (TREE_OPERAND (*tp, 1)); + WALK_SUBTREE (TREE_OPERAND (t, 1)); } break; case STATIC_ASSERT: - WALK_SUBTREE (STATIC_ASSERT_CONDITION (*tp)); - WALK_SUBTREE (STATIC_ASSERT_MESSAGE (*tp)); + WALK_SUBTREE (STATIC_ASSERT_CONDITION (t)); + WALK_SUBTREE (STATIC_ASSERT_MESSAGE (t)); break; default: diff --git a/gcc/tree.cc b/gcc/tree.cc index 5eb6a49da31..dfada652570 100644 --- a/gcc/tree.cc +++ b/gcc/tree.cc @@ -11218,10 +11218,6 @@ tree walk_tree_1 (tree *tp, walk_tree_fn func, void *data, hash_set<tree> *pset, walk_tree_lh lh) { - enum tree_code code; - int walk_subtrees; - tree result; - #define WALK_SUBTREE_TAIL(NODE) \ do \ { \ @@ -11241,14 +11237,15 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, return NULL_TREE; /* Call the function. */ - walk_subtrees = 1; - result = (*func) (tp, &walk_subtrees, data); + int walk_subtrees = 1; + tree result = (*func) (tp, &walk_subtrees, data); /* If we found something, return it. */ if (result) return result; - code = TREE_CODE (*tp); + tree t = *tp; + tree_code code = TREE_CODE (t); /* Even if we didn't, FUNC may have decided that there was nothing interesting below this point in the tree. */ @@ -11256,9 +11253,9 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, { /* But we still need to check our siblings. */ if (code == TREE_LIST) - WALK_SUBTREE_TAIL (TREE_CHAIN (*tp)); + WALK_SUBTREE_TAIL (TREE_CHAIN (t)); else if (code == OMP_CLAUSE) - WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp)); + WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (t)); else return NULL_TREE; } @@ -11288,58 +11285,58 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, break; case TREE_LIST: - WALK_SUBTREE (TREE_VALUE (*tp)); - WALK_SUBTREE_TAIL (TREE_CHAIN (*tp)); + WALK_SUBTREE (TREE_VALUE (t)); + WALK_SUBTREE_TAIL (TREE_CHAIN (t)); case TREE_VEC: { - int len = TREE_VEC_LENGTH (*tp); + int len = TREE_VEC_LENGTH (t); if (len == 0) break; /* Walk all elements but the first. */ while (--len) - WALK_SUBTREE (TREE_VEC_ELT (*tp, len)); + WALK_SUBTREE (TREE_VEC_ELT (t, len)); /* Now walk the first one as a tail call. */ - WALK_SUBTREE_TAIL (TREE_VEC_ELT (*tp, 0)); + WALK_SUBTREE_TAIL (TREE_VEC_ELT (t, 0)); } case VECTOR_CST: { - unsigned len = vector_cst_encoded_nelts (*tp); + unsigned len = vector_cst_encoded_nelts (t); if (len == 0) break; /* Walk all elements but the first. */ while (--len) - WALK_SUBTREE (VECTOR_CST_ENCODED_ELT (*tp, len)); + WALK_SUBTREE (VECTOR_CST_ENCODED_ELT (t, len)); /* Now walk the first one as a tail call. */ - WALK_SUBTREE_TAIL (VECTOR_CST_ENCODED_ELT (*tp, 0)); + WALK_SUBTREE_TAIL (VECTOR_CST_ENCODED_ELT (t, 0)); } case COMPLEX_CST: - WALK_SUBTREE (TREE_REALPART (*tp)); - WALK_SUBTREE_TAIL (TREE_IMAGPART (*tp)); + WALK_SUBTREE (TREE_REALPART (t)); + WALK_SUBTREE_TAIL (TREE_IMAGPART (t)); case CONSTRUCTOR: { unsigned HOST_WIDE_INT idx; constructor_elt *ce; - for (idx = 0; vec_safe_iterate (CONSTRUCTOR_ELTS (*tp), idx, &ce); + for (idx = 0; vec_safe_iterate (CONSTRUCTOR_ELTS (t), idx, &ce); idx++) WALK_SUBTREE (ce->value); } break; case SAVE_EXPR: - WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, 0)); + WALK_SUBTREE_TAIL (TREE_OPERAND (t, 0)); case BIND_EXPR: { tree decl; - for (decl = BIND_EXPR_VARS (*tp); decl; decl = DECL_CHAIN (decl)) + for (decl = BIND_EXPR_VARS (t); decl; decl = DECL_CHAIN (decl)) { /* Walk the DECL_INITIAL and DECL_SIZE. We don't want to walk into declarations that are just mentioned, rather than @@ -11350,23 +11347,23 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, WALK_SUBTREE (DECL_SIZE (decl)); WALK_SUBTREE (DECL_SIZE_UNIT (decl)); } - WALK_SUBTREE_TAIL (BIND_EXPR_BODY (*tp)); + WALK_SUBTREE_TAIL (BIND_EXPR_BODY (t)); } case STATEMENT_LIST: { tree_stmt_iterator i; - for (i = tsi_start (*tp); !tsi_end_p (i); tsi_next (&i)) + for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i)) WALK_SUBTREE (*tsi_stmt_ptr (i)); } break; case OMP_CLAUSE: { - int len = omp_clause_num_ops[OMP_CLAUSE_CODE (*tp)]; + int len = omp_clause_num_ops[OMP_CLAUSE_CODE (t)]; for (int i = 0; i < len; i++) - WALK_SUBTREE (OMP_CLAUSE_OPERAND (*tp, i)); - WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp)); + WALK_SUBTREE (OMP_CLAUSE_OPERAND (t, i)); + WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (t)); } case TARGET_EXPR: @@ -11375,10 +11372,10 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, /* TARGET_EXPRs are peculiar: operands 1 and 3 can be the same. But, we only want to walk once. */ - len = (TREE_OPERAND (*tp, 3) == TREE_OPERAND (*tp, 1)) ? 2 : 3; + len = (TREE_OPERAND (t, 3) == TREE_OPERAND (t, 1)) ? 2 : 3; for (i = 0; i < len; ++i) - WALK_SUBTREE (TREE_OPERAND (*tp, i)); - WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, len)); + WALK_SUBTREE (TREE_OPERAND (t, i)); + WALK_SUBTREE_TAIL (TREE_OPERAND (t, len)); } case DECL_EXPR: @@ -11393,15 +11390,15 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, variable-sized types. Note that DECLs get walked as part of processing the BIND_EXPR. */ - if (TREE_CODE (DECL_EXPR_DECL (*tp)) == TYPE_DECL) + if (TREE_CODE (DECL_EXPR_DECL (t)) == TYPE_DECL) { /* Call the function for the decl so e.g. copy_tree_body_r can replace it with the remapped one. */ - result = (*func) (&DECL_EXPR_DECL (*tp), &walk_subtrees, data); + result = (*func) (&DECL_EXPR_DECL (t), &walk_subtrees, data); if (result || !walk_subtrees) return result; - tree *type_p = &TREE_TYPE (DECL_EXPR_DECL (*tp)); + tree *type_p = &TREE_TYPE (DECL_EXPR_DECL (t)); if (TREE_CODE (*type_p) == ERROR_MARK) return NULL_TREE; @@ -11412,21 +11409,23 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, if (result || !walk_subtrees) return result; + tree type = *type_p; + /* But do not walk a pointed-to type since it may itself need to be walked in the declaration case if it isn't anonymous. */ - if (!POINTER_TYPE_P (*type_p)) + if (!POINTER_TYPE_P (type)) { - result = walk_type_fields (*type_p, func, data, pset, lh); + result = walk_type_fields (type, func, data, pset, lh); if (result) return result; } /* If this is a record type, also walk the fields. */ - if (RECORD_OR_UNION_TYPE_P (*type_p)) + if (RECORD_OR_UNION_TYPE_P (type)) { tree field; - for (field = TYPE_FIELDS (*type_p); field; + for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) { /* We'd like to look at the type of the field, but we can @@ -11439,24 +11438,24 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, WALK_SUBTREE (DECL_FIELD_OFFSET (field)); WALK_SUBTREE (DECL_SIZE (field)); WALK_SUBTREE (DECL_SIZE_UNIT (field)); - if (TREE_CODE (*type_p) == QUAL_UNION_TYPE) + if (TREE_CODE (type) == QUAL_UNION_TYPE) WALK_SUBTREE (DECL_QUALIFIER (field)); } } /* Same for scalar types. */ - else if (TREE_CODE (*type_p) == BOOLEAN_TYPE - || TREE_CODE (*type_p) == ENUMERAL_TYPE - || TREE_CODE (*type_p) == INTEGER_TYPE - || TREE_CODE (*type_p) == FIXED_POINT_TYPE - || TREE_CODE (*type_p) == REAL_TYPE) + else if (TREE_CODE (type) == BOOLEAN_TYPE + || TREE_CODE (type) == ENUMERAL_TYPE + || TREE_CODE (type) == INTEGER_TYPE + || TREE_CODE (type) == FIXED_POINT_TYPE + || TREE_CODE (type) == REAL_TYPE) { - WALK_SUBTREE (TYPE_MIN_VALUE (*type_p)); - WALK_SUBTREE (TYPE_MAX_VALUE (*type_p)); + WALK_SUBTREE (TYPE_MIN_VALUE (type)); + WALK_SUBTREE (TYPE_MAX_VALUE (type)); } - WALK_SUBTREE (TYPE_SIZE (*type_p)); - WALK_SUBTREE_TAIL (TYPE_SIZE_UNIT (*type_p)); + WALK_SUBTREE (TYPE_SIZE (type)); + WALK_SUBTREE_TAIL (TYPE_SIZE_UNIT (type)); } /* FALLTHRU */ @@ -11466,20 +11465,20 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, int i, len; /* Walk over all the sub-trees of this operand. */ - len = TREE_OPERAND_LENGTH (*tp); + len = TREE_OPERAND_LENGTH (t); /* Go through the subtrees. We need to do this in forward order so that the scope of a FOR_EXPR is handled properly. */ if (len) { for (i = 0; i < len - 1; ++i) - WALK_SUBTREE (TREE_OPERAND (*tp, i)); - WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, len - 1)); + WALK_SUBTREE (TREE_OPERAND (t, i)); + WALK_SUBTREE_TAIL (TREE_OPERAND (t, len - 1)); } } /* If this is a type, walk the needed fields in the type. */ - else if (TYPE_P (*tp)) - return walk_type_fields (*tp, func, data, pset, lh); + else if (TYPE_P (t)) + return walk_type_fields (t, func, data, pset, lh); break; }