public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
From: Ian Lance Taylor <iant@google.com>
To: j <j@lambda.is>
Cc: gcc@gcc.gnu.org
Subject: Re: gccgo emits GIMPLE with temporaries for boolean expressions unlike gcc, gdc
Date: Wed, 10 Aug 2022 17:49:55 -0700	[thread overview]
Message-ID: <CAKOQZ8yO=1P4NcJpGWD5QF3PKKveWm_jhck0J11O9TvY_tpesg@mail.gmail.com> (raw)
In-Reply-To: <4ba7b262-ee0b-905f-ba0a-611ee6749184@lambda.is>

On Wed, Aug 3, 2022 at 6:26 AM j <j@lambda.is> wrote:
>
> I've proposed a patch [1] for condition coverage profiling in gcc,
> implemented in the middle-end alongside the branch coverage. I've
> written most of the tests for C and a few for C++ and finally got around
> to try it with a toy example for D and go and noticed something odd
> about Go's CFG construction.
>
> abc.c:
>      int fn (int a, int b, int c) {
>          if (a && (b || c))
>              return a;
>          else
>              return b * c;
>      }
>
> abc.d:
>      int fn (int a, int b, int c) {
>          if (a && (b || c))
>              return a;
>          else
>              return b * c;
>      }
>
> abc.go:
>      func fn (a int, b int, c int) int {
>          a_ := a != 0;
>          b_ := b != 0;
>          c_ := c != 0;
>
>          if a_ && (b_ || c_) {
>              return 1;
>          } else {
>              return 0;
>          }
>      }
>
> All were built with gcc --coverage -fprofile-conditions (my patch, but
> it does not affect this) and no optimization. The C and D programs
> behaved as expected:
>
> gcov --conditions abc.d:
>
>          3:    3:int fn (int a, int b, int c) {
>         3*:    4:    if (a && (b || c))
> conditions outcomes covered 3/6
> condition  1 not covered (false)
> condition  2 not covered (true)
> condition  2 not covered (false)
>          1:    5:        return a;
>          -:    6:    else
>          2:    7:        return b * c;
>
>
> gcov --conditions abc.go:
>          3:    5:func fn (a int, b int, c int) int {
>          3:    6:        a_ := a != 0;
>          3:    7:        b_ := b != 0;
>          3:    8:        c_ := c != 0;
>          -:    9:
>         3*:   10:        if a_ && (b_ || c_) {
> condition outcomes covered 2/2
> condition outcomes covered 1/2
> condition  0 not covered (true)
> condition outcomes covered 2/2
>          1:   11:            return 1;
>          -:   12:        } else {
>          2:   13:            return 0;
>          -:   14:        }
>          -:   15:}
>
> So I dumped the gimple gcc -fdump-tree-gimple abc.go:
>
> int main.fn (int a, int b, int c)
> {
>    int D.2725;
>    int $ret0;
>
>    $ret0 = 0;
>    {
>      bool a_;
>      bool b_;
>      bool c_;
>
>      a_ = a != 0;
>      b_ = b != 0;
>      c_ = c != 0;
>      {
>        {
>          GOTMP.0 = a_;
>          if (GOTMP.0 != 0) goto <D.2719>; else goto <D.2720>;
>          <D.2719>:
>          {
>            {
>              GOTMP.1 = b_;
>              _1 = ~GOTMP.1;
>              if (_1 != 0) goto <D.2721>; else goto <D.2722>;
>              <D.2721>:
>              {
>                GOTMP.1 = c_;
>              }
>              <D.2722>:
>            }
>            GOTMP.2 = GOTMP.1;
>            GOTMP.0 = GOTMP.2;
>          }
>          <D.2720>:
>        }
>        if (GOTMP.0 != 0) goto <D.2723>; else goto <D.2724>;
>        <D.2723>:
>
>
>
>        {
>          {
>            $ret0 = 1;
>            D.2725 = $ret0;
>            // predicted unlikely by early return (on trees) predictor.
>            return D.2725;
>          }
>        }
>        <D.2724>:
>        {
>          {
>            $ret0 = 0;
>            D.2725 = $ret0;
>            // predicted unlikely by early return (on trees) predictor.
>            return D.2725;
>          }
>        }
>      }
>    }
> }
>
> Where as D (and C) is more-or-less as you would expect:
>
> int fn (int a, int b, int c)
>
>
>
> {
>    int D.7895;
>
>    if (a != 0) goto <D.7893>; else goto <D.7891>;
>    <D.7893>:
>    if (b != 0) goto <D.7892>; else goto <D.7894>;
>    <D.7894>:
>    if (c != 0) goto <D.7892>; else goto <D.7891>;
>    <D.7892>:
>    D.7895 = a;
>    // predicted unlikely by early return (on trees) predictor.
>    return D.7895;
>    <D.7891>:
>    D.7895 = b * c;
>    // predicted unlikely by early return (on trees) predictor.
>    return D.7895;
> }
>
> Clearly the decision inference algorithm is unable to properly
> instrument to Go program for condition coverage because of the use of
> temporaries in the emitted GIMPLE. The question is: is this intentional
> and/or required from Go's semantics or could it be considered a defect?
> Is emitting the GIMPLE without the use of temporaries feasible at all?

The Go frontend converts && and || expressions into code that uses
explicit if statements.  This is done largely as an internal
simplification.  Go has rules about the order in which function calls
and certain other kinds of expressions must be evaluated.  Separating
out the order of evaluation imposed by && and || simplifies the
implementation of the other order of evaluation rules.

Ian

      parent reply	other threads:[~2022-08-11  0:50 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-08-03 13:25 j
2022-08-10 11:30 ` Martin Liška
2022-08-11  0:49 ` Ian Lance Taylor [this message]

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='CAKOQZ8yO=1P4NcJpGWD5QF3PKKveWm_jhck0J11O9TvY_tpesg@mail.gmail.com' \
    --to=iant@google.com \
    --cc=gcc@gcc.gnu.org \
    --cc=j@lambda.is \
    /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).