diff options
author | Patrick Palka <ppalka@redhat.com> | 2023-04-21 12:59:37 -0400 |
---|---|---|
committer | Patrick Palka <ppalka@redhat.com> | 2023-04-21 12:59:37 -0400 |
commit | 857c8e3b3bba14bfb078a194993f5f31e0d90391 (patch) | |
tree | 59b11cbdc964155b47fa50c356159e05ce7bb311 /gcc/tree.cc | |
parent | 7508aacf95dca3e340513e08256c19f8e3d38dae (diff) | |
download | gcc-857c8e3b3bba14bfb078a194993f5f31e0d90391.zip gcc-857c8e3b3bba14bfb078a194993f5f31e0d90391.tar.gz gcc-857c8e3b3bba14bfb078a194993f5f31e0d90391.tar.bz2 |
c++, tree: optimize walk_tree_1 and cp_walk_subtrees
These functions currently repeatedly dereference tp during the subtree
walks, 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.
So this patch manually CSEs the dereferences of *tp. This means that a
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 capability anyway.
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.
Diffstat (limited to 'gcc/tree.cc')
-rw-r--r-- | gcc/tree.cc | 103 |
1 files changed, 51 insertions, 52 deletions
diff --git a/gcc/tree.cc b/gcc/tree.cc index 207293c..5f2af07 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; } |