| 1 | // RUN: %clang_cc1 -triple=%itanium_abi_triple -emit-llvm < %s | FileCheck %s -check-prefix CHECK -check-prefix CHECK-IT |
| 2 | // RUN: %clang_cc1 -triple=%ms_abi_triple -emit-llvm < %s | FileCheck %s -check-prefix CHECK -check-prefix CHECK-MS |
| 3 | |
| 4 | int S; |
| 5 | volatile int vS; |
| 6 | |
| 7 | int* pS; |
| 8 | volatile int* pvS; |
| 9 | |
| 10 | int A[10]; |
| 11 | volatile int vA[10]; |
| 12 | |
| 13 | struct { int x; } F; |
| 14 | struct { volatile int x; } vF; |
| 15 | |
| 16 | struct { int x; } F2; |
| 17 | volatile struct { int x; } vF2; |
| 18 | volatile struct { int x; } *vpF2; |
| 19 | |
| 20 | struct { struct { int y; } x; } F3; |
| 21 | volatile struct { struct { int y; } x; } vF3; |
| 22 | |
| 23 | struct { int x:3; } BF; |
| 24 | struct { volatile int x:3; } vBF; |
| 25 | |
| 26 | typedef int v4si __attribute__ ((vector_size (16))); |
| 27 | v4si V; |
| 28 | volatile v4si vV; |
| 29 | |
| 30 | typedef __attribute__(( ext_vector_type(4) )) int extv4; |
| 31 | extv4 VE; |
| 32 | volatile extv4 vVE; |
| 33 | |
| 34 | volatile struct {int x;} aggFct(void); |
| 35 | |
| 36 | typedef volatile int volatile_int; |
| 37 | volatile_int vtS; |
| 38 | |
| 39 | int main() { |
| 40 | int i; |
| 41 | // CHECK: [[I:%[a-zA-Z0-9_.]+]] = alloca i32 |
| 42 | // load |
| 43 | i=S; |
| 44 | // CHECK: load i32, i32* @S |
| 45 | // CHECK: store i32 {{.*}}, i32* [[I]] |
| 46 | i=vS; |
| 47 | // CHECK: load volatile i32, i32* @vS |
| 48 | // CHECK: store i32 {{.*}}, i32* [[I]] |
| 49 | i=*pS; |
| 50 | // CHECK: [[PS_VAL:%[a-zA-Z0-9_.]+]] = load i32*, i32** @pS |
| 51 | // CHECK: load i32, i32* [[PS_VAL]] |
| 52 | // CHECK: store i32 {{.*}}, i32* [[I]] |
| 53 | i=*pvS; |
| 54 | // CHECK: [[PVS_VAL:%[a-zA-Z0-9_.]+]] = load i32*, i32** @pvS |
| 55 | // CHECK: load volatile i32, i32* [[PVS_VAL]] |
| 56 | // CHECK: store i32 {{.*}}, i32* [[I]] |
| 57 | i=A[2]; |
| 58 | // CHECK: load i32, i32* getelementptr {{.*}} @A |
| 59 | // CHECK: store i32 {{.*}}, i32* [[I]] |
| 60 | i=vA[2]; |
| 61 | // CHECK: load volatile i32, i32* getelementptr {{.*}} @vA |
| 62 | // CHECK: store i32 {{.*}}, i32* [[I]] |
| 63 | i=F.x; |
| 64 | // CHECK: load i32, i32* getelementptr {{.*}} @F |
| 65 | // CHECK: store i32 {{.*}}, i32* [[I]] |
| 66 | i=vF.x; |
| 67 | // CHECK: load volatile i32, i32* getelementptr {{.*}} @vF |
| 68 | // CHECK: store i32 {{.*}}, i32* [[I]] |
| 69 | i=F2.x; |
| 70 | // CHECK: load i32, i32* getelementptr {{.*}} @F2 |
| 71 | // CHECK: store i32 {{.*}}, i32* [[I]] |
| 72 | i=vF2.x; |
| 73 | // CHECK: load volatile i32, i32* getelementptr {{.*}} @vF2 |
| 74 | // CHECK: store i32 {{.*}}, i32* [[I]] |
| 75 | i=vpF2->x; |
| 76 | // CHECK: [[VPF2_VAL:%[a-zA-Z0-9_.]+]] = load {{%[a-zA-Z0-9_.]+}}*, {{%[a-zA-Z0-9_.]+}}** @vpF2 |
| 77 | // CHECK: [[ELT:%[a-zA-Z0-9_.]+]] = getelementptr {{.*}} [[VPF2_VAL]] |
| 78 | // CHECK: load volatile i32, i32* [[ELT]] |
| 79 | // CHECK: store i32 {{.*}}, i32* [[I]] |
| 80 | i=F3.x.y; |
| 81 | // CHECK: load i32, i32* getelementptr {{.*}} @F3 |
| 82 | // CHECK: store i32 {{.*}}, i32* [[I]] |
| 83 | i=vF3.x.y; |
| 84 | // CHECK: load volatile i32, i32* getelementptr {{.*}} @vF3 |
| 85 | // CHECK: store i32 {{.*}}, i32* [[I]] |
| 86 | i=BF.x; |
| 87 | // CHECK-IT: load i8, i8* getelementptr {{.*}} @BF |
| 88 | // CHECK-MS: load i32, i32* getelementptr {{.*}} @BF |
| 89 | // CHECK: store i32 {{.*}}, i32* [[I]] |
| 90 | i=vBF.x; |
| 91 | // CHECK-IT: load volatile i8, i8* getelementptr {{.*}} @vBF |
| 92 | // CHECK-MS: load volatile i32, i32* getelementptr {{.*}} @vBF |
| 93 | // CHECK: store i32 {{.*}}, i32* [[I]] |
| 94 | i=V[3]; |
| 95 | // CHECK: load <4 x i32>, <4 x i32>* @V |
| 96 | // CHECK: store i32 {{.*}}, i32* [[I]] |
| 97 | i=vV[3]; |
| 98 | // CHECK: load volatile <4 x i32>, <4 x i32>* @vV |
| 99 | // CHECK: store i32 {{.*}}, i32* [[I]] |
| 100 | i=VE.yx[1]; |
| 101 | // CHECK: load <4 x i32>, <4 x i32>* @VE |
| 102 | // CHECK: store i32 {{.*}}, i32* [[I]] |
| 103 | i=vVE.zy[1]; |
| 104 | // CHECK: load volatile <4 x i32>, <4 x i32>* @vVE |
| 105 | // CHECK: store i32 {{.*}}, i32* [[I]] |
| 106 | i = aggFct().x; // Note: not volatile |
| 107 | // N.b. Aggregate return is extremely target specific, all we can |
| 108 | // really say here is that there probably shouldn't be a volatile |
| 109 | // load. |
| 110 | // CHECK-NOT: load volatile |
| 111 | // CHECK: store i32 {{.*}}, i32* [[I]] |
| 112 | i=vtS; |
| 113 | // CHECK: load volatile i32, i32* @vtS |
| 114 | // CHECK: store i32 {{.*}}, i32* [[I]] |
| 115 | |
| 116 | |
| 117 | // store |
| 118 | S=i; |
| 119 | // CHECK: load i32, i32* [[I]] |
| 120 | // CHECK: store i32 {{.*}}, i32* @S |
| 121 | vS=i; |
| 122 | // CHECK: load i32, i32* [[I]] |
| 123 | // CHECK: store volatile i32 {{.*}}, i32* @vS |
| 124 | *pS=i; |
| 125 | // CHECK: load i32, i32* [[I]] |
| 126 | // CHECK: [[PS_VAL:%[a-zA-Z0-9_.]+]] = load i32*, i32** @pS |
| 127 | // CHECK: store i32 {{.*}}, i32* [[PS_VAL]] |
| 128 | *pvS=i; |
| 129 | // CHECK: load i32, i32* [[I]] |
| 130 | // CHECK: [[PVS_VAL:%[a-zA-Z0-9_.]+]] = load i32*, i32** @pvS |
| 131 | // CHECK: store volatile i32 {{.*}}, i32* [[PVS_VAL]] |
| 132 | A[2]=i; |
| 133 | // CHECK: load i32, i32* [[I]] |
| 134 | // CHECK: store i32 {{.*}}, i32* getelementptr {{.*}} @A |
| 135 | vA[2]=i; |
| 136 | // CHECK: load i32, i32* [[I]] |
| 137 | // CHECK: store volatile i32 {{.*}}, i32* getelementptr {{.*}} @vA |
| 138 | F.x=i; |
| 139 | // CHECK: load i32, i32* [[I]] |
| 140 | // CHECK: store i32 {{.*}}, i32* getelementptr {{.*}} @F |
| 141 | vF.x=i; |
| 142 | // CHECK: load i32, i32* [[I]] |
| 143 | // CHECK: store volatile i32 {{.*}}, i32* getelementptr {{.*}} @vF |
| 144 | F2.x=i; |
| 145 | // CHECK: load i32, i32* [[I]] |
| 146 | // CHECK: store i32 {{.*}}, i32* getelementptr {{.*}} @F2 |
| 147 | vF2.x=i; |
| 148 | // CHECK: load i32, i32* [[I]] |
| 149 | // CHECK: store volatile i32 {{.*}}, i32* getelementptr {{.*}} @vF2 |
| 150 | vpF2->x=i; |
| 151 | // CHECK: load i32, i32* [[I]] |
| 152 | // CHECK: [[VPF2_VAL:%[a-zA-Z0-9_.]+]] = load {{%[a-zA-Z0-9._]+}}*, {{%[a-zA-Z0-9._]+}}** @vpF2 |
| 153 | // CHECK: [[ELT:%[a-zA-Z0-9_.]+]] = getelementptr {{.*}} [[VPF2_VAL]] |
| 154 | // CHECK: store volatile i32 {{.*}}, i32* [[ELT]] |
| 155 | vF3.x.y=i; |
| 156 | // CHECK: load i32, i32* [[I]] |
| 157 | // CHECK: store volatile i32 {{.*}}, i32* getelementptr {{.*}} @vF3 |
| 158 | BF.x=i; |
| 159 | // CHECK: load i32, i32* [[I]] |
| 160 | // CHECK-IT: load i8, i8* getelementptr {{.*}} @BF |
| 161 | // CHECK-MS: load i32, i32* getelementptr {{.*}} @BF |
| 162 | // CHECK-IT: store i8 {{.*}}, i8* getelementptr {{.*}} @BF |
| 163 | // CHECK-MS: store i32 {{.*}}, i32* getelementptr {{.*}} @BF |
| 164 | vBF.x=i; |
| 165 | // CHECK: load i32, i32* [[I]] |
| 166 | // CHECK-IT: load volatile i8, i8* getelementptr {{.*}} @vBF |
| 167 | // CHECK-MS: load volatile i32, i32* getelementptr {{.*}} @vBF |
| 168 | // CHECK-IT: store volatile i8 {{.*}}, i8* getelementptr {{.*}} @vBF |
| 169 | // CHECK-MS: store volatile i32 {{.*}}, i32* getelementptr {{.*}} @vBF |
| 170 | V[3]=i; |
| 171 | // CHECK: load i32, i32* [[I]] |
| 172 | // CHECK: load <4 x i32>, <4 x i32>* @V |
| 173 | // CHECK: store <4 x i32> {{.*}}, <4 x i32>* @V |
| 174 | vV[3]=i; |
| 175 | // CHECK: load i32, i32* [[I]] |
| 176 | // CHECK: load volatile <4 x i32>, <4 x i32>* @vV |
| 177 | // CHECK: store volatile <4 x i32> {{.*}}, <4 x i32>* @vV |
| 178 | vtS=i; |
| 179 | // CHECK: load i32, i32* [[I]] |
| 180 | // CHECK: store volatile i32 {{.*}}, i32* @vtS |
| 181 | |
| 182 | // other ops: |
| 183 | ++S; |
| 184 | // CHECK: load i32, i32* @S |
| 185 | // CHECK: store i32 {{.*}}, i32* @S |
| 186 | ++vS; |
| 187 | // CHECK: load volatile i32, i32* @vS |
| 188 | // CHECK: store volatile i32 {{.*}}, i32* @vS |
| 189 | i+=S; |
| 190 | // CHECK: load i32, i32* @S |
| 191 | // CHECK: load i32, i32* [[I]] |
| 192 | // CHECK: store i32 {{.*}}, i32* [[I]] |
| 193 | i+=vS; |
| 194 | // CHECK: load volatile i32, i32* @vS |
| 195 | // CHECK: load i32, i32* [[I]] |
| 196 | // CHECK: store i32 {{.*}}, i32* [[I]] |
| 197 | ++vtS; |
| 198 | // CHECK: load volatile i32, i32* @vtS |
| 199 | // CHECK: store volatile i32 {{.*}}, i32* @vtS |
| 200 | (void)vF2; |
| 201 | // From vF2 to a temporary |
| 202 | // CHECK: call void @llvm.memcpy.{{.*}}(i8* align {{[0-9]+}} %{{.*}}, i8* {{.*}} @vF2 {{.*}}, i1 true) |
| 203 | vF2 = vF2; |
| 204 | // vF2 to itself |
| 205 | // CHECK: call void @llvm.memcpy.{{.*}}(i8* {{.*@vF2.*}}, i8* {{.*@vF2.*}}, i1 true) |
| 206 | vF2 = vF2 = vF2; |
| 207 | // vF2 to itself twice |
| 208 | // CHECK: call void @llvm.memcpy.{{.*}}(i8* {{.*@vF2.*}}, i8* {{.*@vF2.*}}, i1 true) |
| 209 | // CHECK: call void @llvm.memcpy.{{.*}}(i8* {{.*@vF2.*}}, i8* {{.*@vF2.*}}, i1 true) |
| 210 | vF2 = (vF2, vF2); |
| 211 | // vF2 to a temporary, then vF2 to itself |
| 212 | // CHECK: call void @llvm.memcpy.{{.*}}(i8* align {{[0-9]+}} %{{.*}}, i8* {{.*@vF2.*}}, i1 true) |
| 213 | // CHECK: call void @llvm.memcpy.{{.*}}(i8* {{.*@vF2.*}}, i8* {{.*@vF2.*}}, i1 true) |
| 214 | } |
| 215 | |