1 // RUN: %clang_cc1 -Wno-unused-value -triple %itanium_abi_triple -emit-llvm %s -std=c++98 -o - | FileCheck %s 2 // RUN: %clang_cc1 -Wno-unused-value -triple %itanium_abi_triple -emit-llvm %s -std=c++11 -o - | FileCheck -check-prefix=CHECK -check-prefix=CHECK11 %s 3 4 // CHECK: @i = {{(dso_local )?}}global [[INT:i[0-9]+]] 0 5 volatile int i, j, k; 6 volatile int ar[5]; 7 volatile char c; 8 // CHECK: @ci = {{(dso_local )?}}global [[CINT:.*]] zeroinitializer 9 volatile _Complex int ci; 10 volatile struct S { 11 #ifdef __cplusplus 12 void operator =(volatile struct S&o) volatile; 13 #endif 14 int i; 15 } a, b; 16 17 //void operator =(volatile struct S&o1, volatile struct S&o2) volatile; 18 int printf(const char *, ...); 19 20 21 // CHECK: define {{.*}}void @{{.*}}test 22 void test() { 23 24 asm("nop"); // CHECK: call void asm 25 26 // should not load in C++98 27 i; 28 // CHECK11-NEXT: load volatile [[INT]], ptr @i 29 30 (float)(ci); 31 // CHECK-NEXT: load volatile [[INT]], ptr @ci 32 // CHECK-NEXT: load volatile [[INT]], ptr getelementptr inbounds nuw ([[CINT]], ptr @ci, i32 0, i32 1) 33 // CHECK-NEXT: sitofp [[INT]] 34 35 // These are not uses in C++98: 36 // [expr.static.cast]p6: 37 // The lvalue-to-rvalue . . . conversions are not applied to the expression. 38 (void)ci; 39 // CHECK11-NEXT: load volatile [[INT]], ptr @ci 40 // CHECK11-NEXT: load volatile [[INT]], ptr getelementptr inbounds nuw ([[CINT]], ptr @ci, i32 0, i32 1) 41 42 (void)a; 43 44 (void)(ci=ci); 45 // CHECK-NEXT: [[R:%.*]] = load volatile [[INT]], ptr @ci 46 // CHECK-NEXT: [[I:%.*]] = load volatile [[INT]], ptr getelementptr inbounds nuw ([[CINT]], ptr @ci, i32 0, i32 1) 47 // CHECK-NEXT: store volatile [[INT]] [[R]], ptr @ci 48 // CHECK-NEXT: store volatile [[INT]] [[I]], ptr getelementptr inbounds nuw ([[CINT]], ptr @ci, i32 0, i32 1) 49 50 (void)(i=j); 51 // CHECK-NEXT: [[T:%.*]] = load volatile [[INT]], ptr @j 52 // CHECK-NEXT: store volatile [[INT]] [[T]], ptr @i 53 54 ci+=ci; 55 // CHECK-NEXT: [[R1:%.*]] = load volatile [[INT]], ptr @ci 56 // CHECK-NEXT: [[I1:%.*]] = load volatile [[INT]], ptr getelementptr inbounds nuw ([[CINT]], ptr @ci, i32 0, i32 1) 57 // CHECK-NEXT: [[R2:%.*]] = load volatile [[INT]], ptr @ci 58 // CHECK-NEXT: [[I2:%.*]] = load volatile [[INT]], ptr getelementptr inbounds nuw ([[CINT]], ptr @ci, i32 0, i32 1) 59 // Not sure why they're ordered this way. 60 // CHECK-NEXT: [[R:%.*]] = add [[INT]] [[R2]], [[R1]] 61 // CHECK-NEXT: [[I:%.*]] = add [[INT]] [[I2]], [[I1]] 62 // CHECK-NEXT: store volatile [[INT]] [[R]], ptr @ci 63 // CHECK-NEXT: store volatile [[INT]] [[I]], ptr getelementptr inbounds nuw ([[CINT]], ptr @ci, i32 0, i32 1) 64 65 // Note that C++ requires an extra load volatile over C from the LHS of the '+'. 66 (ci += ci) + ci; 67 // CHECK-NEXT: [[R1:%.*]] = load volatile [[INT]], ptr @ci 68 // CHECK-NEXT: [[I1:%.*]] = load volatile [[INT]], ptr getelementptr inbounds nuw ([[CINT]], ptr @ci, i32 0, i32 1) 69 // CHECK-NEXT: [[R2:%.*]] = load volatile [[INT]], ptr @ci 70 // CHECK-NEXT: [[I2:%.*]] = load volatile [[INT]], ptr getelementptr inbounds nuw ([[CINT]], ptr @ci, i32 0, i32 1) 71 // CHECK-NEXT: [[R:%.*]] = add [[INT]] [[R2]], [[R1]] 72 // CHECK-NEXT: [[I:%.*]] = add [[INT]] [[I2]], [[I1]] 73 // CHECK-NEXT: store volatile [[INT]] [[R]], ptr @ci 74 // CHECK-NEXT: store volatile [[INT]] [[I]], ptr getelementptr inbounds nuw ([[CINT]], ptr @ci, i32 0, i32 1) 75 // CHECK-NEXT: [[R1:%.*]] = load volatile [[INT]], ptr @ci 76 // CHECK-NEXT: [[I1:%.*]] = load volatile [[INT]], ptr getelementptr inbounds nuw ([[CINT]], ptr @ci, i32 0, i32 1) 77 // CHECK-NEXT: [[R2:%.*]] = load volatile [[INT]], ptr @ci 78 // CHECK-NEXT: [[I2:%.*]] = load volatile [[INT]], ptr getelementptr inbounds nuw ([[CINT]], ptr @ci, i32 0, i32 1) 79 // These additions can be elided. 80 // CHECK-NEXT: add [[INT]] [[R1]], [[R2]] 81 // CHECK-NEXT: add [[INT]] [[I1]], [[I2]] 82 83 asm("nop"); // CHECK-NEXT: call void asm 84 85 // Extra load volatile in C++. 86 (i += j) + k; 87 // CHECK-NEXT: load volatile 88 // CHECK-NEXT: load volatile 89 // CHECK-NEXT: add nsw [[INT]] 90 // CHECK-NEXT: store volatile 91 // CHECK-NEXT: load volatile 92 // CHECK-NEXT: load volatile 93 // CHECK-NEXT: add nsw [[INT]] 94 95 asm("nop"); // CHECK-NEXT: call void asm 96 97 // Extra load volatile in C++. 98 (i += j) + 1; 99 // CHECK-NEXT: load volatile 100 // CHECK-NEXT: load volatile 101 // CHECK-NEXT: add nsw [[INT]] 102 // CHECK-NEXT: store volatile 103 // CHECK-NEXT: load volatile 104 // CHECK-NEXT: add nsw [[INT]] 105 106 asm("nop"); // CHECK-NEXT: call void asm 107 108 ci+ci; 109 // CHECK-NEXT: load volatile 110 // CHECK-NEXT: load volatile 111 // CHECK-NEXT: load volatile 112 // CHECK-NEXT: load volatile 113 // CHECK-NEXT: add [[INT]] 114 // CHECK-NEXT: add [[INT]] 115 116 __real i; 117 118 +ci; 119 // CHECK-NEXT: load volatile 120 // CHECK-NEXT: load volatile 121 122 asm("nop"); // CHECK-NEXT: call void asm 123 124 (void)(i=i); 125 // CHECK-NEXT: load volatile 126 // CHECK-NEXT: store volatile 127 128 (float)(i=i); 129 // CHECK-NEXT: load volatile 130 // CHECK-NEXT: store volatile 131 // CHECK-NEXT: load volatile 132 // CHECK-NEXT: sitofp 133 134 (void)i; // This is now a load in C++11 135 // CHECK11-NEXT: load volatile 136 137 i=i; 138 // CHECK-NEXT: load volatile 139 // CHECK-NEXT: store volatile 140 141 // Extra load volatile in C++. 142 i=i=i; 143 // CHECK-NEXT: load volatile 144 // CHECK-NEXT: store volatile 145 // CHECK-NEXT: load volatile 146 // CHECK-NEXT: store volatile 147 148 (void)__builtin_choose_expr(0, i=i, j=j); 149 // CHECK-NEXT: load volatile 150 // CHECK-NEXT: store volatile 151 152 k ? (i=i) : (j=j); 153 // CHECK-NEXT: load volatile 154 // CHECK-NEXT: icmp 155 // CHECK-NEXT: br i1 156 // CHECK: load volatile 157 // CHECK-NEXT: store volatile 158 // CHECK-NEXT: br label 159 // CHECK: load volatile 160 // CHECK-NEXT: store volatile 161 // CHECK-NEXT: br label 162 // CHECK: phi 163 164 (void)(i,(i=i)); // first i is also a load in C++11 165 // CHECK11-NEXT: load volatile 166 // CHECK-NEXT: load volatile 167 // CHECK-NEXT: store volatile 168 169 i=i,k; // k is also a load in C++11 170 // CHECK-NEXT: load volatile [[INT]], ptr @i 171 // CHECK-NEXT: store volatile {{.*}}, ptr @i 172 // CHECK11-NEXT: load volatile [[INT]], ptr @k 173 174 (i=j,k=j); 175 // CHECK-NEXT: load volatile [[INT]], ptr @j 176 // CHECK-NEXT: store volatile {{.*}}, ptr @i 177 // CHECK-NEXT: load volatile [[INT]], ptr @j 178 // CHECK-NEXT: store volatile {{.*}}, ptr @k 179 180 (i=j,k); // k is also a load in C++11 181 // CHECK-NEXT: load volatile [[INT]], ptr @j 182 // CHECK-NEXT: store volatile {{.*}}, ptr @i 183 // CHECK11-NEXT: load volatile [[INT]], ptr @k 184 185 (i,j); // i and j both are loads in C++11 186 // CHECK11-NEXT: load volatile [[INT]], ptr @i 187 // CHECK11-NEXT: load volatile [[INT]], ptr @j 188 189 // Extra load in C++. 190 i=c=k; 191 // CHECK-NEXT: load volatile 192 // CHECK-NEXT: trunc 193 // CHECK-NEXT: store volatile 194 // CHECK-NEXT: load volatile 195 // CHECK-NEXT: sext 196 // CHECK-NEXT: store volatile 197 198 i+=k; 199 // CHECK-NEXT: load volatile 200 // CHECK-NEXT: load volatile 201 // CHECK-NEXT: add nsw [[INT]] 202 // CHECK-NEXT: store volatile 203 204 ci; // ci is a load in C++11 205 // CHECK11-NEXT: load volatile {{.*}} @ci 206 // CHECK11-NEXT: load volatile {{.*}} @ci, i32 0, i32 1 207 208 asm("nop"); // CHECK-NEXT: call void asm 209 210 (int)ci; 211 // CHECK-NEXT: load volatile {{.*}} @ci 212 // CHECK-NEXT: load volatile {{.*}} @ci, i32 0, i32 1 213 214 (bool)ci; 215 // CHECK-NEXT: load volatile {{.*}} @ci 216 // CHECK-NEXT: load volatile {{.*}} @ci, i32 0, i32 1 217 // CHECK-NEXT: icmp ne 218 // CHECK-NEXT: icmp ne 219 // CHECK-NEXT: or i1 220 221 ci=ci; 222 // CHECK-NEXT: load volatile 223 // CHECK-NEXT: load volatile 224 // CHECK-NEXT: store volatile 225 // CHECK-NEXT: store volatile 226 227 asm("nop"); // CHECK-NEXT: call void asm 228 229 // Extra load in C++. 230 ci=ci=ci; 231 // CHECK-NEXT: load volatile 232 // CHECK-NEXT: load volatile 233 // CHECK-NEXT: store volatile 234 // CHECK-NEXT: store volatile 235 // CHECK-NEXT: load volatile 236 // CHECK-NEXT: load volatile 237 // CHECK-NEXT: store volatile 238 // CHECK-NEXT: store volatile 239 240 __imag ci = __imag ci = __imag ci; 241 // CHECK-NEXT: [[T:%.*]] = load volatile [[INT]], ptr getelementptr inbounds nuw ([[CINT]], ptr @ci, i32 0, i32 1) 242 // CHECK-NEXT: store volatile [[INT]] [[T]], ptr getelementptr inbounds nuw ([[CINT]], ptr @ci, i32 0, i32 1) 243 // CHECK-NEXT: [[T:%.*]] = load volatile [[INT]], ptr getelementptr inbounds nuw ([[CINT]], ptr @ci, i32 0, i32 1) 244 // CHECK-NEXT: store volatile [[INT]] [[T]], ptr getelementptr inbounds nuw ([[CINT]], ptr @ci, i32 0, i32 1) 245 246 __real (i = j); 247 // CHECK-NEXT: load volatile 248 // CHECK-NEXT: store volatile 249 250 __imag i; 251 252 // ============================================================ 253 // FIXME: Test cases we get wrong. 254 255 // A use. We load all of a into a copy of a, then load i. gcc forgets to do 256 // the assignment. 257 // (a = a).i; 258 259 // ============================================================ 260 // Test cases where we intentionally differ from gcc, due to suspected bugs in 261 // gcc. 262 263 // Not a use. gcc forgets to do the assignment. 264 // CHECK-NEXT: call {{.*}}void 265 ((a=a),a); 266 267 // Not a use. gcc gets this wrong, it doesn't emit the copy! 268 // CHECK-NEXT: call {{.*}}void 269 (void)(a=a); 270 271 // Not a use. gcc got this wrong in 4.2 and omitted the side effects 272 // entirely, but it is fixed in 4.4.0. 273 __imag (i = j); 274 // CHECK-NEXT: load volatile 275 // CHECK-NEXT: store volatile 276 277 // C++ does an extra load here. Note that we have to do full loads. 278 (float)(ci=ci); 279 // CHECK-NEXT: load volatile 280 // CHECK-NEXT: load volatile 281 // CHECK-NEXT: store volatile 282 // CHECK-NEXT: store volatile 283 // CHECK-NEXT: load volatile 284 // CHECK-NEXT: load volatile 285 // CHECK-NEXT: sitofp 286 287 // Not a use, bug? gcc treats this as not a use, that's probably a 288 // bug due to tree folding ignoring volatile. 289 (int)(ci=ci); 290 // CHECK-NEXT: load volatile 291 // CHECK-NEXT: load volatile 292 // CHECK-NEXT: store volatile 293 // CHECK-NEXT: store volatile 294 // CHECK-NEXT: load volatile 295 // CHECK-NEXT: load volatile 296 297 // A use. 298 (float)(i=i); 299 // CHECK-NEXT: load volatile 300 // CHECK-NEXT: store volatile 301 // CHECK-NEXT: load volatile 302 // CHECK-NEXT: sitofp 303 304 // A use. gcc treats this as not a use, that's probably a bug due to tree 305 // folding ignoring volatile. 306 (int)(i=i); 307 // CHECK-NEXT: load volatile 308 // CHECK-NEXT: store volatile 309 // CHECK-NEXT: load volatile 310 311 // A use. 312 -(i=j); 313 // CHECK-NEXT: load volatile 314 // CHECK-NEXT: store volatile 315 // CHECK-NEXT: load volatile 316 // CHECK-NEXT: sub 317 318 // A use. gcc treats this a not a use, that's probably a bug due to tree 319 // folding ignoring volatile. 320 +(i=k); 321 // CHECK-NEXT: load volatile 322 // CHECK-NEXT: store volatile 323 // CHECK-NEXT: load volatile 324 325 // A use. gcc treats this a not a use, that's probably a bug due to tree 326 // folding ignoring volatile. 327 __real (ci=ci); 328 // CHECK-NEXT: load volatile 329 // CHECK-NEXT: load volatile 330 // CHECK-NEXT: store volatile 331 // CHECK-NEXT: store volatile 332 333 // A use. 334 i + 0; 335 // CHECK-NEXT: load volatile 336 // CHECK-NEXT: add 337 338 // A use. 339 (i=j) + i; 340 // CHECK-NEXT: load volatile 341 // CHECK-NEXT: store volatile 342 // CHECK-NEXT: load volatile 343 // CHECK-NEXT: load volatile 344 // CHECK-NEXT: add 345 346 // A use. gcc treats this as not a use, that's probably a bug due to tree 347 // folding ignoring volatile. 348 (i=j) + 0; 349 // CHECK-NEXT: load volatile 350 // CHECK-NEXT: store volatile 351 // CHECK-NEXT: load volatile 352 // CHECK-NEXT: add 353 354 (i,j)=k; // i is also a load in C++11 355 // CHECK-NEXT: load volatile [[INT]], ptr @k 356 // CHECK11-NEXT: load volatile [[INT]], ptr @i 357 // CHECK-NEXT: store volatile {{.*}}, ptr @j 358 359 (j=k,i)=i; 360 // CHECK-NEXT: load volatile [[INT]], ptr @i 361 // CHECK-NEXT: load volatile [[INT]], ptr @k 362 // CHECK-NEXT: store volatile {{.*}}, ptr @j 363 // CHECK-NEXT: store volatile {{.*}}, ptr @i 364 365 // CHECK-NEXT: ret void 366 } 367