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