From patchwork Fri Sep 13 14:48:06 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Hubicka X-Patchwork-Id: 274791 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id B8AFE2C0159 for ; Sat, 14 Sep 2013 00:48:20 +1000 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:mime-version:content-type; q=dns; s= default; b=acrVbv/drHJnKxsnqTk/OzOZYEcIgVIPOwUzWvNF7G7PQqXjNz+V0 fFFMfzSoHOqGmcSrK2zhNSvV1pEZ4snPCyrPorURUwAXPk/Hza7ir2DtOxHk4G1s R1RooAPqsXe1lH3JTa5PUfnZSrbCoWZYtLHTbVdA46gh7q4nR//JHg= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:mime-version:content-type; s= default; bh=Zoah8BQJTdax9mtLnqQWa4EmaoA=; b=WgEipin+58zeUnUoNqsq iJeGU1t3X952Gq4AD7diqeDBKNb0K6iIfFFYIcnThLU1jGJOgpsIfN1KXpm0wSKw g8DLpIGCgAO2uuqvq1w1j+lDvXlXX/czX34YO7Izdj5b/47+m33WDrga2v74m4dg 9NXr9c94dOJMTwfzztZOWM4= Received: (qmail 4737 invoked by alias); 13 Sep 2013 14:48:12 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 4724 invoked by uid 89); 13 Sep 2013 14:48:11 -0000 Received: from nikam.ms.mff.cuni.cz (HELO nikam.ms.mff.cuni.cz) (195.113.20.16) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-SHA encrypted) ESMTPS; Fri, 13 Sep 2013 14:48:11 +0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.8 required=5.0 tests=AWL, BAYES_00, NO_RELAYS autolearn=ham version=3.3.2 X-HELO: nikam.ms.mff.cuni.cz Received: by nikam.ms.mff.cuni.cz (Postfix, from userid 16202) id DCA95543CD8; Fri, 13 Sep 2013 16:48:06 +0200 (CEST) Date: Fri, 13 Sep 2013 16:48:06 +0200 From: Jan Hubicka To: gcc-patches@gcc.gnu.org Subject: Expand Gimple thunks early Message-ID: <20130913144806.GA7148@kam.mff.cuni.cz> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.20 (2009-06-14) Hi, with improvements on devirtualization side, the thunks are getting more problematic for optimizers. Inliner won't inline them, profiling won't instrument them and there are other places where they bock optimization. This patch solves part of the problem by making gimple thunks to go same way as regular functions. I will cleanup the code and work on getting asm thunks inlined incrementally. This patch also makes it possible for functions to be created in SSA form by making init_datastructures and into_ssa passes to gate themself out when function is in SSA already. I suppose in future we may want to have other places that produce SSA functions themselves intead of going throught he into-ssa path. Bootstrapped/regtested x86_64-linux, will commit it later this weekend after testing on pcc64 too if there are no complains. Honza * tree-into-ssa.c (gate_into_ssa): New. (pass_data_build_ssa): Use it. * cgraph.h (expand_thunk): Update prototype. * cgraphunit.c (analyze_function): Expand thunks early. (expand_thunk): Fix DECL_CONTEXT of reust_decl; build proper cgraph; set in_ssa_p; clear bogus TREE_ASM_WRITTEN; set lowered flag; do not add new function. (assemble_thunks_and_aliases): Update. * tree-ssa.c (gate_init_datastructures): New gate. (pass_data_init_datastructures): Use it. Index: tree-into-ssa.c =================================================================== --- tree-into-ssa.c (revision 202565) +++ tree-into-ssa.c (working copy) @@ -2409,6 +2409,14 @@ rewrite_into_ssa (void) return 0; } +/* Gate for IPCP optimization. */ + +static bool +gate_into_ssa (void) +{ + /* Do nothing for funcions that was produced already in SSA form. */ + return !(cfun->curr_properties & PROP_ssa); +} namespace { @@ -2417,7 +2425,7 @@ const pass_data pass_data_build_ssa = GIMPLE_PASS, /* type */ "ssa", /* name */ OPTGROUP_NONE, /* optinfo_flags */ - false, /* has_gate */ + true, /* has_gate */ true, /* has_execute */ TV_TREE_SSA_OTHER, /* tv_id */ PROP_cfg, /* properties_required */ @@ -2435,6 +2443,7 @@ public: {} /* opt_pass methods: */ + bool gate () { return gate_into_ssa (); } unsigned int execute () { return rewrite_into_ssa (); } }; // class pass_build_ssa Index: cgraph.h =================================================================== --- cgraph.h (revision 202565) +++ cgraph.h (working copy) @@ -757,7 +757,7 @@ void fixup_same_cpp_alias_visibility (sy IN_SSA is true if the gimple is in SSA. */ basic_block init_lowered_empty_function (tree, bool); void cgraph_reset_node (struct cgraph_node *); -void expand_thunk (struct cgraph_node *); +bool expand_thunk (struct cgraph_node *, bool); /* In cgraphclones.c */ Index: cgraphunit.c =================================================================== --- cgraphunit.c (revision 202565) +++ cgraphunit.c (working copy) @@ -592,15 +592,21 @@ analyze_function (struct cgraph_node *no location_t saved_loc = input_location; input_location = DECL_SOURCE_LOCATION (decl); - if (node->symbol.alias) - symtab_resolve_alias - ((symtab_node) node, (symtab_node) cgraph_get_node (node->symbol.alias_target)); - else if (node->thunk.thunk_p) + if (node->thunk.thunk_p) { cgraph_create_edge (node, cgraph_get_node (node->thunk.alias), - NULL, 0, CGRAPH_FREQ_BASE); + NULL, 0, CGRAPH_FREQ_BASE); + if (!expand_thunk (node, false)) + { + node->thunk.alias = NULL; + node->symbol.analyzed = true; + return; + } node->thunk.alias = NULL; } + if (node->symbol.alias) + symtab_resolve_alias + ((symtab_node) node, (symtab_node) cgraph_get_node (node->symbol.alias_target)); else if (node->dispatcher_function) { /* Generate the dispatcher body of multi-versioned functions. */ @@ -1432,10 +1438,12 @@ thunk_adjust (gimple_stmt_iterator * bsi return ret; } -/* Produce assembler for thunk NODE. */ +/* Expand thunk NODE to gimple if possible. + When OUTPUT_ASM_THUNK is true, also produce assembler for + thunks that are not lowered. */ -void -expand_thunk (struct cgraph_node *node) +bool +expand_thunk (struct cgraph_node *node, bool output_asm_thunks) { bool this_adjusting = node->thunk.this_adjusting; HOST_WIDE_INT fixed_offset = node->thunk.fixed_offset; @@ -1445,14 +1453,6 @@ expand_thunk (struct cgraph_node *node) tree thunk_fndecl = node->symbol.decl; tree a; - if (in_lto_p) - cgraph_get_body (node); - a = DECL_ARGUMENTS (thunk_fndecl); - - current_function_decl = thunk_fndecl; - - /* Ensure thunks are emitted in their correct sections. */ - resolve_unique_section (thunk_fndecl, 0, flag_function_sections); if (this_adjusting && targetm.asm_out.can_output_mi_thunk (thunk_fndecl, fixed_offset, @@ -1461,10 +1461,23 @@ expand_thunk (struct cgraph_node *node) const char *fnname; tree fn_block; tree restype = TREE_TYPE (TREE_TYPE (thunk_fndecl)); + + if (!output_asm_thunks) + return false; + + if (in_lto_p) + cgraph_get_body (node); + a = DECL_ARGUMENTS (thunk_fndecl); + current_function_decl = thunk_fndecl; + + /* Ensure thunks are emitted in their correct sections. */ + resolve_unique_section (thunk_fndecl, 0, flag_function_sections); + DECL_RESULT (thunk_fndecl) = build_decl (DECL_SOURCE_LOCATION (thunk_fndecl), RESULT_DECL, 0, restype); + DECL_CONTEXT (DECL_RESULT (thunk_fndecl)) = thunk_fndecl; fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk_fndecl)); /* The back end expects DECL_INITIAL to contain a BLOCK, so we @@ -1506,6 +1519,15 @@ expand_thunk (struct cgraph_node *node) gimple call; gimple ret; + if (in_lto_p) + cgraph_get_body (node); + a = DECL_ARGUMENTS (thunk_fndecl); + + current_function_decl = thunk_fndecl; + + /* Ensure thunks are emitted in their correct sections. */ + resolve_unique_section (thunk_fndecl, 0, flag_function_sections); + DECL_IGNORED_P (thunk_fndecl) = 1; bitmap_obstack_initialize (NULL); @@ -1520,6 +1542,7 @@ expand_thunk (struct cgraph_node *node) DECL_ARTIFICIAL (resdecl) = 1; DECL_IGNORED_P (resdecl) = 1; DECL_RESULT (thunk_fndecl) = resdecl; + DECL_CONTEXT (DECL_RESULT (thunk_fndecl)) = thunk_fndecl; } else resdecl = DECL_RESULT (thunk_fndecl); @@ -1556,6 +1579,7 @@ expand_thunk (struct cgraph_node *node) for (i = 1, arg = DECL_CHAIN (a); i < nargs; i++, arg = DECL_CHAIN (arg)) vargs.quick_push (arg); call = gimple_build_call_vec (build_fold_addr_expr_loc (0, alias), vargs); + node->callees->call_stmt = call; vargs.release (); gimple_call_set_from_thunk (call, true); if (restmp) @@ -1624,6 +1648,9 @@ expand_thunk (struct cgraph_node *node) remove_edge (single_succ_edge (bb)); } + cfun->gimple_df->in_ssa_p = true; + /* FIXME: C++ FE should stop setting TREE_ASM_WRITTEN on thunks. */ + TREE_ASM_WRITTEN (thunk_fndecl) = false; delete_unreachable_blocks (); update_ssa (TODO_update_ssa); #ifdef ENABLE_CHECKING @@ -1633,12 +1660,12 @@ expand_thunk (struct cgraph_node *node) /* Since we want to emit the thunk, we explicitly mark its name as referenced. */ node->thunk.thunk_p = false; - rebuild_cgraph_edges (); - cgraph_add_new_function (thunk_fndecl, true); + node->lowered = true; bitmap_obstack_release (NULL); } current_function_decl = NULL; set_cfun (NULL); + return true; } /* Assemble thunks and aliases associated to NODE. */ @@ -1657,7 +1684,7 @@ assemble_thunks_and_aliases (struct cgra e = e->next_caller; assemble_thunks_and_aliases (thunk); - expand_thunk (thunk); + expand_thunk (thunk, true); } else e = e->next_caller; Index: tree-ssa.c =================================================================== --- tree-ssa.c (revision 202565) +++ tree-ssa.c (working copy) @@ -1084,10 +1084,19 @@ static unsigned int execute_init_datastructures (void) { /* Allocate hash tables, arrays and other structures. */ init_tree_ssa (cfun); return 0; } +/* Gate for IPCP optimization. */ + +static bool +gate_init_datastructures (void) +{ + /* Do nothing for funcions that was produced already in SSA form. */ + return !(cfun->curr_properties & PROP_ssa); +} + namespace { const pass_data pass_data_init_datastructures = @@ -1095,7 +1105,7 @@ const pass_data pass_data_init_datastruc GIMPLE_PASS, /* type */ "*init_datastructures", /* name */ OPTGROUP_NONE, /* optinfo_flags */ - false, /* has_gate */ + true, /* has_gate */ true, /* has_execute */ TV_NONE, /* tv_id */ PROP_cfg, /* properties_required */ @@ -1113,6 +1123,7 @@ public: {} /* opt_pass methods: */ + bool gate () { return gate_init_datastructures (); } unsigned int execute () { return execute_init_datastructures (); } }; // class pass_init_datastructures