1 /* PR tree-optimization/91996 - fold non-constant strlen relational expressions
2    { dg-do run }
3    { dg-options "-O2 -Wall -Wno-unused-local-typedefs" } */
4 
5 typedef __SIZE_TYPE__ size_t;
6 
7 #define NOIPA   __attribute__ ((noipa))
8 
9 #define CONCAT(a, b) a ## b
10 #define CAT(a, b)    CONCAT (a, b)
11 
12 /* Used in tests where EXPR is expected to be folded to false.  */
13 #define ELIM(expr)							\
14   if (expr) {								\
15     extern void								\
16       CAT (CAT (test_on_line_, __LINE__), _not_eliminated)(void);	\
17     CAT (CAT (test_on_line_, __LINE__), _not_eliminated)();		\
18   } typedef void dummy_type
19 
20 
21 /* Set the alignment for targets that depend on it in order to
22    optimize away the ELIM calls.  See pr92128.  */
23 __attribute__ ((aligned(4))) char a[32], b[32];
24 
init(void)25 void init (void)
26 {
27   __builtin_strncpy (a, "abcdefgh", sizeof a);
28   __builtin_strncpy (b, "0123456789", sizeof b);
29 }
30 
fail(const char * func)31 NOIPA void fail (const char *func)
32 {
33   __builtin_printf ("failure in %s\n", func);
34   __builtin_abort ();
35 }
36 
test_global_cpy_4(void)37 NOIPA void test_global_cpy_4 (void)
38 {
39   size_t blen = __builtin_strlen (b);
40   if (blen < 9) return;
41 
42   char *d = a;
43   __builtin_memcpy (d, b, 4);
44 
45   size_t dlen = __builtin_strlen (d);
46   if (dlen != 8)   // cannot be eliminated
47     fail ("test_global");
48 }
49 
50 
test_global_cpy_10(void)51 NOIPA void test_global_cpy_10 (void)
52 {
53   size_t blen = __builtin_strlen (b);
54   if (blen < 9) return;
55 
56   char *d = a;
57   __builtin_memcpy (d, b, 10);
58 
59   size_t dlen = __builtin_strlen (d);
60   if (dlen != 10)   // cannot be eliminated
61     fail ("test_global_cpy_10");
62 }
63 
test_global_cpy_11(void)64 NOIPA void test_global_cpy_11 (void)
65 {
66   size_t blen = __builtin_strlen (b);
67   if (blen < 9) return;
68 
69   char *d = a;
70   __builtin_memcpy (d, b, 11);
71 
72   size_t dlen = __builtin_strlen (d);
73   if (dlen != 10)   // cannot be eliminated
74     fail ("test_global_cpy_11");
75 }
76 
test_global_cpy_20(void)77 NOIPA void test_global_cpy_20 (void)
78 {
79   size_t blen = __builtin_strlen (b);
80   if (blen < 9) return;
81 
82   char *d = a;
83   __builtin_memcpy (d, b, 20);
84 
85   size_t dlen = __builtin_strlen (d);
86   if (dlen != 10)   // cannot be eliminated
87     fail ("test_global_cpy_20");
88 }
89 
test_local_cpy_4(void)90 NOIPA void test_local_cpy_4 (void)
91 {
92   size_t blen = __builtin_strlen (b);
93   if (blen < 9) return;
94 
95 /* Set the alignment for targets that depend on it in order to
96    optimize away the ELIM calls.  See pr92128.  */
97   __attribute__ ((aligned(4))) char a[10] = "abcdefgh";
98   char *d = a;
99   __builtin_memcpy (d, b, 4);
100 
101   size_t dlen = __builtin_strlen (d);
102   ELIM (dlen != 8);
103 }
104 
test_local_cpy_10(void)105 NOIPA void test_local_cpy_10 (void)
106 {
107   size_t blen = __builtin_strlen (b);
108   if (blen < 9) return;
109 
110   char a[32] = "abcdefgh";
111   char *d = a;
112   __builtin_memcpy (d, b, 10);
113 
114   /* B can be longer than 9 and A can initially be longer than 10
115      so the test below cannot be eliminated.  */
116   size_t dlen = __builtin_strlen (d);
117   if (dlen != 10)
118     fail ("test_local_cpy_10");
119 }
120 
test_local_cpy_11(void)121 NOIPA void test_local_cpy_11 (void)
122 {
123   size_t blen = __builtin_strlen (b);
124   if (blen < 9) return;
125 
126   char a[32] = "abcdefgh";
127   char *d = a;
128   __builtin_memcpy (d, b, 11);
129 
130   size_t dlen = __builtin_strlen (d);
131   if (dlen != 10)
132     fail ("test_global_cpy_20");
133 }
134 
test_local_cpy_20(void)135 NOIPA void test_local_cpy_20 (void)
136 {
137   size_t blen = __builtin_strlen (b);
138   if (blen < 9) return;
139 
140   char a[32] = "abcdefgh";
141   char *d = a;
142   __builtin_memcpy (d, b, 20);
143 
144   size_t dlen = __builtin_strlen (d);
145   if (dlen != 10)
146     fail ("test_global_cpy_20");
147 }
148 
test_global_length_eq(void)149 NOIPA void test_global_length_eq (void)
150 {
151   size_t blen = __builtin_strlen (b);
152   if (blen != 10) return;
153 
154   size_t alen = __builtin_strlen (a);
155   if (alen != 8) return;
156 
157   char *d = a;
158   __builtin_memcpy (d, b, 4);
159 
160   size_t dlen = __builtin_strlen (d);
161   ELIM (dlen != 8);
162 }
163 
164 
test_global_length_gt(void)165 NOIPA void test_global_length_gt (void)
166 {
167   size_t blen = __builtin_strlen (b);
168   if (blen < 9) return;
169 
170   size_t alen = __builtin_strlen (a);
171   if (alen < 8) return;
172 
173   char *d = a;
174   __builtin_memcpy (d, b, 4);
175 
176   size_t dlen = __builtin_strlen (d);
177   ELIM (dlen < 8);
178 }
179 
180 #define TEST(name) do { init (); test_ ## name (); } while (0)
181 
main(void)182 int main (void)
183 {
184   TEST (local_cpy_4);
185   TEST (local_cpy_10);
186   TEST (local_cpy_11);
187   TEST (local_cpy_20);
188 
189   TEST (global_cpy_4);
190   TEST (global_cpy_10);
191   TEST (global_cpy_11);
192   TEST (global_cpy_20);
193   TEST (global_length_eq);
194   TEST (global_length_gt);
195 }
196