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

            Bug ID: 82912
           Summary: missing strlen optimization for stpncpy with constant
                    string and bound
           Product: gcc
           Version: 8.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: ---

GCC can figure out the length of the string created by the call to strncpy() in
f0() but it doesn't do the same for stpncpy() in f2() or f3().

Using stpncpy() the way f2() and f3() do is idiomatic and often preferred
because it is assumed to be more efficient than the equivalent sequence
involving strncpy().

See also pr82911 for a similar missed optimization opportunity involving
strncpy().

$ cat c.c && gcc -O2 -S -Wall -Wextra -fdump-tree-optimized=/dev/stdout c.c
void f0 (char *d)
{
  __builtin_strncpy (d, "123", 2);
  d[2] = 0;

  if (__builtin_strlen (d) != 2)   // eliminated, good
    __builtin_abort ();
}

void f2 (char *d)
{
  *__builtin_stpncpy (d, "123", 2) = 0;

  if (__builtin_strlen (d) != 2)   // not eliminated but should be
    __builtin_abort ();
}

void f3 (char *d, _Bool b)
{
  *__builtin_stpncpy (d, b ? "123" : "1234", 2) = 0;

  if (__builtin_strlen (d) != 2)   // not eliminated but could be
    __builtin_abort ();
}

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

f0 (char * d)
{
  <bb 2> [local count: 10000]:
  __builtin_memcpy (d_3(D), "123", 2);
  MEM[(char *)d_3(D) + 2B] = 0;
  return;

}



;; Function f2 (f2, funcdef_no=1, decl_uid=1890, cgraph_uid=1, symbol_order=1)

f2 (char * d)
{
  char * _1;
  long unsigned int _2;

  <bb 2> [local count: 10000]:
  _1 = __builtin_stpncpy (d_4(D), "123", 2);
  *_1 = 0;
  _2 = __builtin_strlen (d_4(D));
  if (_2 != 2)
    goto <bb 3>; [0.04%]
  else
    goto <bb 4>; [99.96%]

  <bb 3> [count: 0]:
  __builtin_abort ();

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

}



;; Function f3 (f3, funcdef_no=2, decl_uid=1894, cgraph_uid=2, symbol_order=2)

f3 (char * d, _Bool b)
{
  char * _1;
  long unsigned int _2;
  const char * iftmp.0_3;

  <bb 2> [local count: 10000]:
  if (b_4(D) != 0)
    goto <bb 4>; [50.00%]
  else
    goto <bb 3>; [50.00%]

  <bb 3> [local count: 5000]:

  <bb 4> [local count: 10000]:
  # iftmp.0_3 = PHI <"123"(2), "1234"(3)>
  _1 = __builtin_stpncpy (d_6(D), iftmp.0_3, 2);
  *_1 = 0;
  _2 = __builtin_strlen (d_6(D));
  if (_2 != 2)
    goto <bb 5>; [0.04%]
  else
    goto <bb 6>; [99.96%]

  <bb 5> [count: 0]:
  __builtin_abort ();

  <bb 6> [local count: 9996]:
  return;

}

Reply via email to