1 /* PR tree-optimization/91996 - fold strlen relational expressions
2
3 The optimization is only implemented for MEM_REF stores and other
4 targets than those below may not transform the memcpy call into
5 such a store.
6 { dg-do compile { target { { aarch64*-*-* i?86-*-* x86_64-*-* } || { { powerpc*-*-* } && lp64 } } } }
7
8 { dg-options "-O2 -Wall -fdump-tree-optimized" }
9 { dg-additional-options "-msse" { target i?86-*-* x86_64-*-* } } */
10
11 #define CHAR_BIT __CHAR_BIT__
12 #define SIZE_MAX __SIZE_MAX__
13 #define LEN_MAX (__PTRDIFF_MAX__ - 2)
14
15 typedef __PTRDIFF_TYPE__ ptrdiff_t;
16 typedef __SIZE_TYPE__ size_t;
17
18 extern void* memcpy (void*, const void*, size_t);
19 extern size_t strlen (const char*);
20
21 #define CONCAT(a, b) a ## b
22 #define CAT(a, b) CONCAT (a, b)
23
24 extern void sink (void*, ...);
25 extern void failure_on_line (int);
26
27 extern char src[];
28 extern char dst[];
29
30 /* Copy (1 << NCPYLOG) bytes from an unknown string SRC with strlen (SRC)
31 in the range [MINSRCLEN, MAXSRCLEN] into DST + DSTOFF and verify that
32 strlen (DST + DSTOFF) is in the range [MINDSTLEN, MAXDSTLEN]. */
33 #define MIN_MAX(dst, dstoff, src, \
34 minsrclen, maxsrclen, mindstlen, maxdstlen, ncpylog) \
35 void CAT (test_on_line_, __LINE__) (void) \
36 { \
37 size_t srclen = strlen (src); \
38 if ((minsrclen) <= srclen && srclen <= (maxsrclen)) { \
39 char *d = (dst) + (dstoff); \
40 memcpy (d, src, (size_t)1 << (ncpylog)); \
41 size_t dstlen = strlen (d); \
42 if (dstlen < (mindstlen) || (maxdstlen) < dstlen) \
43 { \
44 failure_on_line (__LINE__); \
45 } \
46 sink (dst, src); \
47 } \
48 } typedef void dummy_type
49
50 // Verify the lower bound of the resulting strlen range.
51 #define MIN(dst, dstoff, src, minsrclen, mindstlen, ncpylog) \
52 MIN_MAX (dst, dstoff, src, minsrclen, LEN_MAX, mindstlen, LEN_MAX, ncpylog)
53
54 MIN (dst, 0, src, 2, 1, 0);
55 MIN (dst, 0, src, 3, 1, 0);
56 MIN (dst, 0, src, 3, 2, 1);
57 MIN (dst, 0, src, 3, 2, 2);
58 MIN (dst, 0, src, 3, 2, 3);
59
60 MIN (dst, 1, src, 2, 1, 0);
61 MIN (dst, 1, src, 3, 1, 0);
62 MIN (dst, 1, src, 3, 2, 1);
63 MIN (dst, 1, src, 3, 2, 2);
64 MIN (dst, 1, src, 3, 2, 3);
65
66 MIN (dst, 2, src, 2, 1, 0);
67 MIN (dst, 3, src, 3, 1, 0);
68 MIN (dst, 4, src, 3, 2, 1);
69 MIN (dst, 5, src, 3, 2, 2);
70 MIN (dst, 6, src, 3, 2, 3);
71
72
73 MIN (dst, 0, src, 5, 1, 0);
74 MIN (dst, 0, src, 5, 2, 1);
75 MIN (dst, 0, src, 5, 4, 2);
76 MIN (dst, 0, src, 5, 5, 3);
77
78 #if __aarch64__ || __x86_64__
79 /* Of the targets above only aarch64 and x86_64 transform memcpy calls
80 of (2 << 4) bytes into MEM_REF. */
81 MIN (dst, 0, src, 5, 5, 4);
82 #endif
83
84 MIN (dst, 11, src, 5, 1, 0);
85 MIN (dst, 22, src, 5, 2, 1);
86 MIN (dst, 33, src, 5, 4, 2);
87 MIN (dst, 44, src, 5, 5, 3);
88
89 #if __aarch64__ || __x86_64__
90 MIN (dst, 55, src, 5, 5, 4);
91 #endif
92
93 MIN (dst, 11, src, LEN_MAX, 1, 0);
94 MIN (dst, 22, src, LEN_MAX, 2, 1);
95 MIN (dst, 33, src, LEN_MAX, 4, 2);
96 MIN (dst, 44, src, LEN_MAX, 5, 3);
97 MIN (dst, 55, src, LEN_MAX, 5, 4);
98 MIN (dst, 66, src, LEN_MAX, 9, 8);
99 MIN (dst, 66, src, LEN_MAX, LEN_MAX, sizeof (ptrdiff_t) * CHAR_BIT - 1);
100
101
102 MIN_MAX (dst, 0, src, 3, 5, 1, LEN_MAX, 0);
103 MIN_MAX (dst, 0, src, 3, 5, 2, LEN_MAX, 1);
104 MIN_MAX (dst, 0, src, 3, 5, 3, LEN_MAX, 2);
105
106 /* Upper bound not implemented yet.
107 MIN_MAX (dst, 0, src, 3, 5, 3, 5, 3); */
108
109 /* { dg-final { scan-tree-dump-times "failure_on_line \\(" 0 "optimized" } } */