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