Hello. Following patch adds support for target and optimization nodes comparison, which is based on Honza's newly added infrastructure.
Apart from that, there's a small hunk that corrects formatting and removes unnecessary call to a comparison function. Hope it can be applied as one patch. Tested on x86_64-linux-pc without any new regression introduction. Ready for trunk? Thank you, Martin
>From 393eaa47c8aef9a91a1c635016f23ca2f5aa25e4 Mon Sep 17 00:00:00 2001 From: mliska <mli...@suse.cz> Date: Tue, 6 Jan 2015 15:06:18 +0100 Subject: [PATCH] IPA ICF: target and optimization flags comparison. gcc/ChangeLog: 2015-01-06 Martin Liska <mli...@suse.cz> * cgraphunit.c (cgraph_node::create_wrapper): Fix level of indentation. * ipa-icf.c (sem_function::equals_private): Add support for target and (sem_item_optimizer::merge_classes): Remove redundant function comparison. optimization flags comparison. * tree.h (target_opts_for_fn): New function. --- gcc/cgraphunit.c | 52 ++++++++++++++++++++++++++-------------------------- gcc/ipa-icf.c | 44 +++++++++++++++++++++++++++++++++++++++++++- gcc/tree.h | 10 ++++++++++ 3 files changed, 79 insertions(+), 27 deletions(-) diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index c8c8562..81246e2 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -2385,40 +2385,40 @@ cgraphunit_c_finalize (void) void cgraph_node::create_wrapper (cgraph_node *target) { - /* Preserve DECL_RESULT so we get right by reference flag. */ - tree decl_result = DECL_RESULT (decl); + /* Preserve DECL_RESULT so we get right by reference flag. */ + tree decl_result = DECL_RESULT (decl); - /* Remove the function's body but keep arguments to be reused - for thunk. */ - release_body (true); - reset (); + /* Remove the function's body but keep arguments to be reused + for thunk. */ + release_body (true); + reset (); - DECL_RESULT (decl) = decl_result; - DECL_INITIAL (decl) = NULL; - allocate_struct_function (decl, false); - set_cfun (NULL); + DECL_RESULT (decl) = decl_result; + DECL_INITIAL (decl) = NULL; + allocate_struct_function (decl, false); + set_cfun (NULL); - /* Turn alias into thunk and expand it into GIMPLE representation. */ - definition = true; - thunk.thunk_p = true; - thunk.this_adjusting = false; + /* Turn alias into thunk and expand it into GIMPLE representation. */ + definition = true; + thunk.thunk_p = true; + thunk.this_adjusting = false; - cgraph_edge *e = create_edge (target, NULL, 0, CGRAPH_FREQ_BASE); + cgraph_edge *e = create_edge (target, NULL, 0, CGRAPH_FREQ_BASE); - tree arguments = DECL_ARGUMENTS (decl); + tree arguments = DECL_ARGUMENTS (decl); - while (arguments) - { - TREE_ADDRESSABLE (arguments) = false; - arguments = TREE_CHAIN (arguments); - } + while (arguments) + { + TREE_ADDRESSABLE (arguments) = false; + arguments = TREE_CHAIN (arguments); + } - expand_thunk (false, true); - e->call_stmt_cannot_inline_p = true; + expand_thunk (false, true); + e->call_stmt_cannot_inline_p = true; - /* Inline summary set-up. */ - analyze (); - inline_analyze_function (this); + /* Inline summary set-up. */ + analyze (); + inline_analyze_function (this); } #include "gt-cgraphunit.h" diff --git a/gcc/ipa-icf.c b/gcc/ipa-icf.c index c7ba75a..28158b3 100644 --- a/gcc/ipa-icf.c +++ b/gcc/ipa-icf.c @@ -427,6 +427,49 @@ sem_function::equals_private (sem_item *item, if (!equals_wpa (item, ignored_nodes)) return false; + /* Checking function TARGET and OPTIMIZATION flags. */ + cl_target_option *tar1 = target_opts_for_fn (decl); + cl_target_option *tar2 = target_opts_for_fn (m_compared_func->decl); + + if (tar1 != NULL || tar2 != NULL) + { + if (!cl_target_option_eq (tar1, tar2)) + { + if (dump_file && (dump_flags & TDF_DETAILS)) + { + fprintf (dump_file, "Source target flags\n"); + cl_target_option_print (dump_file, 2, tar1); + fprintf (dump_file, "Target target flags\n"); + cl_target_option_print (dump_file, 2, tar2); + } + + return return_false_with_msg ("Target flags are different"); + } + } + else if (tar1 != NULL || tar2 != NULL) + return return_false_with_msg ("Target flags are different"); + + cl_optimization *opt1 = opts_for_fn (decl); + cl_optimization *opt2 = opts_for_fn (m_compared_func->decl); + + if (opt1 != NULL && opt2 != NULL) + { + if (memcmp (opt1, opt2, sizeof(cl_optimization))) + { + if (dump_file && (dump_flags & TDF_DETAILS)) + { + fprintf (dump_file, "Source optimization flags\n"); + cl_optimization_print (dump_file, 2, opt1); + fprintf (dump_file, "Target optimization flags\n"); + cl_optimization_print (dump_file, 2, opt2); + } + + return return_false_with_msg ("optimization flags are different"); + } + } + else if (opt1 != NULL || opt2 != NULL) + return return_false_with_msg ("optimization flags are different"); + /* Checking function arguments. */ tree decl1 = DECL_ATTRIBUTES (decl); tree decl2 = DECL_ATTRIBUTES (m_compared_func->decl); @@ -2302,7 +2345,6 @@ sem_item_optimizer::merge_classes (unsigned int prev_class_count) for (unsigned int j = 1; j < c->members.length (); j++) { sem_item *alias = c->members[j]; - source->equals (alias, m_symtab_node_map); if (dump_file) { diff --git a/gcc/tree.h b/gcc/tree.h index 3e74c7e..e9af9bf 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -4671,6 +4671,16 @@ opts_for_fn (const_tree fndecl) return TREE_OPTIMIZATION (fn_opts); } +/* Return pointer to target flags of FNDECL. */ +static inline cl_target_option * +target_opts_for_fn (const_tree fndecl) +{ + tree fn_opts = DECL_FUNCTION_SPECIFIC_TARGET (fndecl); + if (fn_opts == NULL_TREE) + fn_opts = target_option_default_node; + return TREE_TARGET_OPTION (fn_opts); +} + /* opt flag for function FNDECL, e.g. opts_for_fn (fndecl, optimize) is the optimization level of function fndecl. */ #define opt_for_fn(fndecl, opt) (opts_for_fn (fndecl)->x_##opt) -- 2.1.2