1 /* Test to verify that --param ssa_name_def_chain_limit can be used to
2    limit the maximum number of SSA_NAME assignments the built-in code
3    follows to determine the variable value/string length.
4    { dg-do compile }
5    { dg-options "-O2 -Wall --param ssa-name-def-chain-limit=4 -fdump-tree-optimized" } */
6 
7 void abort (void);
8 int sprintf (char * restrict, const char *restrict, ...);
9 
10 void sink (const char*, ...);
11 
12 const char a0[] = "";
13 const char a1[] = "1";
14 const char a2[] = "12";
15 const char a3[] = "123";
16 const char a4[] = "1234";
17 const char a5[] = "12345";
18 const char a6[] = "123456";
19 const char a7[] = "1234567";
20 const char a8[] = "12345678";
21 const char a9[] = "123456789";
22 
23 int i0, i1, i2, i3, i4, i5, i6, i7, i8;
24 
g1(char * d)25 void g1 (char *d)
26 {
27   const char *p0 = i0 ? a0 : a1;
28   const char *p1 = i1 ? p0 : a2;
29 
30   sink (p0, p1);
31 
32   if (sprintf (d, "%s", p1) > 2)
33     abort ();
34 }
35 
g2(char * d)36 void g2 (char *d)
37 {
38   const char *p0 = i0 ? a0 : a1;
39   const char *p1 = i1 ? p0 : a2;
40   const char *p2 = i2 ? p1 : a3;
41 
42   sink (p0, p1, p2);
43 
44   if (sprintf (d, "%s", p2) > 3)
45     abort ();
46 }
47 
g3(char * d)48 void g3 (char *d)
49 {
50   const char *p0 = i0 ? a0 : a1;
51   const char *p1 = i1 ? p0 : a2;
52   const char *p2 = i2 ? p1 : a3;
53   const char *p3 = i3 ? p2 : a4;
54 
55   sink (p0, p1, p2, p3);
56 
57   if (sprintf (d, "%s", p3) > 4)
58     abort ();
59 }
60 
g4(char * d)61 void g4 (char *d)
62 {
63   const char *p0 = i0 ? a0 : a1;
64   const char *p1 = i1 ? p0 : a2;
65   const char *p2 = i2 ? p1 : a3;
66   const char *p3 = i3 ? p2 : a4;
67   const char *p4 = i4 ? p3 : a5;
68 
69   sink (p0, p1, p2, p3, p4);
70 
71   // p4 below is the result of the following five PHI assignments
72   // and with the limit set to 4 the sprintf call result is not
73   // determined:
74   //   iftmp.0_7 = PHI <&a0(2), &a1(3)>
75   //   iftmp.2_8 = PHI <iftmp.0_7(4), &a2(5)>
76   //   iftmp.4_9 = PHI <iftmp.2_8(6), &a3(7)>
77   //   iftmp.6_10 = PHI <iftmp.4_9(8), &a4(9)>
78   //   iftmp.8_17 = PHI <iftmp.6_10(10), &a5(11)>
79   //   p4 = iftmp.8_17
80   extern void keep_g4 (void);
81   if (sprintf (d, "%s", p4) > 5)
82     keep_g4 ();
83 }
84 
g5(char * d)85 void g5 (char *d)
86 {
87   const char *p0 = i0 ? a0 : a1;
88   const char *p1 = i1 ? p0 : a2;
89   const char *p2 = i2 ? p1 : a3;
90   const char *p3 = i3 ? p2 : a4;
91   const char *p4 = i4 ? p3 : a5;
92   const char *p5 = i5 ? p4 : a6;
93 
94   sink (p0, p1, p2, p3, p4, p5);
95 
96   extern void keep_g5 (void);
97   if (sprintf (d, "%s", p5) > 6)
98     keep_g5 ();
99 
100   /* { dg-final { scan-tree-dump-times "keep_g5" 1 "optimized" } } */
101 }
102 
g6(char * d)103 void g6 (char *d)
104 {
105   const char *p0 = i0 ? a0 : a1;
106   const char *p1 = i1 ? p0 : a2;
107   const char *p2 = i2 ? p1 : a3;
108   const char *p3 = i3 ? p2 : a4;
109   const char *p4 = i4 ? p3 : a5;
110   const char *p5 = i5 ? p4 : a6;
111   const char *p6 = i6 ? p5 : a7;
112 
113   sink (p0, p1, p2, p3, p4, p5, p6);
114 
115   extern void keep_g6 (void);
116   if (sprintf (d, "%s", p6) > 7)
117     keep_g6 ();
118 
119   /* { dg-final { scan-tree-dump-times "keep_g6" 1 "optimized" } } */
120 }
121 
g7(char * d)122 void g7 (char *d)
123 {
124   const char *p0 = i0 ? a0 : a1;
125   const char *p1 = i1 ? p0 : a2;
126   const char *p2 = i2 ? p1 : a3;
127   const char *p3 = i3 ? p2 : a4;
128   const char *p4 = i4 ? p3 : a5;
129   const char *p5 = i5 ? p4 : a6;
130   const char *p6 = i6 ? p5 : a7;
131   const char *p7 = i7 ? p6 : a8;
132 
133   sink (p0, p1, p2, p3, p4, p5, p6, p7);
134 
135   extern void keep_g7 (void);
136   if (sprintf (d, "%s", p7) > 8)
137     keep_g7 ();
138 
139   /* { dg-final { scan-tree-dump-times "keep_g7" 1 "optimized" } } */
140 }
141 
g8(char * d)142 void g8 (char *d)
143 {
144   const char *p0 = i0 ? a0 : a1;
145   const char *p1 = i1 ? p0 : a2;
146   const char *p2 = i2 ? p1 : a3;
147   const char *p3 = i3 ? p2 : a4;
148   const char *p4 = i4 ? p3 : a5;
149   const char *p5 = i5 ? p4 : a6;
150   const char *p6 = i6 ? p5 : a7;
151   const char *p7 = i7 ? p6 : a8;
152   const char *p8 = i8 ? p7 : a9;
153 
154   sink (p0, p1, p2, p3, p4, p5, p6, p7, p8);
155 
156   extern void keep_g8 (void);
157   if (sprintf (d, "%s", p8) > 9)
158     keep_g8 ();
159 
160   /* { dg-final { scan-tree-dump-times "keep_g8" 1 "optimized" } } */
161 }
162 
163 /* { dg-final { scan-tree-dump-not "abort" "optimized" } } */
164