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 | |