From patchwork Thu Apr 14 18:31:32 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 610564 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 3qm8Qd0g1Xz9t3n for ; Fri, 15 Apr 2016 04:31:51 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=hAhWlc5l; dkim-atps=neutral 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:cc:subject:message-id:reply-to:mime-version :content-type; q=dns; s=default; b=jPqNnymHv0Zym33pH/yFiWAakuVk+ IgeNeCfqVp0jOwX1iiQ4vF2+N23XRMrwkFUrhqjio7h/ut+Ckqq6Uc9r4OWjv+hP ktSm2iom9KsrPjZu2ItUKUa/lIgjZtiXFzVN16mW2rhKBQt5d8r7jUfEXw+8WrJn 4qfLbwt9ju5pgo= 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:cc:subject:message-id:reply-to:mime-version :content-type; s=default; bh=sXUkpzOUsbNz7qZBFwEC4XS6eRE=; b=hAh Wlc5llPWsaAPdw/kFTO0QkpX6X9fXQ4Yuwdql77ujkymf9gzzlzAxDWh+slCvFkt 5oG/3c63jVBql2TNRTZTc+xD/QZJKkIDY///dc/lg2t6OQAIGEdjI0vUNSJYx2Ax 8r6w4HgNcy03R0LnbAu530Nv10x9zfVi0WWsKsOg= Received: (qmail 11387 invoked by alias); 14 Apr 2016 18:31:42 -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 11374 invoked by uid 89); 14 Apr 2016 18:31:41 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.9 required=5.0 tests=BAYES_00, KAM_LAZY_DOMAIN_SECURITY, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy=privately X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Thu, 14 Apr 2016 18:31:39 +0000 Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id B2599C084AC0; Thu, 14 Apr 2016 18:31:38 +0000 (UTC) Received: from tucnak.zalov.cz (ovpn-113-22.phx2.redhat.com [10.3.113.22]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u3EIVam5018283 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Thu, 14 Apr 2016 14:31:38 -0400 Received: from tucnak.zalov.cz (localhost [127.0.0.1]) by tucnak.zalov.cz (8.15.2/8.15.2) with ESMTP id u3EIVYb7006070; Thu, 14 Apr 2016 20:31:35 +0200 Received: (from jakub@localhost) by tucnak.zalov.cz (8.15.2/8.15.2/Submit) id u3EIVWN9006069; Thu, 14 Apr 2016 20:31:32 +0200 Date: Thu, 14 Apr 2016 20:31:32 +0200 From: Jakub Jelinek To: Richard Biener , Jan Hubicka Cc: gcc-patches@gcc.gnu.org Subject: [PATCH] Fix -fcompare-debug due to incorrect block pruning (PR c++/70594) Message-ID: <20160414183132.GG19207@tucnak.redhat.com> Reply-To: Jakub Jelinek MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.24 (2015-08-30) X-IsSubscribed: yes Hi! On a testcase Tobias provided privately there is a -fcompare-debug failure due to different cgraph node->order values in the printout. The problem is in different result from the noncall_stmt_may_be_vtbl_ptr_store function on a store, which is caused by too aggressive block pruning with -g0. The noncall_stmt_may_be_vtbl_ptr_store relies on enough BLOCKS to be preserved, such that if block_ultimate_origin of some BLOCK (gimple_block or up through its BLOCK_SUPERCONTEXTs) is a FUNCTION_DECL, then it is a cdtor if the stmt is originally inlined from a cdtor, or is some other FUNCTION_DECL if it is not originally inlined from a cdtor. To achieve that, tree-ssa-live.c attempts to keep the blocks with block_ultimate_origin of FUNCTION_DECL which is cdtor, and nearest block with block_ultimate_origin of FUNCTION_DECL that is not cdtor below the cdtor one. There is: /* For ipa-polymorphic-call.c purposes, preserve blocks: 1) with BLOCK_ABSTRACT_ORIGIN of a ctor/dtor or their clones */ if (inlined_polymorphic_ctor_dtor_block_p (scope, true)) { in_ctor_dtor_block = true; unused = false; } /* 2) inside such blocks, the outermost block with BLOCK_ABSTRACT_ORIGIN being a FUNCTION_DECL. */ else if (in_ctor_dtor_block && BLOCK_ABSTRACT_ORIGIN (scope) && TREE_CODE (BLOCK_ABSTRACT_ORIGIN (scope)) == FUNCTION_DECL) { in_ctor_dtor_block = false; unused = false; } which is roughly right, but there are 2 bugs, both of which affect the testcase I've looked at. 1) the above works well if a non-cdtor function is inlined into cdtor and the cdtor is then inlined into some other function and pruning happens only afterwards, but if a non-cdtor function is inlined into cdtor, then pruning happens on the cdtor, the block with block_ultimate_origin of FUNCTION_DECL can be pruned, and then finally the cdtor function is inlined into some other one and noncall_stmt_may_be_vtbl_ptr_store depends on -g 2) another issue is that noncall_stmt_may_be_vtbl_ptr_store uses block_ultimate_origin, and for the cdtor blocks we use it in remove_unused_scope_block_p too (because inlined_polymorphic_ctor_dtor_block_p calls it), but for the other blocks we just check BLOCK_ABSTRACT_ORIGIN if it is FUNCTION_DECL. If it isn't a FUNCTION_DECL, but block_ultimate_origin is FUNCTION_DECL, we still prune it, even when we shouldn't. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2016-04-14 Jakub Jelinek PR c++/70594 * ipa-utils.h (polymorphic_ctor_dtor_p): New prototype. * ipa-polymorphic-call.c (polymorphic_ctor_dtor_p): New function. (inlined_polymorphic_ctor_dtor_block_p): Use it. * tree-ssa-live.c (remove_unused_scope_block_p): When in_ctor_dtor_block, avoid discarding not just BLOCKs with BLOCK_ABSTRACT_ORIGIN being FUNCTION_DECL, but even when block_ultimate_origin is FUNCTION_DECL. (remove_unused_locals): If current_function_decl is polymorphic_ctor_dtor_p, pass initial true to remove_unused_scope_block_p' is_ctor_dtor_block. Jakub --- gcc/ipa-utils.h.jj 2016-01-04 14:55:51.000000000 +0100 +++ gcc/ipa-utils.h 2016-04-14 16:46:08.828444152 +0200 @@ -70,6 +70,7 @@ void dump_possible_polymorphic_call_targ bool possible_polymorphic_call_target_p (tree, HOST_WIDE_INT, const ipa_polymorphic_call_context &, struct cgraph_node *); +tree polymorphic_ctor_dtor_p (tree, bool); tree inlined_polymorphic_ctor_dtor_block_p (tree, bool); bool decl_maybe_in_construction_p (tree, tree, gimple *, tree); tree vtable_pointer_value_to_binfo (const_tree); --- gcc/ipa-polymorphic-call.c.jj 2016-03-30 16:00:17.000000000 +0200 +++ gcc/ipa-polymorphic-call.c 2016-04-14 16:45:45.407754387 +0200 @@ -479,16 +479,12 @@ contains_type_p (tree outer_type, HOST_W } -/* Return a FUNCTION_DECL if BLOCK represents a constructor or destructor. +/* Return a FUNCTION_DECL if FN represent a constructor or destructor. If CHECK_CLONES is true, also check for clones of ctor/dtors. */ tree -inlined_polymorphic_ctor_dtor_block_p (tree block, bool check_clones) +polymorphic_ctor_dtor_p (tree fn, bool check_clones) { - tree fn = block_ultimate_origin (block); - if (fn == NULL || TREE_CODE (fn) != FUNCTION_DECL) - return NULL_TREE; - if (TREE_CODE (TREE_TYPE (fn)) != METHOD_TYPE || (!DECL_CXX_CONSTRUCTOR_P (fn) && !DECL_CXX_DESTRUCTOR_P (fn))) { @@ -510,6 +506,19 @@ inlined_polymorphic_ctor_dtor_block_p (t return fn; } +/* Return a FUNCTION_DECL if BLOCK represents a constructor or destructor. + If CHECK_CLONES is true, also check for clones of ctor/dtors. */ + +tree +inlined_polymorphic_ctor_dtor_block_p (tree block, bool check_clones) +{ + tree fn = block_ultimate_origin (block); + if (fn == NULL || TREE_CODE (fn) != FUNCTION_DECL) + return NULL_TREE; + + return polymorphic_ctor_dtor_p (fn, check_clones); +} + /* We know that the instance is stored in variable or parameter (not dynamically allocated) and we want to disprove the fact --- gcc/tree-ssa-live.c.jj 2016-01-04 14:55:51.000000000 +0100 +++ gcc/tree-ssa-live.c 2016-04-14 17:24:49.047509853 +0200 @@ -393,14 +393,16 @@ remove_unused_scope_block_p (tree scope, in_ctor_dtor_block = true; unused = false; } - /* 2) inside such blocks, the outermost block with BLOCK_ABSTRACT_ORIGIN + /* 2) inside such blocks, the outermost block with block_ultimate_origin being a FUNCTION_DECL. */ - else if (in_ctor_dtor_block - && BLOCK_ABSTRACT_ORIGIN (scope) - && TREE_CODE (BLOCK_ABSTRACT_ORIGIN (scope)) == FUNCTION_DECL) + else if (in_ctor_dtor_block) { - in_ctor_dtor_block = false; - unused = false; + tree fn = block_ultimate_origin (scope); + if (fn && TREE_CODE (fn) == FUNCTION_DECL) + { + in_ctor_dtor_block = false; + unused = false; + } } for (t = &BLOCK_VARS (scope); *t; t = next) @@ -855,7 +857,9 @@ remove_unused_locals (void) cfun->local_decls->truncate (dstidx); } - remove_unused_scope_block_p (DECL_INITIAL (current_function_decl), false); + remove_unused_scope_block_p (DECL_INITIAL (current_function_decl), + polymorphic_ctor_dtor_p (current_function_decl, + true) != NULL_TREE); clear_unused_block_pointer (); BITMAP_FREE (usedvars);