1  /* PR tree-optimization/92226 - live nul char store to array eliminated
       2     { dg-do compile }
       3     { dg-options "-O2 -fdump-tree-strlen" } */
       4  
       5  #include "strlenopt.h"
       6  
       7  #define NOIPA __attribute__ ((noipa))
       8  
       9  #define T(MIN, MAX, SIZE, IDX)						\
      10    NOIPA void								\
      11    test_ ## MIN ## _ ## MAX ## _ ## SIZE ## _ ## IDX (const char *s)	\
      12    {									\
      13      extern char a ## SIZE[SIZE];					\
      14      char *d = a ## SIZE;						\
      15      size_t len = strlen (s);						\
      16      size_t idx = IDX;							\
      17      if (MIN <= len && len <= MAX)					\
      18        {									\
      19  	strcpy (d, s);							\
      20  	d[idx] = 0;							\
      21  	if (strlen (d) != idx)						\
      22  	  abort ();							\
      23        }									\
      24    } typedef void dummy_type
      25  
      26  
      27  /* The final nul store must be retained but the second strlen call should
      28     be eliminated because the final length of the destination after the nul
      29     store must be equal to the index of the store.  */
      30  T (0, 2, 4, 0);
      31  
      32  /* Not handled yet (see below):
      33     T (0, 2, 4, 1);  */
      34  
      35  /* Not handled yet: in addition to the cases above, the second strlen
      36     call can also be eliminated in those below because in both the final
      37     length of the destination after the nul store must be in the same
      38     range as the length of the source.
      39     T (0, 2, 4, 2);
      40     T (0, 2, 4, 3);  */
      41  
      42  T (2, 3, 4, 0);
      43  T (2, 3, 4, 1);
      44  
      45  /* Not handled yet (see above):
      46     T (2, 3, 4, 2);
      47     T (2, 3, 4, 3);  */
      48  
      49  T (3, 4, 5, 0);
      50  T (3, 4, 5, 1);
      51  T (3, 4, 5, 2);
      52  
      53  /* Not handled yet (see above):
      54     T (3, 4, 5, 3);
      55     T (3, 4, 5, 4);  */
      56  
      57  T (3, 4, 6, 0);
      58  T (3, 4, 6, 1);
      59  T (3, 4, 6, 2);
      60  
      61  /* Not handled yet (see above):
      62     T (3, 4, 6, 3);
      63     T (3, 4, 6, 4);
      64     T (3, 4, 6, 5);  */
      65  
      66  
      67  /* Verify that each function makes just one call to strlen to compute
      68     the length of its argument (and not also to compute the length of
      69     the copy):
      70    { dg-final { scan-tree-dump-times "strlen \\(s_" 9 "strlen1" } }
      71    { dg-final { scan-tree-dump-not "strlen \\(\\&a" "strlen1" } }
      72  
      73    Verify that nul stores into the destination have not been eliminated:
      74    { dg-final { scan-tree-dump-times "a4\\\] = 0;" 2 "strlen1" } }
      75    { dg-final { scan-tree-dump-times "a4 \\\+ 1B\\\] = 0;" 1 "strlen1" } }
      76  
      77    { dg-final { scan-tree-dump-times "a5\\\] = 0;" 1 "strlen1" } }
      78    { dg-final { scan-tree-dump-times "a5 \\\+ 1B\\\] = 0;" 1 "strlen1" } }
      79    { dg-final { scan-tree-dump-times "a5 \\\+ 2B\\\] = 0;" 1 "strlen1" } }
      80  
      81    { dg-final { scan-tree-dump-times "a6\\\] = 0;" 1 "strlen1" } }
      82    { dg-final { scan-tree-dump-times "a6 \\\+ 1B\\\] = 0;" 1 "strlen1" } }
      83    { dg-final { scan-tree-dump-times "a6 \\\+ 2B\\\] = 0;" 1 "strlen1" } }  */