From patchwork Wed Nov 13 21:08:23 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Hubicka X-Patchwork-Id: 1194471 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-513303-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=ucw.cz Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="ZZ0Putwj"; dkim-atps=neutral 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 47Cxzn4FKzz9s4Y for ; Thu, 14 Nov 2019 08:08:37 +1100 (AEDT) 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=hXeefQWam5Bv3A46B7cWtXhVt5dOFyJ7DB4qqVzfVA2OgFuLU9nYv d9/3vxY4LaeG+Nugijz4+azTbP6UEyszw8gC1fwzu2Yc292cmd8YCkRWuT9w+lXO qUAClIye155vXrHMxJ2Vu72r8YRAu1rQHDd6BoZn3YqRvaoI9IdwW8= 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=8BPdZcM3eHs26ylH5Lw5hUxHL34=; b=ZZ0Putwj1bHg2DZwKYW8 6GRyBCAljxsf8kC9VDJ1V8B4uKsuUFgisgohjs+HTk5Kx4F4qZEK2GXStHtgPQiP trmhLv7UMDOYfFsc/X5N5UIdDdxdyDsAXnHYTFXEMacXADHkEM4o/Hp2xCVIK2oC /rSCZh9nw3Bb19yJM/sDoiE= Received: (qmail 74679 invoked by alias); 13 Nov 2019 21:08:28 -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 74672 invoked by uid 89); 13 Nov 2019 21:08:28 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-10.0 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS autolearn=ham version=3.3.1 spammy=kit, cur, ci, new_edges 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 ESMTP; Wed, 13 Nov 2019 21:08:26 +0000 Received: by nikam.ms.mff.cuni.cz (Postfix, from userid 16202) id 251B2282051; Wed, 13 Nov 2019 22:08:23 +0100 (CET) Date: Wed, 13 Nov 2019 22:08:23 +0100 From: Jan Hubicka To: gcc-patches@gcc.gnu.org Subject: Fix ICE when inlining into function containing polymorphic call Message-ID: <20191113210823.wkznroh6m2vr6nul@kam.mff.cuni.cz> MIME-Version: 1.0 Content-Disposition: inline User-Agent: NeoMutt/20170113 (1.7.2) Hi, the testcase causes inline context cache to go out of sync because I forgot to update used flags of parameters in one path of update_indirect_edges_after_inlining. While debugging it I also added better consistency check to ipa-inline-analysis and turned ipa-inline test from ifdef to -fchecking. This uncovered yet another missed upate in recursive inliner. Bootstrapped/regtested x86_64-linux, comitted. PR c++/92421 * ipa-prop.c (update_indirect_edges_after_inlining): Mark parameter as used. * ipa-inline.c (recursive_inlining): Reset node cache after inlining. (inline_small_functions): Remove checking ifdef. * ipa-inline-analysis.c (do_estimate_edge_time): Verify cache consistency. * g++.dg/torture/pr92421.C: New testcase. Index: ipa-prop.c =================================================================== --- ipa-prop.c (revision 278151) +++ ipa-prop.c (working copy) @@ -3537,6 +3537,11 @@ update_indirect_edges_after_inlining (st if (ici->polymorphic && !ipa_get_jf_ancestor_type_preserved (jfunc)) ici->vptr_changed = true; + ipa_set_param_used_by_indirect_call (new_root_info, + ici->param_index, true); + if (ici->polymorphic) + ipa_set_param_used_by_polymorphic_call (new_root_info, + ici->param_index, true); } } else Index: ipa-inline.c =================================================================== --- ipa-inline.c (revision 278151) +++ ipa-inline.c (working copy) @@ -1633,6 +1633,7 @@ recursive_inlining (struct cgraph_edge * } inline_call (curr, false, new_edges, &overall_size, true); + reset_node_cache (node); lookup_recursive_calls (node, curr->callee, &heap); n++; } @@ -1982,11 +1983,10 @@ inline_small_functions (void) if (!edge->inline_failed || !edge->callee->analyzed) continue; -#if CHECKING_P /* Be sure that caches are maintained consistent. This check is affected by scaling roundoff errors when compiling for IPA this we skip it in that case. */ - if (!edge->callee->count.ipa_p () + if (flag_checking && !edge->callee->count.ipa_p () && (!max_count.initialized_p () || !max_count.nonzero_p ())) { sreal cached_badness = edge_badness (edge, false); @@ -1997,6 +1997,9 @@ inline_small_functions (void) if (edge_growth_cache != NULL) edge_growth_cache->remove (edge); + reset_node_cache (edge->caller->inlined_to + ? edge->caller->inlined_to + : edge->caller); gcc_assert (old_size_est == estimate_edge_size (edge)); gcc_assert (old_time_est == estimate_edge_time (edge)); /* FIXME: @@ -2021,9 +2024,6 @@ inline_small_functions (void) } else current_badness = edge_badness (edge, false); -#else - current_badness = edge_badness (edge, false); -#endif if (current_badness != badness) { if (edge_heap.min () && current_badness > edge_heap.min_key ()) Index: ipa-inline-analysis.c =================================================================== --- ipa-inline-analysis.c (revision 278151) +++ ipa-inline-analysis.c (working copy) @@ -210,6 +210,19 @@ do_estimate_edge_time (struct cgraph_edg time = e->entry.time; nonspec_time = e->entry.nonspec_time; hints = e->entry.hints; + if (flag_checking) + { + sreal chk_time, chk_nonspec_time; + int chk_size, chk_min_size; + + ipa_hints chk_hints; + ctx.estimate_size_and_time (&chk_size, &chk_min_size, + &chk_time, &chk_nonspec_time, + &chk_hints); + gcc_assert (chk_size == size && chk_time == time + && chk_nonspec_time == nonspec_time + && chk_hints == hints); + } } else { Index: testsuite/g++.dg/torture/pr92421.C =================================================================== --- testsuite/g++.dg/torture/pr92421.C (nonexistent) +++ testsuite/g++.dg/torture/pr92421.C (working copy) @@ -0,0 +1,174 @@ +/* { dg-do compile } */ +typedef long a; +void *b, *c; +template class d {}; +template bool operator!=(d, d); +class g { +public: + g(char *); +}; +class j { +public: + j(); + void h(); + void i(); + void aj(); +}; +class m { +public: + m(bool); +}; +class n { +public: + operator a(); +}; +class o { +public: + long am(); +}; +class H { +public: + class p {}; + virtual bool accept(const char *, unsigned long, p *, bool); +}; +class q : H { +public: + class r { + public: + enum at { au, av, aw }; + }; + enum { ax }; + virtual void ay(char *, int, const char *, r::at, char *); + virtual bool az(const g &, unsigned = ax); + virtual bool ba(const int &, p *, bool); + void bb(char *bc, long bd, char *, long be) { + class bf : public p { + public: + bf(long); + } bg(be); + accept(bc, bd, &bg, true); + } +}; +class s { + q *bi; + bool bj(); +}; +template class t : q { + bool accept(const char *, unsigned long bd, p *bg, bool) { + bool k(bp || bq), cl = false, err = false; + if (br) + ay("", 1, __func__, r::au, ""); + if (bs) + ay("", 6, __func__, r::av, ""); + char bt[1], cd[1]; + long bu = sizeof(int) + bd, ce = sizeof(L) + bd; + char *bw = bu > sizeof(bt) ? new char : bt, + *cf = ce > sizeof(cd) ? new char : cd; + __builtin___memcpy_chk(b, c, bd, 0); + a by[1]; + int bz = 0; + u cb = *cc((int *)bw, true, by, &bz); + ay("", 1, __func__, r::aw, ""); + if (bw != bt) + delete bw; + __builtin___memcpy_chk(b, c, bd, 0); + cb.ch.i(); + bool ci = cj((L *)cf, bg); + bool atran = bq && bp && cb.ck; + if (atran && !ci && cm(&cb)) + if (cn > co) { + int cp = cb.cq % 6; + v cs = *(ct + cp); + if (cu(&cs)) + cl = true; + } + if (ci) + if (k) + cv.aj(); + cv.h(); + b = cc((int *)bw, false, by, &bz); + if (b) + if (cw(&cb, by, bz)) + if (atran && bp && cx()) + cv.aj(); + if (cl) + if (k) + cv.aj(); + cv.h(); + int cp = cb.cq % 6; + v cs = *(ct + cp); + if (cy()) + err = true; + O da = *(db + cp); + if (da.dc->am() > cs.dc->am() + cs.dd->am() + 1 && de(&da)) + cv.aj(); + return !err; + } + bool ba(const int &, p *, bool) { + d kit, df; + while (kit != df) + ; + cx(); + } + bool az(const g &, unsigned) { + t dj; + int cur; + while (cur) { + int dk, dl; + char dbuf; + dj.bb(&dbuf, dl, &dbuf, dk); + } + } + struct L {}; + struct u { + j ch; + a cq; + bool ck; + }; + struct v { + o *dd; + o *dc; + }; + struct O { + o *dc; + }; + bool cy(); + bool cu(v *); + bool cj(L *, p *); + bool de(O *); + u *cc(int *, bool, a *, int *); + bool cw(u *, a *, int); + bool cx() { + dm.dn(); + bool err = false; + if (dm.l()) + err = true; + return !err; + } + bool cm(u *); + j cv; + int br; + bool bs; + bool bq; + bk dm; + a co; + n cn; + v ct[6]; + O db[6]; + bool bp; +}; +class w : q { +public: + void dn(); + bool l() { + m(true); + if (br) + ay("", 1087, __func__, r::au, ""); + return false; + } + int br; +}; +bool s::bj() { + bi->az(""); + new t; +}