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