[Bug tree-optimization/90710] Bogus Wmaybe-uninitialized caused by __builtin_expect when compiled with -Og

2021-04-06 Thread msebor at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90710

--- Comment #4 from Martin Sebor  ---
Here's a smaller test case showing both the problem (first gcc invocation) and
how it can be avoided (second invocation):

$ (set -x && cat pr90710.c && gcc -Og -S -Wall pr90710.c && gcc -Dint=long -Og
-S -Wall pr90710.c)
+ cat pr90710.c
static inline int f (int x, int *p)
{
  if (x == 0)
return 0;

  *p = x;
  return 1;
}

volatile int z;

void g (int x)
{
  int b, a = f (x, );

  if (a)
z = b;

  if (__builtin_expect (a, 1))
z = b;
}
+ gcc -Og -S -Wall pr90710.c
pr90710.c: In function ‘g’:
pr90710.c:20:7: warning: ‘b’ may be used uninitialized in this function
[-Wmaybe-uninitialized]
   20 | z = b;
  | ~~^~~
pr90710.c:14:7: note: ‘b’ was declared here
   14 |   int b, a = f (x, );
  |   ^
+ gcc -Dint=long -Og -S -Wall pr90710.c

[Bug tree-optimization/90710] Bogus Wmaybe-uninitialized caused by __builtin_expect when compiled with -Og

2021-04-06 Thread msebor at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90710

Martin Sebor  changed:

   What|Removed |Added

   Last reconfirmed|2019-06-02 00:00:00 |2021-4-6
  Known to fail||10.2.1, 11.0, 9.3.0
 CC||msebor at gcc dot gnu.org

--- Comment #3 from Martin Sebor  ---
Reconfirmed with GCC 11.  My enhanced version of trunk under test prints:

pr90710.c: In function ‘testFunction’:
pr90710.c:22:17: warning: ‘value’ may be used uninitialized in this function
[-Wmaybe-uninitialized]
   22 | printf("My if() causes -Wmaybe-uninitialized for my use
of `value': %d\n",value);
  |
^~~~
pr90710.c:17:22: note: when ‘x == 0’
   17 | unsigned int value;
  |  ^
pr90710.c:17:22: note: used when ‘_11 = PHI <0(3), 1(9)> != 0’
pr90710.c:17:22: note: ‘value’ was declared here


The IL the warning sees (annotated with my comments) is below.  The predicate
that guards the possibly uninitialized use is (was_ok_8 != 0 && was_ok_8 == 0),
which the warning should be able to determine is false.  It doesn't because, as
a result of the __builtin_expect() intrinsic which converts the first argument
to long int, the assignment 'was_ok_8 = (int) _11' in bb 4 involves a
conversion that the warning code doesn't handle.  Changing the type of the
variables to long avoids the warning.

__attribute__((noinline))
void testFunction ()
{
  int was_ok;
  unsigned int value;
  volatile unsigned int x;
  unsigned int x.0_1;
  long int _2;
  unsigned int _11;

   [local count: 1073741824]:
  # .MEM_7 = VDEF <.MEM_6(D)>
  x ={v} 1;
  # VUSE <.MEM_7>
  x.0_1 ={v} x;
  if (x.0_1 == 0)
goto ; [34.00%]
  else
goto ; [66.00%]

   [local count: 708669600]:
  goto ; [100.00%]

   [local count: 365072224]:

   [local count: 1073741824]:
  # _11 = PHI <0(3), 1(9)>
  # value_12 = PHI 
  was_ok_8 = (int) _11;<<< int to long conversion gets in the way
  if (was_ok_8 != 0)
goto ; [33.00%]
  else
goto ; [67.00%]  <<< was_ok_8 == 0

   [local count: 719407024]:
  goto ; [100.00%]

   [local count: 354334800]:
  # .MEM_9 = VDEF <.MEM_7>
  printf ("My if() compiles fine: %d\n", value_12);

   [local count: 1073741824]:
  # .MEM_4 = PHI <.MEM_7(10), .MEM_9(5)>
  _2 = (long int) was_ok_8;
  if (_2 != 0)
goto ; [90.00%]   <<< was_ok_8 != 0
  else
goto ; [10.00%]

   [local count: 107374184]:
  goto ; [100.00%]

   [local count: 966367641]:
  ## value_12 used when was_ok_8 != 0 AND was_ok_8 == 0   <<< must be false
  # .MEM_10 = VDEF <.MEM_4>
  printf ("My if() causes -Wmaybe-uninitialized for my use of `value\': %d\n",
value_12);

   [local count: 1073741824]:
  # .MEM_5 = PHI <.MEM_4(11), .MEM_10(7)>
  # VUSE <.MEM_5>
  return;

}

[Bug tree-optimization/90710] Bogus Wmaybe-uninitialized caused by __builtin_expect when compiled with -Og

2019-06-02 Thread sagebar at web dot de
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90710

--- Comment #2 from sagebar at web dot de ---
(In reply to Jeffrey A. Law from comment #1)
> We focus most of our effort on avoiding false positives with -O2
> optimization levels.  As you lower the optimization level (-Og) you will
> almost certainly run into these kinds of issues.
> 
> Elimination of false positive uninitialized warnings is highly dependent
> upon what we call "jump threading".  The purpose of jump threading is to
> realize that certain paths through the CFG are not possible and to use block
> copying to isolate and remove those paths.  At lower optimization levels the
> compiler does not aggressively thread jumps and thus can leave unexecutable
> paths in the CFG which leads to the false positive warning.
> 
> The use of builtin_expect can have these effects too as it impacts the cost
> analysis done during jump threading to determine the cost/benefit of block
> copying  to isolate the path.
> 
> 
> So confirmed, but not likely something we'll fix in the near future.

Thanks for taking the time to explain the what-s and why-s. Dealing with a
long-time -O3-compiled codebase (always having optimizations at max prevents
nasty surprises later), I was originally trying to use -Og to improve the
quality of .debug_info for gdb (I read somewhere that that -Og's supposed to be
used for), but for anyone else that has the same Problem and finds this, I
managed to get it to work well enough by simply not passing any -O* flags for
the time being.

[Bug tree-optimization/90710] Bogus Wmaybe-uninitialized caused by __builtin_expect when compiled with -Og

2019-06-02 Thread law at redhat dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90710

Jeffrey A. Law  changed:

   What|Removed |Added

 Status|UNCONFIRMED |NEW
   Last reconfirmed||2019-06-02
 CC||law at redhat dot com
 Ever confirmed|0   |1

--- Comment #1 from Jeffrey A. Law  ---
We focus most of our effort on avoiding false positives with -O2 optimization
levels.  As you lower the optimization level (-Og) you will almost certainly
run into these kinds of issues.

Elimination of false positive uninitialized warnings is highly dependent upon
what we call "jump threading".  The purpose of jump threading is to realize
that certain paths through the CFG are not possible and to use block copying to
isolate and remove those paths.  At lower optimization levels the compiler does
not aggressively thread jumps and thus can leave unexecutable paths in the CFG
which leads to the false positive warning.

The use of builtin_expect can have these effects too as it impacts the cost
analysis done during jump threading to determine the cost/benefit of block
copying  to isolate the path.


So confirmed, but not likely something we'll fix in the near future.