[Bug tree-optimization/81776] New: missing sprintf optimization due to pointer escape analysis

msebor at gcc dot gnu.org gcc-bugzilla@gcc.gnu.org
Wed Aug 9 02:26:00 GMT 2017


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

            Bug ID: 81776
           Summary: missing sprintf optimization due to pointer escape
                    analysis
           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: ---

When a built-in function like memcpy or strcpy is called with a local buffer
GCC knows that the call doesn't clobber other local buffers.  But the analysis
seems to be missing a case to make the same determination for calls to sprintf
or snprintf.  As a result, as the following case shows, when sprintf if
transformed to strcpy, GCC successfully optimizes away the test and subsequent
call to abort in g1().  But when the same sprintf to strcpy transformation is
defeated by using the '-' flag in the "%-s" directive, GCC fails to make the
same optimization in g2().

$ cat a.c && gcc -O2 -S -Wall -fdump-tree-optimized=/dev/stdout b.c
void f (void*);

struct S { char *a, *b; };

void g1 (struct S *p, const char *s, unsigned n)
{
  p->a = __builtin_malloc (n + 1);
  p->a[0] = 123;

  p->b = __builtin_malloc (n + 1);

  __builtin_sprintf (p->b, "%s", s);

  if (p->a[0] != 123)     // can never be true
    __builtin_abort ();   // eliminated

  __builtin_sprintf (p->b, "%s", s);

  f (p);
}

void g2 (struct S *p, const char *s, unsigned n)
{
  p->a = __builtin_malloc (n + 1);
  p->a[0] = 123;

  p->b = __builtin_malloc (n + 1);

  __builtin_sprintf (p->b, "%-s", s);

  if (p->a[0] != 123)     // can never be true
    __builtin_abort ();   // not eliminated

  __builtin_sprintf (p->a, "%-s", s);

  f (p);
}

;; Function g1 (g1, funcdef_no=0, decl_uid=1822, cgraph_uid=0, symbol_order=0)

g1 (struct S * p, const char * s, unsigned int n)
{
  unsigned int _1;
  long unsigned int _2;
  void * _3;
  void * _4;

  <bb 2> [100.00%] [count: INV]:
  _1 = n_8(D) + 1;
  _2 = (long unsigned int) _1;
  _3 = __builtin_malloc (_2);
  p_11(D)->a = _3;
  MEM[(char *)_3] = 123;
  _4 = __builtin_malloc (_2);
  p_11(D)->b = _4;
  __builtin_strcpy (_4, s_16(D));
  __builtin_strcpy (_4, s_16(D));
  f (p_11(D)); [tail call]
  return;

}



;; Function g2 (g2, funcdef_no=1, decl_uid=1827, cgraph_uid=1, symbol_order=1)

g2 (struct S * p, const char * s, unsigned int n)
{
  unsigned int _1;
  long unsigned int _2;
  void * _3;
  void * _4;
  char * _5;
  char _6;

  <bb 2> [100.00%] [count: INV]:
  _1 = n_7(D) + 1;
  _2 = (long unsigned int) _1;
  _3 = __builtin_malloc (_2);
  p_10(D)->a = _3;
  MEM[(char *)_3] = 123;
  _4 = __builtin_malloc (_2);
  p_10(D)->b = _4;
  __builtin_sprintf (_4, "%-s", s_15(D));
  _5 = p_10(D)->a;
  _6 = *_5;
  if (_6 != 123)
    goto <bb 3>; [0.04%] [count: 0]
  else
    goto <bb 4>; [99.96%] [count: INV]

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

  <bb 4> [99.96%] [count: INV]:
  __builtin_sprintf (_5, "%-s", s_15(D));
  f (p_10(D)); [tail call]
  return;

}


More information about the Gcc-bugs mailing list