diff options
author | jamborm <jamborm@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-08-07 07:15:41 +0000 |
---|---|---|
committer | jamborm <jamborm@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-08-07 07:15:41 +0000 |
commit | 5215027d365b04789c45a180119b17153bf9034b (patch) | |
tree | 7db8c0f01fc8a04789a979aba7c5334034fbdd67 /gcc/ipa-prop.c | |
parent | 33b1ed324ef6e3d54e82c08d99af8086e292bf87 (diff) | |
download | gcc-5215027d365b04789c45a180119b17153bf9034b.tar.gz |
2009-08-07 Martin Jambor <mjambor@suse.cz>
* ipa-prop.h (enum jump_func_type): New value IPA_JF_ANCESTOR, changed
comments.
(struct ipa_pass_through_data): New type.
(struct ipa_ancestor_jf_data): New type.
(union jump_func_value): Removed field formal_id, added fields
pass_through and ancestor.
(struct ipa_param_call_note): Changed type of formal_id to int from
unsigned.
* ipa-prop.c (ipa_print_node_jump_functions): Print pass through with
operations jump functions and ancestor jump functions.
(compute_complex_pass_through): New function.
(compute_scalar_jump_functions): Call compute_complex_pass_through,
reflect changes in the jump function strucutre.
(update_jump_functions_after_inlining): Ignore complex pass-through
and ancestor jump functions.
* ipa-cp.c (ipcp_lattice_from_jfunc): Added support for ancestor and
polynomial pass-through with operation jump functions.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@150554 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/ipa-prop.c')
-rw-r--r-- | gcc/ipa-prop.c | 132 |
1 files changed, 117 insertions, 15 deletions
diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c index fcc4f70435c..2842088d8f1 100644 --- a/gcc/ipa-prop.c +++ b/gcc/ipa-prop.c @@ -300,8 +300,22 @@ ipa_print_node_jump_functions (FILE *f, struct cgraph_node *node) else if (type == IPA_JF_PASS_THROUGH) { fprintf (f, "PASS THROUGH: "); - fprintf (f, "%d\n", jump_func->value.formal_id); + fprintf (f, "%d, op %s ", + jump_func->value.pass_through.formal_id, + tree_code_name[(int) + jump_func->value.pass_through.operation]); + if (jump_func->value.pass_through.operation != NOP_EXPR) + print_generic_expr (dump_file, + jump_func->value.pass_through.operand, 0); + fprintf (dump_file, "\n"); } + else if (type == IPA_JF_ANCESTOR) + { + fprintf (f, "ANCESTOR: "); + fprintf (f, "%d, offset "HOST_WIDE_INT_PRINT_DEC"\n", + jump_func->value.ancestor.formal_id, + jump_func->value.ancestor.offset); + } } } } @@ -320,6 +334,67 @@ ipa_print_all_jump_functions (FILE *f) } } +/* Determine whether passing ssa name NAME constitutes a polynomial + pass-through function or getting an address of an acestor and if so, write + such a jump function to JFUNC. INFO describes the caller. */ + +static void +compute_complex_pass_through (struct ipa_node_params *info, + struct ipa_jump_func *jfunc, + tree name) +{ + HOST_WIDE_INT offset, size, max_size; + tree op1, op2, type; + int index; + gimple stmt = SSA_NAME_DEF_STMT (name); + + if (!is_gimple_assign (stmt)) + return; + op1 = gimple_assign_rhs1 (stmt); + op2 = gimple_assign_rhs2 (stmt); + + if (op2) + { + if (TREE_CODE (op1) != SSA_NAME + || !SSA_NAME_IS_DEFAULT_DEF (op1) + || !is_gimple_ip_invariant (op2)) + return; + + index = ipa_get_param_decl_index (info, SSA_NAME_VAR (op1)); + if (index >= 0) + { + jfunc->type = IPA_JF_PASS_THROUGH; + jfunc->value.pass_through.formal_id = index; + jfunc->value.pass_through.operation = gimple_assign_rhs_code (stmt); + jfunc->value.pass_through.operand = op2; + } + return; + } + + if (TREE_CODE (op1) != ADDR_EXPR) + return; + op1 = TREE_OPERAND (op1, 0); + type = TREE_TYPE (op1); + + op1 = get_ref_base_and_extent (op1, &offset, &size, &max_size); + if (TREE_CODE (op1) != INDIRECT_REF) + return; + op1 = TREE_OPERAND (op1, 0); + if (TREE_CODE (op1) != SSA_NAME + || !SSA_NAME_IS_DEFAULT_DEF (op1)) + return; + + index = ipa_get_param_decl_index (info, SSA_NAME_VAR (op1)); + if (index >= 0) + { + jfunc->type = IPA_JF_ANCESTOR; + jfunc->value.ancestor.formal_id = index; + jfunc->value.ancestor.offset = offset; + jfunc->value.ancestor.type = type; + } +} + + /* Determine the jump functions of scalar arguments. Scalar means SSA names and constants of a number of selected types. INFO is the ipa_node_params structure associated with the caller, FUNCTIONS is a pointer to an array of @@ -343,15 +418,21 @@ compute_scalar_jump_functions (struct ipa_node_params *info, functions[num].type = IPA_JF_CONST; functions[num].value.constant = arg; } - else if ((TREE_CODE (arg) == SSA_NAME) && SSA_NAME_IS_DEFAULT_DEF (arg)) + else if (TREE_CODE (arg) == SSA_NAME) { - int index = ipa_get_param_decl_index (info, SSA_NAME_VAR (arg)); - - if (index >= 0) + if (SSA_NAME_IS_DEFAULT_DEF (arg)) { - functions[num].type = IPA_JF_PASS_THROUGH; - functions[num].value.formal_id = index; + int index = ipa_get_param_decl_index (info, SSA_NAME_VAR (arg)); + + if (index >= 0) + { + functions[num].type = IPA_JF_PASS_THROUGH; + functions[num].value.pass_through.formal_id = index; + functions[num].value.pass_through.operation = NOP_EXPR; + } } + else + compute_complex_pass_through (info, &functions[num], arg); } } } @@ -418,7 +499,8 @@ compute_pass_through_member_ptrs (struct ipa_node_params *info, if (!ipa_is_param_modified (info, index)) { functions[num].type = IPA_JF_PASS_THROUGH; - functions[num].value.formal_id = index; + functions[num].value.pass_through.formal_id = index; + functions[num].value.pass_through.operation = NOP_EXPR; } else undecided_members = true; @@ -883,7 +965,10 @@ ipa_analyze_params_uses (struct cgraph_node *node) /* Update the jump functions associated with call graph edge E when the call graph edge CS is being inlined, assuming that E->caller is already (possibly - indirectly) inlined into CS->callee and that E has not been inlined. */ + indirectly) inlined into CS->callee and that E has not been inlined. + + We keep pass through functions only if they do not contain any operation. + This is sufficient for inlining and greately simplifies things. */ static void update_jump_functions_after_inlining (struct cgraph_edge *cs, @@ -898,17 +983,26 @@ update_jump_functions_after_inlining (struct cgraph_edge *cs, { struct ipa_jump_func *src, *dst = ipa_get_ith_jump_func (args, i); + if (dst->type == IPA_JF_ANCESTOR) + { + dst->type = IPA_JF_UNKNOWN; + continue; + } + if (dst->type != IPA_JF_PASS_THROUGH) continue; - /* We must check range due to calls with variable number of arguments: */ - if (dst->value.formal_id >= (unsigned) ipa_get_cs_argument_count (top)) + /* We must check range due to calls with variable number of arguments and + we cannot combine jump functions with operations. */ + if (dst->value.pass_through.operation != NOP_EXPR + || (dst->value.pass_through.formal_id + >= ipa_get_cs_argument_count (top))) { dst->type = IPA_JF_UNKNOWN; continue; } - src = ipa_get_ith_jump_func (top, dst->value.formal_id); + src = ipa_get_ith_jump_func (top, dst->value.pass_through.formal_id); *dst = *src; } } @@ -959,15 +1053,16 @@ update_call_notes_after_inlining (struct cgraph_edge *cs, continue; /* We must check range due to calls with variable number of arguments: */ - if (nt->formal_id >= (unsigned) ipa_get_cs_argument_count (top)) + if (nt->formal_id >= ipa_get_cs_argument_count (top)) { nt->processed = true; continue; } jfunc = ipa_get_ith_jump_func (top, nt->formal_id); - if (jfunc->type == IPA_JF_PASS_THROUGH) - nt->formal_id = jfunc->value.formal_id; + if (jfunc->type == IPA_JF_PASS_THROUGH + && jfunc->value.pass_through.operation == NOP_EXPR) + nt->formal_id = jfunc->value.pass_through.formal_id; else if (jfunc->type == IPA_JF_CONST || jfunc->type == IPA_JF_CONST_MEMBER_PTR) { @@ -1004,6 +1099,13 @@ update_call_notes_after_inlining (struct cgraph_edge *cs, VEC_safe_push (cgraph_edge_p, heap, *new_edges, new_indirect_edge); top = IPA_EDGE_REF (cs); } + else + { + /* Ancestor jum functions and pass theoughs with operations should + not be used on parameters that then get called. */ + gcc_assert (jfunc->type == IPA_JF_UNKNOWN); + nt->processed = true; + } } return res; } |