public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
From: "slyfox at gcc dot gnu.org" <gcc-bugzilla@gcc.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	[thread overview]
Message-ID: <bug-98499-4-YLKGYy0P1x@http.gcc.gnu.org/bugzilla/> (raw)
In-Reply-To: <bug-98499-4@http.gcc.gnu.org/bugzilla/>

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98499

--- Comment #8 from Sergei Trofimovich <slyfox at gcc dot gnu.org> ---
(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
> > 
> > Aha, that's useful!
> > 
> > Trying to understand the problem better myself: `-fdump-tree-all` has
> > seemingly relevant `036t.ealias` that precedes breaking `037t.fre1`.
> > 
> > I assume `036t.ealias` analyses individual functions locally and does not
> > take into account other details, thus main() analysis should be enough:
> 
> 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.ealias`
is using data from seemingly later `043t.modref1` pass. It is so confusing!

> > ```
> > ...
> > Points-to sets
> > 
> > ANYTHING = { ANYTHING }
> > ESCAPED = { ESCAPED NONLOCAL }
> > NONLOCAL = { ESCAPED NONLOCAL }
> > STOREDANYTHING = { }
> > INTEGER = { ANYTHING }
> > _ZN8ImporterC1Ev = { }
> > imp.0+64 = { ESCAPED NONLOCAL } same as _6
> > imp.64+8 = { ESCAPED NONLOCAL }
> > __builtin_trap = { }
> > main = { }
> > CALLUSED(9) = { ESCAPED NONLOCAL imp.0+64 imp.64+8 } same as callarg(11)
> > CALLCLOBBERED(10) = { ESCAPED NONLOCAL imp.0+64 imp.64+8 } same as
> > callarg(11)
> > callarg(11) = { ESCAPED NONLOCAL imp.0+64 imp.64+8 }
> 
> the above shows we do not consider 'imp' to escape, and thus
> 
> > _6 = { ESCAPED NONLOCAL }
> 
> _6 does not point to 'imp'.
> 
> Relevant parts of handle_rhs_call are probably
> 
>       /* 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)))
>         {
> ...
> 
> specifically lines
> 
>           if (!(flags & (EAF_NOESCAPE | EAF_DIRECT)))
>             make_indirect_escape_constraint (tem);
> 
> 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()` and
assumes 'foo = 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<modref_lattice>
&lattice, int depth,
        {
          if (gimple_return_retval (ret) == 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 = dyn_cast <gcall *> (use_stmt))
        {
          tree callee = gimple_call_fndecl (call);
-
+          if (gimple_call_return_slot_opt_p (call)
+              && gimple_call_lhs (call) != 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_decl,
                                                  callee))
            lattice[index].merge (0);
          else
            {
              int ecf_flags = gimple_call_flags (call);
              bool ignore_stores = ignore_stores_p (current_function_decl,
                                                    ecf_flags);
              bool ignore_retval = ignore_retval_p (current_function_decl,
                                                    ecf_flags);
```

Mechanically ESCAPE bit was lost in Importer::Importer at:

1. in "this->base_path = dir_name (); [r s o]" ipa-modref derived 'DIRECT
NODIRECTESCAPE NOESCAPE' flags as it assumed it's just a memory store without
'this' escape.
2. main() optimised Inporter::Importer(&imp) as a noescape using

  handle_rhs_call()
    -> gimple_call_arg_flags(arg_index = 0)
       -> - fnspec was empty
          - modref's get_modref_function_summary() adds 'DIRECT NODIRECTESCAPE
NOESCAPE'

Is it a reasonable fix? Or it's too conservative and we could easily do better?

I copied predicate from handle_rhs_call(), but did not pick constrain copying:

  /* 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) != NULL_TREE
      && TREE_ADDRESSABLE (TREE_TYPE (gimple_call_lhs (stmt))))
    {
      auto_vec<ce_s> tmpc;
      struct constraint_expr lhsc, *c;
      get_constraint_for_address_of (gimple_call_lhs (stmt), &tmpc);
      lhsc.var = escaped_id;
      lhsc.offset = 0;
      lhsc.type = 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?

  parent reply	other threads:[~2021-01-10 18:39 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-01-02 11:11 [Bug c++/98499] New: " slyfox at gcc dot gnu.org
2021-01-02 22:22 ` [Bug c++/98499] " slyfox at gcc dot gnu.org
2021-01-03 11:44 ` slyfox at gcc dot gnu.org
2021-01-03 20:56 ` slyfox at gcc dot gnu.org
2021-01-03 21:50 ` slyfox at gcc dot gnu.org
2021-01-04 12:28 ` marxin at gcc dot gnu.org
2021-01-05 11:09 ` rguenth at gcc dot gnu.org
2021-01-06 23:11 ` [Bug tree-optimization/98499] " slyfox at gcc dot gnu.org
2021-01-07  8:12 ` rguenth at gcc dot gnu.org
2021-01-10 18:39 ` slyfox at gcc dot gnu.org [this message]
2021-01-28 10:55 ` hubicka at gcc dot gnu.org
2021-01-30 18:02 ` slyfox at gcc dot gnu.org
2021-02-01 18:14 ` cvs-commit at gcc dot gnu.org
2021-02-01 18:39 ` slyfox at gcc dot gnu.org
2021-02-01 18:40 ` slyfox at gcc dot gnu.org

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=bug-98499-4-YLKGYy0P1x@http.gcc.gnu.org/bugzilla/ \
    --to=gcc-bugzilla@gcc.gnu.org \
    --cc=gcc-bugs@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).