215 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			215 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			C
		
	
	
	
| // 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* %{{.*}}, 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* %{{.*}}, i8* {{.*@vF2.*}}, i1 true)
 | |
| // CHECK: call void @llvm.memcpy.{{.*}}(i8* {{.*@vF2.*}}, i8* {{.*@vF2.*}}, i1 true)
 | |
| }
 |