public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: David Malcolm <dmalcolm@redhat.com>
To: priour.be@gmail.com, gcc-patches@gcc.gnu.org
Cc: benjamin priour <vultkayn@gcc.gnu.org>
Subject: Re: [PATCH] analyzer: call off a superseding when diagnostics are unrelated [PR110830]
Date: Fri, 01 Sep 2023 19:48:43 -0400	[thread overview]
Message-ID: <e59ee392ecf33a13a2a6cb7d86d790b22944744b.camel@redhat.com> (raw)
In-Reply-To: <20230901195905.2800474-1-vultkayn@gcc.gnu.org>

On Fri, 2023-09-01 at 21:59 +0200, priour.be@gmail.com wrote:
> From: benjamin priour <vultkayn@gcc.gnu.org>
> 
> Hi,
> 
> Patch succesfully regstrapped off trunk
> 7f2ed06ddc825e8a4e0edfd1d66b5156e6dc1d34
> on x86_64-linux-gnu.
> 
> Is it OK for trunk ?
> 
> Thanks,
> Benjamin.
> 

[...snip...]

>  
> +/* Walk up the two paths to each of their common conditional
> +   branching.  At each branching, make sure both diagnostics'
> +   paths branched similarly.  If there is at least one where
> +   both paths go down a different outcome, then the paths
> +   are incompatible and this function returns FALSE.
> +   Otherwise return TRUE.
> +
> +   Incompatible paths:
> +
> +       <cond Y>
> +       /      \
> +      /        \
> +    true      false
> +     |          |
> +    ...        ...
> +     |          |
> +    ...       stmt x
> +     |
> +   stmt x
> +
> +   Both LHS_PATH and RHS_PATH final enodes should be
> +   over the same gimple statement.  */
> +
> +static bool
> +compatible_epath_p (const exploded_path *lhs_path,
> +                   const exploded_path *rhs_path)
> +{
> +  gcc_assert (lhs_path);
> +  gcc_assert (rhs_path);
> +  int i;
> +  const exploded_edge *outer_eedge;
> +  FOR_EACH_VEC_ELT_REVERSE (lhs_path->m_edges, i, outer_eedge)
> +    {
> +      const superedge *outer_sedge = outer_eedge->m_sedge;
> +      if (!outer_sedge || !outer_eedge->m_src)
> +       continue;
> +      const program_point &outer_src_point = outer_eedge->m_src->get_point ();
> +      switch (outer_src_point.get_kind ())
> +       {
> +         case PK_AFTER_SUPERNODE:
> +           if (const cfg_superedge *cfg_outer_sedge
> +               = outer_sedge->dyn_cast_cfg_superedge ())
> +             {
> +               int j;
> +               const exploded_edge *inner_eedge;
> +               FOR_EACH_VEC_ELT_REVERSE (rhs_path->m_edges, j, inner_eedge)
> +                 {
> +                   const superedge *inner_sedge = inner_eedge->m_sedge;
> +                   if (!inner_sedge || !inner_eedge->m_src)
> +                     continue;
> +                   const program_point &inner_src_point
> +                     = inner_eedge->m_src->get_point ();
> +                   switch (inner_src_point.get_kind ())
> +                     {
> +                       case PK_AFTER_SUPERNODE:
> +                         if (inner_src_point.get_stmt ()
> +                             != outer_src_point.get_stmt ())
> +                           continue;
> +                         if (const cfg_superedge *cfg_inner_sedge
> +                             = inner_sedge->dyn_cast_cfg_superedge ())
> +                           {
> +                             if (cfg_inner_sedge->true_value_p ()
> +                                 != cfg_outer_sedge->true_value_p ())
> +                               return false;
> +                           }
> +                         break;
> +                       default:
> +                         break;
> +                     }
> +                 }
> +             }
> +           break;
> +
> +         default:
> +           break;
> +       }
> +    }
> +    return true;
> +}

