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