From patchwork Fri Oct 3 04:16:54 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Hubicka X-Patchwork-Id: 396144 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.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 8726F140187 for ; Fri, 3 Oct 2014 14:17:11 +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=Gfv95ZSxnkv5cywqz44dewO8DiCruYg42FWmXRvcO/eAcQGAn6fH9 cfOHFVPKjwXgQuDSqNZQUXaRn7+jyax3OHjZKtUxcwJDw2RQEdJk9jeLiL3yXks+ 2c5Kg9kHVJz39dJeHjB/r2/e6otUw9IViX75ixBYuCOItGGMHw6qeg= 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=lW4BUjn8RFLJV0++oEcFrElH/R8=; b=MDK0ZY+4PZxgNJlxl1wK WeERqtfsa5jl3Fo0Sa2tS/B+1MGHWw8KUQMjtyzuXA91rCPT0mL/VCwa2sXX7Rsb gS5qvRtCE9AlCZJVV2BKeunb7nqhvjkge597qLBQAfIbET5K/fuU7mTfP6T54QqP UCPubAK+fBiAs2l+UVJJc9M= Received: (qmail 21082 invoked by alias); 3 Oct 2014 04:17:00 -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 21072 invoked by uid 89); 3 Oct 2014 04:16:59 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.6 required=5.0 tests=AWL, BAYES_00, RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-HELO: nikam.ms.mff.cuni.cz 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-GCM-SHA384 encrypted) ESMTPS; Fri, 03 Oct 2014 04:16:58 +0000 Received: by nikam.ms.mff.cuni.cz (Postfix, from userid 16202) id 023E85444F8; Fri, 3 Oct 2014 06:16:54 +0200 (CEST) Date: Fri, 3 Oct 2014 06:16:54 +0200 From: Jan Hubicka To: gcc-patches@gcc.gnu.org, mjambor@suse.cz Subject: Add dynamic flag into polymorphic call context Message-ID: <20141003041654.GB21871@kam.mff.cuni.cz> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) Hi, this patch adds very basic logic for tracking dynamic wrt static types. Basically it intoruced field DYNAMIC that specify if context represent static storage or type found by get_dynamic_type. Static storage is stronger in a way that we know its size (I do not track at all for dynamic types) and we make assumption that user are not going to placement new it to completely different data type (it is allowed to destroy it and re-construct by hand before it is destroyed again at the end of static storage lifetime) Bootstrapped/regtested x86_64-linux, will comit it shortly (after working out the Ada bootstrap issue I caused). Honza * cgraph.h (ipa_polymorphic_call_context): Turn bools into bitfields; add DYNAMIC; make MAKE_SPECULATIVE private, add POSSIBLE_DYNAMIC_TYPE_CHANGE. * ipa-polymorphic-call.c (ipa_polymorphic_call_context::restrict_to_inner_class): Allow accesses past end of dynamic types. (ipa_polymorphic_call_context::stream_out, speculative_outer_type): Stream dynamic flag. (ipa_polymorphic_call_context::set_by_decl): Clear DYNAMIC. (ipa_polymorphic_call_context::ipa_polymorphic_call_context): Clear DYNAMIC. (ipa_polymorphic_call_context::get_dynamic_type): Use DYNAMIC; set it. (ipa_polymorphic_call_context::combine_with): Propagate dynamic. * ipa-prop.c (update_jump_functions_after_inlining, try_make_edge_direct_virtual_call): Use possible_dynamic_type_change. Index: cgraph.h =================================================================== --- cgraph.h (revision 215817) +++ cgraph.h (working copy) @@ -1281,15 +1281,17 @@ public: tree outer_type; tree speculative_outer_type; /* True if outer object may be in construction or destruction. */ - bool maybe_in_construction; + unsigned maybe_in_construction : 1; /* True if outer object may be of derived type. */ - bool maybe_derived_type; + unsigned maybe_derived_type : 1; /* True if speculative outer object may be of derived type. We always speculate that construction does not happen. */ - bool speculative_maybe_derived_type; + unsigned speculative_maybe_derived_type : 1; /* True if the context is invalid and all calls should be redirected to BUILTIN_UNREACHABLE. */ - bool invalid; + unsigned invalid : 1; + /* True if the outer type is dynamic. */ + unsigned dynamic : 1; /* Build empty "I know nothing" context. */ ipa_polymorphic_call_context (); @@ -1329,12 +1331,9 @@ public: /* Adjust all offsets in contexts by given number of bits. */ void offset_by (HOST_WIDE_INT); - /* Take non-speculative info, merge it with speculative and clear speculatoin. - Used when we no longer manage to keep track of actual outer type, but we - think it is still there. - If OTR_TYPE is set, the transformation can be done more effectively assuming - that context is going to be used only that way. */ - void make_speculative (tree otr_type = NULL); + /* Use when we can not track dynamic type change. This speculatively assume + type change is not happening. */ + void possible_dynamic_type_change (tree otr_type = NULL); /* Assume that both THIS and a given context is valid and strenghten THIS if possible. Return true if any strenghtening was made. If actual type the context is being used in is known, OTR_TYPE should be @@ -1358,6 +1357,7 @@ private: bool set_by_invariant (tree, tree, HOST_WIDE_INT); void clear_outer_type (tree otr_type = NULL); bool speculation_consistent_p (tree, HOST_WIDE_INT, bool, tree); + void make_speculative (tree otr_type = NULL); }; /* Structure containing additional information about an indirect call. */ @@ -2662,6 +2662,7 @@ ipa_polymorphic_call_context::clear_oute offset = 0; maybe_derived_type = true; maybe_in_construction = true; + dynamic = true; } /* Adjust all offsets in contexts by OFF bits. */ Index: ipa-polymorphic-call.c =================================================================== --- ipa-polymorphic-call.c (revision 215817) +++ ipa-polymorphic-call.c (working copy) @@ -167,8 +167,11 @@ ipa_polymorphic_call_context::restrict_t type = otr_type; cur_offset = 0; - /* If derived type is not allowed, we know that the context is invalid. */ - if (!maybe_derived_type) + /* If derived type is not allowed, we know that the context is invalid. + For dynamic types, we really do not have information about + size of the memory location. It is possible that completely + different type is stored after outer_type. */ + if (!maybe_derived_type && !dynamic) { clear_speculation (); invalid = true; @@ -575,7 +578,7 @@ ipa_polymorphic_call_context::dump (FILE fprintf (f, "nothing known"); if (outer_type || offset) { - fprintf (f, "Outer type:"); + fprintf (f, "Outer type%s:", dynamic ? " (dynamic)":""); print_generic_expr (f, outer_type, TDF_SLIM); if (maybe_derived_type) fprintf (f, " (or a derived type)"); @@ -618,6 +621,7 @@ ipa_polymorphic_call_context::stream_out bp_pack_value (&bp, maybe_in_construction, 1); bp_pack_value (&bp, maybe_derived_type, 1); bp_pack_value (&bp, speculative_maybe_derived_type, 1); + bp_pack_value (&bp, dynamic, 1); bp_pack_value (&bp, outer_type != NULL, 1); bp_pack_value (&bp, offset != 0, 1); bp_pack_value (&bp, speculative_outer_type != NULL, 1); @@ -648,6 +652,7 @@ ipa_polymorphic_call_context::stream_in maybe_in_construction = bp_unpack_value (&bp, 1); maybe_derived_type = bp_unpack_value (&bp, 1); speculative_maybe_derived_type = bp_unpack_value (&bp, 1); + dynamic = bp_unpack_value (&bp, 1); bool outer_type_p = bp_unpack_value (&bp, 1); bool offset_p = bp_unpack_value (&bp, 1); bool speculative_outer_type_p = bp_unpack_value (&bp, 1); @@ -690,6 +695,7 @@ ipa_polymorphic_call_context::set_by_dec get_dynamic_type or decl_maybe_in_construction_p. */ maybe_in_construction = true; maybe_derived_type = false; + dynamic = false; } /* CST is an invariant (address of decl), try to get meaningful @@ -889,6 +895,8 @@ ipa_polymorphic_call_context::ipa_polymo return; } + dynamic = true; + /* If the function is constructor or destructor, then the type is possibly in construction, but we know it is not derived type. */ @@ -1192,6 +1200,7 @@ record_known_type (struct type_change_in context.outer_type = type; context.maybe_in_construction = false; context.maybe_derived_type = false; + context.dynamic = true; /* If we failed to find the inner type, we know that the call would be undefined for type produced here. */ if (!context.restrict_to_inner_class (tci->otr_type)) @@ -1540,6 +1549,7 @@ ipa_polymorphic_call_context::get_dynami if (!tci.type_maybe_changed || (outer_type + && !dynamic && !tci.seen_unanalyzed_store && !tci.multiple_types_encountered && offset == tci.offset @@ -1563,6 +1573,7 @@ ipa_polymorphic_call_context::get_dynami { outer_type = TYPE_MAIN_VARIANT (tci.known_current_type); offset = tci.known_current_offset; + dynamic = true; maybe_in_construction = false; maybe_derived_type = false; if (dump_file) @@ -1792,6 +1803,7 @@ ipa_polymorphic_call_context::combine_wi { outer_type = ctx.outer_type; offset = ctx.offset; + dynamic = ctx.dynamic; maybe_in_construction = ctx.maybe_in_construction; maybe_derived_type = ctx.maybe_derived_type; updated = true; @@ -1822,6 +1834,11 @@ ipa_polymorphic_call_context::combine_wi updated = true; maybe_derived_type = false; } + if (dynamic && !ctx.dynamic) + { + updated = true; + dynamic = false; + } } /* If we know the type precisely, there is not much to improve. */ else if (!maybe_derived_type && !maybe_in_construction @@ -1856,6 +1873,7 @@ ipa_polymorphic_call_context::combine_wi outer_type = ctx.outer_type; maybe_derived_type = ctx.maybe_derived_type; offset = ctx.offset; + dynamic = ctx.dynamic; updated = true; } @@ -1906,6 +1924,7 @@ ipa_polymorphic_call_context::combine_wi maybe_in_construction = ctx.maybe_in_construction; maybe_derived_type = ctx.maybe_derived_type; offset = ctx.offset; + dynamic = ctx.dynamic; updated = true; } } @@ -1952,7 +1971,10 @@ invalidate: /* Take non-speculative info, merge it with speculative and clear speculation. Used when we no longer manage to keep track of actual outer type, but we - think it is still there. */ + think it is still there. + + If OTR_TYPE is set, the transformation can be done more effectively assuming + that context is going to be used only that way. */ void ipa_polymorphic_call_context::make_speculative (tree otr_type) @@ -1975,3 +1997,15 @@ ipa_polymorphic_call_context::make_specu spec_maybe_derived_type, otr_type); } + +/* Use when we can not track dynamic type change. This speculatively assume + type change is not happening. */ + +void +ipa_polymorphic_call_context::possible_dynamic_type_change (tree otr_type) +{ + if (dynamic) + make_speculative (otr_type); + else + maybe_in_construction = true; +} Index: ipa-prop.c =================================================================== --- ipa-prop.c (revision 215817) +++ ipa-prop.c (working copy) @@ -2652,7 +2652,7 @@ update_jump_functions_after_inlining (st /* TODO: Make type preserved safe WRT contexts. */ if (!dst->value.ancestor.agg_preserved) - ctx.make_speculative (); + ctx.possible_dynamic_type_change (); ctx.offset_by (dst->value.ancestor.offset); if (!ctx.useless_p ()) { @@ -2722,7 +2722,7 @@ update_jump_functions_after_inlining (st /* TODO: Make type preserved safe WRT contexts. */ if (!dst->value.ancestor.agg_preserved) - ctx.make_speculative (); + ctx.possible_dynamic_type_change (); if (!ctx.useless_p ()) { if (!dst_ctx) @@ -3128,7 +3128,7 @@ try_make_edge_direct_virtual_call (struc /* TODO: We want to record if type change happens. Old code did not do that that seems like a bug. */ - ctx.make_speculative (ie->indirect_info->otr_type); + ctx.possible_dynamic_type_change (ie->indirect_info->otr_type); updated = ie->indirect_info->context.combine_with (ctx, ie->indirect_info->otr_type);