int main() { int i; // load i=S; i=vS; i=*pS; i=*pvS; i=A[2]; i=vA[2]; i=F.x; i=vF.x; i=F2.x; i=vF2.x; i=vpF2->x; i=F3.x.y; i=vF3.x.y; i=BF.x; i=vBF.x; i=V[3]; i=vV[3]; i=VE.yx[1]; i=vVE.zy[1]; i = aggFct().x; i=vtS; // store S=i; vS=i; *pS=i; *pvS=i; A[2]=i; vA[2]=i; F.x=i; vF.x=i; F2.x=i; vF2.x=i; vpF2->x=i; vF3.x.y=i; BF.x=i; vBF.x=i; V[3]=i; vV[3]=i; vtS=i; // other ops: ++S; ++vS; i+=S; i+=vS; ++vtS; (void)vF2; vF2 = vF2; vF2 = vF2 = vF2; vF2 = (vF2, vF2); }
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) }