Daniel Dunbar | f64e44c | 2009-11-30 18:17:34 +0000 | [diff] [blame] | 1 | // Output file should have no calls to error() with folding. |
Daniel Dunbar | a572887 | 2009-12-15 20:14:24 +0000 | [diff] [blame] | 2 | // RUN: %clang_cc1 -triple i386-unknown-unknown -O3 -emit-llvm -o %t %s |
Daniel Dunbar | f64e44c | 2009-11-30 18:17:34 +0000 | [diff] [blame] | 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 | |
Daniel Dunbar | 30e682e | 2009-11-30 20:00:35 +0000 | [diff] [blame] | 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 | |
Daniel Dunbar | f64e44c | 2009-11-30 18:17:34 +0000 | [diff] [blame] | 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 | |
Daniel Dunbar | 30e682e | 2009-11-30 20:00:35 +0000 | [diff] [blame] | 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 | |
Anders Carlsson | 08e9e45 | 2010-01-24 00:20:05 +0000 | [diff] [blame] | 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 | |
Daniel Dunbar | f64e44c | 2009-11-30 18:17:34 +0000 | [diff] [blame] | 151 | extern "C" void error(); |
| 152 | extern "C" void print(const char *Name, unsigned N); |
| 153 | |
Anders Carlsson | 08e9e45 | 2010-01-24 00:20:05 +0000 | [diff] [blame] | 154 | #define ORDER2(a, b) (pow(a, 1) * pow(b, 2)) |
| 155 | #define ORDER3(a, b, c) (ORDER2(a, b) * pow(c, 3)) |
Daniel Dunbar | f64e44c | 2009-11-30 18:17:34 +0000 | [diff] [blame] | 156 | #define ORDER4(a, b, c, d) (ORDER3(a, b, c) * pow(d, 4)) |
Daniel Dunbar | 30e682e | 2009-11-30 20:00:35 +0000 | [diff] [blame] | 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)) |
Daniel Dunbar | f64e44c | 2009-11-30 18:17:34 +0000 | [diff] [blame] | 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(); |
Daniel Dunbar | 30e682e | 2009-11-30 20:00:35 +0000 | [diff] [blame] | 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 | |
Daniel Dunbar | 9f16f13 | 2010-01-23 00:26:29 +0000 | [diff] [blame] | 190 | // CHECK: call void @print(i8* {{.*}}, i32 1251552576) |
Daniel Dunbar | 30e682e | 2009-11-30 20:00:35 +0000 | [diff] [blame] | 191 | print("f6", f6()); |
Daniel Dunbar | 9f16f13 | 2010-01-23 00:26:29 +0000 | [diff] [blame] | 192 | if (f6() != ORDER6(3, 7, 11, 5, 13, 2)) |
| 193 | error(); |
Anders Carlsson | 08e9e45 | 2010-01-24 00:20:05 +0000 | [diff] [blame] | 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(); |
Daniel Dunbar | f64e44c | 2009-11-30 18:17:34 +0000 | [diff] [blame] | 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 |