https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95699

            Bug ID: 95699
           Summary: __builtin_constant_p inconsistencies
           Product: gcc
           Version: 10.1.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
          Assignee: unassigned at gcc dot gnu.org
          Reporter: vincent-gcc at vinc17 dot net
  Target Milestone: ---

Consider the following code on x86_64 (written for a 64-bit long), compiled
with -O2.

With gcc-9 (Debian 9.3.0-13) 9.3.0, I get:
0
1
1

With gcc-10 (Debian 10.1.0-3) 10.1.0, I get:
0
1
0

I'm not sure about the exact __builtin_constant_p specification, i.e. whether
it may be duplicated into two branches so that the argument can become a
constant for GCC (I think it should as this may allow the selection of code
optimized for constants), and how this can be influenced by "volatile".

But the first two cases are very similar, so that I would expect the same
value, but I get 0 / 1 with both GCC 9 and GCC 10. Concerning the third case,
the constantness has been lost in GCC 10, which is unexpected if a result 1 is
allowed.

Moreover, if I remove the second condition ("&& ...") in the printf, I always
get 0 (i.e. false), which is counter-intuitive: adding a "&& ..." condition
should never change a false condition to true (the results 1 I obtain above).

int printf (const char *__restrict __format, ...);

#undef C
#define C 0x7fffffffffffffffUL

static void tst1a (void)
{
  volatile unsigned long r0 = 0;
  unsigned long r;

  r = r0;
  if (r < C)
    r = C;

  printf ("%d\n", __builtin_constant_p (r) && r == C);
}

#undef C
#define C 0x8000000000000000UL

static void tst1b (void)
{
  volatile unsigned long r0 = 0;
  unsigned long r;

  r = r0;
  if (r < C)
    r = C;

  printf ("%d\n", __builtin_constant_p (r) && r == C);
}

static void tst2 (void)
{
  volatile unsigned long r0 = 0;
  unsigned long r;

  r = r0;
  if (r < 0x8000000000000000)
    r = 0x8000000000000000;
  r *= r;

  printf ("%d\n", __builtin_constant_p (r) && r < 1);
}

int main (void)
{
  tst1a ();
  tst1b ();
  tst2 ();
  return 0;
}

Reply via email to