re PR tree-optimization/91183 (strlen of a strcpy result with a conditional source...
authorMartin Sebor <msebor@redhat.com>
Thu, 25 Jul 2019 19:03:00 +0000 (19:03 +0000)
committerMartin Sebor <msebor@gcc.gnu.org>
Thu, 25 Jul 2019 19:03:00 +0000 (13:03 -0600)
PR tree-optimization/91183
PR tree-optimization/86688

gcc/testsuite/ChangeLog:
* gcc.dg/strlenopt-70.c: Fix bugs.
* gcc.dg/strlenopt-71.c: Same.
* gcc.dg/strlenopt-72.c: Same.

From-SVN: r273812

gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/strlenopt-70.c
gcc/testsuite/gcc.dg/strlenopt-71.c
gcc/testsuite/gcc.dg/strlenopt-72.c

index 0ff528b..b395a9a 100644 (file)
@@ -1,3 +1,11 @@
+2019-07-25  Martin Sebor  <msebor@redhat.com>
+
+       PR tree-optimization/91183
+       PR tree-optimization/86688
+       * gcc.dg/strlenopt-70.c: Fix bugs.
+       * gcc.dg/strlenopt-71.c: Same.
+       * gcc.dg/strlenopt-72.c: Same.
+
 2019-07-25  Vladimir Makarov  <vmakarov@redhat.com>
 
        PR rtl-optimization/91223
index 2dc42d6..97ba140 100644 (file)
 
 #define CHAR_BIT __CHAR_BIT__
 
-typedef __INT16_TYPE__  int16_t;
-typedef __INT32_TYPE__  int32_t;
-typedef __INT64_TYPE__  int64_t;
-typedef __UINT64_TYPE__ uint64_t;
+typedef __UINT16_TYPE__  uint16_t;
+typedef __UINT32_TYPE__  uint32_t;
+typedef __UINT64_TYPE__  uint64_t;
+typedef __UINT64_TYPE__  uint64_t;
 
 #define CAT(x, y) x ## y
 #define CONCAT(x, y) CAT (x, y)
@@ -43,16 +43,6 @@ typedef __UINT64_TYPE__ uint64_t;
     ELIM (!(strlen (a) expect));                               \
   } while (0)
 
-/* Same as above but the assignment consisting of the two quadwords
-   QW1 and QW2 to support int128_t.  */
-#define T2(init, type, off, qw0, qw1, expect) do {                     \
-    char a[32];                                                                \
-    memcpy (a, init ? init : "", init ? sizeof init - 1: 0);           \
-    type assign = ((type)qw0 << (sizeof (type) * CHAR_BIT / 2)) | (type)qw1; \
-    *(type*)(a + off) = assign;                                                \
-    ELIM (!(strlen (a) expect));                                       \
-  } while (0)
-
 /* Same as T but works around the optimizer dropping the initializing
    store before the assignment and defeating the strlen optimization.  */
 #define TX(init, type, off, assign, expect) do {               \
@@ -63,231 +53,273 @@ typedef __UINT64_TYPE__ uint64_t;
     ELIM (!(strlen (a) expect));                               \
   } while (0)
 
+/* Evaluates to an element at index I of the literal S padded with nuls
+   on the right.  */
+#define ELT(s, i)   ((s "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0")[i])
 
 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
-#  define I16(s) ((s[0] << 8) + s[1])
-#  define I32(s) ((s[0] << 24) + (s[1] << 16) + (s[2] << 8) + s[3])
-#  define I64(s)                                               \
-  (((uint64_t)s[0] << 56)                                      \
-   + ((uint64_t)s[1] << 48)                                    \
-   + ((uint64_t)s[2] << 40)                                    \
-   + ((uint64_t)s[3] << 32)                                    \
-   + ((uint64_t)s[4] << 24)                                    \
-   + ((uint64_t)s[5] << 16)                                    \
-   + ((uint64_t)s[6] << 8)                                     \
-   + s[7])
+/* Form a big-endian 16, 32, 64, and 128-byte integer from a string.  */
+#  define I16(s) (((uint16_t)ELT (s, 0) << 8) + (uint16_t)ELT (s, 1))
+#  define I32(s)                               \
+  (((uint32_t)ELT (s, 0) << 24)                        \
+   + ((uint32_t)ELT (s, 1) << 16)              \
+   + ((uint32_t)ELT (s, 2) << 8)               \
+   + (uint32_t)ELT (s, 3))
+#  define I64(s)                               \
+  (((uint64_t)ELT (s, 0) << 56)                        \
+   + ((uint64_t)ELT (s, 1) << 48)              \
+   + ((uint64_t)ELT (s, 2) << 40)              \
+   + ((uint64_t)ELT (s, 3) << 32)              \
+   + ((uint64_t)ELT (s, 4) << 24)              \
+   + ((uint64_t)ELT (s, 5) << 16)              \
+   + ((uint64_t)ELT (s, 6) << 8)               \
+   + ELT (s, 7))
+#  define I128(s)                              \
+  (((uint128_t)ELT (s, 0) << (64 + 56))                \
+   + ((uint128_t)ELT (s, 1) << (64 + 48))      \
+   + ((uint128_t)ELT (s, 2) << (64 + 40))      \
+   + ((uint128_t)ELT (s, 3) << (64 + 32))      \
+   + ((uint128_t)ELT (s, 4) << (64 + 24))      \
+   + ((uint128_t)ELT (s, 5) << (64 + 16))      \
+   + ((uint128_t)ELT (s, 6) << (64 + 8))       \
+   + ((uint128_t)ELT (s, 7) << 64)             \
+   + ((uint128_t)ELT (s, 8) << 56)             \
+   + ((uint128_t)ELT (s, 9) << 48)             \
+   + ((uint128_t)ELT (s, 10) << 40)            \
+   + ((uint128_t)ELT (s, 11) << 32)            \
+   + ((uint128_t)ELT (s, 12) << 24)            \
+   + ((uint128_t)ELT (s, 13) << 16)            \
+   + ((uint128_t)ELT (s, 14) << 8)             \
+   + (uint128_t)ELT (s, 15))
+
 #elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
-#  define I16(s) ((s[1] << 8) + s[0])
-#  define I32(s) ((s[3] << 24) + (s[2] << 16) + (s[1] << 8) + s[0])
-#  define I64(s)                                               \
-  (((uint64_t)s[7] << 56)                                      \
-   + ((uint64_t)s[6] << 48)                                    \
-   + ((uint64_t)s[5] << 40)                                    \
-   + ((uint64_t)s[4] << 32)                                    \
-   + ((uint64_t)s[3] << 24)                                    \
-   + ((uint64_t)s[2] << 16)                                    \
-   + ((uint64_t)s[1] << 8)                                     \
-   + s[0])
+/* Form a little-endian 16, 32, 64, and 128-byte integer from a string.  */
+#  define I16(s) (((uint16_t)ELT (s, 1) << 8) + (uint16_t)ELT (s, 0))
+#  define I32(s)                               \
+  (((uint32_t)ELT (s, 3) << 24)                        \
+   + ((uint32_t)ELT (s, 2) << 16)              \
+   + ((uint32_t)ELT (s, 1) << 8)               \
+   + (uint32_t)ELT (s, 0))
+#  define I64(s)                               \
+  (((uint64_t)ELT (s, 7) << 56)                        \
+   + ((uint64_t)ELT (s, 6) << 48)              \
+   + ((uint64_t)ELT (s, 5) << 40)              \
+   + ((uint64_t)ELT (s, 4) << 32)              \
+   + ((uint64_t)ELT (s, 3) << 24)              \
+   + ((uint64_t)ELT (s, 2) << 16)              \
+   + ((uint64_t)ELT (s, 1) << 8)               \
+   + ELT (s, 0))
+#  define I128(s)                              \
+  (((uint128_t)ELT (s, 15) << (64 + 56))       \
+   + ((uint128_t)ELT (s, 14) << (64 + 48))     \
+   + ((uint128_t)ELT (s, 13) << (64 + 40))     \
+   + ((uint128_t)ELT (s, 12) << (64 + 32))     \
+   + ((uint128_t)ELT (s, 11) << (64 + 24))     \
+   + ((uint128_t)ELT (s, 10) << (64 + 16))     \
+   + ((uint128_t)ELT (s, 9) << (64 + 8))       \
+   + ((uint128_t)ELT (s, 8) << 64)             \
+   + ((uint128_t)ELT (s, 7) << 56)             \
+   + ((uint128_t)ELT (s, 6) << 48)             \
+   + ((uint128_t)ELT (s, 5) << 40)             \
+   + ((uint128_t)ELT (s, 4) << 32)             \
+   + ((uint128_t)ELT (s, 3) << 24)             \
+   + ((uint128_t)ELT (s, 2) << 16)             \
+   + ((uint128_t)ELT (s, 1) << 8)              \
+   + (uint128_t)ELT (s, 0))
 #endif
 
 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
 
 void store_16bit_be (void)
 {
-  T ("xxx", int16_t, 0, 0x0001, == 0);
-  T ("xxx", int16_t, 0, 0x0010, == 0);
-  T ("xxx", int16_t, 0, 0x0011, == 0);
-  T ("xxx", int16_t, 0, 0x0100, == 1);
-  T ("xxx", int16_t, 0, 0x1000, == 1);
-  T ("xxx", int16_t, 0, 0x1100, == 1);
+  T ("xxx", uint16_t, 0, 0x0001, == 0);
+  T ("xxx", uint16_t, 0, 0x0010, == 0);
+  T ("xxx", uint16_t, 0, 0x0011, == 0);
+  T ("xxx", uint16_t, 0, 0x0100, == 1);
+  T ("xxx", uint16_t, 0, 0x1000, == 1);
+  T ("xxx", uint16_t, 0, 0x1100, == 1);
 }
 
 #elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
 
 void store_16bit_le (int i)
 {
-  int16_t x0000 = I16 ("\0\0");
-  int16_t x0001 = 0x0001;
-  int16_t x0010 = 0x0010;
-  int16_t x0011 = 0x0011;
-  int16_t x0100 = 0x0100;
-  int16_t x1000 = 0x1000;
-  int16_t x1100 = 0x1100;
-
-  T (0,        int16_t, 0, x0000, == 0);
-  T ("x",      int16_t, 0, x0000, == 0);
-  T ("xx",     int16_t, 0, x0000, == 0);
-  T ("xxxx",   int16_t, 0, x0000, == 0);
-  T (0,        int16_t, 0, x0001, == 1);
-  T ("\0\0\0", int16_t, 0, x0001, == 1);
-  T (0,        int16_t, 0, x0010, == 1);
-  T ("x\0\0",  int16_t, 0, x0010, == 1);
-  T (0,        int16_t, 0, x0011, == 1);
-  T ("xx\0",   int16_t, 0, x0011, == 1);
-  T (0,        int16_t, 0, x0100, == 0);
-  T ("\0\0\0", int16_t, 0, x0100, == 0);
-  T (0,        int16_t, 0, x1000, == 0);
-  T ("x\0\0",  int16_t, 0, x1000, == 0);
-  T (0,        int16_t, 0, x1100, == 0);
-  T ("xx\0",   int16_t, 0, x1100, == 0);
+  uint16_t x0000 = I16 ("\0\0");
+  uint16_t x0001 = 0x0001;
+  uint16_t x0010 = 0x0010;
+  uint16_t x0011 = 0x0011;
+  uint16_t x0100 = 0x0100;
+  uint16_t x1000 = 0x1000;
+  uint16_t x1100 = 0x1100;
+
+  T (0,        uint16_t, 0, x0000, == 0);
+  T ("x",      uint16_t, 0, x0000, == 0);
+  T ("xx",     uint16_t, 0, x0000, == 0);
+  T ("xxxx",   uint16_t, 0, x0000, == 0);
+  T (0,        uint16_t, 0, x0001, == 1);
+  T ("\0\0\0", uint16_t, 0, x0001, == 1);
+  T (0,        uint16_t, 0, x0010, == 1);
+  T ("x\0\0",  uint16_t, 0, x0010, == 1);
+  T (0,        uint16_t, 0, x0011, == 1);
+  T ("xx\0",   uint16_t, 0, x0011, == 1);
+  T (0,        uint16_t, 0, x0100, == 0);
+  T ("\0\0\0", uint16_t, 0, x0100, == 0);
+  T (0,        uint16_t, 0, x1000, == 0);
+  T ("x\0\0",  uint16_t, 0, x1000, == 0);
+  T (0,        uint16_t, 0, x1100, == 0);
+  T ("xx\0",   uint16_t, 0, x1100, == 0);
 
   // FIXME: This fails because of the next test but succeeds on its own.
-  // T (0,        int16_t, 0, i ? x0001 : x0010, == 1);
-  T ("xxx",    int16_t, 0, i ? x0100 : x1100, == 0);
+  // T (0,        uint16_t, 0, i ? x0001 : x0010, == 1);
+  T ("xxx",    uint16_t, 0, i ? x0100 : x1100, == 0);
 }
 
 #endif
 
 void store_32bit (volatile int i)
 {
-  T (0,      int32_t, 0, 0, == 0);
-  T ("x",    int32_t, 0, 0, == 0);
-  T ("xx",   int32_t, 0, 0, == 0);
-  T ("xxx",  int32_t, 0, 0, == 0);
-  T ("xxxx", int32_t, 0, 0, == 0);
-
-  T ("\0",   int32_t, 1, 0, == 0);
-  T ("x",    int32_t, 1, 0, == 1);
-  T ("xx",   int32_t, 2, 0, == 2);
-  T ("xxx",  int32_t, 3, 0, == 3);
-
-  T ("xxx",  int32_t, 0, I32 ("\01\0\0\0"), == 1);
-  T ("xxx",  int32_t, 0, I32 ("\0\01\0\0"), == 0);
-  T ("xxx",  int32_t, 0, I32 ("\0\0\01\0"), == 0);
-  T ("xxx",  int32_t, 0, I32 ("\0\0\0\01"), == 0);
-
-  T ("xxx",  int32_t, 0, I32 ("\1\2\0\0"), == 2);
-  T ("xxx",  int32_t, 0, I32 ("\0\1\2\0"), == 0);
-  T ("xxx",  int32_t, 0, I32 ("\0\0\1\2"), == 0);
-
-  T ("xxx",  int32_t, 0, I32 ("\1\2\3\0"), == 3);
-  T ("xxx",  int32_t, 0, I32 ("\0\1\2\3"), == 0);
-
-  int32_t x00332211 = I32 ("123\0");
-  int32_t x00002211 = I32 ("12\0\0");
-  int32_t x00000011 = I32 ("1\0\0\0");
-
-  T ("xxxx", int32_t, 0, i ? x00332211 : x00002211, <= 3);
-  T ("xxxx", int32_t, 0, i ? x00332211 : x00002211, >= 2);
-  T ("xxxx", int32_t, 0, i ? x00332211 : x00000011, <= 3);
-  T ("xxxx", int32_t, 0, i ? x00332211 : x00000011, >= 1);
-
-  TX ("abcde",  int32_t, 0, i ? I32 ("1234") : I32 ("1235"), == 5);
-  TX ("abcde",  int32_t, 1, i ? I32 ("1234") : I32 ("1235"), == 5);
-
-  TX ("abcdef", int32_t, 0, i ? I32 ("1235") : I32 ("1234"), == 6);
-  TX ("abcdef", int32_t, 1, i ? I32 ("1235") : I32 ("1234"), == 6);
-  TX ("abcdef", int32_t, 2, i ? I32 ("1235") : I32 ("1234"), == 6);
-  TX ("abcdef", int32_t, 3, i ? I32 ("124\0") : I32 ("123\0"), == 6);
-  TX ("abcdef", int32_t, 3, i ? I32 ("12\0\0") : I32 ("13\0\0"), == 5);
-
-  TX ("abcdef", int32_t, 3, i ? I32 ("12\0\0") : I32 ("123\0"), >= 5);
-  TX ("abcdef", int32_t, 3, i ? I32 ("12\0\0") : I32 ("123\0"), < 7);
+  T (0,      uint32_t, 0, 0, == 0);
+  T ("x",    uint32_t, 0, 0, == 0);
+  T ("xx",   uint32_t, 0, 0, == 0);
+  T ("xxx",  uint32_t, 0, 0, == 0);
+  T ("xxxx", uint32_t, 0, 0, == 0);
+
+  T ("\0",   uint32_t, 1, 0, == 0);
+  T ("x",    uint32_t, 1, 0, == 1);
+  T ("xx",   uint32_t, 2, 0, == 2);
+  T ("xxx",  uint32_t, 3, 0, == 3);
+
+  T ("xxx",  uint32_t, 0, I32 ("\1\0\0\0"), == 1);
+  T ("xxx",  uint32_t, 0, I32 ("\0\1\0\0"), == 0);
+  T ("xxx",  uint32_t, 0, I32 ("\0\0\1\0"), == 0);
+  T ("xxx",  uint32_t, 0, I32 ("\0\0\0\1"), == 0);
+
+  T ("xxx",  uint32_t, 0, I32 ("\1\2\0\0"), == 2);
+  T ("xxx",  uint32_t, 0, I32 ("\0\1\2\0"), == 0);
+  T ("xxx",  uint32_t, 0, I32 ("\0\0\1\2"), == 0);
+
+  T ("xxx",  uint32_t, 0, I32 ("\1\2\3\0"), == 3);
+  T ("xxx",  uint32_t, 0, I32 ("\0\1\2\3"), == 0);
+
+  uint32_t x00332211 = I32 ("123\0");
+  uint32_t x00002211 = I32 ("12\0\0");
+  uint32_t x00000011 = I32 ("1\0\0\0");
+
+  T ("xxxx", uint32_t, 0, i ? x00332211 : x00002211, <= 3);
+  T ("xxxx", uint32_t, 0, i ? x00332211 : x00002211, >= 2);
+  T ("xxxx", uint32_t, 0, i ? x00332211 : x00000011, <= 3);
+  T ("xxxx", uint32_t, 0, i ? x00332211 : x00000011, >= 1);
+
+  TX ("abcde",  uint32_t, 0, i ? I32 ("1234") : I32 ("1235"), == 5);
+  TX ("abcde",  uint32_t, 1, i ? I32 ("1234") : I32 ("1235"), == 5);
+
+  TX ("abcdef", uint32_t, 0, i ? I32 ("1235") : I32 ("1234"), == 6);
+  TX ("abcdef", uint32_t, 1, i ? I32 ("1235") : I32 ("1234"), == 6);
+  TX ("abcdef", uint32_t, 2, i ? I32 ("1235") : I32 ("1234"), == 6);
+  TX ("abcdef", uint32_t, 3, i ? I32 ("124\0") : I32 ("123\0"), == 6);
+  TX ("abcdef", uint32_t, 3, i ? I32 ("12\0\0") : I32 ("13\0\0"), == 5);
+
+  TX ("abcdef", uint32_t, 3, i ? I32 ("12\0\0") : I32 ("123\0"), >= 5);
+  TX ("abcdef", uint32_t, 3, i ? I32 ("12\0\0") : I32 ("123\0"), < 7);
 }
 
 void store_64bit (int i)
 {
-  T2 ("xxxxxxx", int64_t, 0,                0, I32 ("\1\0\0\0"), == 1);
-  T2 ("xxxxxxx", int64_t, 0,                0, I32 ("\0\1\0\0"), == 0);
-  T2 ("xxxxxxx", int64_t, 0,                0, I32 ("\0\0\1\0"), == 0);
-  T2 ("xxxxxxx", int64_t, 0,                0, I32 ("\0\00\0\1"), == 0);
-  T2 ("xxxxxxx", int64_t, 0, I32 ("\1\0\0\0"), 0, == 0);
-  T2 ("xxxxxxx", int64_t, 0, I32 ("\0\1\0\0"), 0, == 0);
-  T2 ("xxxxxxx", int64_t, 0, I32 ("\0\0\1\0"), 0, == 0);
-  T2 ("xxxxxxx", int64_t, 0, I32 ("\0\0\0\1"), 0, == 0);
-
-  T2 ("xxxxxxx", int64_t, 0, 0, I32 ("\1\2\0\0"), == 2);
-  T2 ("xxxxxxx", int64_t, 0, 0, I32 ("\0\1\2\0"), == 0);
-  T2 ("xxxxxxx", int64_t, 0, 0, I32 ("\0\0\1\2"), == 0);
-
-  T2 ("xxxxxxx", int64_t, 0, 0, I32 ("\1\2\3\0"), == 3);
-  T2 ("xxxxxxx", int64_t, 0, 0, I32 ("\0\1\2\3"), == 0);
-
-  T2 ("xxxxxxx", int64_t, 0, 0, I32 ("\1\2\3\4"), == 4);
-  T2 ("xxxxxxx", int64_t, 0, I32 ("\5\0\0\0"), I32 ("\1\2\3\4"), == 5);
-  T2 ("xxxxxxx", int64_t, 0, I32 ("\5\6\0\0"), I32 ("\1\2\3\4"), == 6);
-  T2 ("xxxxxxx", int64_t, 0, I32 ("\5\6\7\0"), I32 ("\1\2\3\4"), == 7);
-
-  int64_t x7777777 = I64 ("\7\7\7\7\7\7\7");
-  int64_t x666666 = I64 ("\6\6\6\6\6\6\0");
-  int64_t x4444 = I64 ("\4\4\4\4\0\0\0");
-  int64_t x3333 = I64 ("\3\3\3\3\0\0\0");
-  int64_t x1 = I64 ("\1\0\0\0\0\0\0");
-
-  T ("x\0xxxxxx", int64_t, 0, i ? x7777777 : x666666, <= 7);
-  T ("xx\0xxxxx", int64_t, 0, i ? x7777777 : x666666, >= 6);
-  T ("xxx\0xxxx", int64_t, 0, i ? x666666 : x1, <= 6);
-  T ("xxxx\0xxx", int64_t, 0, i ? x666666 : x1, >= 1);
-  T ("xxxxxx\0x", int64_t, 0, i ? x4444 : x3333, == 4);
+  T ("xxxxxxx", uint64_t, 0, I64 ("\1\0\0\0\0\0\0\0\0"), == 1);
+  T ("xxxxxxx", uint64_t, 0, I64 ("\0\1\0\0\0\0\0\0\0"), == 0);
+  T ("xxxxxxx", uint64_t, 0, I64 ("\0\0\1\0\0\0\0\0\0"), == 0);
+  T ("xxxxxxx", uint64_t, 0, I64 ("\0\0\0\1\0\0\0\0\0"), == 0);
+  T ("xxxxxxx", uint64_t, 0, I64 ("\0\0\0\0\1\0\0\0\0"), == 0);
+  T ("xxxxxxx", uint64_t, 0, I64 ("\0\0\0\0\0\1\0\0\0"), == 0);
+  T ("xxxxxxx", uint64_t, 0, I64 ("\0\0\0\0\0\0\1\0\0"), == 0);
+  T ("xxxxxxx", uint64_t, 0, I64 ("\0\0\0\0\0\0\0\1\0"), == 0);
+
+  T ("xxxxxxx", uint64_t, 0, I64 ("\1\2\0\0\0\0\0\0\0"), == 2);
+  T ("xxxxxxx", uint64_t, 0, I64 ("\0\1\2\0\0\0\0\0\0"), == 0);
+  T ("xxxxxxx", uint64_t, 0, I64 ("\0\0\1\2\0\0\0\0\0"), == 0);
+
+  T ("xxxxxxx", uint64_t, 0, I64 ("\1\2\3\0\0\0\0\0\0"), == 3);
+  T ("xxxxxxx", uint64_t, 0, I64 ("\0\1\2\3\0\0\0\0\0"), == 0);
+
+  T ("xxxxxxx", uint64_t, 0, I64 ("\1\2\3\4\0\0\0\0\0"), == 4);
+  T ("xxxxxxx", uint64_t, 0, I64 ("\1\2\3\4\5\0\0\0\0"), == 5);
+  T ("xxxxxxx", uint64_t, 0, I64 ("\1\2\3\4\5\6\0\0\0"), == 6);
+  T ("xxxxxxx", uint64_t, 0, I64 ("\1\2\3\4\5\6\7\0\0"), == 7);
+
+  uint64_t x7777777 = I64 ("\7\7\7\7\7\7\7");
+  uint64_t x666666 = I64 ("\6\6\6\6\6\6\0");
+  uint64_t x4444 = I64 ("\4\4\4\4\0\0\0");
+  uint64_t x3333 = I64 ("\3\3\3\3\0\0\0");
+  uint64_t x1 = I64 ("\1\0\0\0\0\0\0");
+
+  T ("x\0xxxxxx", uint64_t, 0, i ? x7777777 : x666666, <= 7);
+  T ("xx\0xxxxx", uint64_t, 0, i ? x7777777 : x666666, >= 6);
+  T ("xxx\0xxxx", uint64_t, 0, i ? x666666 : x1, <= 6);
+  T ("xxxx\0xxx", uint64_t, 0, i ? x666666 : x1, >= 1);
+  T ("xxxxxx\0x", uint64_t, 0, i ? x4444 : x3333, == 4);
 }
 
-#ifdef __uint128_t
+#if __SIZEOF_INT128__
 
 typedef __uint128_t     uint128_t;
 
 void store_128bit (void)
 {
-  uint64_t x1 = I64 ("\1\0\0\0\0\0\0\0");
-  uint64_t x01 = I64 ("\0\1\0\0\0\0\0\0");
-  uint64_t x001 = I64 ("\0\0\1\0\0\0\0\0");
-  uint64_t x0001 = I64 ("\0\0\0\1\0\0\0\0");
-  uint64_t x00001 = I64 ("\0\0\0\0\1\0\0\0");
-  uint64_t x000001 = I64 ("\0\0\0\0\0\1\0\0");
-  uint64_t x0000001 = I64 ("\0\0\0\0\0\0\1\0");
-  uint64_t x00000001 = I64 ("\0\0\0\0\0\0\0\1");
-
-  T2 ("xxxxxxx", uint128_t, 0, 0,        x1, == 1);
-  T2 ("xxxxxxx", uint128_t, 0, 0,       x01, == 0);
-  T2 ("xxxxxxx", uint128_t, 0, 0,      x001, == 0);
-  T2 ("xxxxxxx", uint128_t, 0, 0,     x0001, == 0);
-  T2 ("xxxxxxx", uint128_t, 0, 0,    x00001, == 0);
-  T2 ("xxxxxxx", uint128_t, 0, 0,   x000001, == 0);
-  T2 ("xxxxxxx", uint128_t, 0, 0,  x0000001, == 0);
-  T2 ("xxxxxxx", uint128_t, 0, 0, x00000001, == 0);
-
-  T2 ("xxxxxxx", uint128_t, 0,        x1, 0, == 0);
-  T2 ("xxxxxxx", uint128_t, 0,       x01, 0, == 0);
-  T2 ("xxxxxxx", uint128_t, 0,      x001, 0, == 0);
-  T2 ("xxxxxxx", uint128_t, 0,     x0001, 0, == 0);
-  T2 ("xxxxxxx", uint128_t, 0,    x00001, 0, == 0);
-  T2 ("xxxxxxx", uint128_t, 0,   x000001, 0, == 0);
-  T2 ("xxxxxxx", uint128_t, 0,  x0000001, 0, == 0);
-  T2 ("xxxxxxx", uint128_t, 0, x00000001, 0, == 0);
-
-  T2 ("xxxxxxx", uint128_t, 0, 0, I64 ("\2\1\0\0\0\0\0\0"), == 2);
-  T2 ("xxxxxxx", uint128_t, 0, 0, I64 ("\0\2\1\0\0\0\0\0"), == 0);
-
-  T2 ("xxxxxxx", uint128_t, 0, 0, I64 ("\3\2\1\0\0\0\0\0"), == 3);
-  T2 ("xxxxxxx", uint128_t, 0, 0, I64 ("\0\3\2\1\0\0\0\0"), == 0);
-
-  uint64_t x4321     = I64 ("\4\3\2\1\0\0\0\0");
-  uint64_t x54321    = I64 ("\5\4\3\2\1\0\0\0");
-  uint64_t x654321   = I64 ("\6\5\4\3\2\1\0\0");
-  uint64_t x7654321  = I64 ("\7\6\5\4\3\2\1\0");
-  uint64_t x87654321 = I64 ("8\7\6\5\4\3\2\1");
-  uint64_t x9        = I64 ("9\0\0\0\0\0\0\0");
-  uint64_t xa9       = I64 ("a9\0\0\0\0\0\0");
-  uint64_t xba9      = I64 ("ba9\0\0\0\0\0\0");
-  uint64_t xcba9     = I64 ("cba9\0\0\0\0\0");
-  uint64_t xdcba9    = I64 ("dcba9\0\0\0\0");
-  uint64_t xedcba9   = I64 ("edcba9\0\0\0\0");
-  uint64_t xfedcba9  = I64 ("fedcba9\0\0\0");
-
-  T2 (0, uint128_t, 0,        0,     x4321, ==  4);
-  T2 (0, uint128_t, 0,        0,    x54321, ==  5);
-  T2 (0, uint128_t, 0,        0,   x654321, ==  6);
-  T2 (0, uint128_t, 0,        0,  x7654321, ==  7);
-  T2 (0, uint128_t, 0,        0, x87654321, ==  8);
-  T2 (0, uint128_t, 0,       x9, x87654321, ==  9);
-  T2 (0, uint128_t, 0,      xa9, x87654321, == 10);
-  T2 (0, uint128_t, 0,     xba9, x87654321, == 11);
-  T2 (0, uint128_t, 0,    xcba9, x87654321, == 12);
-  T2 (0, uint128_t, 0,   xdcba9, x87654321, == 13);
-  T2 (0, uint128_t, 0,  xedcba9, x87654321, == 14);
-  T2 (0, uint128_t, 0, xfedcba9, x87654321, == 15);
+  uint128_t x1    = I128 ("\1");
+  uint128_t x1z1  = I128 ("\0\1");
+  uint128_t x2z1  = I128 ("\0\0\1");
+  uint128_t x3z1  = I128 ("\0\0\0\1");
+  uint128_t x4z1  = I128 ("\0\0\0\0\1");
+  uint128_t x5z1  = I128 ("\0\0\0\0\0\1");
+  uint128_t x6z1  = I128 ("\0\0\0\0\0\0\1");
+  uint128_t x7z1  = I128 ("\0\0\0\0\0\0\0\1");
+  uint128_t x8z1  = I128 ("\0\0\0\0\0\0\0\0\1");
+  uint128_t x9z1  = I128 ("\0\0\0\0\0\0\0\0\0\1");
+  uint128_t x10z1 = I128 ("\0\0\0\0\0\0\0\0\0\0\1");
+  uint128_t x11z1 = I128 ("\0\0\0\0\0\0\0\0\0\0\0\1");
+  uint128_t x12z1 = I128 ("\0\0\0\0\0\0\0\0\0\0\0\0\1");
+  uint128_t x13z1 = I128 ("\0\0\0\0\0\0\0\0\0\0\0\0\0\1");
+  uint128_t x14z1 = I128 ("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1");
+  uint128_t x15z1 = I128 ("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1");
+
+  T ("xxxxxxx", uint128_t, 0, x1, == 1);
+  T ("xxxxxxx", uint128_t, 0, x1z1, == 0);
+  T ("xxxxxxx", uint128_t, 0, x2z1, == 0);
+  T ("xxxxxxx", uint128_t, 0, x3z1, == 0);
+  T ("xxxxxxx", uint128_t, 0, x4z1, == 0);
+  T ("xxxxxxx", uint128_t, 0, x5z1, == 0);
+  T ("xxxxxxx", uint128_t, 0, x6z1, == 0);
+  T ("xxxxxxx", uint128_t, 0, x7z1, == 0);
+  T ("xxxxxxx", uint128_t, 0, x8z1, == 0);
+  T ("xxxxxxx", uint128_t, 0, x9z1, == 0);
+  T ("xxxxxxx", uint128_t, 0, x10z1, == 0);
+  T ("xxxxxxx", uint128_t, 0, x11z1, == 0);
+  T ("xxxxxxx", uint128_t, 0, x12z1, == 0);
+  T ("xxxxxxx", uint128_t, 0, x13z1, == 0);
+  T ("xxxxxxx", uint128_t, 0, x14z1, == 0);
+  T ("xxxxxxx", uint128_t, 0, x15z1, == 0);
+
+  T ("xxxxxxx", uint128_t, 0, I128 ("\2\1"), == 2);
+  T ("xxxxxxx", uint128_t, 0, I128 ("\0\2\1"), == 0);
+
+  T ("xxxxxxx", uint128_t, 0, I128 ("\3\2\1"), == 3);
+  T ("xxxxxxx", uint128_t, 0, I128 ("\0\3\2\1"), == 0);
+
+  T ("xxxxxxx", uint128_t, 0, I128 ("\1\2\3\4"), == 4);
+  T ("xxxxxxx", uint128_t, 0, I128 ("\1\2\3\4\5"), == 5);
+  T ("xxxxxxx", uint128_t, 0, I128 ("\1\2\3\4\5\6"), == 6);
+  T ("xxxxxxx", uint128_t, 0, I128 ("\1\2\3\4\5\6\7"), == 7);
+  T ("xxxxxxx", uint128_t, 0, I128 ("\1\2\3\4\5\6\7\10"), == 8);
+  T ("xxxxxxx", uint128_t, 0, I128 ("\1\2\3\4\5\6\7\10\11"), == 9);
+  T ("xxxxxxx", uint128_t, 0, I128 ("\1\2\3\4\5\6\7\10\11\12"), == 10);
+  T ("xxxxxxx", uint128_t, 0, I128 ("\1\2\3\4\5\6\7\10\11\12\13"), == 11);
+  T ("xxxxxxx", uint128_t, 0, I128 ("\1\2\3\4\5\6\7\10\11\12\13\14"), == 12);
+  T ("xxxxxxx", uint128_t, 0, I128 ("\1\2\3\4\5\6\7\10\11\12\13\14\15"), == 13);
+  T ("xxxxxxx", uint128_t, 0, I128 ("\1\2\3\4\5\6\7\10\11\12\13\14\15\16"), == 14);
+  T ("xxxxxxx", uint128_t, 0, I128 ("\1\2\3\4\5\6\7\10\11\12\13\14\15\16\17"), == 15);
 }
 
-#endif   // __uint128_t
+#endif   // __SIZEOF_INT128__
 
 /* { dg-final { scan-tree-dump-times "strlen" 0 "optimized" } }
    { dg-final { scan-tree-dump-times "_not_eliminated_" 0 "optimized" } } */
index 1905519..fd4c4a9 100644 (file)
@@ -8,8 +8,8 @@
 
 #define CHAR_BIT __CHAR_BIT__
 
-typedef __INT16_TYPE__ int16_t;
-typedef __INT32_TYPE__ int32_t;
+typedef __UINT16_TYPE__ uint16_t;
+typedef __UINT32_TYPE__ uint32_t;
 
 #define NOIPA __attribute__ ((noclone, noinline, noipa))
 
@@ -40,12 +40,23 @@ NOIPA void terminate (void)
       }                                                                        \
   } while (0)
 
+
+#define ELT(s, i)   ((s "\0\0\0\0")[i])
+
 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
-#  define I16(s) ((s[0] << 8) + s[1])
-#  define I32(s) ((s[0] << 24) + (s[1] << 16) + (s[2] << 8) + s[3])
+#  define I16(s) (((uint16_t)ELT (s, 0) << 8) + (uint16_t)ELT (s, 1))
+#  define I32(s)                               \
+  (((uint32_t)ELT (s, 0) << 24)                        \
+   + ((uint32_t)ELT (s, 1) << 16)              \
+   + ((uint32_t)ELT (s, 2) << 8)               \
+   + (uint32_t)ELT (s, 3))
 #elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
-#  define I16(s) ((s[1] << 8) + s[0])
-#  define I32(s) ((s[3] << 24) + (s[2] << 16) + (s[1] << 8) + s[0])
+#  define I16(s) (((uint16_t)ELT (s, 1) << 8) + (uint16_t)ELT (s, 0))
+#  define I32(s)                               \
+  (((uint32_t)ELT (s, 3) << 24)                        \
+   + ((uint32_t)ELT (s, 2) << 16)              \
+   + ((uint32_t)ELT (s, 1) << 8)               \
+   + (uint32_t)ELT (s, 0))
 #endif
 
 char a[32];
@@ -53,21 +64,21 @@ char a[32];
 NOIPA void
 i16_1 (void)
 {
-  *(int16_t*)a = I16 ("12");
-  *(int16_t*)(a + 2) = I16 ("3");
+  *(uint16_t*)a = I16 ("12");
+  *(uint16_t*)(a + 2) = I16 ("3");
   VERIFY (a, "123");
 
-  *(int16_t*)(a + 1) = I16 ("23");
+  *(uint16_t*)(a + 1) = I16 ("23");
   VERIFY (a, "123");
 
-  *(int16_t*)(a) = I16 ("12");
+  *(uint16_t*)(a) = I16 ("12");
   VERIFY (a, "123");
 
-  *(int16_t*)(a + 1) = I16 ("2");
+  *(uint16_t*)(a + 1) = I16 ("2");
   VERIFY (a, "12");
 
-  *(int16_t*)(a + 3) = I16 ("45");
-  *(int16_t*)(a + 2) = I16 ("34");
+  *(uint16_t*)(a + 3) = I16 ("45");
+  *(uint16_t*)(a + 2) = I16 ("34");
   VERIFY (a, "12345");
 }
 
@@ -77,19 +88,19 @@ i16_2 (void)
   strcpy (a, "12");
   strcat (a, "34");
 
-  *(int16_t*)a = I16 ("12");
+  *(uint16_t*)a = I16 ("12");
   VERIFY (a, "1234");
 
-  *(int16_t*)(a + 1) = I16 ("12");
+  *(uint16_t*)(a + 1) = I16 ("12");
   VERIFY (a, "1124");
 
-  *(int16_t*)(a + 2) = I16 ("12");
+  *(uint16_t*)(a + 2) = I16 ("12");
   VERIFY (a, "1112");
 
-  *(int16_t*)(a + 3) = I16 ("12");
+  *(uint16_t*)(a + 3) = I16 ("12");
   VERIFY (a, "11112");
 
-  *(int16_t*)(a + 4) = I16 ("12");
+  *(uint16_t*)(a + 4) = I16 ("12");
   VERIFY (a, "111112");
 }
 
@@ -97,10 +108,10 @@ i16_2 (void)
 NOIPA void
 i32_1 (void)
 {
-  *(int32_t*)a = I32 ("1234");
+  *(uint32_t*)a = I32 ("1234");
   VERIFY (a, "1234");
 
-  *(int32_t*)(a + 1) = I32 ("2345");
+  *(uint32_t*)(a + 1) = I32 ("2345");
   VERIFY (a, "12345");
 }
 
@@ -110,22 +121,22 @@ i32_2 (void)
   strcpy (a, "12");
   strcat (a, "34");
 
-  *(int32_t*)a = I32 ("1234");
+  *(uint32_t*)a = I32 ("1234");
   VERIFY (a, "1234");
 
-  *(int32_t*)(a + 4) = I32 ("567");
+  *(uint32_t*)(a + 4) = I32 ("567");
   VERIFY (a, "1234567");
 
-  *(int32_t*)(a + 7) = I32 ("89\0");
+  *(uint32_t*)(a + 7) = I32 ("89\0");
   VERIFY (a, "123456789");
 
-  *(int32_t*)(a + 3) = I32 ("4567");
+  *(uint32_t*)(a + 3) = I32 ("4567");
   VERIFY (a, "123456789");
 
-  *(int32_t*)(a + 2) = I32 ("3456");
+  *(uint32_t*)(a + 2) = I32 ("3456");
   VERIFY (a, "123456789");
 
-  *(int32_t*)(a + 1) = I32 ("2345");
+  *(uint32_t*)(a + 1) = I32 ("2345");
   VERIFY (a, "123456789");
 }
 
@@ -136,25 +147,25 @@ i32_3 (void)
   strcpy (a, "1234");
   strcat (a, "5678");
 
