public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
From: Mark Wielaard <mark@klomp.org>
To: David Malcolm <dmalcolm@redhat.com>, gcc@gcc.gnu.org
Cc: Julian Seward <sewardj42@gmail.com>
Subject: Re: Uninit warnings due to optimizing short-circuit conditionals
Date: Mon, 14 Feb 2022 18:37:25 +0100	[thread overview]
Message-ID: <3bfbfbf02e2d17d45b4a91e5ea5f855e0a62e5f5.camel@klomp.org> (raw)
In-Reply-To: <ab8b3b762fcabc2827e3b2f82cff6a11c9cd2ee3.camel@redhat.com>

On Mon, 2022-02-14 at 12:20 -0500, David Malcolm wrote:
> On Mon, 2022-02-14 at 17:57 +0100, Mark Wielaard wrote:
> > On Mon, 2022-02-14 at 10:57 -0500, David Malcolm wrote:
> > > [CCing Mark in the hopes of insight from the valgrind side of
> > > things]
> > 
> > Adding Julian to CC so he can correct me if I say something silly.
> > 
> > > There is a false positive from -Wanalyzer-use-of-uninitialized-
> > > value on
> > > gcc.dg/analyzer/pr102692.c here:
> > > 
> > >   ‘fix_overlays_before’: events 1-3
> > >     |
> > >     |   75 |   while (tail
> > >     |      |          ~~~~
> > >     |   76 |          && (tem = make_lisp_ptr (tail, 5),
> > >     |      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > >     |      |          |
> > >     |      |          (1) following ‘false’ branch (when ‘tail’ is
> > > NULL)...
> > >     |   77 |              (end = marker_position (XOVERLAY (tem)-
> > > > end)) >= pos))
> > > 
> > >     |      |             
> > > ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > >     |......
> > >     |   82 |   if (!tail || end < prev || !tail->next)
> > >     |      |       ~~~~~    ~~~~~~~~~~
> > >     |      |       |            |
> > >     |      |       |            (3) use of uninitialized value
> > > ‘end’ here
> > >     |      |       (2) ...to here
> > >     |
> > > 
> > > The issue is that inner || of the conditionals have been folded
> > > within the
> > > frontend from a chain of control flow:
> > > 
> > >    5   │   if (tail == 0B) goto <D.1986>; else goto <D.1988>;
> > >    6   │   <D.1988>:
> > >    7   │   if (end < prev) goto <D.1986>; else goto <D.1989>;
> > >    8   │   <D.1989>:
> > >    9   │   _1 = tail->next;
> > >   10   │   if (_1 == 0B) goto <D.1986>; else goto <D.1987>;
> > >   11   │   <D.1986>:
> > > 
> > > to an OR expr (and then to a bitwise-or by the gimplifier):
> > > 
> > >    5   │   _1 = tail == 0B;
> > >    6   │   _2 = end < prev;
> > >    7   │   _3 = _1 | _2;
> > >    8   │   if (_3 != 0) goto <D.1986>; else goto <D.1988>;
> > >    9   │   <D.1988>:
> > >   10   │   _4 = tail->next;
> > >   11   │   if (_4 == 0B) goto <D.1986>; else goto <D.1987>;
> > > 
> > > This happens for sufficiently simple conditionals in
> > > fold_truth_andor.
> > > In particular, the (end < prev) is short-circuited without
> > > optimization,
> > > but is evaluated with optimization, leading to the false positive.
> > > 
> > > Given how early this folding occurs, it seems the simplest fix is
> > > to
> > > try to detect places where this optimization appears to have
> > > happened,
> > > and suppress uninit warnings within the statement that would have
> > > been short-circuited (and thus e.g. ignoring them when evaluating
> > > _2
> > > above for the case where _1 is known to be true at the (_1 | _2) ,
> > > and
> > > thus _2 being redundant).
> > > 
> > > Attached is a patch that implements this.
> > > 
> > > There are some more details in the patch, but I'm wondering if this
> > > is a
> > > known problem, and how e.g. valgrind copes with such code.  My
> > > patch
> > > feels like something of a hack, but I'm not sure of any other way
> > > around
> > > it given that the conditional is folded directly within the
> > > frontend.
> > 
> > As far as I know this is what valgrind memcheck also does with an
> > bitwise or. It knows that _3 is defined and true if either _1 or _2
> > is
> > defined and true. Or more generically that the result bits of a
> > bitwise
> > or are defined for those bits that are both defined or where one is
> > defined and has the value 1.
> 
> Aha - thanks.  I think the distinction here is that:
> 
> * GCC's -fanalyzer complains about uninitialized values immediately
> when it sees one being fetched for use in any expression (replacing the
> value with a safe one to avoid further complaints), without considering
> how they are going to be used in the expression, whereas
> 
> * it sounds like valgrind keeps track of uninitialized bits, propagates
> the "uninit-ness" of the bits, and complains at certain times when
> uninitialized bits are used in certain ways.

Yes. valgrind keeps track of uninitialized bits and propagates them
around till "use". Where use is anything that might alter the
observable behavior of the program. Which is control flow transfers,
conditional moves, addresses used in memory accesses, and data passed
to system calls.

This paper describes some of the memcheck tricks:
https://valgrind.org/docs/memcheck2005.pdf

Cheers,

Mark

  reply	other threads:[~2022-02-14 17:37 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-02-14 15:57 David Malcolm
2022-02-14 16:26 ` Jeff Law
2022-02-14 17:10   ` David Malcolm
2022-02-14 16:57 ` Mark Wielaard
2022-02-14 17:20   ` David Malcolm
2022-02-14 17:37     ` Mark Wielaard [this message]
2022-02-15  7:25       ` Richard Biener
2022-02-15 12:29         ` Mark Wielaard
2022-02-15 13:00           ` Julian Seward
2022-02-15 13:28             ` Richard Biener
2022-02-15 21:40               ` 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=3bfbfbf02e2d17d45b4a91e5ea5f855e0a62e5f5.camel@klomp.org \
    --to=mark@klomp.org \
    --cc=dmalcolm@redhat.com \
    --cc=gcc@gcc.gnu.org \
    --cc=sewardj42@gmail.com \
    /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).