(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.dg/
strlenopt-70.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 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  
      10  #include "strlenopt.h"
      11  
      12  #define CHAR_BIT __CHAR_BIT__
      13  
      14  typedef __UINT16_TYPE__  uint16_t;
      15  typedef __UINT32_TYPE__  uint32_t;
      16  typedef __UINT64_TYPE__  uint64_t;
      17  typedef __UINT64_TYPE__  uint64_t;
      18  
      19  #define CAT(x, y) x ## y
      20  #define CONCAT(x, y) CAT (x, y)
      21  #define FAILNAME(name) CONCAT (call_ ## name ##_on_line_, __LINE__)
      22  
      23  #define FAIL(name) do {				\
      24      extern void FAILNAME (name) (void);		\
      25      FAILNAME (name)();				\
      26    } while (0)
      27  
      28  /* Macros to emit a call to function named
      29       call_failed_to_be_eliminated_on_line_NNN()
      30     for each call that's expected to be eliminated.  The dg-final
      31     scan-tree-dump-time directive at the bottom of the test verifies
      32     that no such call appears in output.  */
      33  #define ELIM(expr)					\
      34    if ((expr)) FAIL (not_eliminated); else (void)0
      35  
      36  /* Verify that 'strlen (A) EXPECT' is folded to true.  When non-null,
      37     the first sizeof (INIT) - 1 bytes of the INIT arrray are stored
      38     in A first, followed by *(TYPE*)A = ASSIGN.  */
      39  #define T(init, type, off, assign, expect) do {			\
      40      char a[32];							\
      41      memcpy (a, init ? init : "", init ? sizeof init - 1 : 0);	\
      42      *(type*)(a + off) = assign;					\
      43      ELIM (!(strlen (a) expect));				\
      44    } while (0)
      45  
      46  /* Same as T but works around the optimizer dropping the initializing
      47     store before the assignment and defeating the strlen optimization.  */
      48  #define TX(init, type, off, assign, expect) do {		\
      49      char a[32];							\
      50      strcpy (a, init + 2);					\
      51      strcat (a, init + sizeof (init) - 3);			\
      52      *(type*)(a + off) = assign;					\
      53      ELIM (!(strlen (a) expect));				\
      54    } while (0)
      55  
      56  /* Evaluates to an element at index I of the literal S padded with nuls
      57     on the right.  */
      58  #define ELT(s, i)   ((s "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0")[i])
      59  
      60  #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
      61  /* Form a big-endian 16, 32, 64, and 128-byte integer from a string.  */
      62  #  define I16(s) (((uint16_t)ELT (s, 0) << 8) + (uint16_t)ELT (s, 1))
      63  #  define I32(s)				\
      64    (((uint32_t)ELT (s, 0) << 24)			\
      65     + ((uint32_t)ELT (s, 1) << 16)		\
      66     + ((uint32_t)ELT (s, 2) << 8)		\
      67     + (uint32_t)ELT (s, 3))
      68  #  define I64(s)				\
      69    (((uint64_t)ELT (s, 0) << 56)			\
      70     + ((uint64_t)ELT (s, 1) << 48)		\
      71     + ((uint64_t)ELT (s, 2) << 40)		\
      72     + ((uint64_t)ELT (s, 3) << 32)		\
      73     + ((uint64_t)ELT (s, 4) << 24)		\
      74     + ((uint64_t)ELT (s, 5) << 16)		\
      75     + ((uint64_t)ELT (s, 6) << 8)		\
      76     + ELT (s, 7))
      77  #  define I128(s)				\
      78    (((uint128_t)ELT (s, 0) << (64 + 56))		\
      79     + ((uint128_t)ELT (s, 1) << (64 + 48))	\
      80     + ((uint128_t)ELT (s, 2) << (64 + 40))	\
      81     + ((uint128_t)ELT (s, 3) << (64 + 32))	\
      82     + ((uint128_t)ELT (s, 4) << (64 + 24))	\
      83     + ((uint128_t)ELT (s, 5) << (64 + 16))	\
      84     + ((uint128_t)ELT (s, 6) << (64 + 8))	\
      85     + ((uint128_t)ELT (s, 7) << 64)		\
      86     + ((uint128_t)ELT (s, 8) << 56)		\
      87     + ((uint128_t)ELT (s, 9) << 48)		\
      88     + ((uint128_t)ELT (s, 10) << 40)		\
      89     + ((uint128_t)ELT (s, 11) << 32)		\
      90     + ((uint128_t)ELT (s, 12) << 24)		\
      91     + ((uint128_t)ELT (s, 13) << 16)		\
      92     + ((uint128_t)ELT (s, 14) << 8)		\
      93     + (uint128_t)ELT (s, 15))
      94  
      95  #elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
      96  /* Form a little-endian 16, 32, 64, and 128-byte integer from a string.  */
      97  #  define I16(s) (((uint16_t)ELT (s, 1) << 8) + (uint16_t)ELT (s, 0))
      98  #  define I32(s)				\
      99    (((uint32_t)ELT (s, 3) << 24)			\
     100     + ((uint32_t)ELT (s, 2) << 16)		\
     101     + ((uint32_t)ELT (s, 1) << 8)		\
     102     + (uint32_t)ELT (s, 0))
     103  #  define I64(s)				\
     104    (((uint64_t)ELT (s, 7) << 56)			\
     105     + ((uint64_t)ELT (s, 6) << 48)		\
     106     + ((uint64_t)ELT (s, 5) << 40)		\
     107     + ((uint64_t)ELT (s, 4) << 32)		\
     108     + ((uint64_t)ELT (s, 3) << 24)		\
     109     + ((uint64_t)ELT (s, 2) << 16)		\
     110     + ((uint64_t)ELT (s, 1) << 8)		\
     111     + ELT (s, 0))
     112  #  define I128(s)				\
     113    (((uint128_t)ELT (s, 15) << (64 + 56))	\
     114     + ((uint128_t)ELT (s, 14) << (64 + 48))	\
     115     + ((uint128_t)ELT (s, 13) << (64 + 40))	\
     116     + ((uint128_t)ELT (s, 12) << (64 + 32))	\
     117     + ((uint128_t)ELT (s, 11) << (64 + 24))	\
     118     + ((uint128_t)ELT (s, 10) << (64 + 16))	\
     119     + ((uint128_t)ELT (s, 9) << (64 + 8))	\
     120     + ((uint128_t)ELT (s, 8) << 64)		\
     121     + ((uint128_t)ELT (s, 7) << 56)		\
     122     + ((uint128_t)ELT (s, 6) << 48)		\
     123     + ((uint128_t)ELT (s, 5) << 40)		\
     124     + ((uint128_t)ELT (s, 4) << 32)		\
     125     + ((uint128_t)ELT (s, 3) << 24)		\
     126     + ((uint128_t)ELT (s, 2) << 16)		\
     127     + ((uint128_t)ELT (s, 1) << 8)		\
     128     + (uint128_t)ELT (s, 0))
     129  #endif
     130  
     131  #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
     132  
     133  void store_16bit_be (void)
     134  {
     135    T ("xxx", uint16_t, 0, 0x0001, == 0);
     136    T ("xxx", uint16_t, 0, 0x0010, == 0);
     137    T ("xxx", uint16_t, 0, 0x0011, == 0);
     138    T ("xxx", uint16_t, 0, 0x0100, == 1);
     139    T ("xxx", uint16_t, 0, 0x1000, == 1);
     140    T ("xxx", uint16_t, 0, 0x1100, == 1);
     141  }
     142  
     143  #elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
     144  
     145  void store_16bit_le (int i)
     146  {
     147    uint16_t x0000 = I16 ("\0\0");
     148    uint16_t x0001 = 0x0001;
     149    uint16_t x0010 = 0x0010;
     150    uint16_t x0011 = 0x0011;
     151    uint16_t x0100 = 0x0100;
     152    uint16_t x1000 = 0x1000;
     153    uint16_t x1100 = 0x1100;
     154  
     155    T (0,        uint16_t, 0, x0000, == 0);
     156    T ("x",      uint16_t, 0, x0000, == 0);
     157    T ("xx",     uint16_t, 0, x0000, == 0);
     158    T ("xxxx",   uint16_t, 0, x0000, == 0);
     159    T (0,        uint16_t, 0, x0001, == 1);
     160    T ("\0\0\0", uint16_t, 0, x0001, == 1);
     161    T (0,        uint16_t, 0, x0010, == 1);
     162    T ("x\0\0",  uint16_t, 0, x0010, == 1);
     163    T (0,        uint16_t, 0, x0011, == 1);
     164    T ("xx\0",   uint16_t, 0, x0011, == 1);
     165    T (0,        uint16_t, 0, x0100, == 0);
     166    T ("\0\0\0", uint16_t, 0, x0100, == 0);
     167    T (0,        uint16_t, 0, x1000, == 0);
     168    T ("x\0\0",  uint16_t, 0, x1000, == 0);
     169    T (0,        uint16_t, 0, x1100, == 0);
     170    T ("xx\0",   uint16_t, 0, x1100, == 0);
     171  
     172    // FIXME: This fails because of the next test but succeeds on its own.
     173    // T (0,        uint16_t, 0, i ? x0001 : x0010, == 1);
     174    T ("xxx",    uint16_t, 0, i ? x0100 : x1100, == 0);
     175  }
     176  
     177  #endif
     178  
     179  void store_32bit (volatile int i)
     180  {
     181    T (0,      uint32_t, 0, 0, == 0);
     182    T ("x",    uint32_t, 0, 0, == 0);
     183    T ("xx",   uint32_t, 0, 0, == 0);
     184    T ("xxx",  uint32_t, 0, 0, == 0);
     185    T ("xxxx", uint32_t, 0, 0, == 0);
     186  
     187    T ("\0",   uint32_t, 1, 0, == 0);
     188    T ("x",    uint32_t, 1, 0, == 1);
     189    T ("xx",   uint32_t, 2, 0, == 2);
     190    T ("xxx",  uint32_t, 3, 0, == 3);
     191  
     192    T ("xxx",  uint32_t, 0, I32 ("\1\0\0\0"), == 1);
     193    T ("xxx",  uint32_t, 0, I32 ("\0\1\0\0"), == 0);
     194    T ("xxx",  uint32_t, 0, I32 ("\0\0\1\0"), == 0);
     195    T ("xxx",  uint32_t, 0, I32 ("\0\0\0\1"), == 0);
     196  
     197    T ("xxx",  uint32_t, 0, I32 ("\1\2\0\0"), == 2);
     198    T ("xxx",  uint32_t, 0, I32 ("\0\1\2\0"), == 0);
     199    T ("xxx",  uint32_t, 0, I32 ("\0\0\1\2"), == 0);
     200  
     201    T ("xxx",  uint32_t, 0, I32 ("\1\2\3\0"), == 3);
     202    T ("xxx",  uint32_t, 0, I32 ("\0\1\2\3"), == 0);
     203  
     204    uint32_t x123_ = I32 ("123\0");
     205    uint32_t x12__ = I32 ("12\0\0");
     206    uint32_t x1___ = I32 ("1\0\0\0");
     207  
     208    // FIXME: Upper bound not implemented yet.
     209    /* T ("xxxx", uint32_t, 0, i ? x123_ : x12__, <= 3); */
     210    T ("xxxx", uint32_t, 0, i ? x123_ : x12__, >= 2);
     211    T ("xxxx", uint32_t, 0, i ? x12__ : x123_, >= 2);
     212    /* T ("xxxx", uint32_t, 0, i ? x123_ : x1___, <= 3); */
     213    T ("xxxx", uint32_t, 0, i ? x123_ : x1___, >= 1);
     214    T ("xxxx", uint32_t, 0, i ? x1___ : x123_, >= 1);
     215  
     216    TX ("abcde",  uint32_t, 0, i ? I32 ("1234") : I32 ("1235"), == 5);
     217    TX ("abcde",  uint32_t, 1, i ? I32 ("1234") : I32 ("1235"), == 5);
     218  
     219    TX ("abcdef", uint32_t, 0, i ? I32 ("1235") : I32 ("1234"), == 6);
     220    TX ("abcdef", uint32_t, 1, i ? I32 ("1235") : I32 ("1234"), == 6);
     221    TX ("abcdef", uint32_t, 2, i ? I32 ("1235") : I32 ("1234"), == 6);
     222    TX ("abcdef", uint32_t, 3, i ? I32 ("124\0") : I32 ("123\0"), == 6);
     223    TX ("abcdef", uint32_t, 3, i ? I32 ("12\0\0") : I32 ("13\0\0"), == 5);
     224  
     225    TX ("abcdef", uint32_t, 3, i ? I32 ("12\0\0") : I32 ("123\0"), >= 5);
     226    /* FIXME: Upper bound not implemented yet.  */
     227    /* TX ("abcdef", uint32_t, 3, i ? I32 ("12\0\0") : I32 ("123\0"), < 7); */
     228  }
     229  
     230  void store_64bit (int i)
     231  {
     232    T ("xxxxxxx", uint64_t, 0, I64 ("\1\0\0\0\0\0\0\0\0"), == 1);
     233    T ("xxxxxxx", uint64_t, 0, I64 ("\0\1\0\0\0\0\0\0\0"), == 0);
     234    T ("xxxxxxx", uint64_t, 0, I64 ("\0\0\1\0\0\0\0\0\0"), == 0);
     235    T ("xxxxxxx", uint64_t, 0, I64 ("\0\0\0\1\0\0\0\0\0"), == 0);
     236    T ("xxxxxxx", uint64_t, 0, I64 ("\0\0\0\0\1\0\0\0\0"), == 0);
     237    T ("xxxxxxx", uint64_t, 0, I64 ("\0\0\0\0\0\1\0\0\0"), == 0);
     238    T ("xxxxxxx", uint64_t, 0, I64 ("\0\0\0\0\0\0\1\0\0"), == 0);
     239    T ("xxxxxxx", uint64_t, 0, I64 ("\0\0\0\0\0\0\0\1\0"), == 0);
     240  
     241    T ("xxxxxxx", uint64_t, 0, I64 ("\1\2\0\0\0\0\0\0\0"), == 2);
     242    T ("xxxxxxx", uint64_t, 0, I64 ("\0\1\2\0\0\0\0\0\0"), == 0);
     243    T ("xxxxxxx", uint64_t, 0, I64 ("\0\0\1\2\0\0\0\0\0"), == 0);
     244  
     245    T ("xxxxxxx", uint64_t, 0, I64 ("\1\2\3\0\0\0\0\0\0"), == 3);
     246    T ("xxxxxxx", uint64_t, 0, I64 ("\0\1\2\3\0\0\0\0\0"), == 0);
     247  
     248    T ("xxxxxxx", uint64_t, 0, I64 ("\1\2\3\4\0\0\0\0\0"), == 4);
     249    T ("xxxxxxx", uint64_t, 0, I64 ("\1\2\3\4\5\0\0\0\0"), == 5);
     250    T ("xxxxxxx", uint64_t, 0, I64 ("\1\2\3\4\5\6\0\0\0"), == 6);
     251    T ("xxxxxxx", uint64_t, 0, I64 ("\1\2\3\4\5\6\7\0\0"), == 7);
     252  
     253    uint64_t x7777777_ = I64 ("\7\7\7\7\7\7\7");
     254    uint64_t x666666__ = I64 ("\6\6\6\6\6\6\0");
     255    uint64_t x4444____ = I64 ("\4\4\4\4\0\0\0");
     256    uint64_t x4343____ = I64 ("\4\3\4\3\0\0\0");
     257    uint64_t x1_______ = I64 ("\1\0\0\0\0\0\0");
     258  
     259    /* FIXME: Upper bound not implemented yet.  */
     260    /* T ("x\0xxxxxx", uint64_t, 0, i ? x7777777_ : x666666__, <= 7); */
     261    T ("xx\0xxxxx", uint64_t, 0, i ? x7777777_ : x666666__, >= 6);
     262    T ("xxx\0xxxx", uint64_t, 1, i ? x7777777_ : x666666__, >= 7);
     263    /* T ("xxx\0xxxx", uint64_t, 0, i ? x666666__ : x1, <= 6); */
     264    T ("xxxx\0xxx", uint64_t, 0, i ? x666666__ : x1_______, >= 1);
     265    T ("xxxxxx\0x", uint64_t, 0, i ? x4444____ : x4343____, == 4);
     266  }
     267  
     268  #if __SIZEOF_INT128__
     269  
     270  typedef __uint128_t     uint128_t;
     271  
     272  void store_128bit (void)
     273  {
     274    uint128_t x1    = I128 ("\1");
     275    uint128_t x1z1  = I128 ("\0\1");
     276    uint128_t x2z1  = I128 ("\0\0\1");
     277    uint128_t x3z1  = I128 ("\0\0\0\1");
     278    uint128_t x4z1  = I128 ("\0\0\0\0\1");
     279    uint128_t x5z1  = I128 ("\0\0\0\0\0\1");
     280    uint128_t x6z1  = I128 ("\0\0\0\0\0\0\1");
     281    uint128_t x7z1  = I128 ("\0\0\0\0\0\0\0\1");
     282    uint128_t x8z1  = I128 ("\0\0\0\0\0\0\0\0\1");
     283    uint128_t x9z1  = I128 ("\0\0\0\0\0\0\0\0\0\1");
     284    uint128_t x10z1 = I128 ("\0\0\0\0\0\0\0\0\0\0\1");
     285    uint128_t x11z1 = I128 ("\0\0\0\0\0\0\0\0\0\0\0\1");
     286    uint128_t x12z1 = I128 ("\0\0\0\0\0\0\0\0\0\0\0\0\1");
     287    uint128_t x13z1 = I128 ("\0\0\0\0\0\0\0\0\0\0\0\0\0\1");
     288    uint128_t x14z1 = I128 ("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1");
     289    uint128_t x15z1 = I128 ("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1");
     290  
     291    T ("xxxxxxx", uint128_t, 0, x1, == 1);
     292    T ("xxxxxxx", uint128_t, 0, x1z1, == 0);
     293    T ("xxxxxxx", uint128_t, 0, x2z1, == 0);
     294    T ("xxxxxxx", uint128_t, 0, x3z1, == 0);
     295    T ("xxxxxxx", uint128_t, 0, x4z1, == 0);
     296    T ("xxxxxxx", uint128_t, 0, x5z1, == 0);
     297    T ("xxxxxxx", uint128_t, 0, x6z1, == 0);
     298    T ("xxxxxxx", uint128_t, 0, x7z1, == 0);
     299    T ("xxxxxxx", uint128_t, 0, x8z1, == 0);
     300    T ("xxxxxxx", uint128_t, 0, x9z1, == 0);
     301    T ("xxxxxxx", uint128_t, 0, x10z1, == 0);
     302    T ("xxxxxxx", uint128_t, 0, x11z1, == 0);
     303    T ("xxxxxxx", uint128_t, 0, x12z1, == 0);
     304    T ("xxxxxxx", uint128_t, 0, x13z1, == 0);
     305    T ("xxxxxxx", uint128_t, 0, x14z1, == 0);
     306    T ("xxxxxxx", uint128_t, 0, x15z1, == 0);
     307  
     308    T ("xxxxxxx", uint128_t, 0, I128 ("\2\1"), == 2);
     309    T ("xxxxxxx", uint128_t, 0, I128 ("\0\2\1"), == 0);
     310  
     311    T ("xxxxxxx", uint128_t, 0, I128 ("\3\2\1"), == 3);
     312    T ("xxxxxxx", uint128_t, 0, I128 ("\0\3\2\1"), == 0);
     313  
     314    T ("xxxxxxx", uint128_t, 0, I128 ("\1\2\3\4"), == 4);
     315    T ("xxxxxxx", uint128_t, 0, I128 ("\1\2\3\4\5"), == 5);
     316    T ("xxxxxxx", uint128_t, 0, I128 ("\1\2\3\4\5\6"), == 6);
     317    T ("xxxxxxx", uint128_t, 0, I128 ("\1\2\3\4\5\6\7"), == 7);
     318    T ("xxxxxxx", uint128_t, 0, I128 ("\1\2\3\4\5\6\7\10"), == 8);
     319    T ("xxxxxxx", uint128_t, 0, I128 ("\1\2\3\4\5\6\7\10\11"), == 9);
     320    T ("xxxxxxx", uint128_t, 0, I128 ("\1\2\3\4\5\6\7\10\11\12"), == 10);
     321    T ("xxxxxxx", uint128_t, 0, I128 ("\1\2\3\4\5\6\7\10\11\12\13"), == 11);
     322    T ("xxxxxxx", uint128_t, 0, I128 ("\1\2\3\4\5\6\7\10\11\12\13\14"), == 12);
     323    T ("xxxxxxx", uint128_t, 0, I128 ("\1\2\3\4\5\6\7\10\11\12\13\14\15"), == 13);
     324    T ("xxxxxxx", uint128_t, 0, I128 ("\1\2\3\4\5\6\7\10\11\12\13\14\15\16"), == 14);
     325    T ("xxxxxxx", uint128_t, 0, I128 ("\1\2\3\4\5\6\7\10\11\12\13\14\15\16\17"), == 15);
     326  }
     327  
     328  #endif   // __SIZEOF_INT128__
     329  
     330  /* { dg-final { scan-tree-dump-times "strlen" 0 "optimized" } }
     331     { dg-final { scan-tree-dump-times "_not_eliminated_" 0 "optimized" } } */