1 /* PR tree-optimization/83821 - local aggregate initialization defeats
2 strlen optimization
3
4 Avoid exercising targets other than x86_64 in LP64 mode due to PR 83543
5 - strlen of a local array member not optimized on some targets
6 { dg-do compile { target { { i?86-*-* x86_64-*-* } && lp64 } } }
7
8 { dg-options "-O2 -Wall -fdump-tree-optimized" } */
9
10 #include "strlenopt.h"
11
12 #define CAT(x, y) x ## y
13 #define CONCAT(x, y) CAT (x, y)
14 #define FAILNAME(name) CONCAT (call_ ## name ##_on_line_, __LINE__)
15
16 #define FAIL(name) do { \
17 extern void FAILNAME (name) (void); \
18 FAILNAME (name)(); \
19 } while (0)
20
21 /* Macro to emit a call to function named
22 call_in_true_branch_not_eliminated_on_line_NNN()
23 for each call that's expected to be eliminated. The dg-final
24 scan-tree-dump-time directive at the bottom of the test verifies
25 that no such call appears in output. */
26 #define ELIM(expr) \
27 if (!(expr)) FAIL (in_true_branch_not_eliminated); else (void)0
28
29 /* Macro to emit a call to a function named
30 call_made_in_{true,false}_branch_on_line_NNN()
31 for each call that's expected to be retained. The dg-final
32 scan-tree-dump-time directive at the bottom of the test verifies
33 that the expected number of both kinds of calls appears in output
34 (a pair for each line with the invocation of the KEEP() macro. */
35 #define KEEP(expr) \
36 if (expr) \
37 FAIL (made_in_true_branch); \
38 else \
39 FAIL (made_in_false_branch)
40
41 #define STR10 "0123456789"
42 #define STR20 STR10 STR10
43 #define STR30 STR20 STR10
44 #define STR40 STR20 STR20
45
46 void elim_char_array_init_consecutive (void)
47 {
48 char a[][10] = { "1", "12", "123", "1234", "12345", "12345" };
49
50 ELIM (strlen (a[0]) == 1);
51 ELIM (strlen (a[1]) == 2);
52 ELIM (strlen (a[2]) == 3);
53 ELIM (strlen (a[3]) == 4);
54 ELIM (strlen (a[4]) == 5);
55 }
56
57 void elim_char_array_cpy_consecutive (void)
58 {
59 char a[5][10];
60
61 strcpy (a[0], "12345");
62 strcpy (a[1], "1234");
63 strcpy (a[2], "123");
64 strcpy (a[3], "12");
65 strcpy (a[4], "1");
66
67 ELIM (strlen (a[0]) == 5);
68 ELIM (strlen (a[1]) == 4);
69 ELIM (strlen (a[2]) == 3);
70 ELIM (strlen (a[3]) == 2);
71 ELIM (strlen (a[4]) == 1);
72 }
73
74 void elim_clear_char_array_cpy_consecutive (void)
75 {
76 char a[5][10] = { };
77
78 strcpy (a[0], "12345");
79 strcpy (a[1], "1234");
80 strcpy (a[2], "123");
81 strcpy (a[3], "12");
82 strcpy (a[4], "1");
83
84 ELIM (strlen (a[0]) == 5);
85 ELIM (strlen (a[1]) == 4);
86 ELIM (strlen (a[2]) == 3);
87 ELIM (strlen (a[3]) == 2);
88 ELIM (strlen (a[4]) == 1);
89 }
90
91 struct Consec
92 {
93 char s1[sizeof STR40];
94 char s2[sizeof STR40];
95 const char *p1;
96 const char *p2;
97 };
98
99 void elim_struct_init_consecutive (void)
100 {
101 struct Consec a = { STR10, STR10, STR10, STR10 };
102
103 ELIM (strlen (a.s1) == sizeof STR10 - 1);
104 ELIM (strlen (a.s2) == sizeof STR10 - 1);
105 ELIM (strlen (a.p1) == sizeof STR10 - 1);
106 ELIM (strlen (a.p2) == sizeof STR10 - 1);
107 }
108
109 void elim_struct_array_init_consecutive (void)
110 {
111 struct Consec a[2] = {
112 { STR10, STR20, STR30, STR40 },
113 { STR40, STR30, STR20, STR10 }
114 };
115
116 ELIM (strlen (a[0].s1) == sizeof STR10 - 1);
117 ELIM (strlen (a[0].s2) == sizeof STR20 - 1);
118 ELIM (strlen (a[0].p1) == sizeof STR30 - 1);
119 ELIM (strlen (a[0].p2) == sizeof STR40 - 1);
120
121 ELIM (strlen (a[1].s1) == sizeof STR40 - 1);
122 ELIM (strlen (a[1].s2) == sizeof STR30 - 1);
123 ELIM (strlen (a[1].p1) == sizeof STR20 - 1);
124 ELIM (strlen (a[1].p2) == sizeof STR10 - 1);
125 }
126
127 struct NonConsec
128 {
129 char s1[sizeof STR40];
130 int i1;
131 char s2[sizeof STR40];
132 int i2;
133 const char *p1;
134 int i3;
135 const char *p2;
136 int i4;
137 };
138
139 void elim_struct_init_nonconsecutive (void)
140 {
141 struct NonConsec b = { STR10, 123, STR20, 456, b.s1, 789, b.s2, 123 };
142
143 ELIM (strlen (b.s1) == sizeof STR10 - 1);
144 ELIM (strlen (b.s2) == sizeof STR20 - 1);
145 ELIM (strlen (b.p1) == sizeof STR10 - 1);
146 ELIM (strlen (b.p2) == sizeof STR20 - 1);
147 }
148
149 void elim_struct_assign_tmp_nonconsecutive (void)
150 {
151 struct NonConsec b = { "a", 1, "b", 2, "c", 3, "d", 4 };
152
153 b = (struct NonConsec){ STR10, 123, STR20, 456, STR30, 789, STR40, 123 };
154
155 ELIM (strlen (b.s1) == sizeof STR10 - 1);
156 ELIM (strlen (b.s2) == sizeof STR20 - 1);
157 ELIM (strlen (b.p1) == sizeof STR30 - 1);
158 ELIM (strlen (b.p2) == sizeof STR40 - 1);
159 }
160
161 const struct NonConsec bcst = {
162 STR40, -1, STR30, -2, STR20, -3, STR10, -4
163 };
164
165 void elim_struct_assign_cst_nonconsecutive (void)
166 {
167 struct NonConsec b = { "a", 1, "b", 2, "c", 3, "d" };
168
169 b = bcst;
170
171 ELIM (strlen (b.s1) == sizeof STR40 - 1);
172 ELIM (strlen (b.s2) == sizeof STR30 - 1);
173 ELIM (strlen (b.p1) == sizeof STR20 - 1);
174 ELIM (strlen (b.p2) == sizeof STR10 - 1);
175 }
176
177 void elim_struct_copy_cst_nonconsecutive (void)
178 {
179 struct NonConsec b = { "a", 1, "b", 2, "c", 3, "d" };
180 memcpy (&b, &bcst, sizeof b);
181
182 /* ELIM (strlen (b.s1) == sizeof STR40 - 1);
183 ELIM (strlen (b.s2) == sizeof STR30 - 1); */
184 ELIM (strlen (b.p1) == sizeof STR20 - 1);
185 ELIM (strlen (b.p2) == sizeof STR10 - 1);
186 }
187
188
189 #line 1000
190
191 int sink (void*);
192
193 void keep_init_nonconsecutive (void)
194 {
195 struct NonConsec b = {
196 STR10, 123, STR20, 456, b.s1, 789, b.s2,
197 sink (&b)
198 };
199
200 KEEP (strlen (b.s1) == sizeof STR10 - 1);
201 KEEP (strlen (b.s2) == sizeof STR10 - 1);
202 KEEP (strlen (b.p1) == sizeof STR10 - 1);
203 KEEP (strlen (b.p2) == sizeof STR10 - 1);
204 }
205
206 void keep_assign_tmp_nonconsecutive (void)
207 {
208 struct NonConsec b = { "a", 1, "b", 2, "c", 3, "d", 4 };
209
210 b = (struct NonConsec){
211 STR10, 123, STR20, 456, STR30, 789, STR40,
212 sink (&b)
213 };
214
215 KEEP (strlen (b.s1) == sizeof STR10 - 1);
216 KEEP (strlen (b.s2) == sizeof STR20 - 1);
217 KEEP (strlen (b.p1) == sizeof STR30 - 1);
218 KEEP (strlen (b.p2) == sizeof STR40 - 1);
219 }
220
221 /* { dg-final { scan-tree-dump-times "call_in_true_branch_not_eliminated_" 0 "optimized" } }
222
223 { dg-final { scan-tree-dump-times "call_made_in_true_branch_on_line_1\[0-9\]\[0-9\]\[0-9\]" 8 "optimized" } }
224 { dg-final { scan-tree-dump-times "call_made_in_false_branch_on_line_1\[0-9\]\[0-9\]\[0-9\]" 8 "optimized" } } */