1 | // Output file should have no calls to error() with folding. |
2 | // RUN: %clang_cc1 -triple i386-unknown-unknown -mllvm -inline-threshold=1024 -O3 -emit-llvm -o %t %s |
3 | // RUN: FileCheck %s < %t |
4 | |
5 | static unsigned pow(unsigned Base, unsigned Power) { |
6 | unsigned Val = 1; |
7 | while (Power--) |
8 | Val *= Base; |
9 | return Val; |
10 | } |
11 | |
12 | struct TempTracker { |
13 | unsigned Product, Index; |
14 | |
15 | TempTracker() : Product(1), Index(0) {} |
16 | |
17 | }; |
18 | |
19 | // FIXME: This can be used to check elision as well, if P = 0 hacks are removed. |
20 | struct A { |
21 | TempTracker &TT; |
22 | mutable unsigned P; |
23 | bool Truth; |
24 | |
25 | A(TempTracker &_TT, unsigned _P, bool _Truth = true) |
26 | : TT(_TT), P(_P), Truth(_Truth) {} |
27 | A(const A &RHS) : TT(RHS.TT), P(RHS.P), Truth(RHS.Truth) { RHS.P = 0; } |
28 | ~A() { |
29 | if (P) |
30 | TT.Product *= pow(P, ++TT.Index); |
31 | } |
32 | |
33 | A &operator=(const A &RHS) { |
34 | TT = RHS.TT; |
35 | P = RHS.P; |
36 | Truth = RHS.Truth; |
37 | RHS.P = 0; |
38 | return *this; |
39 | } |
40 | |
41 | operator bool () { return Truth; } |
42 | }; |
43 | |
44 | // 3, 7, 2 |
45 | static unsigned f0(bool val = false) { |
46 | TempTracker tt; |
47 | { |
48 | A a(tt, 2); |
49 | if ((A(tt, 3), val)) |
50 | A b(tt, 5); |
51 | A c(tt, 7); |
52 | } |
53 | return tt.Product; |
54 | } |
55 | |
56 | // 3, 5, 7, 2 |
57 | static unsigned f1(bool val = true) { |
58 | TempTracker tt; |
59 | { |
60 | A a(tt, 2); |
61 | if ((A(tt, 3), val)) |
62 | A b(tt, 5); |
63 | A c(tt, 7); |
64 | } |
65 | return tt.Product; |
66 | } |
67 | |
68 | // 5, 3, 7, 2 |
69 | static unsigned f2() { |
70 | TempTracker tt; |
71 | { |
72 | A a(tt, 2); |
73 | if (A b = A(tt, 3)) |
74 | A c(tt, 5); |
75 | A d(tt, 7); |
76 | } |
77 | return tt.Product; |
78 | } |
79 | |
80 | // 7, 3, 11, 2 |
81 | static unsigned f3() { |
82 | TempTracker tt; |
83 | { |
84 | A a(tt, 2); |
85 | if (A b = A(tt, 3, false)) |
86 | A c(tt, 5); |
87 | else |
88 | A c(tt, 7); |
89 | A d(tt, 11); |
90 | } |
91 | return tt.Product; |
92 | } |
93 | |
94 | // 3, 7, 2 |
95 | static unsigned f4() { |
96 | TempTracker tt; |
97 | { |
98 | A a(tt, 2); |
99 | while (A b = A(tt, 3, false)) |
100 | A c(tt, 5); |
101 | A c(tt, 7); |
102 | } |
103 | return tt.Product; |
104 | } |
105 | |
106 | // 5, 3, 7, 2 |
107 | static unsigned f5() { |
108 | TempTracker tt; |
109 | { |
110 | A a(tt, 2); |
111 | while (A b = A(tt, 3, true)) { |
112 | A c(tt, 5); |
113 | break; |
114 | } |
115 | A c(tt, 7); |
116 | } |
117 | return tt.Product; |
118 | } |
119 | |
120 | // 3, 7, 11, 5, 13, 2 |
121 | static unsigned f6() { |
122 | TempTracker tt; |
123 | { |
124 | A a(tt, 2); |
125 | for (A b = (A(tt, 3), A(tt, 5)), c = (A(tt, 7), A(tt, 11));;) |
126 | break; |
127 | A c(tt, 13); |
128 | } |
129 | return tt.Product; |
130 | } |
131 | |
132 | // 5, 2 |
133 | static unsigned f7() { |
134 | TempTracker tt; |
135 | { |
136 | (void)((A(tt, 2, false) && A(tt, 3, false)) || A(tt, 5, false)); |
137 | } |
138 | return tt.Product; |
139 | } |
140 | |
141 | // 5, 2 |
142 | static unsigned f8() { |
143 | TempTracker tt; |
144 | |
145 | { |
146 | (void)((A(tt, 2) || A(tt, 3)) && A(tt, 5)); |
147 | } |
148 | return tt.Product; |
149 | } |
150 | |
151 | extern "C" void error(); |
152 | extern "C" void print(const char *Name, unsigned N); |
153 | |
154 | #define ORDER2(a, b) (pow(a, 1) * pow(b, 2)) |
155 | #define ORDER3(a, b, c) (ORDER2(a, b) * pow(c, 3)) |
156 | #define ORDER4(a, b, c, d) (ORDER3(a, b, c) * pow(d, 4)) |
157 | #define ORDER5(a, b, c, d, e) (ORDER4(a, b, c, d) * pow(e, 5)) |
158 | #define ORDER6(a, b, c, d, e, f) (ORDER5(a, b, c, d, e) * pow(f, 6)) |
159 | void test() { |
160 | // CHECK: call void @print(i8* {{.*}}, i32 1176) |
161 | print("f0", f0()); |
162 | if (f0() != ORDER3(3, 7, 2)) |
163 | error(); |
164 | |
165 | // CHECK: call void @print(i8* {{.*}}, i32 411600) |
166 | print("f1", f1()); |
167 | if (f1() != ORDER4(3, 5, 7, 2)) |
168 | error(); |
169 | |
170 | // CHECK: call void @print(i8* {{.*}}, i32 246960) |
171 | print("f2", f2()); |
172 | if (f2() != ORDER4(5, 3, 7, 2)) |
173 | error(); |
174 | |
175 | // CHECK: call void @print(i8* {{.*}}, i32 1341648) |
176 | print("f3", f3()); |
177 | if (f3() != ORDER4(7, 3, 11, 2)) |
178 | error(); |
179 | |
180 | // CHECK: call void @print(i8* {{.*}}, i32 1176) |
181 | print("f4", f4()); |
182 | if (f4() != ORDER3(3, 7, 2)) |
183 | error(); |
184 | |
185 | // CHECK: call void @print(i8* {{.*}}, i32 246960) |
186 | print("f5", f5()); |
187 | if (f5() != ORDER4(5, 3, 7, 2)) |
188 | error(); |
189 | |
190 | // CHECK: call void @print(i8* {{.*}}, i32 1251552576) |
191 | print("f6", f6()); |
192 | if (f6() != ORDER6(3, 7, 11, 5, 13, 2)) |
193 | error(); |
194 | |
195 | // CHECK: call void @print(i8* {{.*}}, i32 20) |
196 | print("f7", f7()); |
197 | if (f7() != ORDER2(5, 2)) |
198 | error(); |
199 | |
200 | // CHECK: call void @print(i8* {{.*}}, i32 20) |
201 | print("f8", f8()); |
202 | if (f8() != ORDER2(5, 2)) |
203 | error(); |
204 | } |
205 | |
206 | |
207 | |
208 | #ifdef HARNESS |
209 | |
210 | #include <cstdlib> |
211 | #include <cstdio> |
212 | |
213 | extern "C" void error() { |
214 | abort(); |
215 | } |
216 | |
217 | extern "C" void print(const char *name, unsigned N) { |
218 | printf("%s: %d\n", name, N); |
219 | } |
220 | |
221 | int main() { |
222 | test(); |
223 | return 0; |
224 | } |
225 | |
226 | #endif |
227 | |