diff options
author | Eric Botcazou <ebotcazou@adacore.com> | 2009-06-30 17:26:32 +0000 |
---|---|---|
committer | Eric Botcazou <ebotcazou@gcc.gnu.org> | 2009-06-30 17:26:32 +0000 |
commit | f82a627cf51e998b3d1c5c02f7e7c00b4aef1b0c (patch) | |
tree | 46e380a758cc2f203dbeec25be5417a9a9bca764 /gcc/tree.c | |
parent | c1a5cfab17521708db174ed25707f2eee57727fe (diff) | |
download | gcc-f82a627cf51e998b3d1c5c02f7e7c00b4aef1b0c.zip gcc-f82a627cf51e998b3d1c5c02f7e7c00b4aef1b0c.tar.gz gcc-f82a627cf51e998b3d1c5c02f7e7c00b4aef1b0c.tar.bz2 |
cgraphunit.c (cgraph_finalize_compilation_unit): Call finalize_size_functions before further processing.
* cgraphunit.c (cgraph_finalize_compilation_unit): Call
finalize_size_functions before further processing.
* stor-layout.c: Include cgraph.h, tree-inline.h and tree-dump.h.
(variable_size): Call self_referential_size on size expressions
that contain a PLACEHOLDER_EXPR.
(size_functions): New static variable.
(copy_self_referential_tree_r): New static function.
(self_referential_size): Likewise.
(finalize_size_functions): New global function.
* tree.c: Include tree-inline.h.
(push_without_duplicates): New static function.
(find_placeholder_in_expr): New global function.
(substitute_in_expr) <tcc_declaration>: Return the replacement object
on equality.
<tcc_expression>: Likewise.
<tcc_vl_exp>: If the replacement object is a constant, try to inline
the call in the expression.
* tree.h (finalize_size_functions): Declare.
(find_placeholder_in_expr): Likewise.
(FIND_PLACEHOLDER_IN_EXPR): New macro.
(substitute_placeholder_in_expr): Update comment.
* tree-inline.c (remap_decl): Do not unshare trees if do_not_unshare
is true.
(copy_tree_body_r): Likewise.
(copy_tree_body): New static function.
(maybe_inline_call_in_expr): New global function.
* tree-inline.h (struct copy_body_data): Add do_not_unshare field.
(maybe_inline_call_in_expr): Declare.
* Makefile.in (tree.o): Depend on TREE_INLINE_H.
(stor-layout.o): Depend on CGRAPH_H, TREE_INLINE_H, TREE_DUMP_H and
GIMPLE_H.
ada/
* gcc-interface/decl.c: Include tree-inline.h.
(annotate_value) <CALL_EXPR>: Try to inline the call in the expression.
* gcc-interface/utils.c (max_size) <CALL_EXPR>: Likewise.
* gcc-interface/utils2.c: Include tree-inline.
(known_alignment) <CALL_EXPR>: Likewise.
From-SVN: r149112
Diffstat (limited to 'gcc/tree.c')
-rw-r--r-- | gcc/tree.c | 123 |
1 files changed, 118 insertions, 5 deletions
@@ -45,6 +45,7 @@ along with GCC; see the file COPYING3. If not see #include "output.h" #include "target.h" #include "langhooks.h" +#include "tree-inline.h" #include "tree-iterator.h" #include "basic-block.h" #include "tree-flow.h" @@ -2678,11 +2679,102 @@ type_contains_placeholder_p (tree type) return result; } +/* Push tree EXP onto vector QUEUE if it is not already present. */ + +static void +push_without_duplicates (tree exp, VEC (tree, heap) **queue) +{ + unsigned int i; + tree iter; + + for (i = 0; VEC_iterate (tree, *queue, i, iter); i++) + if (simple_cst_equal (iter, exp) == 1) + break; + + if (!iter) + VEC_safe_push (tree, heap, *queue, exp); +} + +/* Given a tree EXP, find all occurences of references to fields + in a PLACEHOLDER_EXPR and place them in vector REFS without + duplicates. Also record VAR_DECLs and CONST_DECLs. Note that + we assume here that EXP contains only arithmetic expressions + or CALL_EXPRs with PLACEHOLDER_EXPRs occurring only in their + argument list. */ + +void +find_placeholder_in_expr (tree exp, VEC (tree, heap) **refs) +{ + enum tree_code code = TREE_CODE (exp); + tree inner; + int i; + + /* We handle TREE_LIST and COMPONENT_REF separately. */ + if (code == TREE_LIST) + { + FIND_PLACEHOLDER_IN_EXPR (TREE_CHAIN (exp), refs); + FIND_PLACEHOLDER_IN_EXPR (TREE_VALUE (exp), refs); + } + else if (code == COMPONENT_REF) + { + for (inner = TREE_OPERAND (exp, 0); + REFERENCE_CLASS_P (inner); + inner = TREE_OPERAND (inner, 0)) + ; + + if (TREE_CODE (inner) == PLACEHOLDER_EXPR) + push_without_duplicates (exp, refs); + else + FIND_PLACEHOLDER_IN_EXPR (TREE_OPERAND (exp, 0), refs); + } + else + switch (TREE_CODE_CLASS (code)) + { + case tcc_constant: + break; + + case tcc_declaration: + /* Variables allocated to static storage can stay. */ + if (!TREE_STATIC (exp)) + push_without_duplicates (exp, refs); + break; + + case tcc_expression: + /* This is the pattern built in ada/make_aligning_type. */ + if (code == ADDR_EXPR + && TREE_CODE (TREE_OPERAND (exp, 0)) == PLACEHOLDER_EXPR) + { + push_without_duplicates (exp, refs); + break; + } + + /* Fall through... */ + + case tcc_exceptional: + case tcc_unary: + case tcc_binary: + case tcc_comparison: + case tcc_reference: + for (i = 0; i < TREE_CODE_LENGTH (code); i++) + FIND_PLACEHOLDER_IN_EXPR (TREE_OPERAND (exp, i), refs); + break; + + case tcc_vl_exp: + for (i = 1; i < TREE_OPERAND_LENGTH (exp); i++) + FIND_PLACEHOLDER_IN_EXPR (TREE_OPERAND (exp, i), refs); + break; + + default: + gcc_unreachable (); + } +} + /* Given a tree EXP, a FIELD_DECL F, and a replacement value R, return a tree with all occurrences of references to F in a - PLACEHOLDER_EXPR replaced by R. Note that we assume here that EXP - contains only arithmetic expressions or a CALL_EXPR with a - PLACEHOLDER_EXPR occurring only in its arglist. */ + PLACEHOLDER_EXPR replaced by R. Also handle VAR_DECLs and + CONST_DECLs. Note that we assume here that EXP contains only + arithmetic expressions or CALL_EXPRs with PLACEHOLDER_EXPRs + occurring only in their argument list. */ tree substitute_in_expr (tree exp, tree f, tree r) @@ -2733,14 +2825,24 @@ substitute_in_expr (tree exp, tree f, tree r) switch (TREE_CODE_CLASS (code)) { case tcc_constant: - case tcc_declaration: return exp; + case tcc_declaration: + if (exp == f) + return r; + else + return exp; + + case tcc_expression: + if (exp == f) + return r; + + /* Fall through... */ + case tcc_exceptional: case tcc_unary: case tcc_binary: case tcc_comparison: - case tcc_expression: case tcc_reference: switch (TREE_CODE_LENGTH (code)) { @@ -2803,6 +2905,17 @@ substitute_in_expr (tree exp, tree f, tree r) new_tree = NULL_TREE; + /* If we are trying to replace F with a constant, inline back + functions which do nothing else than computing a value from + the arguments they are passed. This makes it possible to + fold partially or entirely the replacement expression. */ + if (CONSTANT_CLASS_P (r) && code == CALL_EXPR) + { + tree t = maybe_inline_call_in_expr (exp); + if (t) + return SUBSTITUTE_IN_EXPR (t, f, r); + } + for (i = 1; i < TREE_OPERAND_LENGTH (exp); i++) { tree op = TREE_OPERAND (exp, i); |