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

            Bug ID: 92128
           Summary: fold more non-constant strlen relational expressions
           Product: gcc
           Version: 9.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: ---

With pr91996 resolved GCC can make use of strlen range information in some
contexts but not in others.  The test for pr91996 only enabled on a subset of
those where GCC is known to be able to do this, but even for those it is
specially crafted to exercise only the contexts where the optimization was
implemented.  On other targets (e.g., arm-*-*), or even on others such as
aarch64-*-* where the test passes, other similar test cases fail.  This is
because the solution for pr91996 was only put in place for multi-byte
assignments via MEM_REF but not also for calls to memcpy.

$ cat c.c && gcc -O2 -S -Wall -fdump-tree-optimized=/dev/stdout c.c
typedef __SIZE_TYPE__ size_t;

void f (char *d, const char *s)
{
  if (__builtin_strlen (s) < 5) return;

  __builtin_memcpy (d, s, 16);         // when size is a small power of two

  size_t n1 = __builtin_strlen (d);
  if (n1 < 5)                          // this is folded to false
    __builtin_abort ();
}

void g (char *d, const char *s)
{
  if (__builtin_strlen (s) < 5) return;

  __builtin_memcpy (d, s, 32);         // with larger power of two or
non-power-of-two sizes

  size_t n1 = __builtin_strlen (d);
  if (n1 < 5)                          // this is not folded
    __builtin_abort ();
}


;; Function f (f, funcdef_no=0, decl_uid=1932, cgraph_uid=1, symbol_order=0)

Removing basic block 5
f (char * d, const char * s)
{
  long unsigned int _1;
  __int128 unsigned _5;

  <bb 2> [local count: 1073741824]:
  _1 = __builtin_strlen (s_4(D));
  if (_1 <= 4)
    goto <bb 4>; [34.00%]
  else
    goto <bb 3>; [66.00%]

  <bb 3> [local count: 708669605]:
  _5 = MEM <__int128 unsigned> [(char * {ref-all})s_4(D)];
  MEM <__int128 unsigned> [(char * {ref-all})d_6(D)] = _5;

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

}



;; Function g (g, funcdef_no=1, decl_uid=1937, cgraph_uid=2, symbol_order=1)

Removing basic block 6
Removing basic block 7
g (char * d, const char * s)
{
  size_t n1;
  long unsigned int _1;

  <bb 2> [local count: 1073741824]:
  _1 = __builtin_strlen (s_4(D));
  if (_1 <= 4)
    goto <bb 5>; [51.12%]
  else
    goto <bb 3>; [48.88%]

  <bb 3> [local count: 524845004]:
  __builtin_memcpy (d_5(D), s_4(D), 32);
  n1_7 = __builtin_strlen (d_5(D));
  if (n1_7 <= 4)
    goto <bb 4>; [0.00%]
  else
    goto <bb 5>; [100.00%]

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

  <bb 5> [local count: 1073741828]:
  return;

}

Reply via email to