[...snip...]

Thanks for the patch.  I think the high-level idea is good, but I'm not
sure the implementation is correct:

- it is O(n^2), where n is the length of exploded_path.
- it walks backwards through the LHS path, and for each eedge from a
PK_AFTER_SUPERNODE it walks backwards from the end of the RHS epath; it
only looks at the "true" flag on CFG edges.  I think this works for
simple cases, but the way it restarts the rhs_path iteration from the
end of the rhs_path each time "feels" incorrect.

An eedge from a PK_AFTER_SUPERNODE is presumably just an eedge that has
a non-NULL m_sedge i.e. an exploded edge relating to an edge in the
supergraph.  Rather than looking at flags, can we simply compare
superedge pointers?  For example, if we care that we followed the
"true" path of a conditional in both lhs and rhs epaths, we can look to
see if both have an eedge where the superedge is the cfg_superedge
wrapping the CFG "true" edge i.e. I think we can simply compare the
superedge pointers.

Or is there some detail here that I'm misunderstanding?

I *think* it's possible to implement it in O(n) with something like
this:  (warning: untested code follows!)

  /* For compatibility, there should effectively be the same
     vector of superedges followed in both epaths.
     Walk backwards through each epath, looking at the superedges.  */
  // FIXME: really?  Benjamin, have I understood this correctly?

  gcc_assert (lhs_path->length () > 0);
  gcc_assert (rhs_path->length () > 0);

  int lhs_idx = lhs_path->length () - 1;
  int rhs_idx = rhs_path->length () - 1;

  while (lhs_idx >= 0 && rhs_idx >= 0)
    {
      /* Find next LHS superedge, if any.  */
      while (lhs_idx >= 0)
        {
	  const exploded_edge *lhs_eedge = lhs_path->m_edges[lhs_idx];
	  if (lhs_eedge->m_sedge)
	    break;
	  else
	    lhs_idx--;
	}

      /* Find next RHS superedge, if any.  */
      while (rhs_idx >= 0)
        {
	  const exploded_edge *rhs_eedge = rhs_path->m_edges[rhs_idx];
	  if (rhs_eedge->m_sedge)
	    break;
	  else
	    rhs_idx--;
	}

      const exploded_edge *lhs_eedge
        (lhs_idx >= 0 ? lhs_path->m_edges[lhs_idx] : nullptr);
      const exploded_edge *rhs_eedge
        (rhs_idx >= 0 ? rhs_path->m_edges[rhs_idx] : nullptr);

      if (lhs_eedge && rhs_edge)
        {
	  /* If we followed different superedges, the paths are
	     not compatible.  */
	  if (lhs_eedge->m_sedge != rhs_eedge->m_sedge)
	    return false;

          /* Otherwise, we found an (LHS, RHS) pair of eedges
             both relating to the same superedge.  */
           lhs_idx--;
           rhs_idx--;
           continue;
        }
      else if (lhs_eedge == nullptr && rhs_eedge == nullptr)
        {
	  /* Finished traversing both epaths; they are compatible.  */
	  return true;
        }

      /* Otherwise, one epath ran out of superedges before the other;
         they are not compatible.  */
      return false;
    }

Does that make any sense, or have I misunderstood?

Thanks
Dave


  reply	other threads:[~2023-09-01 23:48 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-09-01 19:59 priour.be
2023-09-01 23:48 ` David Malcolm [this message]
2023-09-06 19:16   ` [PATCH v2] analyzer: Call " priour.be
2023-09-06 20:30     ` David Malcolm
2023-09-11  8:23     ` Andreas Schwab
2023-09-14 20:39       ` [pushed] analyzer: fix missing return in compatible_epath_p David Malcolm

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=e59ee392ecf33a13a2a6cb7d86d790b22944744b.camel@redhat.com \
    --to=dmalcolm@redhat.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=priour.be@gmail.com \
    --cc=vultkayn@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).