Commit 310bc633 by Martin Jambor Committed by Martin Jambor

ipa-prop.h: Include alloc-pool.h, all sorts of updates to general comments.

2011-07-18  Martin Jambor  <mjambor@suse.cz>

	* ipa-prop.h: Include alloc-pool.h, all sorts of updates to general
	comments.
	(ipcp_values_pool): Declare.
	(ipcp_sources_pool): Likewise.
	(ipcp_lattice): Changed to forward declaration.
	(ipa_param_descriptor): Removed fields ipcp_lattice, types and
	cannot_devirtualize.
	(ipa_node_params): New fields descriptors, lattices, known_vals,
	clone_for_all_contexts and node dead, removed fields params and
	count_scale.
	(ipa_set_param_count): Removed.
	(ipa_get_param_count): Made to work with descriptors vector.
	(ipa_get_param): Updated.
	(ipa_param_cannot_devirtualize_p): Removed.
	(ipa_param_types_vec_empty): Likewise.
	(ipa_set_param_used): New function.
	(ipa_get_param_used): Updated to use descriptors vector.
	(ipa_func_list): Removed.
	(ipa_init_func_list): Removed declaration.
	(ipa_push_func_to_list_1): Likewise.
	(ipa_pop_func_from_list): Likewise.
	(ipa_push_func_to_list): Removed.
	(ipa_lattice_from_jfunc): Remove declaration.
	(ipa_get_jf_pass_through_result): Declare.
	(ipa_get_jf_ancestor_result): Likewise.
	(ipa_value_from_jfunc): Likewise.
	(ipa_get_lattice): Update.
	(ipa_lat_is_single_const): New function.
	* ipa-prop.c (ipa_push_func_to_list_1): Removed.
	(ipa_init_func_list): Likewise.
	(ipa_pop_func_from_list): Likewise.
	(ipa_get_param_decl_index): Fix coding style.
	(count_formal_params): Removed.
	(count_formal_params_1): Renamed to count_formal_params.
	(ipa_populate_param_decls): Update to use descriptors vector.
	(ipa_initialize_node_params): Likewise.
	(visit_ref_for_mod_analysis): Use ipa_set_param_used.
	(ipa_analyze_params_uses): Likewise.
	(ipa_free_node_params_substructures): Likewise and free also lattices
	and known values.
	(duplicate_array): Removed.
	(ipa_edge_duplication_hook): Add the new edge to the list of edge
	clones.
	(ipa_node_duplication_hook): Update to use new lattices.
	(ipa_free_all_structures_after_ipa_cp): Free alloc pools.
	(ipa_free_all_structures_after_iinln): Likewise.
	(ipa_write_node_info): Update to use new lattices.
	(ipa_read_node_info): Likewise.
	(ipa_get_jf_pass_through_result): New function.
	(ipa_get_jf_ancestor_result): Likewise.
	(ipa_value_from_jfunc): Likewise.
	(ipa_cst_from_jfunc): Reimplemented using ipa_value_from_jfunc.
	* ipa-cp.c: Reimplemented.
	* params.def (PARAM_DEVIRT_TYPE_LIST_SIZE): Removed.
	(PARAM_IPA_CP_VALUE_LIST_SIZE): New parameter.
	(PARAM_IPA_CP_EVAL_THRESHOLD): Likewise.
	* Makefile.in (IPA_PROP_H): Added alloc-pool.h to dependencies.

	* doc/invoke.texi (devirt-type-list-size): Removed description.
	(ipa-cp-value-list-size): Added description.

	* testsuite/gcc.dg/ipa/ipa-1.c: Updated testcase dump scan.
	* testsuite/gcc.dg/ipa/ipa-2.c: Likewise.
	* testsuite/gcc.dg/ipa/ipa-3.c: Likewise and made functions static.
	* testsuite/gcc.dg/ipa/ipa-4.c: Updated testcase dump scan.
	* testsuite/gcc.dg/ipa/ipa-5.c: Likewise.
	* testsuite/gcc.dg/ipa/ipa-7.c: Likewise.
	* testsuite/gcc.dg/ipa/ipa-8.c: Updated testcase dump scan.
	* testsuite/gcc.dg/ipa/ipacost-1.c: Likewise.
	* testsuite/gcc.dg/ipa/ipacost-2.c: Likewise and increased sizes
	of some functions.
	* testsuite/gcc.dg/ipa/ipcp-1.c: New test.
	* testsuite/gcc.dg/ipa/ipcp-2.c: Likewise.
	* testsuite/gcc.dg/tree-ssa/ipa-cp-1.c: Updated testcase.

