Fix handling of tail bytes of buffer in SSE2/SSSE3 x86-64 version strn{,case}cmp
[platform/upstream/glibc.git] / string / test-memcmp.c
1 /* Test and measure memcmp functions.
2    Copyright (C) 1999, 2002, 2003, 2005 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4    Written by Jakub Jelinek <jakub@redhat.com>, 1999.
5
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
10
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public
17    License along with the GNU C Library; if not, write to the Free
18    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19    02111-1307 USA.  */
20
21 #define TEST_MAIN
22 #include "test-string.h"
23
24 typedef int (*proto_t) (const char *, const char *, size_t);
25 int simple_memcmp (const char *, const char *, size_t);
26
27 IMPL (simple_memcmp, 0)
28 IMPL (memcmp, 1)
29
30 int
31 simple_memcmp (const char *s1, const char *s2, size_t n)
32 {
33   int ret = 0;
34
35   while (n--
36          && (ret = *(unsigned char *) s1++ - *(unsigned char *) s2++) == 0);
37   return ret;
38 }
39
40 static int
41 check_result (impl_t *impl, const char *s1, const char *s2, size_t len,
42               int exp_result)
43 {
44   int result = CALL (impl, s1, s2, len);
45   if ((exp_result == 0 && result != 0)
46       || (exp_result < 0 && result >= 0)
47       || (exp_result > 0 && result <= 0))
48     {
49       error (0, 0, "Wrong result in function %s %d %d", impl->name,
50              result, exp_result);
51       ret = 1;
52       return -1;
53     }
54
55   return 0;
56 }
57
58 static void
59 do_one_test (impl_t *impl, const char *s1, const char *s2, size_t len,
60              int exp_result)
61 {
62   if (check_result (impl, s1, s2, len, exp_result) < 0)
63     return;
64
65   if (HP_TIMING_AVAIL)
66     {
67       hp_timing_t start __attribute ((unused));
68       hp_timing_t stop __attribute ((unused));
69       hp_timing_t best_time = ~ (hp_timing_t) 0;
70       size_t i;
71
72       for (i = 0; i < 32; ++i)
73         {
74           HP_TIMING_NOW (start);
75           CALL (impl, s1, s2, len);
76           HP_TIMING_NOW (stop);
77           HP_TIMING_BEST (best_time, start, stop);
78         }
79
80       printf ("\t%zd", (size_t) best_time);
81     }
82 }
83
84 static void
85 do_test (size_t align1, size_t align2, size_t len, int exp_result)
86 {
87   size_t i;
88   char *s1, *s2;
89
90   if (len == 0)
91     return;
92
93   align1 &= 7;
94   if (align1 + len >= page_size)
95     return;
96
97   align2 &= 7;
98   if (align2 + len >= page_size)
99     return;
100
101   s1 = (char *) (buf1 + align1);
102   s2 = (char *) (buf2 + align2);
103
104   for (i = 0; i < len; i++)
105     s1[i] = s2[i] = 1 + 23 * i % 255;
106
107   s1[len] = align1;
108   s2[len] = align2;
109   s2[len - 1] -= exp_result;
110
111   if (HP_TIMING_AVAIL)
112     printf ("Length %4zd, alignment %2zd/%2zd:", len, align1, align2);
113
114   FOR_EACH_IMPL (impl, 0)
115     do_one_test (impl, s1, s2, len, exp_result);
116
117   if (HP_TIMING_AVAIL)
118     putchar ('\n');
119 }
120
121 static void
122 do_random_tests (void)
123 {
124   size_t i, j, n, align1, align2, pos, len;
125   int result;
126   long r;
127   unsigned char *p1 = buf1 + page_size - 512;
128   unsigned char *p2 = buf2 + page_size - 512;
129
130   for (n = 0; n < ITERATIONS; n++)
131     {
132       align1 = random () & 31;
133       if (random () & 1)
134         align2 = random () & 31;
135       else
136         align2 = align1 + (random () & 24);
137       pos = random () & 511;
138       j = align1;
139       if (align2 > j)
140         j = align2;
141       if (pos + j >= 512)
142         pos = 511 - j - (random () & 7);
143       len = random () & 511;
144       if (len + j >= 512)
145         len = 511 - j - (random () & 7);
146       j = len + align1 + 64;
147       if (j > 512) j = 512;
148       for (i = 0; i < j; ++i)
149         p1[i] = random () & 255;
150       for (i = 0; i < j; ++i)
151         p2[i] = random () & 255;
152
153       result = 0;
154       if (pos >= len)
155         memcpy (p2 + align2, p1 + align1, len);
156       else
157         {
158           memcpy (p2 + align2, p1 + align1, pos);
159           if (p2[align2 + pos] == p1[align1 + pos])
160             {
161               p2[align2 + pos] = random () & 255;
162               if (p2[align2 + pos] == p1[align1 + pos])
163                 p2[align2 + pos] = p1[align1 + pos] + 3 + (random () & 127);
164             }
165
166           if (p1[align1 + pos] < p2[align2 + pos])
167             result = -1;
168           else
169             result = 1;
170         }
171
172       FOR_EACH_IMPL (impl, 1)
173         {
174           r = CALL (impl, (char *) (p1 + align1), (char *) (p2 + align2), len);
175           /* Test whether on 64-bit architectures where ABI requires
176              callee to promote has the promotion been done.  */
177           asm ("" : "=g" (r) : "0" (r));
178           if ((r == 0 && result)
179               || (r < 0 && result >= 0)
180               || (r > 0 && result <= 0))
181             {
182               error (0, 0, "Iteration %zd - wrong result in function %s (%zd, %zd, %zd, %zd) %ld != %d, p1 %p p2 %p",
183                      n, impl->name, align1, align2, len, pos, r, result, p1, p2);
184               ret = 1;
185             }
186         }
187     }
188 }
189
190 static void
191 check1 (void)
192 {
193   char s1[116], s2[116];
194   int n, exp_result;
195
196   s1[0] = -108;
197   s2[0] = -108;
198   s1[1] = 99;
199   s2[1] = 99;
200   s1[2] = -113;
201   s2[2] = -113;
202   s1[3] = 1;
203   s2[3] = 1;
204   s1[4] = 116;
205   s2[4] = 116;
206   s1[5] = 99;
207   s2[5] = 99;
208   s1[6] = -113;
209   s2[6] = -113;
210   s1[7] = 1;
211   s2[7] = 1;
212   s1[8] = 84;
213   s2[8] = 84;
214   s1[9] = 99;
215   s2[9] = 99;
216   s1[10] = -113;
217   s2[10] = -113;
218   s1[11] = 1;
219   s2[11] = 1;
220   s1[12] = 52;
221   s2[12] = 52;
222   s1[13] = 99;
223   s2[13] = 99;
224   s1[14] = -113;
225   s2[14] = -113;
226   s1[15] = 1;
227   s2[15] = 1;
228   s1[16] = -76;
229   s2[16] = -76;
230   s1[17] = -14;
231   s2[17] = -14;
232   s1[18] = -109;
233   s2[18] = -109;
234   s1[19] = 1;
235   s2[19] = 1;
236   s1[20] = -108;
237   s2[20] = -108;
238   s1[21] = -14;
239   s2[21] = -14;
240   s1[22] = -109;
241   s2[22] = -109;
242   s1[23] = 1;
243   s2[23] = 1;
244   s1[24] = 84;
245   s2[24] = 84;
246   s1[25] = -15;
247   s2[25] = -15;
248   s1[26] = -109;
249   s2[26] = -109;
250   s1[27] = 1;
251   s2[27] = 1;
252   s1[28] = 52;
253   s2[28] = 52;
254   s1[29] = -15;
255   s2[29] = -15;
256   s1[30] = -109;
257   s2[30] = -109;
258   s1[31] = 1;
259   s2[31] = 1;
260   s1[32] = 20;
261   s2[32] = 20;
262   s1[33] = -15;
263   s2[33] = -15;
264   s1[34] = -109;
265   s2[34] = -109;
266   s1[35] = 1;
267   s2[35] = 1;
268   s1[36] = 20;
269   s2[36] = 20;
270   s1[37] = -14;
271   s2[37] = -14;
272   s1[38] = -109;
273   s2[38] = -109;
274   s1[39] = 1;
275   s2[39] = 1;
276   s1[40] = 52;
277   s2[40] = 52;
278   s1[41] = -14;
279   s2[41] = -14;
280   s1[42] = -109;
281   s2[42] = -109;
282   s1[43] = 1;
283   s2[43] = 1;
284   s1[44] = 84;
285   s2[44] = 84;
286   s1[45] = -14;
287   s2[45] = -14;
288   s1[46] = -109;
289   s2[46] = -109;
290   s1[47] = 1;
291   s2[47] = 1;
292   s1[48] = 116;
293   s2[48] = 116;
294   s1[49] = -14;
295   s2[49] = -14;
296   s1[50] = -109;
297   s2[50] = -109;
298   s1[51] = 1;
299   s2[51] = 1;
300   s1[52] = 116;
301   s2[52] = 116;
302   s1[53] = -15;
303   s2[53] = -15;
304   s1[54] = -109;
305   s2[54] = -109;
306   s1[55] = 1;
307   s2[55] = 1;
308   s1[56] = -44;
309   s2[56] = -44;
310   s1[57] = -14;
311   s2[57] = -14;
312   s1[58] = -109;
313   s2[58] = -109;
314   s1[59] = 1;
315   s2[59] = 1;
316   s1[60] = -108;
317   s2[60] = -108;
318   s1[61] = -15;
319   s2[61] = -15;
320   s1[62] = -109;
321   s2[62] = -109;
322   s1[63] = 1;
323   s2[63] = 1;
324   s1[64] = -76;
325   s2[64] = -76;
326   s1[65] = -15;
327   s2[65] = -15;
328   s1[66] = -109;
329   s2[66] = -109;
330   s1[67] = 1;
331   s2[67] = 1;
332   s1[68] = -44;
333   s2[68] = -44;
334   s1[69] = -15;
335   s2[69] = -15;
336   s1[70] = -109;
337   s2[70] = -109;
338   s1[71] = 1;
339   s2[71] = 1;
340   s1[72] = -12;
341   s2[72] = -12;
342   s1[73] = -15;
343   s2[73] = -15;
344   s1[74] = -109;
345   s2[74] = -109;
346   s1[75] = 1;
347   s2[75] = 1;
348   s1[76] = -12;
349   s2[76] = -12;
350   s1[77] = -14;
351   s2[77] = -14;
352   s1[78] = -109;
353   s2[78] = -109;
354   s1[79] = 1;
355   s2[79] = 1;
356   s1[80] = 20;
357   s2[80] = -68;
358   s1[81] = -12;
359   s2[81] = 64;
360   s1[82] = -109;
361   s2[82] = -106;
362   s1[83] = 1;
363   s2[83] = 1;
364   s1[84] = -12;
365   s2[84] = -12;
366   s1[85] = -13;
367   s2[85] = -13;
368   s1[86] = -109;
369   s2[86] = -109;
370   s1[87] = 1;
371   s2[87] = 1;
372   s1[88] = -44;
373   s2[88] = -44;
374   s1[89] = -13;
375   s2[89] = -13;
376   s1[90] = -109;
377   s2[90] = -109;
378   s1[91] = 1;
379   s2[91] = 1;
380   s1[92] = -76;
381   s2[92] = -76;
382   s1[93] = -13;
383   s2[93] = -13;
384   s1[94] = -109;
385   s2[94] = -109;
386   s1[95] = 1;
387   s2[95] = 1;
388   s1[96] = -108;
389   s2[96] = -108;
390   s1[97] = -13;
391   s2[97] = -13;
392   s1[98] = -109;
393   s2[98] = -109;
394   s1[99] = 1;
395   s2[99] = 1;
396   s1[100] = 116;
397   s2[100] = 116;
398   s1[101] = -13;
399   s2[101] = -13;
400   s1[102] = -109;
401   s2[102] = -109;
402   s1[103] = 1;
403   s2[103] = 1;
404   s1[104] = 84;
405   s2[104] = 84;
406   s1[105] = -13;
407   s2[105] = -13;
408   s1[106] = -109;
409   s2[106] = -109;
410   s1[107] = 1;
411   s2[107] = 1;
412   s1[108] = 52;
413   s2[108] = 52;
414   s1[109] = -13;
415   s2[109] = -13;
416   s1[110] = -109;
417   s2[110] = -109;
418   s1[111] = 1;
419   s2[111] = 1;
420   s1[112] = 20;
421   s2[112] = 20;
422   s1[113] = -13;
423   s2[113] = -13;
424   s1[114] = -109;
425   s2[114] = -109;
426   s1[115] = 1;
427   s2[115] = 1;
428
429   n = 116;
430   exp_result = simple_memcmp (s1, s2, n);
431   FOR_EACH_IMPL (impl, 0)
432     check_result (impl, s1, s2, n, exp_result);
433 }
434
435 int
436 test_main (void)
437 {
438   size_t i;
439
440   test_init ();
441
442   check1 ();
443
444   printf ("%23s", "");
445   FOR_EACH_IMPL (impl, 0)
446     printf ("\t%s", impl->name);
447   putchar ('\n');
448
449   for (i = 1; i < 16; ++i)
450     {
451       do_test (i, i, i, 0);
452       do_test (i, i, i, 1);
453       do_test (i, i, i, -1);
454     }
455
456   for (i = 0; i < 16; ++i)
457     {
458       do_test (0, 0, i, 0);
459       do_test (0, 0, i, 1);
460       do_test (0, 0, i, -1);
461     }
462
463   for (i = 1; i < 10; ++i)
464     {
465       do_test (0, 0, 2 << i, 0);
466       do_test (0, 0, 2 << i, 1);
467       do_test (0, 0, 2 << i, -1);
468       do_test (0, 0, 16 << i, 0);
469       do_test (8 - i, 2 * i, 16 << i, 0);
470       do_test (0, 0, 16 << i, 1);
471       do_test (0, 0, 16 << i, -1);
472     }
473
474   for (i = 1; i < 8; ++i)
475     {
476       do_test (i, 2 * i, 8 << i, 0);
477       do_test (i, 2 * i, 8 << i, 1);
478       do_test (i, 2 * i, 8 << i, -1);
479     }
480
481   do_random_tests ();
482   return ret;
483 }
484
485 #include "../test-skeleton.c"