1 /* { dg-do run } */
2 /* { dg-options "-O2 -fdump-tree-strlen -fdump-tree-optimized" } */
3
4 #include "strlenopt.h"
5
6 __attribute__((noinline, noclone)) char *
fn1(int r)7 fn1 (int r)
8 {
9 char *p = r ? "a" : "bc";
10 /* String length for p varies, therefore strchr below isn't
11 optimized away. */
12 return strchr (p, '\0');
13 }
14
15 __attribute__((noinline, noclone)) size_t
fn2(int r)16 fn2 (int r)
17 {
18 char *p, q[10];
19 strcpy (q, "abc");
20 p = r ? "a" : q;
21 /* String length for p varies, therefore strlen below isn't
22 optimized away. */
23 return strlen (p);
24 }
25
26 __attribute__((noinline, noclone)) size_t
fn3(char * p,int n)27 fn3 (char *p, int n)
28 {
29 int i;
30 p = strchr (p, '\0');
31 /* strcat here can be optimized into memcpy. */
32 strcat (p, "abcd");
33 for (i = 0; i < n; i++)
34 if ((i % 123) == 53)
35 /* strcat here is optimized into strlen and memcpy. */
36 strcat (p, "efg");
37 /* The strlen here can't be optimized away, as in the loop string
38 length of p might change. */
39 return strlen (p);
40 }
41
42 char buf[64];
43
44 __attribute__((noinline, noclone)) size_t
fn4(char * x,int n)45 fn4 (char *x, int n)
46 {
47 int i;
48 size_t l;
49 char a[64];
50 char *p = strchr (x, '\0');
51 /* strcpy here is optimized into memcpy, length computed as p - x + 1. */
52 strcpy (a, x);
53 /* strcat here is optimized into memcpy. */
54 strcat (p, "abcd");
55 for (i = 0; i < n; i++)
56 if ((i % 123) == 53)
57 /* strcat here is optimized into strlen and memcpy. */
58 strcat (a, "efg");
59 /* The strlen should be optimized here into 4. */
60 l = strlen (p);
61 /* This stays strcpy. */
62 strcpy (buf, a);
63 return l;
64 }
65
66 int
main()67 main ()
68 {
69 volatile int l = 1;
70 char b[64];
71
72 if (memcmp (fn1 (l) - 1, "a", 2) != 0)
73 abort ();
74 if (memcmp (fn1 (!l) - 2, "bc", 3) != 0)
75 abort ();
76 if (fn2 (l) != 1 || fn2 (!l) != 3)
77 abort ();
78 memset (b, '\0', sizeof b);
79 memset (b, 'a', 3);
80 if (fn3 (b, 10) != 4 || memcmp (b, "aaaabcd", 8) != 0)
81 abort ();
82 if (fn3 (b, 128) != 7 || memcmp (b, "aaaabcdabcdefg", 15) != 0)
83 abort ();
84 if (fn3 (b, 256) != 10 || memcmp (b, "aaaabcdabcdefgabcdefgefg", 25) != 0)
85 abort ();
86 if (fn4 (b, 10) != 4
87 || memcmp (b, "aaaabcdabcdefgabcdefgefgabcd", 29) != 0
88 || memcmp (buf, "aaaabcdabcdefgabcdefgefg", 25) != 0)
89 abort ();
90 if (fn4 (b, 128) != 4
91 || memcmp (b, "aaaabcdabcdefgabcdefgefgabcdabcd", 33) != 0
92 || memcmp (buf, "aaaabcdabcdefgabcdefgefgabcdefg", 32) != 0)
93 abort ();
94 if (fn4 (b, 256) != 4
95 || memcmp (b, "aaaabcdabcdefgabcdefgefgabcdabcdabcd", 37) != 0
96 || memcmp (buf, "aaaabcdabcdefgabcdefgefgabcdabcdefgefg", 39) != 0)
97 abort ();
98 return 0;
99 }
100
101 /* { dg-final { scan-tree-dump-times "strlen \\(" 4 "strlen" } } */
102 /* { dg-final { scan-tree-dump-times "memcpy \\(" 6 "strlen" } } */
103 /* { dg-final { scan-tree-dump-times "strcpy \\(" 1 "strlen" } } */
104 /* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */
105 /* { dg-final { scan-tree-dump-times "strchr \\(" 3 "strlen" } } */
106 /* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen" } } */
107 /* { dg-final { cleanup-tree-dump "strlen" } } */
108 /* { dg-final { scan-tree-dump-times "return 4;" 1 "optimized" } } */
109 /* { dg-final { cleanup-tree-dump "optimized" } } */
110