public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* gccgo emits GIMPLE with temporaries for boolean expressions unlike gcc, gdc
@ 2022-08-03 13:25 j
  2022-08-10 11:30 ` Martin Liška
  2022-08-11  0:49 ` Ian Lance Taylor
  0 siblings, 2 replies; 3+ messages in thread
From: j @ 2022-08-03 13:25 UTC (permalink / raw)
  To: gcc


Hello,

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?

Thanks,
Jørgen

[1] https://gcc.gnu.org/pipermail/gcc-patches/2022-July/598165.html

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2022-08-11  0:50 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-08-03 13:25 gccgo emits GIMPLE with temporaries for boolean expressions unlike gcc, gdc j
2022-08-10 11:30 ` Martin Liška
2022-08-11  0:49 ` Ian Lance Taylor

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).