(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.dg/
strlenopt-20.c
       1  /* { dg-do run } */
       2  /* { dg-options "-O2 -fdump-tree-strlen" } */
       3  
       4  #include "strlenopt.h"
       5  
       6  __attribute__((noinline, noclone)) const char *
       7  fn1 (int x, int y)
       8  {
       9    const char *p;
      10    switch (x)
      11      {
      12      case 0:
      13        p = "abcd";
      14        /* Prevent cswitch optimization.  */
      15        asm volatile ("" : : : "memory");
      16        break;
      17      case 1:
      18        p = "efgh";
      19        break;
      20      case 2:
      21        p = "ijkl";
      22        break;
      23      default:
      24        p = "mnop";
      25        break;
      26      }
      27    if (y)
      28      /* strchr should be optimized into p + 4 here.  */
      29      return strchr (p, '\0');
      30    else
      31      /* and strlen into 3.  */
      32      return p + strlen (p + 1);
      33  }
      34  
      35  __attribute__((noinline, noclone)) size_t
      36  fn2 (char *p, char *q)
      37  {
      38    size_t l;
      39    /* Both strcpy calls can be optimized into memcpy, strlen needs to stay.  */
      40    strcpy (p, "abc");
      41    p[3] = 'd';
      42    l = strlen (p);
      43    strcpy (q, p);
      44    return l;
      45  }
      46  
      47  __attribute__((noinline, noclone)) char *
      48  fn3 (char *p)
      49  {
      50    char *c;
      51    /* The strcpy call can be optimized into memcpy, strchr needs to stay,
      52       strcat is optimized into memcpy.  */
      53    strcpy (p, "abc");
      54    p[3] = 'd';
      55    c = strchr (p, '\0');
      56    strcat (p, "efgh");
      57    return c;
      58  }
      59  
      60  int
      61  main ()
      62  {
      63    int i;
      64    char buf[64], buf2[64];
      65    for (i = 0; i < 5; i++)
      66      {
      67        const char *p = "abcdefghijklmnop" + (i < 3 ? i : 3) * 4;
      68        const char *q;
      69        q = fn1 (i, 1);
      70        if (memcmp (q - 4, p, 4) != 0 || q[0] != '\0')
      71  	abort ();
      72        q = fn1 (i, 0);
      73        if (memcmp (q - 3, p, 4) != 0 || q[1] != '\0')
      74  	abort ();
      75      }
      76    memset (buf, '\0', sizeof buf);
      77    memset (buf + 4, 'z', 2);
      78    if (fn2 (buf, buf2) != 6
      79        || memcmp (buf, "abcdzz", 7) != 0
      80        || memcmp (buf2, "abcdzz", 7) != 0)
      81      abort ();
      82    memset (buf, '\0', sizeof buf);
      83    memset (buf + 4, 'z', 2);
      84    if (fn3 (buf) != buf + 6 || memcmp (buf, "abcdzzefgh", 11) != 0)
      85      abort ();
      86    return 0;
      87  }
      88  
      89  /* { dg-final { scan-tree-dump-times "strlen \\(" 2 "strlen1" } } */
      90  /* { dg-final { scan-tree-dump-times "memcpy \\(" 4 "strlen1" } } */
      91  /* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen1" } } */
      92  /* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen1" } } */
      93  /* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen1" } } */
      94  /* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen1" } } */