From-SVN: r176424
parent ca176e1c
2011-07-18 Martin Jambor <mjambor@suse.cz>
* ipa-prop.h: Include alloc-pool.h, all sorts of updates to general
comments.
(ipcp_values_pool): Declare.
(ipcp_sources_pool): Likewise.
(ipcp_lattice): Changed to forward declaration.
(ipa_param_descriptor): Removed fields ipcp_lattice, types and
cannot_devirtualize.
(ipa_node_params): New fields descriptors, lattices, known_vals,
clone_for_all_contexts and node dead, removed fields params and
count_scale.
(ipa_set_param_count): Removed.
(ipa_get_param_count): Made to work with descriptors vector.
(ipa_get_param): Updated.
(ipa_param_cannot_devirtualize_p): Removed.
(ipa_param_types_vec_empty): Likewise.
(ipa_set_param_used): New function.
(ipa_get_param_used): Updated to use descriptors vector.
(ipa_func_list): Removed.
(ipa_init_func_list): Removed declaration.
(ipa_push_func_to_list_1): Likewise.
(ipa_pop_func_from_list): Likewise.
(ipa_push_func_to_list): Removed.
(ipa_lattice_from_jfunc): Remove declaration.
(ipa_get_jf_pass_through_result): Declare.
(ipa_get_jf_ancestor_result): Likewise.
(ipa_value_from_jfunc): Likewise.
(ipa_get_lattice): Update.
(ipa_lat_is_single_const): New function.
* ipa-prop.c (ipa_push_func_to_list_1): Removed.
(ipa_init_func_list): Likewise.
(ipa_pop_func_from_list): Likewise.
(ipa_get_param_decl_index): Fix coding style.
(count_formal_params): Removed.
(count_formal_params_1): Renamed to count_formal_params.
(ipa_populate_param_decls): Update to use descriptors vector.
(ipa_initialize_node_params): Likewise.
(visit_ref_for_mod_analysis): Use ipa_set_param_used.
(ipa_analyze_params_uses): Likewise.
(ipa_free_node_params_substructures): Likewise and free also lattices
and known values.
(duplicate_array): Removed.
(ipa_edge_duplication_hook): Add the new edge to the list of edge
clones.
(ipa_node_duplication_hook): Update to use new lattices.
(ipa_free_all_structures_after_ipa_cp): Free alloc pools.
(ipa_free_all_structures_after_iinln): Likewise.
(ipa_write_node_info): Update to use new lattices.
(ipa_read_node_info): Likewise.
(ipa_get_jf_pass_through_result): New function.
(ipa_get_jf_ancestor_result): Likewise.
(ipa_value_from_jfunc): Likewise.
(ipa_cst_from_jfunc): Reimplemented using ipa_value_from_jfunc.
* ipa-cp.c: Reimplemented.
* params.def (PARAM_DEVIRT_TYPE_LIST_SIZE): Removed.
(PARAM_IPA_CP_VALUE_LIST_SIZE): New parameter.
(PARAM_IPA_CP_EVAL_THRESHOLD): Likewise.
* Makefile.in (IPA_PROP_H): Added alloc-pool.h to dependencies.
* doc/invoke.texi (devirt-type-list-size): Removed description.
(ipa-cp-value-list-size): Added description.
2011-07-18 Richard Henderson <rth@redhat.com> 2011-07-18 Richard Henderson <rth@redhat.com>
* bb-reorder.c (fix_crossing_conditional_branches): Emit all insns * bb-reorder.c (fix_crossing_conditional_branches): Emit all insns
......
...@@ -1006,7 +1006,7 @@ LTO_STREAMER_H = lto-streamer.h $(LINKER_PLUGIN_API_H) $(TARGET_H) \ ...@@ -1006,7 +1006,7 @@ LTO_STREAMER_H = lto-streamer.h $(LINKER_PLUGIN_API_H) $(TARGET_H) \
$(CGRAPH_H) $(VEC_H) vecprim.h $(TREE_H) $(GIMPLE_H) \ $(CGRAPH_H) $(VEC_H) vecprim.h $(TREE_H) $(GIMPLE_H) \
$(GCOV_IO_H) $(GCOV_IO_H)
TREE_VECTORIZER_H = tree-vectorizer.h $(TREE_DATA_REF_H) TREE_VECTORIZER_H = tree-vectorizer.h $(TREE_DATA_REF_H)
IPA_PROP_H = ipa-prop.h $(TREE_H) $(VEC_H) $(CGRAPH_H) $(GIMPLE_H) IPA_PROP_H = ipa-prop.h $(TREE_H) $(VEC_H) $(CGRAPH_H) $(GIMPLE_H) alloc-pool.h
GSTAB_H = gstab.h stab.def GSTAB_H = gstab.h stab.def
BITMAP_H = bitmap.h $(HASHTAB_H) statistics.h BITMAP_H = bitmap.h $(HASHTAB_H) statistics.h
GCC_PLUGIN_H = gcc-plugin.h highlev-plugin-common.h $(CONFIG_H) $(SYSTEM_H) \ GCC_PLUGIN_H = gcc-plugin.h highlev-plugin-common.h $(CONFIG_H) $(SYSTEM_H) \
......
...@@ -9006,11 +9006,11 @@ loop in the loop nest by a given number of iterations. The strip ...@@ -9006,11 +9006,11 @@ loop in the loop nest by a given number of iterations. The strip
length can be changed using the @option{loop-block-tile-size} length can be changed using the @option{loop-block-tile-size}
parameter. The default value is 51 iterations. parameter. The default value is 51 iterations.
@item devirt-type-list-size @item ipa-cp-value-list-size
IPA-CP attempts to track all possible types passed to a function's IPA-CP attempts to track all possible values and types passed to a function's
parameter in order to perform devirtualization. parameter in order to propagate them and perform devirtualization.
@option{devirt-type-list-size} is the maximum number of types it @option{ipa-cp-value-list-size} is the maximum number of values and types it
stores per a single formal parameter of a function. stores per one formal parameter of a function.
@item lto-partitions @item lto-partitions
Specify desired number of partitions produced during WHOPR compilation. Specify desired number of partitions produced during WHOPR compilation.
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -65,65 +65,6 @@ static struct cgraph_2edge_hook_list *edge_duplication_hook_holder; ...@@ -65,65 +65,6 @@ static struct cgraph_2edge_hook_list *edge_duplication_hook_holder;
static struct cgraph_2node_hook_list *node_duplication_hook_holder; static struct cgraph_2node_hook_list *node_duplication_hook_holder;
static struct cgraph_node_hook_list *function_insertion_hook_holder; static struct cgraph_node_hook_list *function_insertion_hook_holder;
/* Add cgraph NODE described by INFO to the worklist WL regardless of whether
it is in one or not. It should almost never be used directly, as opposed to
ipa_push_func_to_list. */
void
ipa_push_func_to_list_1 (struct ipa_func_list **wl,
struct cgraph_node *node,
struct ipa_node_params *info)
{
struct ipa_func_list *temp;
info->node_enqueued = 1;
temp = XCNEW (struct ipa_func_list);
temp->node = node;
temp->next = *wl;
*wl = temp;
}
/* Initialize worklist to contain all functions. */
struct ipa_func_list *
ipa_init_func_list (void)
{
struct cgraph_node *node;
struct ipa_func_list * wl;
wl = NULL;
for (node = cgraph_nodes; node; node = node->next)
if (node->analyzed && !node->alias)
{
struct ipa_node_params *info = IPA_NODE_REF (node);
/* Unreachable nodes should have been eliminated before ipcp and
inlining. */
gcc_assert (node->needed || node->reachable);
ipa_push_func_to_list_1 (&wl, node, info);
}
return wl;
}
/* Remove a function from the worklist WL and return it. */
struct cgraph_node *
ipa_pop_func_from_list (struct ipa_func_list **wl)
{
struct ipa_node_params *info;
struct ipa_func_list *first;
struct cgraph_node *node;
first = *wl;
*wl = (*wl)->next;
node = first->node;
free (first);
info = IPA_NODE_REF (node);
info->node_enqueued = 0;
return node;
}
/* Return index of the formal whose tree is PTREE in function which corresponds /* Return index of the formal whose tree is PTREE in function which corresponds
to INFO. */ to INFO. */
...@@ -134,7 +75,7 @@ ipa_get_param_decl_index (struct ipa_node_params *info, tree ptree) ...@@ -134,7 +75,7 @@ ipa_get_param_decl_index (struct ipa_node_params *info, tree ptree)
count = ipa_get_param_count (info); count = ipa_get_param_count (info);
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
if (ipa_get_param(info, i) == ptree) if (ipa_get_param (info, i) == ptree)
return i; return i;
return -1; return -1;
...@@ -157,7 +98,8 @@ ipa_populate_param_decls (struct cgraph_node *node, ...@@ -157,7 +98,8 @@ ipa_populate_param_decls (struct cgraph_node *node,
param_num = 0; param_num = 0;
for (parm = fnargs; parm; parm = DECL_CHAIN (parm)) for (parm = fnargs; parm; parm = DECL_CHAIN (parm))
{ {
info->params[param_num].decl = parm; VEC_index (ipa_param_descriptor_t,
info->descriptors, param_num)->decl = parm;
param_num++; param_num++;
} }
} }
...@@ -165,7 +107,7 @@ ipa_populate_param_decls (struct cgraph_node *node, ...@@ -165,7 +107,7 @@ ipa_populate_param_decls (struct cgraph_node *node,
/* Return how many formal parameters FNDECL has. */ /* Return how many formal parameters FNDECL has. */
static inline int static inline int
count_formal_params_1 (tree fndecl) count_formal_params (tree fndecl)
{ {
tree parm; tree parm;
int count = 0; int count = 0;
...@@ -176,19 +118,6 @@ count_formal_params_1 (tree fndecl) ...@@ -176,19 +118,6 @@ count_formal_params_1 (tree fndecl)
return count; return count;
} }
/* Count number of formal parameters in NOTE. Store the result to the
appropriate field of INFO. */
static void
ipa_count_formal_params (struct cgraph_node *node,
struct ipa_node_params *info)
{
int param_num;
param_num = count_formal_params_1 (node->decl);
ipa_set_param_count (info, param_num);
}
/* Initialize the ipa_node_params structure associated with NODE by counting /* Initialize the ipa_node_params structure associated with NODE by counting
the function parameters, creating the descriptors and populating their the function parameters, creating the descriptors and populating their
param_decls. */ param_decls. */
...@@ -198,12 +127,17 @@ ipa_initialize_node_params (struct cgraph_node *node) ...@@ -198,12 +127,17 @@ ipa_initialize_node_params (struct cgraph_node *node)
{ {
struct ipa_node_params *info = IPA_NODE_REF (node); struct ipa_node_params *info = IPA_NODE_REF (node);
if (!info->params) if (!info->descriptors)
{ {
ipa_count_formal_params (node, info); int param_count;
info->params = XCNEWVEC (struct ipa_param_descriptor,
ipa_get_param_count (info)); param_count = count_formal_params (node->decl);
ipa_populate_param_decls (node, info); if (param_count)
{
VEC_safe_grow_cleared (ipa_param_descriptor_t, heap,
info->descriptors, param_count);
ipa_populate_param_decls (node, info);
}
} }
} }
...@@ -1497,7 +1431,7 @@ visit_ref_for_mod_analysis (gimple stmt ATTRIBUTE_UNUSED, ...@@ -1497,7 +1431,7 @@ visit_ref_for_mod_analysis (gimple stmt ATTRIBUTE_UNUSED,
{ {
int index = ipa_get_param_decl_index (info, op); int index = ipa_get_param_decl_index (info, op);
gcc_assert (index >= 0); gcc_assert (index >= 0);
info->params[index].used = true; ipa_set_param_used (info, index, true);
} }
return false; return false;
...@@ -1529,7 +1463,7 @@ ipa_analyze_params_uses (struct cgraph_node *node, ...@@ -1529,7 +1463,7 @@ ipa_analyze_params_uses (struct cgraph_node *node,
the flag during modification analysis. */ the flag during modification analysis. */
if (is_gimple_reg (parm) if (is_gimple_reg (parm)
&& gimple_default_def (DECL_STRUCT_FUNCTION (node->decl), parm)) && gimple_default_def (DECL_STRUCT_FUNCTION (node->decl), parm))
info->params[i].used = true; ipa_set_param_used (info, i, true);
} }
func = DECL_STRUCT_FUNCTION (decl); func = DECL_STRUCT_FUNCTION (decl);
...@@ -1936,8 +1870,11 @@ ipa_free_all_edge_args (void) ...@@ -1936,8 +1870,11 @@ ipa_free_all_edge_args (void)
void void
ipa_free_node_params_substructures (struct ipa_node_params *info) ipa_free_node_params_substructures (struct ipa_node_params *info)
{ {
free (info->params); VEC_free (ipa_param_descriptor_t, heap, info->descriptors);
free (info->lattices);
/* Lattice values and their sources are deallocated with their alocation
pool. */
VEC_free (tree, heap, info->known_vals);
memset (info, 0, sizeof (*info)); memset (info, 0, sizeof (*info));
} }
...@@ -1980,22 +1917,6 @@ ipa_node_removal_hook (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED) ...@@ -1980,22 +1917,6 @@ ipa_node_removal_hook (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
ipa_free_node_params_substructures (IPA_NODE_REF (node)); ipa_free_node_params_substructures (IPA_NODE_REF (node));
} }
/* Helper function to duplicate an array of size N that is at SRC and store a
pointer to it to DST. Nothing is done if SRC is NULL. */
static void *
duplicate_array (void *src, size_t n)
{
void *p;
if (!src)
return NULL;
p = xmalloc (n);
memcpy (p, src, n);
return p;
}
static struct ipa_jump_func * static struct ipa_jump_func *
duplicate_ipa_jump_func_array (const struct ipa_jump_func * src, size_t n) duplicate_ipa_jump_func_array (const struct ipa_jump_func * src, size_t n)
{ {
...@@ -2040,22 +1961,15 @@ ipa_node_duplication_hook (struct cgraph_node *src, struct cgraph_node *dst, ...@@ -2040,22 +1961,15 @@ ipa_node_duplication_hook (struct cgraph_node *src, struct cgraph_node *dst,
ATTRIBUTE_UNUSED void *data) ATTRIBUTE_UNUSED void *data)
{ {
struct ipa_node_params *old_info, *new_info; struct ipa_node_params *old_info, *new_info;
int param_count, i;
ipa_check_create_node_params (); ipa_check_create_node_params ();
old_info = IPA_NODE_REF (src); old_info = IPA_NODE_REF (src);
new_info = IPA_NODE_REF (dst); new_info = IPA_NODE_REF (dst);
param_count = ipa_get_param_count (old_info);
ipa_set_param_count (new_info, param_count); new_info->descriptors = VEC_copy (ipa_param_descriptor_t, heap,
new_info->params = (struct ipa_param_descriptor *) old_info->descriptors);
duplicate_array (old_info->params, new_info->lattices = NULL;
sizeof (struct ipa_param_descriptor) * param_count);
for (i = 0; i < param_count; i++)
new_info->params[i].types = VEC_copy (tree, heap,
old_info->params[i].types);
new_info->ipcp_orig_node = old_info->ipcp_orig_node; new_info->ipcp_orig_node = old_info->ipcp_orig_node;
new_info->count_scale = old_info->count_scale;
new_info->called_with_var_arguments = old_info->called_with_var_arguments; new_info->called_with_var_arguments = old_info->called_with_var_arguments;
new_info->uses_analysis_done = old_info->uses_analysis_done; new_info->uses_analysis_done = old_info->uses_analysis_done;
...@@ -2127,6 +2041,8 @@ ipa_free_all_structures_after_ipa_cp (void) ...@@ -2127,6 +2041,8 @@ ipa_free_all_structures_after_ipa_cp (void)
{ {
ipa_free_all_edge_args (); ipa_free_all_edge_args ();
ipa_free_all_node_params (); ipa_free_all_node_params ();
free_alloc_pool (ipcp_sources_pool);
free_alloc_pool (ipcp_values_pool);
ipa_unregister_cgraph_hooks (); ipa_unregister_cgraph_hooks ();
} }
} }
...@@ -2142,6 +2058,10 @@ ipa_free_all_structures_after_iinln (void) ...@@ -2142,6 +2058,10 @@ ipa_free_all_structures_after_iinln (void)
ipa_free_all_edge_args (); ipa_free_all_edge_args ();
ipa_free_all_node_params (); ipa_free_all_node_params ();
ipa_unregister_cgraph_hooks (); ipa_unregister_cgraph_hooks ();
if (ipcp_sources_pool)
free_alloc_pool (ipcp_sources_pool);
if (ipcp_values_pool)
free_alloc_pool (ipcp_values_pool);
} }
/* Print ipa_tree_map data structures of all functions in the /* Print ipa_tree_map data structures of all functions in the
...@@ -2196,7 +2116,7 @@ ipa_get_vector_of_formal_parms (tree fndecl) ...@@ -2196,7 +2116,7 @@ ipa_get_vector_of_formal_parms (tree fndecl)
int count; int count;
tree parm; tree parm;
count = count_formal_params_1 (fndecl); count = count_formal_params (fndecl);
args = VEC_alloc (tree, heap, count); args = VEC_alloc (tree, heap, count);
for (parm = DECL_ARGUMENTS (fndecl); parm; parm = DECL_CHAIN (parm)) for (parm = DECL_ARGUMENTS (fndecl); parm; parm = DECL_CHAIN (parm))
VEC_quick_push (tree, args, parm); VEC_quick_push (tree, args, parm);
...@@ -2859,7 +2779,7 @@ ipa_write_node_info (struct output_block *ob, struct cgraph_node *node) ...@@ -2859,7 +2779,7 @@ ipa_write_node_info (struct output_block *ob, struct cgraph_node *node)
gcc_assert (!info->node_enqueued); gcc_assert (!info->node_enqueued);
gcc_assert (!info->ipcp_orig_node); gcc_assert (!info->ipcp_orig_node);
for (j = 0; j < ipa_get_param_count (info); j++) for (j = 0; j < ipa_get_param_count (info); j++)
bp_pack_value (&bp, info->params[j].used, 1); bp_pack_value (&bp, ipa_is_param_used (info, j), 1);
lto_output_bitpack (&bp); lto_output_bitpack (&bp);
for (e = node->callees; e; e = e->next_callee) for (e = node->callees; e; e = e->next_callee)
{ {
...@@ -2900,7 +2820,7 @@ ipa_read_node_info (struct lto_input_block *ib, struct cgraph_node *node, ...@@ -2900,7 +2820,7 @@ ipa_read_node_info (struct lto_input_block *ib, struct cgraph_node *node,
info->uses_analysis_done = true; info->uses_analysis_done = true;
info->node_enqueued = false; info->node_enqueued = false;
for (k = 0; k < ipa_get_param_count (info); k++) for (k = 0; k < ipa_get_param_count (info); k++)
info->params[k].used = bp_unpack_value (&bp, 1); ipa_set_param_used (info, k, bp_unpack_value (&bp, 1));
for (e = node->callees; e; e = e->next_callee) for (e = node->callees; e; e = e->next_callee)
{ {
struct ipa_edge_args *args = IPA_EDGE_REF (e); struct ipa_edge_args *args = IPA_EDGE_REF (e);
...@@ -3064,82 +2984,3 @@ ipa_update_after_lto_read (void) ...@@ -3064,82 +2984,3 @@ ipa_update_after_lto_read (void)
} }
} }
/* Given the jump function JFUNC, compute the lattice LAT that describes the
value coming down the callsite. INFO describes the caller node so that
pass-through jump functions can be evaluated. */
void
ipa_lattice_from_jfunc (struct ipa_node_params *info, struct ipcp_lattice *lat,
struct ipa_jump_func *jfunc)
{
if (jfunc->type == IPA_JF_CONST)
{
lat->type = IPA_CONST_VALUE;
lat->constant = jfunc->value.constant;
}
else if (jfunc->type == IPA_JF_PASS_THROUGH)
{
struct ipcp_lattice *caller_lat;
tree cst;
caller_lat = ipa_get_lattice (info, jfunc->value.pass_through.formal_id);
lat->type = caller_lat->type;
if (caller_lat->type != IPA_CONST_VALUE)
return;
cst = caller_lat->constant;
if (jfunc->value.pass_through.operation != NOP_EXPR)
{
tree restype;
if (TREE_CODE_CLASS (jfunc->value.pass_through.operation)
== tcc_comparison)
restype = boolean_type_node;
else
restype = TREE_TYPE (cst);
cst = fold_binary (jfunc->value.pass_through.operation,
restype, cst, jfunc->value.pass_through.operand);
}
if (!cst || !is_gimple_ip_invariant (cst))
lat->type = IPA_BOTTOM;
lat->constant = cst;
}
else if (jfunc->type == IPA_JF_ANCESTOR)
{
struct ipcp_lattice *caller_lat;
tree t;
caller_lat = ipa_get_lattice (info, jfunc->value.ancestor.formal_id);
lat->type = caller_lat->type;
if (caller_lat->type != IPA_CONST_VALUE)
return;
if (TREE_CODE (caller_lat->constant) != ADDR_EXPR)
{
/* This can happen when the constant is a NULL pointer. */
lat->type = IPA_BOTTOM;
return;
}
t = TREE_OPERAND (caller_lat->constant, 0);
t = build_ref_for_offset (EXPR_LOCATION (t), t,
jfunc->value.ancestor.offset,
jfunc->value.ancestor.type, NULL, false);
lat->constant = build_fold_addr_expr (t);
}
else
lat->type = IPA_BOTTOM;
}
/* Determine whether JFUNC evaluates to a constant and if so, return it.
Otherwise return NULL. INFO describes the caller node so that pass-through
jump functions can be evaluated. */
tree
ipa_cst_from_jfunc (struct ipa_node_params *info, struct ipa_jump_func *jfunc)
{
struct ipcp_lattice lat;
ipa_lattice_from_jfunc (info, &lat, jfunc);
if (lat.type == IPA_CONST_VALUE)
return lat.constant;
else
return NULL_TREE;
}
...@@ -25,6 +25,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -25,6 +25,7 @@ along with GCC; see the file COPYING3. If not see
#include "vec.h" #include "vec.h"
#include "cgraph.h" #include "cgraph.h"
#include "gimple.h" #include "gimple.h"
#include "alloc-pool.h"
/* The following definitions and interfaces are used by /* The following definitions and interfaces are used by
interprocedural analyses or parameters. */ interprocedural analyses or parameters. */
...@@ -32,7 +33,10 @@ along with GCC; see the file COPYING3. If not see ...@@ -32,7 +33,10 @@ along with GCC; see the file COPYING3. If not see
/* ipa-prop.c stuff (ipa-cp, indirect inlining): */ /* ipa-prop.c stuff (ipa-cp, indirect inlining): */
/* A jump function for a callsite represents the values passed as actual /* A jump function for a callsite represents the values passed as actual
arguments of the callsite. There are three main types of values : arguments of the callsite. They were originally proposed in a paper called
"Interprocedural Constant Propagation", by David Callahan, Keith D Cooper,
Ken Kennedy, Linda Torczon in Comp86, pg 152-161. There are three main
types of values :
Pass-through - the caller's formal parameter is passed as an actual Pass-through - the caller's formal parameter is passed as an actual
argument, possibly one simple operation performed on it. argument, possibly one simple operation performed on it.
...@@ -41,7 +45,8 @@ along with GCC; see the file COPYING3. If not see ...@@ -41,7 +45,8 @@ along with GCC; see the file COPYING3. If not see
Unknown - neither of the above. Unknown - neither of the above.
IPA_JF_CONST_MEMBER_PTR stands for C++ member pointers, it is a special IPA_JF_CONST_MEMBER_PTR stands for C++ member pointers, it is a special
constant in this regard. Other constants are represented with IPA_JF_CONST. constant in this regard because it is in fact a structure consisting of two
values. Other constants are represented with IPA_JF_CONST.
IPA_JF_ANCESTOR is a special pass-through jump function, which means that IPA_JF_ANCESTOR is a special pass-through jump function, which means that
the result is an address of a part of the object pointed to by the formal the result is an address of a part of the object pointed to by the formal
...@@ -130,95 +135,65 @@ struct GTY (()) ipa_jump_func ...@@ -130,95 +135,65 @@ struct GTY (()) ipa_jump_func
} GTY ((desc ("%1.type"))) value; } GTY ((desc ("%1.type"))) value;
}; };
/* All formal parameters in the program have a lattice associated with it /* Summary describing a single formal parameter. */
computed by the interprocedural stage of IPCP.
There are three main values of the lattice:
IPA_TOP - unknown,
IPA_BOTTOM - variable,
IPA_CONST_VALUE - simple scalar constant,
We also use this type to propagate types accross the call graph for the
purpose of devirtualization. In that case, IPA_CONST_VALUE denotes a known
type, rather than a constant. */
enum ipa_lattice_type
{
IPA_BOTTOM,
IPA_CONST_VALUE,
IPA_TOP
};
/* All formal parameters in the program have a cval computed by
the interprocedural stage of IPCP. See enum ipa_lattice_type for
the various types of lattices supported */
struct ipcp_lattice
{
enum ipa_lattice_type type;
tree constant;
};
/* Structure describing a single formal parameter. */
struct ipa_param_descriptor struct ipa_param_descriptor
{ {
/* IPA-CP lattice. */
struct ipcp_lattice ipcp_lattice;
/* PARAM_DECL of this parameter. */ /* PARAM_DECL of this parameter. */
tree decl; tree decl;
/* Vector of BINFOs of types that this argument might encounter. NULL
basically means a top value, bottom is marked by the cannot_devirtualize
flag below.*/
VEC (tree, heap) *types;
/* The parameter is used. */ /* The parameter is used. */
unsigned used : 1; unsigned used : 1;
/* Set when parameter type cannot be used for devirtualization. */
unsigned cannot_devirtualize : 1;
}; };
typedef struct ipa_param_descriptor ipa_param_descriptor_t;
DEF_VEC_O (ipa_param_descriptor_t);
DEF_VEC_ALLOC_O (ipa_param_descriptor_t, heap);
struct ipcp_lattice;
/* ipa_node_params stores information related to formal parameters of functions /* ipa_node_params stores information related to formal parameters of functions
and some other information for interprocedural passes that operate on and some other information for interprocedural passes that operate on
parameters (such as ipa-cp). */ parameters (such as ipa-cp). */
struct ipa_node_params struct ipa_node_params
{ {
/* Number of formal parameters of this function. When set to 0, this /* Information about individual formal parameters that are gathered when
function's parameters would not be analyzed by IPA CP. */ summaries are generated. */
int param_count; VEC (ipa_param_descriptor_t, heap) *descriptors;
/* Pointer to an array of structures describing individual formal
parameters. */
struct ipcp_lattice *lattices;
/* Only for versioned nodes this field would not be NULL,
it points to the node that IPA cp cloned from. */
struct cgraph_node *ipcp_orig_node;
/* If this node is an ipa-cp clone, these are the known values that describe
what it has been specialized for. */
VEC (tree, heap) *known_vals;
/* Whether this function is called with variable number of actual /* Whether this function is called with variable number of actual
arguments. */ arguments. */
unsigned called_with_var_arguments : 1; unsigned called_with_var_arguments : 1;
/* Set when it is possible to create specialized versions of this node. */
unsigned node_versionable : 1;
/* Whether the param uses analysis has already been performed. */ /* Whether the param uses analysis has already been performed. */
unsigned uses_analysis_done : 1; unsigned uses_analysis_done : 1;
/* Whether the function is enqueued in an ipa_func_list. */ /* Whether the function is enqueued in ipa-cp propagation stack. */
unsigned node_enqueued : 1; unsigned node_enqueued : 1;
/* Pointer to an array of structures describing individual formal /* Whether we should create a specialized version based on values that are
parameters. */ known to be constant in all contexts. */
struct ipa_param_descriptor *params; unsigned clone_for_all_contexts : 1;
/* Only for versioned nodes this field would not be NULL, /* Node has been completely replaced by clones and will be removed after
it points to the node that IPA cp cloned from. */ ipa-cp is finished. */
struct cgraph_node *ipcp_orig_node; unsigned node_dead : 1;
/* Meaningful only for original functions. Expresses the
ratio between the direct calls and sum of all invocations of
this function (given by profiling info). It is used to calculate
the profiling information of the original function and the versioned
one. */
gcov_type count_scale;
}; };
/* ipa_node_params access functions. Please use these to access fields that /* ipa_node_params access functions. Please use these to access fields that
are or will be shared among various passes. */ are or will be shared among various passes. */
/* Set the number of formal parameters. */
static inline void
ipa_set_param_count (struct ipa_node_params *info, int count)
{
info->param_count = count;
}
/* Return the number of formal parameters. */ /* Return the number of formal parameters. */
static inline int static inline int
ipa_get_param_count (struct ipa_node_params *info) ipa_get_param_count (struct ipa_node_params *info)
{ {
return info->param_count; return VEC_length (ipa_param_descriptor_t, info->descriptors);
} }
/* Return the declaration of Ith formal parameter of the function corresponding /* Return the declaration of Ith formal parameter of the function corresponding
...@@ -228,39 +203,25 @@ ipa_get_param_count (struct ipa_node_params *info) ...@@ -228,39 +203,25 @@ ipa_get_param_count (struct ipa_node_params *info)
static inline tree static inline tree
ipa_get_param (struct ipa_node_params *info, int i) ipa_get_param (struct ipa_node_params *info, int i)
{ {
gcc_assert (i >= 0 && i <= info->param_count); return VEC_index (ipa_param_descriptor_t, info->descriptors, i)->decl;
return info->params[i].decl;
}
/* Return the used flag corresponding to the Ith formal parameter of
the function associated with INFO. */
static inline bool
ipa_is_param_used (struct ipa_node_params *info, int i)
{
gcc_assert (i >= 0 && i <= info->param_count);
return info->params[i].used;
} }
/* Return the cannot_devirtualize flag corresponding to the Ith formal /* Set the used flag corresponding to the Ith formal parameter of the function
parameter of the function associated with INFO. The corresponding function associated with INFO to VAL. */
to set the flag is ipa_set_param_cannot_devirtualize. */
static inline bool static inline void
ipa_param_cannot_devirtualize_p (struct ipa_node_params *info, int i) ipa_set_param_used (struct ipa_node_params *info, int i, bool val)
{ {
gcc_assert (i >= 0 && i <= info->param_count); VEC_index (ipa_param_descriptor_t, info->descriptors, i)->used = val;
return info->params[i].cannot_devirtualize;
} }
/* Return true iff the vector of possible types of the Ith formal parameter of /* Return the used flag corresponding to the Ith formal parameter of the
the function associated with INFO is empty. */ function associated with INFO. */
static inline bool static inline bool
ipa_param_types_vec_empty (struct ipa_node_params *info, int i) ipa_is_param_used (struct ipa_node_params *info, int i)
{ {
gcc_assert (i >= 0 && i <= info->param_count); return VEC_index (ipa_param_descriptor_t, info->descriptors, i)->used;
return info->params[i].types == NULL;
} }
/* Flag this node as having callers with variable number of arguments. */ /* Flag this node as having callers with variable number of arguments. */
...@@ -279,8 +240,6 @@ ipa_is_called_with_var_arguments (struct ipa_node_params *info) ...@@ -279,8 +240,6 @@ ipa_is_called_with_var_arguments (struct ipa_node_params *info)
return info->called_with_var_arguments; return info->called_with_var_arguments;
} }
/* ipa_edge_args stores information related to a callsite and particularly its /* ipa_edge_args stores information related to a callsite and particularly its
arguments. It can be accessed by the IPA_EDGE_REF macro. */ arguments. It can be accessed by the IPA_EDGE_REF macro. */
typedef struct GTY(()) ipa_edge_args typedef struct GTY(()) ipa_edge_args
...@@ -402,33 +361,6 @@ ipa_edge_args_info_available_for_edge_p (struct cgraph_edge *edge) ...@@ -402,33 +361,6 @@ ipa_edge_args_info_available_for_edge_p (struct cgraph_edge *edge)
ipa_edge_args_vector)); ipa_edge_args_vector));
} }
/* A function list element. It is used to create a temporary worklist used in
the propagation stage of IPCP. (can be used for more IPA optimizations) */
struct ipa_func_list
{
struct cgraph_node *node;
struct ipa_func_list *next;
};
/* ipa_func_list interface. */
struct ipa_func_list *ipa_init_func_list (void);
void ipa_push_func_to_list_1 (struct ipa_func_list **, struct cgraph_node *,
struct ipa_node_params *);
struct cgraph_node *ipa_pop_func_from_list (struct ipa_func_list **);
/* Add cgraph NODE to the worklist WL if it is not already in one. */
static inline void
ipa_push_func_to_list (struct ipa_func_list **wl, struct cgraph_node *node)
{
struct ipa_node_params *info = IPA_NODE_REF (node);
if (!info->node_enqueued)
ipa_push_func_to_list_1 (wl, node, info);
}
void ipa_analyze_node (struct cgraph_node *);
/* Function formal parameters related computations. */ /* Function formal parameters related computations. */
void ipa_initialize_node_params (struct cgraph_node *node); void ipa_initialize_node_params (struct cgraph_node *node);
bool ipa_propagate_indirect_call_infos (struct cgraph_edge *cs, bool ipa_propagate_indirect_call_infos (struct cgraph_edge *cs,
...@@ -438,12 +370,18 @@ bool ipa_propagate_indirect_call_infos (struct cgraph_edge *cs, ...@@ -438,12 +370,18 @@ bool ipa_propagate_indirect_call_infos (struct cgraph_edge *cs,
struct cgraph_edge *ipa_make_edge_direct_to_target (struct cgraph_edge *, tree, struct cgraph_edge *ipa_make_edge_direct_to_target (struct cgraph_edge *, tree,
tree); tree);
/* Functions related to both. */
void ipa_analyze_node (struct cgraph_node *);
/* Debugging interface. */ /* Debugging interface. */
void ipa_print_node_params (FILE *, struct cgraph_node *node); void ipa_print_node_params (FILE *, struct cgraph_node *node);
void ipa_print_all_params (FILE *); void ipa_print_all_params (FILE *);
void ipa_print_node_jump_functions (FILE *f, struct cgraph_node *node); void ipa_print_node_jump_functions (FILE *f, struct cgraph_node *node);
void ipa_print_all_jump_functions (FILE * f); void ipa_print_all_jump_functions (FILE * f);
void ipcp_verify_propagated_values (void);
extern alloc_pool ipcp_values_pool;
extern alloc_pool ipcp_sources_pool;
/* Structure to describe transformations of formal parameters and actual /* Structure to describe transformations of formal parameters and actual
arguments. Each instance describes one new parameter and they are meant to arguments. Each instance describes one new parameter and they are meant to
...@@ -521,9 +459,6 @@ void ipa_prop_write_jump_functions (cgraph_node_set set); ...@@ -521,9 +459,6 @@ void ipa_prop_write_jump_functions (cgraph_node_set set);
void ipa_prop_read_jump_functions (void); void ipa_prop_read_jump_functions (void);
void ipa_update_after_lto_read (void); void ipa_update_after_lto_read (void);
int ipa_get_param_decl_index (struct ipa_node_params *, tree); int ipa_get_param_decl_index (struct ipa_node_params *, tree);
void ipa_lattice_from_jfunc (struct ipa_node_params *info,
struct ipcp_lattice *lat,
struct ipa_jump_func *jfunc);
tree ipa_cst_from_jfunc (struct ipa_node_params *info, tree ipa_cst_from_jfunc (struct ipa_node_params *info,
struct ipa_jump_func *jfunc); struct ipa_jump_func *jfunc);
...@@ -532,13 +467,4 @@ tree ipa_cst_from_jfunc (struct ipa_node_params *info, ...@@ -532,13 +467,4 @@ tree ipa_cst_from_jfunc (struct ipa_node_params *info,
tree build_ref_for_offset (location_t, tree, HOST_WIDE_INT, tree, tree build_ref_for_offset (location_t, tree, HOST_WIDE_INT, tree,
gimple_stmt_iterator *, bool); gimple_stmt_iterator *, bool);
/* Return the lattice corresponding to the Ith formal parameter of the function
described by INFO. */
static inline struct ipcp_lattice *
ipa_get_lattice (struct ipa_node_params *info, int i)
{
gcc_assert (i >= 0 && i <= info->param_count);
return &(info->params[i].ipcp_lattice);
}
#endif /* IPA_PROP_H */ #endif /* IPA_PROP_H */
...@@ -860,12 +860,18 @@ DEFPARAM (PARAM_IPA_SRA_PTR_GROWTH_FACTOR, ...@@ -860,12 +860,18 @@ DEFPARAM (PARAM_IPA_SRA_PTR_GROWTH_FACTOR,
"a pointer to an aggregate with", "a pointer to an aggregate with",
2, 0, 0) 2, 0, 0)
DEFPARAM (PARAM_DEVIRT_TYPE_LIST_SIZE, DEFPARAM (PARAM_IPA_CP_VALUE_LIST_SIZE,
"devirt-type-list-size", "ipa-cp-value-list-size",
"Maximum size of a type list associated with each parameter for " "Maximum size of a list of values associated with each parameter for "
"devirtualization", "interprocedural constant propagation",
8, 0, 0) 8, 0, 0)
DEFPARAM (PARAM_IPA_CP_EVAL_THRESHOLD,
"ipa-cp-eval-threshold",
"Threshold ipa-cp opportunity evaluation that is still considered "
"beneficial to clone.",
500, 0, 0)
/* WHOPR partitioning configuration. */ /* WHOPR partitioning configuration. */
DEFPARAM (PARAM_LTO_PARTITIONS, DEFPARAM (PARAM_LTO_PARTITIONS,
......
2011-07-18 Martin Jambor <mjambor@suse.cz>
* gcc.dg/ipa/ipa-1.c: Updated testcase dump scan.
* gcc.dg/ipa/ipa-2.c: Likewise.
* gcc.dg/ipa/ipa-3.c: Likewise and made functions static.
* gcc.dg/ipa/ipa-4.c: Updated testcase dump scan.
* gcc.dg/ipa/ipa-5.c: Likewise.
* gcc.dg/ipa/ipa-7.c: Likewise.
* gcc.dg/ipa/ipa-8.c: Updated testcase dump scan.
* gcc.dg/ipa/ipacost-1.c: Likewise.
* gcc.dg/ipa/ipacost-2.c: Likewise and increased sizes of some
functions.
* gcc.dg/ipa/ipcp-1.c: New test.
* gcc.dg/ipa/ipcp-2.c: Likewise.
* gcc.dg/tree-ssa/ipa-cp-1.c: Updated testcase.
2011-07-18 Jakub Jelinek <jakub@redhat.com> 2011-07-18 Jakub Jelinek <jakub@redhat.com>
PR middle-end/49675 PR middle-end/49675
......
...@@ -24,9 +24,8 @@ int main () ...@@ -24,9 +24,8 @@ int main ()
} }
/* { dg-final { scan-ipa-dump-times "versioned function" 2 "cp" } } */ /* { dg-final { scan-ipa-dump "Creating a specialized node of f" "cp" } } */
/* { dg-final { scan-ipa-dump "replacing param a with const 7" "cp" } } */ /* { dg-final { scan-ipa-dump "replacing param a with const 7" "cp" } } */
/* { dg-final { scan-ipa-dump "replacing param b with const 7" "cp" } } */
/* { dg-final { cleanup-ipa-dump "cp" } } */ /* { dg-final { cleanup-ipa-dump "cp" } } */
...@@ -22,7 +22,6 @@ int main () ...@@ -22,7 +22,6 @@ int main ()
} }
/* { dg-final { scan-ipa-dump-times "versioned function" 2 "cp" } } */ /* { dg-final { scan-ipa-dump "Creating a specialized node of f" "cp" } } */
/* { dg-final { scan-ipa-dump "replacing param a with const 7" "cp" } } */ /* { dg-final { scan-ipa-dump "replacing param a with const 7" "cp" } } */
/* { dg-final { scan-ipa-dump "replacing param c with const 3" "cp" } } */
/* { dg-final { cleanup-ipa-dump "cp" } } */ /* { dg-final { cleanup-ipa-dump "cp" } } */
...@@ -7,12 +7,12 @@ ...@@ -7,12 +7,12 @@
#include <stdio.h> #include <stdio.h>
void t(void); void t(void);
int g (double b, double c) static int g (double b, double c)
{ {
t(); t();
return (int)(b+c); return (int)(b+c);
} }
int f (double a) static int f (double a)
{ {
if (a > 0) if (a > 0)
g (a, 3.1); g (a, 3.1);
...@@ -28,8 +28,9 @@ int main () ...@@ -28,8 +28,9 @@ int main ()
} }
/* { dg-final { scan-ipa-dump-times "versioned function" 2 "cp" } } */ /* { dg-final { scan-ipa-dump "Creating a specialized node of f" "cp" } } */
/* { dg-final { scan-ipa-dump "replacing param a with const 7" "cp" } } */ /* { dg-final { scan-ipa-dump "replacing param a with const 7" "cp" } } */
/* { dg-final { scan-ipa-dump "Creating a specialized node of g" "cp" } } */
/* { dg-final { scan-ipa-dump "replacing param b with const 7" "cp" } } */ /* { dg-final { scan-ipa-dump "replacing param b with const 7" "cp" } } */
/* { dg-final { scan-ipa-dump "replacing param c with const 3" "cp" } } */ /* { dg-final { scan-ipa-dump "replacing param c with const 3" "cp" } } */
/* { dg-final { cleanup-ipa-dump "cp" } } */ /* { dg-final { cleanup-ipa-dump "cp" } } */
...@@ -25,6 +25,6 @@ int main () ...@@ -25,6 +25,6 @@ int main ()
} }
/* { dg-final { scan-ipa-dump-times "versioned function" 1 "cp" } } */ /* { dg-final { scan-ipa-dump "Creating a specialized node of f" "cp" } } */
/* { dg-final { scan-ipa-dump-times "replacing param a with const 7" 1 "cp" } } */ /* { dg-final { scan-ipa-dump-times "replacing param a with const 7" 1 "cp" } } */
/* { dg-final { cleanup-ipa-dump "cp" } } */ /* { dg-final { cleanup-ipa-dump "cp" } } */
...@@ -26,8 +26,7 @@ int main () ...@@ -26,8 +26,7 @@ int main ()
return 0; return 0;
} }
/* { dg-final { scan-ipa-dump-times "Creating a specialized node" 2 "cp" } } */
/* { dg-final { scan-ipa-dump-times "versioned function" 2 "cp" } } */
/* { dg-final { scan-ipa-dump "replacing param c with const 3" "cp" } } */ /* { dg-final { scan-ipa-dump "replacing param c with const 3" "cp" } } */
/* { dg-final { scan-ipa-dump "replacing param a with const 7" "cp" } } */ /* { dg-final { scan-ipa-dump "replacing param a with const 7" "cp" } } */
/* { dg-final { cleanup-ipa-dump "cp" } } */ /* { dg-final { cleanup-ipa-dump "cp" } } */
...@@ -26,8 +26,8 @@ int main () ...@@ -26,8 +26,8 @@ int main ()
} }
/* { dg-final { scan-ipa-dump-times "versioned function" 1 "cp" } } */ /* { dg-final { scan-ipa-dump "Creating a specialized node of f" "cp" } } */
/* { dg-final { scan-ipa-dump-times "replacing param a with const 7" 1 "cp" } } */ /* { dg-final { scan-ipa-dump-times "replacing param . with const 7" 1 "cp" } } */
/* { dg-final { cleanup-ipa-dump "cp" } } */ /* { dg-final { cleanup-ipa-dump "cp" } } */
...@@ -22,8 +22,9 @@ int main () ...@@ -22,8 +22,9 @@ int main ()
} }
/* { dg-final { scan-ipa-dump-times "versioned function" 2 "cp" } } */ /* { dg-final { scan-ipa-dump "Creating a specialized node of f" "cp" } } */
/* { dg-final { scan-ipa-dump "replacing param a with const 7" "cp" } } */ /* { dg-final { scan-ipa-dump "replacing param a with const 7" "cp" } } */
/* { dg-final { scan-ipa-dump "Creating a specialized node of g" "cp" } } */
/* { dg-final { scan-ipa-dump "replacing param b with const 7" "cp" } } */ /* { dg-final { scan-ipa-dump "replacing param b with const 7" "cp" } } */
/* { dg-final { cleanup-ipa-dump "cp" } } */ /* { dg-final { cleanup-ipa-dump "cp" } } */
......
...@@ -51,10 +51,10 @@ main() ...@@ -51,10 +51,10 @@ main()
i_can_not_be_propagated_fully2 (array); i_can_not_be_propagated_fully2 (array);
} }
/* { dg-final { scan-ipa-dump-times "versioned function i_can_be_propagated_fully2" 1 "cp" } } */ /* { dg-final { scan-ipa-dump-times "Creating a specialized node of i_can_be_propagated_fully2" 1 "cp" } } */
/* { dg-final { scan-ipa-dump-times "versioned function i_can_be_propagated_fully " 1 "cp" } } */ /* { dg-final { scan-ipa-dump-times "Creating a specialized node of i_can_be_propagated_fully/" 1 "cp" } } */
/* { dg-final { scan-ipa-dump-not "versioned function i_can_not_be_propagated_fully2" "cp" } } */ /* { dg-final { scan-ipa-dump-not "Creating a specialized node of i_can_not_be_propagated_fully2" "cp" } } */
/* { dg-final { scan-ipa-dump-not "versioned function i_can_not_be_propagated_fully " "cp" } } */ /* { dg-final { scan-ipa-dump-not "Creating a specialized node of i_can_not_be_propagated_fully/" "cp" } } */
/* { dg-final { scan-tree-dump-not "i_can_be_propagated_fully " "optimized" } } */ /* { dg-final { scan-tree-dump-not "i_can_be_propagated_fully " "optimized" } } */
/* { dg-final { scan-tree-dump-not "i_can_be_propagated_fully2 " "optimized" } } */ /* { dg-final { scan-tree-dump-not "i_can_be_propagated_fully2 " "optimized" } } */
/* { dg-final { cleanup-ipa-dump "cp" } } */ /* { dg-final { cleanup-ipa-dump "cp" } } */
......
...@@ -40,8 +40,23 @@ i_can_not_be_propagated_fully (int *a) ...@@ -40,8 +40,23 @@ i_can_not_be_propagated_fully (int *a)
int int
i_can_not_be_propagated_fully2 (int *a) i_can_not_be_propagated_fully2 (int *a)
{ {
int i;
i_can_not_be_propagated_fully (a); i_can_not_be_propagated_fully (a);
for (i=0;i<50;i++)
{
t(a[i] + 1);
t(a[i+1] + 1);
t(a[i+2] + 1);
t(a[i+3] + 1);
}
i_can_not_be_propagated_fully (a); i_can_not_be_propagated_fully (a);
for (i=0;i<50;i++)
{
t(a[i] + 2);
t(a[i+1] + 2);
t(a[i+2] + 2);
t(a[i+3] + 2);
}
i_can_not_be_propagated_fully (a); i_can_not_be_propagated_fully (a);
} }
main() main()
...@@ -50,15 +65,15 @@ main() ...@@ -50,15 +65,15 @@ main()
i_can_be_propagated_fully2 (array); i_can_be_propagated_fully2 (array);
i_can_be_propagated_fully2 (array); i_can_be_propagated_fully2 (array);
for (i = 0; i < 100; i++) for (i = 0; i < 7; i++)
i_can_not_be_propagated_fully2 (array); i_can_not_be_propagated_fully2 (array);
i_can_not_be_propagated_fully2 (array); i_can_not_be_propagated_fully2 (array);
} }
/* { dg-final { scan-ipa-dump-times "versioned function i_can_be_propagated_fully2" 1 "cp" } } */ /* { dg-final { scan-ipa-dump-times "Creating a specialized node of i_can_be_propagated_fully2" 1 "cp" } } */
/* { dg-final { scan-ipa-dump-times "versioned function i_can_be_propagated_fully " 1 "cp" } } */ /* { dg-final { scan-ipa-dump-times "Creating a specialized node of i_can_be_propagated_fully/" 1 "cp" } } */
/* { dg-final { scan-ipa-dump-times "versioned function i_can_not_be_propagated_fully2" 1 "cp" } } */ /* { dg-final { scan-ipa-dump-not "Creating a specialized node of i_can_not_be_propagated_fully2" "cp" } } */
/* { dg-final { scan-ipa-dump-times "versioned function i_can_not_be_propagated_fully " 1 "cp" } } */ /* { dg-final { scan-ipa-dump-not "Creating a specialized node of i_can_not_be_propagated_fully/" "cp" } } */
/* { dg-final { scan-tree-dump-not "i_can_be_propagated_fully \\(" "optimized" } } */ /* { dg-final { scan-tree-dump-not "i_can_be_propagated_fully \\(" "optimized" } } */
/* { dg-final { scan-tree-dump-not "i_can_be_propagated_fully2 \\(" "optimized" } } */ /* { dg-final { scan-tree-dump-not "i_can_be_propagated_fully2 \\(" "optimized" } } */
/* { dg-final { cleanup-ipa-dump "cp" } } */ /* { dg-final { cleanup-ipa-dump "cp" } } */
......
/* Test that IPA-CP is able to figure out that poth parameters a are constant 7
even though f and h recursively call each other and specialize them
accordinly. */
/* { dg-do compile } */
/* { dg-options "-O3 -fipa-cp -fipa-cp-clone -fdump-ipa-cp -fno-early-inlining" } */
/* { dg-add-options bind_pic_locally } */
extern void use_stuff (int);
static
int g (int b, int c)
{
int i;
for (i = 0; i < b; i++)
use_stuff (c);
}
static void f (int a, int x, int z);
static void h (int z, int a)
{
use_stuff (z);
f (a, 9, 10);
}
static void
f (int a, int x, int z)
{
if (z > 1)
g (a, x);
else
h (5, a);
}
int
main (int argc, char *argv[])
{
int i;
for (i = 0; i < 100; i++)
f (7, 8, argc);
return 0;
}
/* { dg-final { scan-ipa-dump "Creating a specialized node of f.*for all known contexts" "cp" } } */
/* { dg-final { scan-ipa-dump "replacing param a with const 7" "cp" } } */
/* { dg-final { cleanup-ipa-dump "cp" } } */
/* { dg-do compile } */
/* { dg-options "-O3 -fipa-cp -fipa-cp-clone -fdump-ipa-cp -fno-early-inlining" } */
/* { dg-add-options bind_pic_locally } */
extern int get_stuff (int);
extern void do_stuff (int);
extern void do_stuff2 (int);
extern void do_other_stuff (void);
extern int get_element (int, int, int);
extern int adjust (int, int, int, int);
extern int count;
int
foo (int s, int p)
{
int c, r = 0;
for (c = 0 ; c < count; c++)
{
r += get_stuff (s);
/* The following is just something big that can go away. */
if (p != 0)
{
int a[64][64];
int i, j, k;
for (i = 0; i < 64; i++)
for (j = 0; j < 64; j++)
a[i][j] = get_element (p + c, i, j);
for (k = 0; k < 4; k++)
{
r = r / 2;
for (i = 1; i < 63; i++)
for (j = 62; j > 0; j--)
a[i][j] += adjust (a[i-1][j], a[i][j-1],
a[i+1][j], a[i][j+1]);
for (i = 4; i < 64; i += 4)
for (j = 4; j < 64; j += 4)
r += a[i][j] / 4;
}
}
}
return r;
}
int
bar (int p, int q)
{
if (q > 0)
do_stuff (q);
else
do_stuff (-q);
if (q % 2)
do_stuff2 (2 * q);
else
do_stuff2 (2 * (q + 1));
return foo (4, p);
}
int
bah (int p, int q)
{
int i, j;
while (q < -20)
q += get_stuff (-q);
for (i = 0; i < 36; i++)
for (j = 0; j < 36; j++)
do_stuff (get_stuff (q * i + 2));
bar (p, q);
}
int
top1 (int q)
{
do_other_stuff ();
return bah (0, q);
}
int
top2 (int q)
{
do_stuff (200);
do_other_stuff ();
return bah (16, q);
}
/* { dg-final { scan-ipa-dump-times "Creating a specialized node of foo" 1 "cp" } } */
/* { dg-final { scan-ipa-dump-times "replacing param p with const 0" 3 "cp" } } */
/* { dg-final { scan-ipa-dump "replacing param s with const 4" "cp" } } */
/* { dg-final { cleanup-ipa-dump "cp" } } */
...@@ -5,9 +5,13 @@ ...@@ -5,9 +5,13 @@
int int
very_long_function(int a) very_long_function(int a)
{ {
return very_long_function (a)/4; if (a > 0)
return 2 * a + very_long_function (a)/4;
else
return 2 * -a + very_long_function (a)/4;
} }
main()
blah ()
{ {
very_long_function (1); very_long_function (1);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment