1 /* PR tree-optimization/86711 - wrong folding of memchr
2 
3    Verify that calls to memchr() with constant arrays initialized
4    with wide string literals are folded.
5 
6    { dg-do compile }
7    { dg-options "-O1 -Wall -fdump-tree-optimized" } */
8 
9 #include "strlenopt.h"
10 
11 typedef __WCHAR_TYPE__ wchar_t;
12 
13 extern void* memchr (const void*, int, size_t);
14 
15 #define CONCAT(x, y) x ## y
16 #define CAT(x, y) CONCAT (x, y)
17 #define FAILNAME(name) CAT (call_ ## name ##_on_line_, __LINE__)
18 
19 #define FAIL(name) do {				\
20     extern void FAILNAME (name) (void);		\
21     FAILNAME (name)();				\
22   } while (0)
23 
24 /* Macro to emit a call to funcation named
25    call_in_true_branch_not_eliminated_on_line_NNN()
26    for each call that's expected to be eliminated.  The dg-final
27    scan-tree-dump-time directive at the bottom of the test verifies
28    that no such call appears in output.  */
29 #define ELIM(expr)							\
30   if (!(expr)) FAIL (in_true_branch_not_eliminated); else (void)0
31 
32 #define T(s, n) ELIM (strlen (s) == n)
33 
34 
35 static const wchar_t wc = L'1';
36 static const wchar_t ws1[] = L"1";
37 static const wchar_t wsx[] = L"\x12345678";		/* { dg-warning "hex escape" "" { target { ! 4byte_wchar_t } } } */
38 static const wchar_t ws4[] = L"\x00123456\x12005678\x12340078\x12345600";		/* { dg-warning "hex escape" "" { target { ! 4byte_wchar_t } } } */
39 
test_wide(void)40 void test_wide (void)
41 {
42   int i0 = 0;
43   int i1 = i0 + 1;
44   int i2 = i1 + 1;
45   int i3 = i2 + 1;
46   int i4 = i3 + 1;
47 
48   ELIM (memchr (L"" + 1, 0, 0) == 0);
49   ELIM (memchr (&wc + 1, 0, 0) == 0);
50   ELIM (memchr (L"\x12345678", 0, sizeof (wchar_t)) == 0);		/* { dg-warning "hex escape" "" { target { ! 4byte_wchar_t } } } */
51 
52   const size_t nb = sizeof ws4;
53   const size_t nwb = sizeof (wchar_t);
54 
55   const char *pws1 = (const char*)ws1;
56   const char *pws4 = (const char*)ws4;
57   const char *pwsx = (const char*)wsx;
58 
59 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
60   ELIM (memchr (ws1, 0, sizeof ws1) == pws1 + 1);
61   ELIM (memchr (wsx, 0, sizeof wsx) == pwsx + sizeof *wsx);
62 
63   ELIM (memchr (&ws4[0], 0, nb) == pws4 + 3);
64   ELIM (memchr (&ws4[1], 0, nb - 1 * nwb) == pws4 + 1 * nwb + 2);
65   ELIM (memchr (&ws4[2], 0, nb - 2 * nwb) == pws4 + 2 * nwb + 1);
66   ELIM (memchr (&ws4[3], 0, nb - 3 * nwb) == pws4 + 3 * nwb + 0);
67   ELIM (memchr (&ws4[4], 0, nb - 4 * nwb) == pws4 + 4 * nwb + 0);
68 
69   ELIM (memchr (&ws4[i0], 0, nb) == pws4 + 3);
70   ELIM (memchr (&ws4[i1], 0, nb - 1 * nwb) == pws4 + 1 * nwb + 2);
71   ELIM (memchr (&ws4[i2], 0, nb - 2 * nwb) == pws4 + 2 * nwb + 1);
72   ELIM (memchr (&ws4[i3], 0, nb - 3 * nwb) == pws4 + 3 * nwb + 0);
73   ELIM (memchr (&ws4[i4], 0, nb - 4 * nwb) == pws4 + 4 * nwb + 0);
74 #else
75   ELIM (memchr (ws1, 0, sizeof ws1) == pws1 + 0);
76   ELIM (memchr (wsx, 0, sizeof wsx) == pwsx + sizeof *wsx);
77 
78   ELIM (memchr (&ws4[0], 0, nb) == pws4 + 0);
79   ELIM (memchr (&ws4[1], 0, nb - 1 * nwb) == pws4 + 1 * nwb + 1);
80   ELIM (memchr (&ws4[2], 0, nb - 2 * nwb) == pws4 + 2 * nwb + 2);
81   ELIM (memchr (&ws4[3], 0, nb - 3 * nwb) == pws4 + 3 * nwb + 3);
82   ELIM (memchr (&ws4[4], 0, nb - 4 * nwb) == pws4 + 4 * nwb + 0);
83 
84   ELIM (memchr (&ws4[i0], 0, nb) == pws4 + 0);
85   ELIM (memchr (&ws4[i1], 0, nb - 1 * nwb) == pws4 + 1 * nwb + 1);
86   ELIM (memchr (&ws4[i2], 0, nb - 2 * nwb) == pws4 + 2 * nwb + 2);
87   ELIM (memchr (&ws4[i3], 0, nb - 3 * nwb) == pws4 + 3 * nwb + 3);
88   ELIM (memchr (&ws4[i4], 0, nb - 4 * nwb) == pws4 + 4 * nwb + 0);
89 #endif
90 }
91 
92 /* { dg-final { scan-tree-dump-times "memchr" 0 "optimized" } }
93    { dg-final { scan-tree-dump-times "call_in_true_branch_not_eliminated" 0 "optimized" } } */
94