(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.dg/
strlenopt-73.c
       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 stores
       4     involving PHI nodes with distinct strings of the same length of at
       5     least 16 bytes.
       6  
       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  #define T(expect, N, ncpy, cond) do {		\
      35      char CONCAT (arr_, __LINE__)[N];		\
      36      char *pa = CONCAT (arr_, __LINE__);		\
      37      memcpy (pa, cond, ncpy);			\
      38      ELIM (!(expect strlen (pa)));		\
      39      sink (pa);					\
      40    } while (0)
      41  
      42  void sink (void*);
      43  
      44  const char a32[33] = "0123456789abcdef0123456789abcdef";
      45  const char b32[33] = "fedcba9876543210fedcba9876543210";
      46  
      47  const char a16[33] = "0123456789abcdef";
      48  const char b16[33] = "fedcba9876543210";
      49  
      50  int i0, i1, i2;
      51  
      52  void test_copy_cond_equal_length (void)
      53  {
      54    // The test below is represented as this:
      55    //   # iftmp.0_3 = PHI <&b16(2), &a16(3)>
      56    //   MEM <unsigned char[17]> [(char * {ref-all})&a]
      57    //     = MEM <unsigned char[17]> [(char * {ref-all})iftmp.0_3];
      58    //   _2 = strlen (&a);
      59    T (16 ==, 17, 17, i0 ? a16 : b16);
      60    T (16 ==, 17, 17, i0 ? a16 : b16);
      61    T (15 ==, 17, 16, (i0 ? a16 : b16) +  1);
      62    T (14 ==, 17, 15, (i0 ? a16 : b16) +  2);
      63    T ( 0 ==, 17,  1, (i0 ? a16 : b16) + 16);
      64  
      65    T (31 ==, 33, 32, (i0 ? a32 : b32) +  1);
      66    T (30 ==, 33, 31, (i0 ? a32 : b32) +  2);
      67    T (29 ==, 33, 30, (i0 ? a32 : b32) +  3);
      68    T ( 1 ==, 33,  2, (i0 ? a32 : b32) + 31);
      69    T ( 0 ==, 33,  1, (i0 ? a32 : b32) + 32);
      70  }
      71  
      72  #if (defined(__i386__) && defined(__SSE__)) || defined(__x86_64__) || defined(__aarch64__) \
      73      || defined(__s390__) || defined(__powerpc64__)
      74  
      75  /* The following tests assume GCC transforms the memcpy calls into
      76     long long assignments which it does only on targets that define
      77     the MOVE_MAX macro to 8 or higher.  Enable on a set of targets
      78     known to do that.  */
      79  
      80  const char a4[16] = "0123";
      81  const char b4[16] = "3210";
      82  
      83  void test_copy_cond_unequal_length_i64 (void)
      84  {
      85    T (2 <, 16, 8, i0 ? a4 + 1 : b4 + 0);
      86    T (1 <, 16, 8, i0 ? a4 + 1 : b4 + 2);
      87    T (0 <, 16, 8, i0 ? a4 + 1 : b4 + 3);
      88  
      89    T (1 <, 16, 8, i0 ? a4 + 2 : b4 + 0);
      90    T (1 <, 16, 8, i0 ? a4 + 2 : b4 + 1);
      91    T (0 <, 16, 8, i0 ? a4 + 2 : b4 + 3);
      92  }
      93  
      94  #endif
      95  
      96  
      97  #if defined(__x86_64__) && __SIZEOF_INT128__ == 16
      98  
      99  /* The following tests assume GCC transforms the memcpy calls into
     100     int128_t assignments which it does only on targets that define
     101     the MOVE_MAX macro to 16.  That's only s390 and x86_64 with
     102     int128_t support.  */
     103  
     104  const char a8[32] = "01234567";
     105  const char b8[32] = "76543210";
     106  
     107  void test_copy_cond_unequal_length_i128 (void)
     108  {
     109    T (6 <, 32, 16, i0 ? a8 + 1 : b8 + 0);
     110    T (5 <, 32, 16, i0 ? a8 + 1 : b8 + 2);
     111    T (4 <, 32, 16, i0 ? a8 + 1 : b8 + 3);
     112    T (3 <, 32, 16, i0 ? a8 + 1 : b8 + 4);
     113    T (2 <, 32, 16, i0 ? a8 + 1 : b8 + 5);
     114    T (1 <, 32, 16, i0 ? a8 + 1 : b8 + 6);
     115    T (0 <, 32, 16, i0 ? a8 + 1 : b8 + 7);
     116  
     117    T (5 <, 32, 16, i0 ? a8 + 2 : b8 + 0);
     118    T (5 <, 32, 16, i0 ? a8 + 2 : b8 + 1);
     119    T (3 <, 32, 16, i0 ? a8 + 2 : b8 + 3);
     120    T (2 <, 32, 16, i0 ? a8 + 2 : b8 + 4);
     121    T (1 <, 32, 16, i0 ? a8 + 2 : b8 + 5);
     122    T (0 <, 32, 16, i0 ? a8 + 2 : b8 + 6);
     123  
     124    T (4 <, 32, 16, i0 ? a8 + 3 : b8 + 0);
     125    T (4 <, 32, 16, i0 ? a8 + 3 : b8 + 1);
     126    T (4 <, 32, 16, i0 ? a8 + 3 : b8 + 2);
     127    T (3 <, 32, 16, i0 ? a8 + 3 : b8 + 4);
     128    T (2 <, 32, 16, i0 ? a8 + 3 : b8 + 5);
     129    T (1 <, 32, 16, i0 ? a8 + 3 : b8 + 6);
     130    T (0 <, 32, 16, i0 ? a8 + 3 : b8 + 7);
     131  
     132    T (3 <, 32, 16, i0 ? a8 + 4 : b8 + 0);
     133    T (3 <, 32, 16, i0 ? a8 + 4 : b8 + 1);
     134    T (3 <, 32, 16, i0 ? a8 + 4 : b8 + 2);
     135    T (3 <, 32, 16, i0 ? a8 + 4 : b8 + 3);
     136    T (2 <, 32, 16, i0 ? a8 + 4 : b8 + 5);
     137    T (1 <, 32, 16, i0 ? a8 + 4 : b8 + 6);
     138    T (0 <, 32, 16, i0 ? a8 + 4 : b8 + 7);
     139  }
     140  
     141  #endif   /* Support for i128_t stores.  */
     142  
     143  /* { dg-final { scan-tree-dump-times "strlen" 0 "optimized" } }
     144     { dg-final { scan-tree-dump-times "_not_eliminated_" 0 "optimized" } } */