From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 48) id 9EDC9385782E; Sun, 10 Jan 2021 18:39:45 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 9EDC9385782E From: "slyfox at gcc dot gnu.org" To: gcc-bugs@gcc.gnu.org Subject: [Bug tree-optimization/98499] [11 Regression] Possibly bad std::string initialization in constructors Date: Sun, 10 Jan 2021 18:39:45 +0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: changed X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: gcc X-Bugzilla-Component: tree-optimization X-Bugzilla-Version: 11.0 X-Bugzilla-Keywords: wrong-code X-Bugzilla-Severity: normal X-Bugzilla-Who: slyfox at gcc dot gnu.org X-Bugzilla-Status: NEW X-Bugzilla-Resolution: X-Bugzilla-Priority: P1 X-Bugzilla-Assigned-To: unassigned at gcc dot gnu.org X-Bugzilla-Target-Milestone: 11.0 X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: Message-ID: In-Reply-To: References: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Bugzilla-URL: http://gcc.gnu.org/bugzilla/ Auto-Submitted: auto-generated MIME-Version: 1.0 X-BeenThere: gcc-bugs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-bugs mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 10 Jan 2021 18:39:45 -0000 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D98499 --- Comment #8 from Sergei Trofimovich --- (In reply to Richard Biener from comment #7) > (In reply to Sergei Trofimovich from comment #6) > > (In reply to Richard Biener from comment #5) > > > Possibly in discovering pure/constness. See uses of > > > gimple_call_return_slot_opt_p in tree-ssa-structalias.c > >=20 > > Aha, that's useful! > >=20 > > Trying to understand the problem better myself: `-fdump-tree-all` has > > seemingly relevant `036t.ealias` that precedes breaking `037t.fre1`. > >=20 > > I assume `036t.ealias` analyses individual functions locally and does n= ot > > take into account other details, thus main() analysis should be enough: >=20 > Well - it does take into account fnspecs derived by modref analysis for > Importer::Importer - specifically ... Oh, thank you! Only after many printf() attempts it sunk in that `036t.eali= as` is using data from seemingly later `043t.modref1` pass. It is so confusing! > > ``` > > ... > > Points-to sets > >=20 > > ANYTHING =3D { ANYTHING } > > ESCAPED =3D { ESCAPED NONLOCAL } > > NONLOCAL =3D { ESCAPED NONLOCAL } > > STOREDANYTHING =3D { } > > INTEGER =3D { ANYTHING } > > _ZN8ImporterC1Ev =3D { } > > imp.0+64 =3D { ESCAPED NONLOCAL } same as _6 > > imp.64+8 =3D { ESCAPED NONLOCAL } > > __builtin_trap =3D { } > > main =3D { } > > CALLUSED(9) =3D { ESCAPED NONLOCAL imp.0+64 imp.64+8 } same as callarg(= 11) > > CALLCLOBBERED(10) =3D { ESCAPED NONLOCAL imp.0+64 imp.64+8 } same as > > callarg(11) > > callarg(11) =3D { ESCAPED NONLOCAL imp.0+64 imp.64+8 } >=20 > the above shows we do not consider 'imp' to escape, and thus >=20 > > _6 =3D { ESCAPED NONLOCAL } >=20 > _6 does not point to 'imp'. >=20 > Relevant parts of handle_rhs_call are probably >=20 > /* As we compute ESCAPED context-insensitive we do not gain > any precision with just EAF_NOCLOBBER but not EAF_NOESCAPE > set. The argument would still get clobbered through the > escape solution. */ > if ((flags & EAF_NOCLOBBER) > && (flags & (EAF_NOESCAPE | EAF_NODIRECTESCAPE))) > { > ... >=20 > specifically lines >=20 > if (!(flags & (EAF_NOESCAPE | EAF_DIRECT))) > make_indirect_escape_constraint (tem); >=20 > probably do not trigger because of the invalid modref analysis. I suggest > to look at the early modref pass dump (it's after FRE but still applies > to callers) Yeah, that makes sense. Minor correction: we get into second branch of handle_rhs_call(): else if (flags & (EAF_NOESCAPE | EAF_NODIRECTESCAPE)) I traced it through around and I agree it looks like an ipa-modref bug. Mechanically ipa-modref does not handle `gimple_call_return_slot_opt_p()` a= nd assumes 'foo =3D bar() [return slot optimization]' never escape 'foo'. As a workaround I attempted to pessimize modref and it fixes the test case: ```diff --- a/gcc/ipa-modref.c +++ b/gcc/ipa-modref.c @@ -1614,23 +1614,26 @@ analyze_ssa_name_flags (tree name, vec &lattice, int depth, { if (gimple_return_retval (ret) =3D=3D name) lattice[index].merge (~EAF_UNUSED); else if (memory_access_to (gimple_return_retval (ret), name)) lattice[index].merge_direct_load (); } /* Account for LHS store, arg loads and flags from callee function. = */ else if (gcall *call =3D dyn_cast (use_stmt)) { tree callee =3D gimple_call_fndecl (call); - + if (gimple_call_return_slot_opt_p (call) + && gimple_call_lhs (call) !=3D NULL_TREE + && TREE_ADDRESSABLE (TREE_TYPE (gimple_call_lhs (call)))) + lattice[index].merge (0); /* Recursion would require bit of propagation; give up for now. = */ - if (callee && !ipa && recursive_call_p (current_function_decl, + else if (callee && !ipa && recursive_call_p (current_function_dec= l, callee)) lattice[index].merge (0); else { int ecf_flags =3D gimple_call_flags (call); bool ignore_stores =3D ignore_stores_p (current_function_decl, ecf_flags); bool ignore_retval =3D ignore_retval_p (current_function_decl, ecf_flags); ``` Mechanically ESCAPE bit was lost in Importer::Importer at: 1. in "this->base_path =3D dir_name (); [r s o]" ipa-modref derived 'DIRECT NODIRECTESCAPE NOESCAPE' flags as it assumed it's just a memory store witho= ut 'this' escape. 2. main() optimised Inporter::Importer(&imp) as a noescape using handle_rhs_call() -> gimple_call_arg_flags(arg_index =3D 0) -> - fnspec was empty - modref's get_modref_function_summary() adds 'DIRECT NODIRECTESC= APE NOESCAPE' Is it a reasonable fix? Or it's too conservative and we could easily do bet= ter? I copied predicate from handle_rhs_call(), but did not pick constrain copyi= ng: /* And if we applied NRV the address of the return slot escapes as well. = */ if (gimple_call_return_slot_opt_p (stmt) && gimple_call_lhs (stmt) !=3D NULL_TREE && TREE_ADDRESSABLE (TREE_TYPE (gimple_call_lhs (stmt)))) { auto_vec tmpc; struct constraint_expr lhsc, *c; get_constraint_for_address_of (gimple_call_lhs (stmt), &tmpc); lhsc.var =3D escaped_id; lhsc.offset =3D 0; lhsc.type =3D SCALAR; FOR_EACH_VEC_ELT (tmpc, i, c) process_constraint (new_constraint (lhsc, *c)); } Would constraint copy transfer to ipa-modref framework roughly the same?=