| // RUN: %clang_cc1 -triple=%itanium_abi_triple -emit-llvm < %s | FileCheck %s -check-prefix CHECK -check-prefix CHECK-IT | 
 | // RUN: %clang_cc1 -triple=%ms_abi_triple -emit-llvm < %s | FileCheck %s -check-prefix CHECK -check-prefix CHECK-MS | 
 |  | 
 | int S; | 
 | volatile int vS; | 
 |  | 
 | int* pS; | 
 | volatile int* pvS; | 
 |  | 
 | int A[10]; | 
 | volatile int vA[10]; | 
 |  | 
 | struct { int x; } F; | 
 | struct { volatile int x; } vF; | 
 |  | 
 | struct { int x; } F2; | 
 | volatile struct { int x; } vF2; | 
 | volatile struct { int x; } *vpF2; | 
 |  | 
 | struct { struct { int y; } x; } F3; | 
 | volatile struct { struct { int y; } x; } vF3; | 
 |  | 
 | struct { int x:3; } BF; | 
 | struct { volatile int x:3; } vBF; | 
 |  | 
 | typedef int v4si __attribute__ ((vector_size (16))); | 
 | v4si V; | 
 | volatile v4si vV; | 
 |  | 
 | typedef __attribute__(( ext_vector_type(4) )) int extv4; | 
 | extv4 VE; | 
 | volatile extv4 vVE; | 
 |  | 
 | volatile struct {int x;} aggFct(void); | 
 |  | 
 | typedef volatile int volatile_int; | 
 | volatile_int vtS; | 
 |  | 
 | int main() { | 
 |   int i; | 
 | // CHECK: [[I:%[a-zA-Z0-9_.]+]] = alloca i32 | 
 |   // load | 
 |   i=S; | 
 | // CHECK: load i32, i32* @S | 
 | // CHECK: store i32 {{.*}}, i32* [[I]] | 
 |   i=vS; | 
 | // CHECK: load volatile i32, i32* @vS | 
 | // CHECK: store i32 {{.*}}, i32* [[I]] | 
 |   i=*pS; | 
 | // CHECK: [[PS_VAL:%[a-zA-Z0-9_.]+]] = load i32*, i32** @pS | 
 | // CHECK: load i32, i32* [[PS_VAL]] | 
 | // CHECK: store i32 {{.*}}, i32* [[I]] | 
 |   i=*pvS; | 
 | // CHECK: [[PVS_VAL:%[a-zA-Z0-9_.]+]] = load i32*, i32** @pvS | 
 | // CHECK: load volatile i32, i32* [[PVS_VAL]] | 
 | // CHECK: store i32 {{.*}}, i32* [[I]] | 
 |   i=A[2]; | 
 | // CHECK: load i32, i32* getelementptr {{.*}} @A | 
 | // CHECK: store i32 {{.*}}, i32* [[I]] | 
 |   i=vA[2]; | 
 | // CHECK: load volatile i32, i32* getelementptr {{.*}} @vA | 
 | // CHECK: store i32 {{.*}}, i32* [[I]] | 
 |   i=F.x; | 
 | // CHECK: load i32, i32* getelementptr {{.*}} @F | 
 | // CHECK: store i32 {{.*}}, i32* [[I]] | 
 |   i=vF.x; | 
 | // CHECK: load volatile i32, i32* getelementptr {{.*}} @vF | 
 | // CHECK: store i32 {{.*}}, i32* [[I]] | 
 |   i=F2.x; | 
 | // CHECK: load i32, i32* getelementptr {{.*}} @F2 | 
 | // CHECK: store i32 {{.*}}, i32* [[I]] | 
 |   i=vF2.x; | 
 | // CHECK: load volatile i32, i32* getelementptr {{.*}} @vF2 | 
 | // CHECK: store i32 {{.*}}, i32* [[I]] | 
 |   i=vpF2->x; | 
 | // CHECK: [[VPF2_VAL:%[a-zA-Z0-9_.]+]] = load {{%[a-zA-Z0-9_.]+}}*, {{%[a-zA-Z0-9_.]+}}** @vpF2 | 
 | // CHECK: [[ELT:%[a-zA-Z0-9_.]+]] = getelementptr {{.*}} [[VPF2_VAL]] | 
 | // CHECK: load volatile i32, i32* [[ELT]] | 
 | // CHECK: store i32 {{.*}}, i32* [[I]] | 
 |   i=F3.x.y; | 
 | // CHECK: load i32, i32* getelementptr {{.*}} @F3 | 
 | // CHECK: store i32 {{.*}}, i32* [[I]] | 
 |   i=vF3.x.y; | 
 | // CHECK: load volatile i32, i32* getelementptr {{.*}} @vF3 | 
 | // CHECK: store i32 {{.*}}, i32* [[I]] | 
 |   i=BF.x; | 
 | // CHECK-IT: load i8, i8* getelementptr {{.*}} @BF | 
 | // CHECK-MS: load i32, i32* getelementptr {{.*}} @BF | 
 | // CHECK: store i32 {{.*}}, i32* [[I]] | 
 |   i=vBF.x; | 
 | // CHECK-IT: load volatile i8, i8* getelementptr {{.*}} @vBF | 
 | // CHECK-MS: load volatile i32, i32* getelementptr {{.*}} @vBF | 
 | // CHECK: store i32 {{.*}}, i32* [[I]] | 
 |   i=V[3]; | 
 | // CHECK: load <4 x i32>, <4 x i32>* @V | 
 | // CHECK: store i32 {{.*}}, i32* [[I]] | 
 |   i=vV[3]; | 
 | // CHECK: load volatile <4 x i32>, <4 x i32>* @vV | 
 | // CHECK: store i32 {{.*}}, i32* [[I]] | 
 |   i=VE.yx[1]; | 
 | // CHECK: load <4 x i32>, <4 x i32>* @VE | 
 | // CHECK: store i32 {{.*}}, i32* [[I]] | 
 |   i=vVE.zy[1]; | 
 | // CHECK: load volatile <4 x i32>, <4 x i32>* @vVE | 
 | // CHECK: store i32 {{.*}}, i32* [[I]] | 
 |   i = aggFct().x; // Note: not volatile | 
 |   // N.b. Aggregate return is extremely target specific, all we can | 
 |   // really say here is that there probably shouldn't be a volatile | 
 |   // load. | 
 | // CHECK-NOT: load volatile | 
 | // CHECK: store i32 {{.*}}, i32* [[I]] | 
 |   i=vtS; | 
 | // CHECK: load volatile i32, i32* @vtS | 
 | // CHECK: store i32 {{.*}}, i32* [[I]] | 
 |  | 
 |  | 
 |   // store | 
 |   S=i; | 
 | // CHECK: load i32, i32* [[I]] | 
 | // CHECK: store i32 {{.*}}, i32* @S | 
 |   vS=i; | 
 | // CHECK: load i32, i32* [[I]] | 
 | // CHECK: store volatile i32 {{.*}}, i32* @vS | 
 |   *pS=i; | 
 | // CHECK: load i32, i32* [[I]] | 
 | // CHECK: [[PS_VAL:%[a-zA-Z0-9_.]+]] = load i32*, i32** @pS | 
 | // CHECK: store i32 {{.*}}, i32* [[PS_VAL]] | 
 |   *pvS=i; | 
 | // CHECK: load i32, i32* [[I]] | 
 | // CHECK: [[PVS_VAL:%[a-zA-Z0-9_.]+]] = load i32*, i32** @pvS | 
 | // CHECK: store volatile i32 {{.*}}, i32* [[PVS_VAL]] | 
 |   A[2]=i; | 
 | // CHECK: load i32, i32* [[I]] | 
 | // CHECK: store i32 {{.*}}, i32* getelementptr {{.*}} @A | 
 |   vA[2]=i; | 
 | // CHECK: load i32, i32* [[I]] | 
 | // CHECK: store volatile i32 {{.*}}, i32* getelementptr {{.*}} @vA | 
 |   F.x=i; | 
 | // CHECK: load i32, i32* [[I]] | 
 | // CHECK: store i32 {{.*}}, i32* getelementptr {{.*}} @F | 
 |   vF.x=i; | 
 | // CHECK: load i32, i32* [[I]] | 
 | // CHECK: store volatile i32 {{.*}}, i32* getelementptr {{.*}} @vF | 
 |   F2.x=i; | 
 | // CHECK: load i32, i32* [[I]] | 
 | // CHECK: store i32 {{.*}}, i32* getelementptr {{.*}} @F2 | 
 |   vF2.x=i; | 
 | // CHECK: load i32, i32* [[I]] | 
 | // CHECK: store volatile i32 {{.*}}, i32* getelementptr {{.*}} @vF2 | 
 |   vpF2->x=i; | 
 | // CHECK: load i32, i32* [[I]] | 
 | // CHECK: [[VPF2_VAL:%[a-zA-Z0-9_.]+]] = load {{%[a-zA-Z0-9._]+}}*, {{%[a-zA-Z0-9._]+}}** @vpF2 | 
 | // CHECK: [[ELT:%[a-zA-Z0-9_.]+]] = getelementptr {{.*}} [[VPF2_VAL]] | 
 | // CHECK: store volatile i32 {{.*}}, i32* [[ELT]] | 
 |   vF3.x.y=i; | 
 | // CHECK: load i32, i32* [[I]] | 
 | // CHECK: store volatile i32 {{.*}}, i32* getelementptr {{.*}} @vF3 | 
 |   BF.x=i; | 
 | // CHECK: load i32, i32* [[I]] | 
 | // CHECK-IT: load i8, i8* getelementptr {{.*}} @BF | 
 | // CHECK-MS: load i32, i32* getelementptr {{.*}} @BF | 
 | // CHECK-IT: store i8 {{.*}}, i8* getelementptr {{.*}} @BF | 
 | // CHECK-MS: store i32 {{.*}}, i32* getelementptr {{.*}} @BF | 
 |   vBF.x=i; | 
 | // CHECK: load i32, i32* [[I]] | 
 | // CHECK-IT: load volatile i8, i8* getelementptr {{.*}} @vBF | 
 | // CHECK-MS: load volatile i32, i32* getelementptr {{.*}} @vBF | 
 | // CHECK-IT: store volatile i8 {{.*}}, i8* getelementptr {{.*}} @vBF | 
 | // CHECK-MS: store volatile i32 {{.*}}, i32* getelementptr {{.*}} @vBF | 
 |   V[3]=i; | 
 | // CHECK: load i32, i32* [[I]] | 
 | // CHECK: load <4 x i32>, <4 x i32>* @V | 
 | // CHECK: store <4 x i32> {{.*}}, <4 x i32>* @V | 
 |   vV[3]=i; | 
 | // CHECK: load i32, i32* [[I]] | 
 | // CHECK: load volatile <4 x i32>, <4 x i32>* @vV | 
 | // CHECK: store volatile <4 x i32> {{.*}}, <4 x i32>* @vV | 
 |   vtS=i; | 
 | // CHECK: load i32, i32* [[I]] | 
 | // CHECK: store volatile i32 {{.*}}, i32* @vtS | 
 |  | 
 |   // other ops: | 
 |   ++S; | 
 | // CHECK: load i32, i32* @S | 
 | // CHECK: store i32 {{.*}}, i32* @S | 
 |   ++vS; | 
 | // CHECK: load volatile i32, i32* @vS | 
 | // CHECK: store volatile i32 {{.*}}, i32* @vS | 
 |   i+=S; | 
 | // CHECK: load i32, i32* @S | 
 | // CHECK: load i32, i32* [[I]] | 
 | // CHECK: store i32 {{.*}}, i32* [[I]] | 
 |   i+=vS; | 
 | // CHECK: load volatile i32, i32* @vS | 
 | // CHECK: load i32, i32* [[I]] | 
 | // CHECK: store i32 {{.*}}, i32* [[I]] | 
 |   ++vtS; | 
 | // CHECK: load volatile i32, i32* @vtS | 
 | // CHECK: store volatile i32 {{.*}}, i32* @vtS | 
 |   (void)vF2; | 
 |   // From vF2 to a temporary | 
 | // CHECK: call void @llvm.memcpy.{{.*}}(i8* align {{[0-9]+}} %{{.*}}, i8* {{.*}} @vF2 {{.*}}, i1 true) | 
 |   vF2 = vF2; | 
 |   // vF2 to itself | 
 | // CHECK: call void @llvm.memcpy.{{.*}}(i8* {{.*@vF2.*}}, i8* {{.*@vF2.*}}, i1 true) | 
 |   vF2 = vF2 = vF2; | 
 |   // vF2 to itself twice | 
 | // CHECK: call void @llvm.memcpy.{{.*}}(i8* {{.*@vF2.*}}, i8* {{.*@vF2.*}}, i1 true) | 
 | // CHECK: call void @llvm.memcpy.{{.*}}(i8* {{.*@vF2.*}}, i8* {{.*@vF2.*}}, i1 true) | 
 |   vF2 = (vF2, vF2); | 
 |   // vF2 to a temporary, then vF2 to itself | 
 | // CHECK: call void @llvm.memcpy.{{.*}}(i8* align {{[0-9]+}} %{{.*}}, i8* {{.*@vF2.*}}, i1 true) | 
 | // CHECK: call void @llvm.memcpy.{{.*}}(i8* {{.*@vF2.*}}, i8* {{.*@vF2.*}}, i1 true) | 
 | } |