1  /* PR tree-optimization/91183 - strlen of a strcpy result with a conditional
       2     source not folded
       3     Test to verify that strlen can determine string lengths from wider stores
       4     than narrow characters.  This matters because on targets that can handle
       5     unaligned stores and where GCC lowers multi-character stores into smaller
       6     numbers of wider stores.
       7     { dg-do compile }
       8     { dg-options "-O2 -fdump-tree-optimized" }
       9     On strictly aligned targets the consecutive char assignments used
      10     by the test aren't merged.  When they involve multiple trailing nuls
      11     these assignments then defeat the strlen optimization as a result of
      12     pr83821.  When the bug is resolved the directive below can be removed.
      13     { dg-require-effective-target non_strict_align } */
      14  
      15  #include "strlenopt.h"
      16  
      17  #define CAT(x, y) x ## y
      18  #define CONCAT(x, y) CAT (x, y)
      19  #define FAILNAME(name) CONCAT (call_ ## name ##_on_line_, __LINE__)
      20  
      21  #define FAIL(name) do {				\
      22      extern void FAILNAME (name) (void);		\
      23      FAILNAME (name)();				\
      24    } while (0)
      25  
      26  /* Macros to emit a call to function named
      27       call_failed_to_be_eliminated_on_line_NNN()
      28     for each call that's expected to be eliminated.  The dg-final
      29     scan-tree-dump-time directive at the bottom of the test verifies
      30     that no such call appears in output.  */
      31  #define ELIM(expr)					\
      32    if ((expr)) FAIL (not_eliminated); else (void)0
      33  
      34  #undef T
      35  #define T(N, ncpy, expect, assign) do {				\
      36      char a[N], b[N];						\
      37      assign;							\
      38      memcpy (b, a, ncpy);					\
      39      ELIM (!(expect == strlen (b)));				\
      40    } while (0)
      41  
      42  void test_copy (void)
      43  {
      44    T (2, 1, 0, (a[0] = 0));
      45    T (2, 2, 0, (a[0] = 0, a[1] = 0));
      46    T (2, 2, 1, (a[0] = '1', a[1] = 0));
      47    T (4, 3, 2, (a[0] = '1', a[1] = '2', a[2] = 0));
      48    // Not handled due to pr83821:
      49    // T (4, 3, 1, (a[0] = '1', a[1] = 0, a[2] = '2'));
      50    T (4, 2, 1, (a[0] = '1', a[1] = 0,   a[2] = 0,   a[3] = 0));
      51    // Not handled due to pr83821:
      52    // T (4, 3, 1, (a[0] = '1', a[1] = 0,   a[2] = 0,   a[3] = 0));
      53    T (4, 4, 1, (a[0] = '1', a[1] = 0,   a[2] = 0,   a[3] = 0));
      54    T (4, 3, 2, (a[0] = '1', a[1] = '2', a[2] = 0,   a[3] = 0));
      55    T (4, 4, 2, (a[0] = '1', a[1] = '2', a[2] = 0,   a[3] = 0));
      56    T (4, 4, 3, (a[0] = '1', a[1] = '2', a[2] = '3', a[3] = 0));
      57    T (5, 4, 1, (a[0] = '1', a[1] = 0,   a[2] = 0,   a[3] = 0));
      58    T (5, 4, 2, (a[0] = '1', a[1] = '2', a[2] = 0,   a[3] = 0));
      59    T (5, 4, 3, (a[0] = '1', a[1] = '2', a[2] = '3', a[3] = 0));
      60    // Not handled:
      61    // T (5, 5, 1, (a[0] = '1', a[1] = 0,   a[2] = 0,   a[3] = 0,   a[4] = 0));
      62    // T (5, 5, 2, (a[0] = '1', a[1] = '2', a[2] = 0,   a[3] = 0,   a[4] = 0));
      63    // T (5, 5, 3, (a[0] = '1', a[1] = '2', a[2] = '3', a[3] = 0,   a[4] = 0));
      64    T (5, 5, 4, (a[0] = '1', a[1] = '2', a[2] = '3', a[3] = '4', a[4] = 0));
      65  }
      66  
      67  
      68  /* { dg-final { scan-tree-dump-times "strlen" 0 "optimized" } }
      69     { dg-final { scan-tree-dump-times "_not_eliminated_" 0 "optimized" } } */