-  *(int32_t*)a = I32 ("1234");
+  *(uint32_t*)a = I32 ("1234");
   VERIFY (a, "12345678");
 
-  *(int32_t*)(a + 1) = I32 ("234");
+  *(uint32_t*)(a + 1) = I32 ("234");
   VERIFY (a, "1234");
 
-  *(int32_t*)(a + 2) = I32 ("3456");
+  *(uint32_t*)(a + 2) = I32 ("3456");
   VERIFY (a, "12345678");
 
-  *(int32_t*)(a + 3) = I32 ("4567");
+  *(uint32_t*)(a + 3) = I32 ("4567");
   VERIFY (a, "12345678");
 
-  *(int32_t*)(a + 4) = I32 ("5678");
+  *(uint32_t*)(a + 4) = I32 ("5678");
   VERIFY (a, "12345678");
 
-  *(int32_t*)(a + 5) = I32 ("6789");
+  *(uint32_t*)(a + 5) = I32 ("6789");
   VERIFY (a, "123456789");
 
-  *(int32_t*)(a + 6) = I32 ("789A");
+  *(uint32_t*)(a + 6) = I32 ("789A");
   VERIFY (a, "123456789A");
 }
 
@@ -166,25 +177,25 @@ i32_4 (void)
   strcpy (a, "1234");
   strcat (a, "5678");
 
-  *(int32_t*)a = vzero ? I32 ("1\0\0\0") : I32 ("1234");
+  *(uint32_t*)a = vzero ? I32 ("1\0\0\0") : I32 ("1234");
   VERIFY (a, "12345678");
 
-  *(int32_t*)a = vzero ? I32 ("12\0\0") : I32 ("1234");
+  *(uint32_t*)a = vzero ? I32 ("12\0\0") : I32 ("1234");
   VERIFY (a, "12345678");
 
-  *(int32_t*)a = vzero ? I32 ("123\0") : I32 ("1234");
+  *(uint32_t*)a = vzero ? I32 ("123\0") : I32 ("1234");
   VERIFY (a, "12345678");
 
-  *(int32_t*)a = vzero ? I32 ("1234") : I32 ("1234");
+  *(uint32_t*)a = vzero ? I32 ("1234") : I32 ("1234");
   VERIFY (a, "12345678");
 
-  *(int32_t*)a = vzero ? I32 ("1235") : I32 ("1234");
+  *(uint32_t*)a = vzero ? I32 ("1235") : I32 ("1234");
   VERIFY (a, "12345678");
 
-  *(int32_t*)a = vzero ? I32 ("1234") : I32 ("123\0");
+  *(uint32_t*)a = vzero ? I32 ("1234") : I32 ("123\0");
   VERIFY (a, "123");
 
-  *(int32_t*)(a + 3) = vzero ? I32 ("456\0") : I32 ("4567");
+  *(uint32_t*)(a + 3) = vzero ? I32 ("456\0") : I32 ("4567");
   VERIFY (a, "12345678");
 }
 
index a06cc4f..9c00a95 100644 (file)
@@ -5,7 +5,12 @@
    unaligned stores and where GCC lowers multi-character stores into smaller
    numbers of wider stores.
    { dg-do compile }
-   { dg-options "-O2 -fdump-tree-optimized" }  */
+   { dg-options "-O2 -fdump-tree-optimized" }
+   On strictly aligned targets the consecutive char assignments used
+   by the test aren't merged.  When they involve multiple trailing nuls
+   these assignments then defeat the strlen optimization as a result of
+   pr83821.  When the bug is resolved the directive below can be removed.
+   { dg-require-effective-target non_strict_align } */
 
 #include "strlenopt.h"