From patchwork Mon Sep 23 12:59:17 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Hubicka X-Patchwork-Id: 277169 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 1E8072C011A for ; Mon, 23 Sep 2013 22:59:30 +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=JxuUthTovIGQEkuEXYtUh4xjEpnDogw50zue1X4N689k15f5E5FKX 53J8O3f7tVHA1aFg8rSz9IKxFjKHjYhDOG1l1FFMSKEKBeaJ20cE4oWnX/XN8e1P Q7QTT4U/ny9qyy9oTpgpwXA1rMd9pPt12z+hmWBar+i5DlzuEh359A= 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=BMeOhyUrSEkMIqF0KTXDyk19gak=; b=aTQSSRM6uQznDKpQTzLr F/Cul6K9bRarqMVfowpMCgwoyDXFjh8534fBcnPjLjHYHYexoiTAwO9nwZBThY30 fTocJDDeNsw8k1bA/PcFSZIGEa0eWiO0SLHGlHnLcpLe1iC3aygw7sv1ciL7vFA+ CotP94rWamZwTFVlB9IM5tA= Received: (qmail 14100 invoked by alias); 23 Sep 2013 12:59:23 -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 14087 invoked by uid 89); 23 Sep 2013 12:59:22 -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; Mon, 23 Sep 2013 12:59:22 +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 83D5D543065; Mon, 23 Sep 2013 14:59:17 +0200 (CEST) Date: Mon, 23 Sep 2013 14:59:17 +0200 From: Jan Hubicka To: gcc-patches@gcc.gnu.org, jason@redhat.com, mjambor@suse.cz Subject: Type inheritance graph analysis & speculative devirtualization, part 4/7 (the verifier) Message-ID: <20130923125917.GA21510@kam.mff.cuni.cz> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.20 (2009-06-14) Hi, this is the last patch of the series. This patch adds sanity check that all devirtualizations are among ones predicted by possible_polymorphic_call_targets. This sanity check was very useful to chase out numberous problems in this area. The patch check the type based devirtualization to go in the directions predicted, but it also reality checks agains folding based devirt. In my tree I use gcc_assert. I turned it into dump only, since i think it is matter of time until someone construct type inconsistent testcase that uses virtual table of completely incompatible class to resolve the call. I was thinking about making this a warning, but I am not sure how useful it would be (except for my sanity check) and whether we would not run into problems with fase positives on specialized code pretty much as we do with all the backend warnings. So for now i am just dumping and will keep it an assert in my local tree. I am still not enabling the check in full strength - we build type inheritance graph based on defined methods in the unit. We however ignore types that has only external methods and thus it is possible that new external calls will be discovered. This is solved by an incremental patch. Bootstrapped/regtested x86_64-linux, will commit it shortly. Honza * ipa-cp.c (ipa_get_indirect_edge_target_1): Add sanity check for ipa-devirt. * ipa-utils.h (possible_polymorphic_call_target_p): New function. * ipa-devirt.c (possible_polymorphic_call_target_p): Be tolerant of external calls * gimple-fold.c: Include ipa-utils.h and gimple-pretty-print.h (gimple_fold_call): Dump inconsistent devirtualizations; add sanity check for type based devirtualizations. * ipa-prop.c: Include ipa-utils.h (ipa_intraprocedural_devirtualization): Add sanity check. (try_make_edge_direct_virtual_call): Likewise. Index: ipa-cp.c =================================================================== --- ipa-cp.c (revision 202812) +++ ipa-cp.c (working copy) @@ -1484,6 +1484,7 @@ ipa_get_indirect_edge_target_1 (struct c HOST_WIDE_INT token, anc_offset; tree otr_type; tree t; + tree target; if (param_index == -1 || known_vals.length () <= (unsigned int) param_index) @@ -1552,7 +1553,7 @@ ipa_get_indirect_edge_target_1 (struct c binfo = get_binfo_at_offset (binfo, anc_offset, otr_type); if (!binfo) return NULL_TREE; - return gimple_get_virt_method_for_binfo (token, binfo); + target = gimple_get_virt_method_for_binfo (token, binfo); } else { @@ -1561,8 +1562,15 @@ ipa_get_indirect_edge_target_1 (struct c binfo = get_binfo_at_offset (t, anc_offset, otr_type); if (!binfo) return NULL_TREE; - return gimple_get_virt_method_for_binfo (token, binfo); + target = gimple_get_virt_method_for_binfo (token, binfo); } +#ifdef ENABLE_CHECKING + if (target) + gcc_assert (possible_polymorphic_call_target_p + (ie, cgraph_get_node (target))); +#endif + + return target; } Index: ipa-utils.h =================================================================== --- ipa-utils.h (revision 202812) +++ ipa-utils.h (working copy) @@ -108,6 +108,19 @@ possible_polymorphic_call_target_p (stru return possible_polymorphic_call_target_p (e->indirect_info->otr_type, e->indirect_info->otr_token, n); } + +/* Return true if N can be possibly target of a polymorphic call of + OBJ_TYPE_REF expression CALL. */ + +inline bool +possible_polymorphic_call_target_p (tree call, + struct cgraph_node *n) +{ + return possible_polymorphic_call_target_p (obj_type_ref_class (call), + tree_low_cst + (OBJ_TYPE_REF_TOKEN (call), 1), + n); +} #endif /* GCC_IPA_UTILS_H */ Index: ipa-devirt.c =================================================================== --- ipa-devirt.c (revision 202812) +++ ipa-devirt.c (working copy) @@ -905,13 +905,19 @@ possible_polymorphic_call_target_p (tree { vec targets; unsigned int i; + bool final; if (!odr_hash.is_created ()) return true; - targets = possible_polymorphic_call_targets (otr_type, otr_token); + targets = possible_polymorphic_call_targets (otr_type, otr_token, &final); for (i = 0; i < targets.length (); i++) if (n == targets[i]) return true; + + /* At a moment we allow middle end to dig out new external declarations + as a targets of polymorphic calls. */ + if (!final && !n->symbol.definition) + return true; return false; } Index: gimple-fold.c =================================================================== --- gimple-fold.c (revision 202812) +++ gimple-fold.c (working copy) @@ -30,6 +30,8 @@ along with GCC; see the file COPYING3. #include "tree-ssa-propagate.h" #include "target.h" #include "gimple-fold.h" +#include "ipa-utils.h" +#include "gimple-pretty-print.h" /* Return true when DECL can be referenced from current unit. FROM_DECL (if non-null) specify constructor of variable DECL was taken from. @@ -1116,6 +1118,19 @@ gimple_fold_call (gimple_stmt_iterator * { if (gimple_call_addr_fndecl (OBJ_TYPE_REF_EXPR (callee)) != NULL_TREE) { + if (dump_file && virtual_method_call_p (callee) + && !possible_polymorphic_call_target_p + (callee, cgraph_get_node (gimple_call_addr_fndecl + (OBJ_TYPE_REF_EXPR (callee))))) + { + fprintf (dump_file, + "Type inheritnace inconsistent devirtualization of "); + print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM); + fprintf (dump_file, " to "); + print_generic_expr (dump_file, callee, TDF_SLIM); + fprintf (dump_file, "\n"); + } + gimple_call_set_fn (stmt, OBJ_TYPE_REF_EXPR (callee)); changed = true; } @@ -1131,6 +1146,11 @@ gimple_fold_call (gimple_stmt_iterator * tree fndecl = gimple_get_virt_method_for_binfo (token, binfo); if (fndecl) { +#ifdef ENABLE_CHECKING + gcc_assert (possible_polymorphic_call_target_p + (callee, cgraph_get_node (fndecl))); + +#endif gimple_call_set_fndecl (stmt, fndecl); changed = true; } Index: ipa-prop.c =================================================================== --- ipa-prop.c (revision 202812) +++ ipa-prop.c (working copy) @@ -38,6 +38,7 @@ along with GCC; see the file COPYING3. #include "data-streamer.h" #include "tree-streamer.h" #include "params.h" +#include "ipa-utils.h" /* Intermediate information about a parameter that is only useful during the run of ipa_analyze_node and is not kept afterwards. */ @@ -2196,6 +2197,11 @@ ipa_intraprocedural_devirtualization (gi token = OBJ_TYPE_REF_TOKEN (otr); fndecl = gimple_get_virt_method_for_binfo (tree_low_cst (token, 1), binfo); +#ifdef ENABLE_CHECKING + if (fndecl) + gcc_assert (possible_polymorphic_call_target_p + (otr, cgraph_get_node (fndecl))); +#endif return fndecl; } @@ -2651,7 +2657,13 @@ try_make_edge_direct_virtual_call (struc return NULL; if (target) - return ipa_make_edge_direct_to_target (ie, target); + { +#ifdef ENABLE_CHECKING + gcc_assert (possible_polymorphic_call_target_p + (ie, cgraph_get_node (target))); +#endif + return ipa_make_edge_direct_to_target (ie, target); + } else return NULL; }