[Bug tree-optimization/97185] New: inconsistent builtin elimination for impossible range

msebor at gcc dot gnu.org gcc-bugzilla@gcc.gnu.org
Wed Sep 23 20:18:52 GMT 2020


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

            Bug ID: 97185
           Summary: inconsistent builtin elimination for impossible range
           Product: gcc
           Version: 11.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: msebor at gcc dot gnu.org
  Target Milestone: ---

In the test case below GCC eliminates the memcpy and memmove calls because the
only valid bound they are called with is zero.  But the same optimization isn't
done for the any of the remaining calls, including memset, resulting in
warnings noting that the range is (most likely) invalid.  GCC should be
consistent and either eliminate all the calls (preferably), or none of them.

$ cat z.c && gcc -O2 -S -fdump-tree-optimized=/dev/stdout z.c
void f0 (void *p, const void *q, int n)
{ 
  if (n > 0) return;
  __builtin_memcpy (p, q, n);
}

void f1 (void *p, const void *q, int n)
{
  if (n > 0) return;
  __builtin_memmove (p, q, n);
}

void f2 (char *p, const char *q, int n)
{
  if (n > 0) return;
  __builtin_strncpy (p, q, n);
}

void f3 (void *p, int n)
{ 
  if (n > 0) return;
  __builtin_memset (p, 0, n);
}

void* f4 (const void *p, int n)
{
  if (n > 0) return 0;
  return __builtin_memchr (p, 0, n);
}

int f5 (const void *p, const void *q, int n)
{
  if (n > 0) return 0;
  return __builtin_memcmp (p, q, n);
}


;; Function f0 (f0, funcdef_no=0, decl_uid=1933, cgraph_uid=1, symbol_order=0)

f0 (void * p, const void * q, int n)
{
  <bb 2> [local count: 1073741824]:
  return;

}



;; Function f1 (f1, funcdef_no=1, decl_uid=1938, cgraph_uid=2, symbol_order=1)

f1 (void * p, const void * q, int n)
{
  <bb 2> [local count: 1073741824]:
  return;

}



;; Function f2 (f2, funcdef_no=2, decl_uid=1943, cgraph_uid=3, symbol_order=2)

Removing basic block 5
f2 (char * p, const char * q, int n)
{
  long unsigned int _1;

  <bb 2> [local count: 1073741824]:
  if (n_3(D) > 0)
    goto <bb 4>; [60.08%]
  else
    goto <bb 3>; [39.92%]

  <bb 3> [local count: 428637736]:
  _1 = (long unsigned int) n_3(D);
  __builtin_strncpy (p_5(D), q_6(D), _1); [tail call]

  <bb 4> [local count: 1073741824]:
  return;

}


z.c: In function ‘f2’:
z.c:16:3: warning: ‘__builtin_strncpy’ specified size between
18446744071562067968 and 0 exceeds maximum object size 9223372036854775807
[-Wstringop-overflow=]
   16 |   __builtin_strncpy (p, q, n);
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~

;; Function f3 (f3, funcdef_no=3, decl_uid=1947, cgraph_uid=4, symbol_order=3)

Removing basic block 5
f3 (void * p, int n)
{
  long unsigned int _1;

  <bb 2> [local count: 1073741824]:
  if (n_3(D) > 0)
    goto <bb 4>; [60.08%]
  else
    goto <bb 3>; [39.92%]

  <bb 3> [local count: 428637736]:
  _1 = (long unsigned int) n_3(D);
  __builtin_memset (p_5(D), 0, _1); [tail call]

  <bb 4> [local count: 1073741824]:
  return;

}


z.c: In function ‘f3’:
z.c:22:3: warning: ‘__builtin_memset’ specified size between
18446744071562067968 and 18446744073709551615 exceeds maximum object size
9223372036854775807 [-Wstringop-overflow=]
   22 |   __builtin_memset (p, 0, n);
      |   ^~~~~~~~~~~~~~~~~~~~~~~~~~

;; Function f4 (f4, funcdef_no=4, decl_uid=1951, cgraph_uid=5, symbol_order=4)

Removing basic block 5
f4 (const void * p, int n)
{
  long unsigned int _1;
  void * _2;
  void * _6;

  <bb 2> [local count: 1073741824]:
  if (n_3(D) > 0)
    goto <bb 4>; [23.24%]
  else
    goto <bb 3>; [76.76%]

  <bb 3> [local count: 824204225]:
  _1 = (long unsigned int) n_3(D);
  _6 = __builtin_memchr (p_5(D), 0, _1); [tail call]

  <bb 4> [local count: 1073741824]:
  # _2 = PHI <_6(3), 0B(2)>
  return _2;

}


z.c: In function ‘f4’:
z.c:28:10: warning: ‘__builtin_memchr’ specified bound [18446744071562067968,
0] exceeds maximum object size 9223372036854775807 [-Wstringop-overread]
   28 |   return __builtin_memchr (p, 0, n);
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~

;; Function f5 (f5, funcdef_no=5, decl_uid=1956, cgraph_uid=6, symbol_order=5)

Removing basic block 5
f5 (const void * p, const void * q, int n)
{
  long unsigned int _1;
  int _2;
  int _7;

  <bb 2> [local count: 1073741824]:
  if (n_3(D) > 0)
    goto <bb 4>; [42.57%]
  else
    goto <bb 3>; [57.43%]

  <bb 3> [local count: 616649929]:
  _1 = (long unsigned int) n_3(D);
  _7 = __builtin_memcmp (p_5(D), q_6(D), _1); [tail call]

  <bb 4> [local count: 1073741824]:
  # _2 = PHI <_7(3), 0(2)>
  return _2;

}


z.c: In function ‘f5’:
z.c:34:10: warning: ‘__builtin_memcmp’ specified bound [18446744071562067968,
0] exceeds maximum object size 9223372036854775807 [-Wstringop-overread]
   34 |   return __builtin_memcmp (p, q, n);
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~


More information about the Gcc-bugs mailing list