1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes=asan -asan-instrumentation-with-call-threshold=0 -S | FileCheck %s
3 ; RUN: opt < %s -passes=asan -asan-instrumentation-with-call-threshold=0 -asan-instrument-reads=0 -asan-instrument-writes=0 -S | FileCheck %s -check-prefix=DISABLED
5 ; Support ASan instrumentation for constant-mask llvm.masked.{load,store}
7 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
10 declare void @llvm.masked.store.v4f32.p0(<4 x float>, ptr, i32, <4 x i1>) argmemonly nounwind
11 declare void @llvm.masked.store.v8i32.p0(<8 x i32>, ptr, i32, <8 x i1>) argmemonly nounwind
12 declare void @llvm.masked.store.v4p0.p0(<4 x ptr>, ptr, i32, <4 x i1>) argmemonly nounwind
14 define void @store.v4f32.1110(ptr %p, <4 x float> %arg) sanitize_address {
15 ; CHECK-LABEL: @store.v4f32.1110(
16 ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr <4 x float>, ptr [[P:%.*]], i64 0, i64 0
17 ; CHECK-NEXT: [[TMP2:%.*]] = ptrtoint ptr [[TMP1]] to i64
18 ; CHECK-NEXT: call void @__asan_store4(i64 [[TMP2]])
19 ; CHECK-NEXT: [[TMP3:%.*]] = getelementptr <4 x float>, ptr [[P]], i64 0, i64 1
20 ; CHECK-NEXT: [[TMP4:%.*]] = ptrtoint ptr [[TMP3]] to i64
21 ; CHECK-NEXT: call void @__asan_store4(i64 [[TMP4]])
22 ; CHECK-NEXT: [[TMP5:%.*]] = getelementptr <4 x float>, ptr [[P]], i64 0, i64 2
23 ; CHECK-NEXT: [[TMP6:%.*]] = ptrtoint ptr [[TMP5]] to i64
24 ; CHECK-NEXT: call void @__asan_store4(i64 [[TMP6]])
25 ; CHECK-NEXT: tail call void @llvm.masked.store.v4f32.p0(<4 x float> [[ARG:%.*]], ptr [[P]], i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 false>)
26 ; CHECK-NEXT: ret void
28 ; DISABLED-LABEL: @store.v4f32.1110(
29 ; DISABLED-NEXT: tail call void @llvm.masked.store.v4f32.p0(<4 x float> [[ARG:%.*]], ptr [[P:%.*]], i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 false>)
30 ; DISABLED-NEXT: ret void
32 tail call void @llvm.masked.store.v4f32.p0(<4 x float> %arg, ptr %p, i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 false>)
36 define void @store.v8i32.10010110(ptr %p, <8 x i32> %arg) sanitize_address {
37 ; CHECK-LABEL: @store.v8i32.10010110(
38 ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr <8 x i32>, ptr [[P:%.*]], i64 0, i64 0
39 ; CHECK-NEXT: [[TMP2:%.*]] = ptrtoint ptr [[TMP1]] to i64
40 ; CHECK-NEXT: call void @__asan_store4(i64 [[TMP2]])
41 ; CHECK-NEXT: [[TMP3:%.*]] = getelementptr <8 x i32>, ptr [[P]], i64 0, i64 3
42 ; CHECK-NEXT: [[TMP4:%.*]] = ptrtoint ptr [[TMP3]] to i64
43 ; CHECK-NEXT: call void @__asan_store4(i64 [[TMP4]])
44 ; CHECK-NEXT: [[TMP5:%.*]] = getelementptr <8 x i32>, ptr [[P]], i64 0, i64 5
45 ; CHECK-NEXT: [[TMP6:%.*]] = ptrtoint ptr [[TMP5]] to i64
46 ; CHECK-NEXT: call void @__asan_store4(i64 [[TMP6]])
47 ; CHECK-NEXT: [[TMP7:%.*]] = getelementptr <8 x i32>, ptr [[P]], i64 0, i64 6
48 ; CHECK-NEXT: [[TMP8:%.*]] = ptrtoint ptr [[TMP7]] to i64
49 ; CHECK-NEXT: call void @__asan_store4(i64 [[TMP8]])
50 ; CHECK-NEXT: tail call void @llvm.masked.store.v8i32.p0(<8 x i32> [[ARG:%.*]], ptr [[P]], i32 8, <8 x i1> <i1 true, i1 false, i1 false, i1 true, i1 false, i1 true, i1 true, i1 false>)
51 ; CHECK-NEXT: ret void
53 ; DISABLED-LABEL: @store.v8i32.10010110(
54 ; DISABLED-NEXT: tail call void @llvm.masked.store.v8i32.p0(<8 x i32> [[ARG:%.*]], ptr [[P:%.*]], i32 8, <8 x i1> <i1 true, i1 false, i1 false, i1 true, i1 false, i1 true, i1 true, i1 false>)
55 ; DISABLED-NEXT: ret void
57 tail call void @llvm.masked.store.v8i32.p0(<8 x i32> %arg, ptr %p, i32 8, <8 x i1> <i1 true, i1 false, i1 false, i1 true, i1 false, i1 true, i1 true, i1 false>)
61 define void @store.v4i64.0001(ptr %p, <4 x ptr> %arg) sanitize_address {
62 ; CHECK-LABEL: @store.v4i64.0001(
63 ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr <4 x ptr>, ptr [[P:%.*]], i64 0, i64 3
64 ; CHECK-NEXT: [[TMP2:%.*]] = ptrtoint ptr [[TMP1]] to i64
65 ; CHECK-NEXT: call void @__asan_store8(i64 [[TMP2]])
66 ; CHECK-NEXT: tail call void @llvm.masked.store.v4p0.p0(<4 x ptr> [[ARG:%.*]], ptr [[P]], i32 8, <4 x i1> <i1 false, i1 false, i1 false, i1 true>)
67 ; CHECK-NEXT: ret void
69 ; DISABLED-LABEL: @store.v4i64.0001(
70 ; DISABLED-NEXT: tail call void @llvm.masked.store.v4p0.p0(<4 x ptr> [[ARG:%.*]], ptr [[P:%.*]], i32 8, <4 x i1> <i1 false, i1 false, i1 false, i1 true>)
71 ; DISABLED-NEXT: ret void
73 tail call void @llvm.masked.store.v4p0.p0(<4 x ptr> %arg, ptr %p, i32 8, <4 x i1> <i1 false, i1 false, i1 false, i1 true>)
77 define void @store.v4f32.variable(ptr %p, <4 x float> %arg, <4 x i1> %mask) sanitize_address {
78 ; CHECK-LABEL: @store.v4f32.variable(
79 ; CHECK-NEXT: [[TMP1:%.*]] = extractelement <4 x i1> [[MASK:%.*]], i64 0
80 ; CHECK-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP5:%.*]]
82 ; CHECK-NEXT: [[TMP3:%.*]] = getelementptr <4 x float>, ptr [[P:%.*]], i64 0, i64 0
83 ; CHECK-NEXT: [[TMP4:%.*]] = ptrtoint ptr [[TMP3]] to i64
84 ; CHECK-NEXT: call void @__asan_store4(i64 [[TMP4]])
85 ; CHECK-NEXT: br label [[TMP5]]
87 ; CHECK-NEXT: [[TMP6:%.*]] = extractelement <4 x i1> [[MASK]], i64 1
88 ; CHECK-NEXT: br i1 [[TMP6]], label [[TMP7:%.*]], label [[TMP10:%.*]]
90 ; CHECK-NEXT: [[TMP8:%.*]] = getelementptr <4 x float>, ptr [[P]], i64 0, i64 1
91 ; CHECK-NEXT: [[TMP9:%.*]] = ptrtoint ptr [[TMP8]] to i64
92 ; CHECK-NEXT: call void @__asan_store4(i64 [[TMP9]])
93 ; CHECK-NEXT: br label [[TMP10]]
95 ; CHECK-NEXT: [[TMP11:%.*]] = extractelement <4 x i1> [[MASK]], i64 2
96 ; CHECK-NEXT: br i1 [[TMP11]], label [[TMP12:%.*]], label [[TMP15:%.*]]
98 ; CHECK-NEXT: [[TMP13:%.*]] = getelementptr <4 x float>, ptr [[P]], i64 0, i64 2
99 ; CHECK-NEXT: [[TMP14:%.*]] = ptrtoint ptr [[TMP13]] to i64
100 ; CHECK-NEXT: call void @__asan_store4(i64 [[TMP14]])
101 ; CHECK-NEXT: br label [[TMP15]]
103 ; CHECK-NEXT: [[TMP16:%.*]] = extractelement <4 x i1> [[MASK]], i64 3
104 ; CHECK-NEXT: br i1 [[TMP16]], label [[TMP17:%.*]], label [[TMP20:%.*]]
106 ; CHECK-NEXT: [[TMP18:%.*]] = getelementptr <4 x float>, ptr [[P]], i64 0, i64 3
107 ; CHECK-NEXT: [[TMP19:%.*]] = ptrtoint ptr [[TMP18]] to i64
108 ; CHECK-NEXT: call void @__asan_store4(i64 [[TMP19]])
109 ; CHECK-NEXT: br label [[TMP20]]
111 ; CHECK-NEXT: tail call void @llvm.masked.store.v4f32.p0(<4 x float> [[ARG:%.*]], ptr [[P]], i32 4, <4 x i1> [[MASK]])
112 ; CHECK-NEXT: ret void
114 ; DISABLED-LABEL: @store.v4f32.variable(
115 ; DISABLED-NEXT: tail call void @llvm.masked.store.v4f32.p0(<4 x float> [[ARG:%.*]], ptr [[P:%.*]], i32 4, <4 x i1> [[MASK:%.*]])
116 ; DISABLED-NEXT: ret void
118 tail call void @llvm.masked.store.v4f32.p0(<4 x float> %arg, ptr %p, i32 4, <4 x i1> %mask)
122 ;; Store using two masked.stores, which should instrument them both.
123 define void @store.v4f32.1010.split(ptr %p, <4 x float> %arg) sanitize_address {
124 ; CHECK-LABEL: @store.v4f32.1010.split(
125 ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr <4 x float>, ptr [[P:%.*]], i64 0, i64 2
126 ; CHECK-NEXT: [[TMP2:%.*]] = ptrtoint ptr [[TMP1]] to i64
127 ; CHECK-NEXT: call void @__asan_store4(i64 [[TMP2]])
128 ; CHECK-NEXT: tail call void @llvm.masked.store.v4f32.p0(<4 x float> [[ARG:%.*]], ptr [[P]], i32 4, <4 x i1> <i1 false, i1 false, i1 true, i1 false>)
129 ; CHECK-NEXT: ret void
131 ; DISABLED-LABEL: @store.v4f32.1010.split(
132 ; DISABLED-NEXT: tail call void @llvm.masked.store.v4f32.p0(<4 x float> [[ARG:%.*]], ptr [[P:%.*]], i32 4, <4 x i1> <i1 false, i1 false, i1 true, i1 false>)
133 ; DISABLED-NEXT: ret void
135 tail call void @llvm.masked.store.v4f32.p0(<4 x float> %arg, ptr %p, i32 4, <4 x i1> <i1 false, i1 false, i1 true, i1 false>)
139 ;; Store using a masked.store after a full store. Shouldn't instrument the second one.
140 define void @store.v4f32.0010.after.full.store(ptr %p, <4 x float> %arg) sanitize_address {
141 ; CHECK-LABEL: @store.v4f32.0010.after.full.store(
142 ; CHECK-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[P:%.*]] to i64
143 ; CHECK-NEXT: call void @__asan_store16(i64 [[TMP1]])
144 ; CHECK-NEXT: store <4 x float> [[ARG:%.*]], ptr [[P]], align 16
145 ; CHECK-NEXT: tail call void @llvm.masked.store.v4f32.p0(<4 x float> [[ARG]], ptr [[P]], i32 4, <4 x i1> <i1 false, i1 false, i1 true, i1 false>)
146 ; CHECK-NEXT: ret void
148 ; DISABLED-LABEL: @store.v4f32.0010.after.full.store(
149 ; DISABLED-NEXT: store <4 x float> [[ARG:%.*]], ptr [[P:%.*]], align 16
150 ; DISABLED-NEXT: tail call void @llvm.masked.store.v4f32.p0(<4 x float> [[ARG]], ptr [[P]], i32 4, <4 x i1> <i1 false, i1 false, i1 true, i1 false>)
151 ; DISABLED-NEXT: ret void
153 store <4 x float> %arg, ptr %p
154 tail call void @llvm.masked.store.v4f32.p0(<4 x float> %arg, ptr %p, i32 4, <4 x i1> <i1 false, i1 false, i1 true, i1 false>)
158 ;;;;;;;;;;;;;;;; LOAD
159 declare <4 x float> @llvm.masked.load.v4f32.p0(ptr, i32, <4 x i1>, <4 x float>) argmemonly nounwind
160 declare <8 x i32> @llvm.masked.load.v8i32.p0(ptr, i32, <8 x i1>, <8 x i32>) argmemonly nounwind
161 declare <4 x ptr> @llvm.masked.load.v4p0.p0(ptr, i32, <4 x i1>, <4 x ptr>) argmemonly nounwind
163 define <8 x i32> @load.v8i32.11100001(ptr %p, <8 x i32> %arg) sanitize_address {
164 ; CHECK-LABEL: @load.v8i32.11100001(
165 ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr <8 x i32>, ptr [[P:%.*]], i64 0, i64 0
166 ; CHECK-NEXT: [[TMP2:%.*]] = ptrtoint ptr [[TMP1]] to i64
167 ; CHECK-NEXT: call void @__asan_load4(i64 [[TMP2]])
168 ; CHECK-NEXT: [[TMP3:%.*]] = getelementptr <8 x i32>, ptr [[P]], i64 0, i64 1
169 ; CHECK-NEXT: [[TMP4:%.*]] = ptrtoint ptr [[TMP3]] to i64
170 ; CHECK-NEXT: call void @__asan_load4(i64 [[TMP4]])
171 ; CHECK-NEXT: [[TMP5:%.*]] = getelementptr <8 x i32>, ptr [[P]], i64 0, i64 2
172 ; CHECK-NEXT: [[TMP6:%.*]] = ptrtoint ptr [[TMP5]] to i64
173 ; CHECK-NEXT: call void @__asan_load4(i64 [[TMP6]])
174 ; CHECK-NEXT: [[TMP7:%.*]] = getelementptr <8 x i32>, ptr [[P]], i64 0, i64 7
175 ; CHECK-NEXT: [[TMP8:%.*]] = ptrtoint ptr [[TMP7]] to i64
176 ; CHECK-NEXT: call void @__asan_load4(i64 [[TMP8]])
177 ; CHECK-NEXT: [[RES:%.*]] = tail call <8 x i32> @llvm.masked.load.v8i32.p0(ptr [[P]], i32 8, <8 x i1> <i1 true, i1 true, i1 true, i1 false, i1 false, i1 false, i1 false, i1 true>, <8 x i32> [[ARG:%.*]])
178 ; CHECK-NEXT: ret <8 x i32> [[RES]]
180 ; DISABLED-LABEL: @load.v8i32.11100001(
181 ; DISABLED-NEXT: [[RES:%.*]] = tail call <8 x i32> @llvm.masked.load.v8i32.p0(ptr [[P:%.*]], i32 8, <8 x i1> <i1 true, i1 true, i1 true, i1 false, i1 false, i1 false, i1 false, i1 true>, <8 x i32> [[ARG:%.*]])
182 ; DISABLED-NEXT: ret <8 x i32> [[RES]]
184 %res = tail call <8 x i32> @llvm.masked.load.v8i32.p0(ptr %p, i32 8, <8 x i1> <i1 true, i1 true, i1 true, i1 false, i1 false, i1 false, i1 false, i1 true>, <8 x i32> %arg)
188 define <4 x float> @load.v4f32.1001(ptr %p, <4 x float> %arg) sanitize_address {
189 ; CHECK-LABEL: @load.v4f32.1001(
190 ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr <4 x float>, ptr [[P:%.*]], i64 0, i64 0
191 ; CHECK-NEXT: [[TMP2:%.*]] = ptrtoint ptr [[TMP1]] to i64
192 ; CHECK-NEXT: call void @__asan_load4(i64 [[TMP2]])
193 ; CHECK-NEXT: [[TMP3:%.*]] = getelementptr <4 x float>, ptr [[P]], i64 0, i64 3
194 ; CHECK-NEXT: [[TMP4:%.*]] = ptrtoint ptr [[TMP3]] to i64
195 ; CHECK-NEXT: call void @__asan_load4(i64 [[TMP4]])
196 ; CHECK-NEXT: [[RES:%.*]] = tail call <4 x float> @llvm.masked.load.v4f32.p0(ptr [[P]], i32 4, <4 x i1> <i1 true, i1 false, i1 false, i1 true>, <4 x float> [[ARG:%.*]])
197 ; CHECK-NEXT: ret <4 x float> [[RES]]
199 ; DISABLED-LABEL: @load.v4f32.1001(
200 ; DISABLED-NEXT: [[RES:%.*]] = tail call <4 x float> @llvm.masked.load.v4f32.p0(ptr [[P:%.*]], i32 4, <4 x i1> <i1 true, i1 false, i1 false, i1 true>, <4 x float> [[ARG:%.*]])
201 ; DISABLED-NEXT: ret <4 x float> [[RES]]
203 %res = tail call <4 x float> @llvm.masked.load.v4f32.p0(ptr %p, i32 4, <4 x i1> <i1 true, i1 false, i1 false, i1 true>, <4 x float> %arg)
207 define <4 x ptr> @load.v4i64.0001(ptr %p, <4 x ptr> %arg) sanitize_address {
208 ; CHECK-LABEL: @load.v4i64.0001(
209 ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr <4 x ptr>, ptr [[P:%.*]], i64 0, i64 3
210 ; CHECK-NEXT: [[TMP2:%.*]] = ptrtoint ptr [[TMP1]] to i64
211 ; CHECK-NEXT: call void @__asan_load8(i64 [[TMP2]])
212 ; CHECK-NEXT: [[RES:%.*]] = tail call <4 x ptr> @llvm.masked.load.v4p0.p0(ptr [[P]], i32 8, <4 x i1> <i1 false, i1 false, i1 false, i1 true>, <4 x ptr> [[ARG:%.*]])
213 ; CHECK-NEXT: ret <4 x ptr> [[RES]]
215 ; DISABLED-LABEL: @load.v4i64.0001(
216 ; DISABLED-NEXT: [[RES:%.*]] = tail call <4 x ptr> @llvm.masked.load.v4p0.p0(ptr [[P:%.*]], i32 8, <4 x i1> <i1 false, i1 false, i1 false, i1 true>, <4 x ptr> [[ARG:%.*]])
217 ; DISABLED-NEXT: ret <4 x ptr> [[RES]]
219 %res = tail call <4 x ptr> @llvm.masked.load.v4p0.p0(ptr %p, i32 8, <4 x i1> <i1 false, i1 false, i1 false, i1 true>, <4 x ptr> %arg)
223 define <4 x float> @load.v4f32.variable(ptr %p, <4 x float> %arg, <4 x i1> %mask) sanitize_address {
224 ; CHECK-LABEL: @load.v4f32.variable(
225 ; CHECK-NEXT: [[TMP1:%.*]] = extractelement <4 x i1> [[MASK:%.*]], i64 0
226 ; CHECK-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP5:%.*]]
228 ; CHECK-NEXT: [[TMP3:%.*]] = getelementptr <4 x float>, ptr [[P:%.*]], i64 0, i64 0
229 ; CHECK-NEXT: [[TMP4:%.*]] = ptrtoint ptr [[TMP3]] to i64
230 ; CHECK-NEXT: call void @__asan_load4(i64 [[TMP4]])
231 ; CHECK-NEXT: br label [[TMP5]]
233 ; CHECK-NEXT: [[TMP6:%.*]] = extractelement <4 x i1> [[MASK]], i64 1
234 ; CHECK-NEXT: br i1 [[TMP6]], label [[TMP7:%.*]], label [[TMP10:%.*]]
236 ; CHECK-NEXT: [[TMP8:%.*]] = getelementptr <4 x float>, ptr [[P]], i64 0, i64 1
237 ; CHECK-NEXT: [[TMP9:%.*]] = ptrtoint ptr [[TMP8]] to i64
238 ; CHECK-NEXT: call void @__asan_load4(i64 [[TMP9]])
239 ; CHECK-NEXT: br label [[TMP10]]
241 ; CHECK-NEXT: [[TMP11:%.*]] = extractelement <4 x i1> [[MASK]], i64 2
242 ; CHECK-NEXT: br i1 [[TMP11]], label [[TMP12:%.*]], label [[TMP15:%.*]]
244 ; CHECK-NEXT: [[TMP13:%.*]] = getelementptr <4 x float>, ptr [[P]], i64 0, i64 2
245 ; CHECK-NEXT: [[TMP14:%.*]] = ptrtoint ptr [[TMP13]] to i64
246 ; CHECK-NEXT: call void @__asan_load4(i64 [[TMP14]])
247 ; CHECK-NEXT: br label [[TMP15]]
249 ; CHECK-NEXT: [[TMP16:%.*]] = extractelement <4 x i1> [[MASK]], i64 3
250 ; CHECK-NEXT: br i1 [[TMP16]], label [[TMP17:%.*]], label [[TMP20:%.*]]
252 ; CHECK-NEXT: [[TMP18:%.*]] = getelementptr <4 x float>, ptr [[P]], i64 0, i64 3
253 ; CHECK-NEXT: [[TMP19:%.*]] = ptrtoint ptr [[TMP18]] to i64
254 ; CHECK-NEXT: call void @__asan_load4(i64 [[TMP19]])
255 ; CHECK-NEXT: br label [[TMP20]]
257 ; CHECK-NEXT: [[RES:%.*]] = tail call <4 x float> @llvm.masked.load.v4f32.p0(ptr [[P]], i32 4, <4 x i1> [[MASK]], <4 x float> [[ARG:%.*]])
258 ; CHECK-NEXT: ret <4 x float> [[RES]]
260 ; DISABLED-LABEL: @load.v4f32.variable(
261 ; DISABLED-NEXT: [[RES:%.*]] = tail call <4 x float> @llvm.masked.load.v4f32.p0(ptr [[P:%.*]], i32 4, <4 x i1> [[MASK:%.*]], <4 x float> [[ARG:%.*]])
262 ; DISABLED-NEXT: ret <4 x float> [[RES]]
264 %res = tail call <4 x float> @llvm.masked.load.v4f32.p0(ptr %p, i32 4, <4 x i1> %mask, <4 x float> %arg)
268 ;; Load using two masked.loads, which should instrument them both.
269 define <4 x float> @load.v4f32.1001.split(ptr %p, <4 x float> %arg) sanitize_address {
270 ; CHECK-LABEL: @load.v4f32.1001.split(
271 ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr <4 x float>, ptr [[P:%.*]], i64 0, i64 0
272 ; CHECK-NEXT: [[TMP2:%.*]] = ptrtoint ptr [[TMP1]] to i64
273 ; CHECK-NEXT: call void @__asan_load4(i64 [[TMP2]])
274 ; CHECK-NEXT: [[RES:%.*]] = tail call <4 x float> @llvm.masked.load.v4f32.p0(ptr [[P]], i32 4, <4 x i1> <i1 true, i1 false, i1 false, i1 false>, <4 x float> [[ARG:%.*]])
275 ; CHECK-NEXT: [[TMP3:%.*]] = getelementptr <4 x float>, ptr [[P]], i64 0, i64 3
276 ; CHECK-NEXT: [[TMP4:%.*]] = ptrtoint ptr [[TMP3]] to i64
277 ; CHECK-NEXT: call void @__asan_load4(i64 [[TMP4]])
278 ; CHECK-NEXT: [[RES2:%.*]] = tail call <4 x float> @llvm.masked.load.v4f32.p0(ptr [[P]], i32 4, <4 x i1> <i1 false, i1 false, i1 false, i1 true>, <4 x float> [[RES]])
279 ; CHECK-NEXT: ret <4 x float> [[RES2]]
281 ; DISABLED-LABEL: @load.v4f32.1001.split(
282 ; DISABLED-NEXT: [[RES:%.*]] = tail call <4 x float> @llvm.masked.load.v4f32.p0(ptr [[P:%.*]], i32 4, <4 x i1> <i1 true, i1 false, i1 false, i1 false>, <4 x float> [[ARG:%.*]])
283 ; DISABLED-NEXT: [[RES2:%.*]] = tail call <4 x float> @llvm.masked.load.v4f32.p0(ptr [[P]], i32 4, <4 x i1> <i1 false, i1 false, i1 false, i1 true>, <4 x float> [[RES]])
284 ; DISABLED-NEXT: ret <4 x float> [[RES2]]
286 %res = tail call <4 x float> @llvm.masked.load.v4f32.p0(ptr %p, i32 4, <4 x i1> <i1 true, i1 false, i1 false, i1 false>, <4 x float> %arg)
287 %res2 = tail call <4 x float> @llvm.masked.load.v4f32.p0(ptr %p, i32 4, <4 x i1> <i1 false, i1 false, i1 false, i1 true>, <4 x float> %res)
288 ret <4 x float> %res2
291 ;; Load using a masked.load after a full load. Shouldn't instrument the second one.
292 define <4 x float> @load.v4f32.1001.after.full.load(ptr %p, <4 x float> %arg) sanitize_address {
293 ; CHECK-LABEL: @load.v4f32.1001.after.full.load(
294 ; CHECK-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[P:%.*]] to i64
295 ; CHECK-NEXT: call void @__asan_load16(i64 [[TMP1]])
296 ; CHECK-NEXT: [[RES:%.*]] = load <4 x float>, ptr [[P]], align 16
297 ; CHECK-NEXT: [[RES2:%.*]] = tail call <4 x float> @llvm.masked.load.v4f32.p0(ptr [[P]], i32 4, <4 x i1> <i1 false, i1 false, i1 false, i1 true>, <4 x float> [[ARG:%.*]])
298 ; CHECK-NEXT: ret <4 x float> [[RES2]]
300 ; DISABLED-LABEL: @load.v4f32.1001.after.full.load(
301 ; DISABLED-NEXT: [[RES:%.*]] = load <4 x float>, ptr [[P:%.*]], align 16
302 ; DISABLED-NEXT: [[RES2:%.*]] = tail call <4 x float> @llvm.masked.load.v4f32.p0(ptr [[P]], i32 4, <4 x i1> <i1 false, i1 false, i1 false, i1 true>, <4 x float> [[ARG:%.*]])
303 ; DISABLED-NEXT: ret <4 x float> [[RES2]]
305 %res = load <4 x float>, ptr %p
306 %res2 = tail call <4 x float> @llvm.masked.load.v4f32.p0(ptr %p, i32 4, <4 x i1> <i1 false, i1 false, i1 false, i1 true>, <4 x float> %arg)
307 ret <4 x float> %res2
310 ;; Scalable vector tests
311 ;; ---------------------------
312 declare <vscale x 4 x float> @llvm.masked.load.nxv4f32.p0(ptr, i32, <vscale x 4 x i1>, <vscale x 4 x float>)
313 declare void @llvm.masked.store.nxv4f32.p0(<vscale x 4 x float>, ptr, i32, <vscale x 4 x i1>)
315 define <vscale x 4 x float> @scalable.load.nxv4f32(ptr %p, <vscale x 4 x i1> %mask) sanitize_address {
316 ; CHECK-LABEL: @scalable.load.nxv4f32(
317 ; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.vscale.i64()
318 ; CHECK-NEXT: [[TMP2:%.*]] = mul i64 [[TMP1]], 4
319 ; CHECK-NEXT: br label [[DOTSPLIT:%.*]]
321 ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[TMP0:%.*]] ], [ [[IV_NEXT:%.*]], [[TMP7:%.*]] ]
322 ; CHECK-NEXT: [[TMP3:%.*]] = extractelement <vscale x 4 x i1> [[MASK:%.*]], i64 [[IV]]
323 ; CHECK-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP7]]
325 ; CHECK-NEXT: [[TMP5:%.*]] = getelementptr <vscale x 4 x float>, ptr [[P:%.*]], i64 0, i64 [[IV]]
326 ; CHECK-NEXT: [[TMP6:%.*]] = ptrtoint ptr [[TMP5]] to i64
327 ; CHECK-NEXT: call void @__asan_load4(i64 [[TMP6]])
328 ; CHECK-NEXT: br label [[TMP7]]
330 ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
331 ; CHECK-NEXT: [[IV_CHECK:%.*]] = icmp eq i64 [[IV_NEXT]], [[TMP2]]
332 ; CHECK-NEXT: br i1 [[IV_CHECK]], label [[DOTSPLIT_SPLIT:%.*]], label [[DOTSPLIT]]
333 ; CHECK: .split.split:
334 ; CHECK-NEXT: [[RES:%.*]] = tail call <vscale x 4 x float> @llvm.masked.load.nxv4f32.p0(ptr [[P]], i32 4, <vscale x 4 x i1> [[MASK]], <vscale x 4 x float> undef)
335 ; CHECK-NEXT: ret <vscale x 4 x float> [[RES]]
337 ; DISABLED-LABEL: @scalable.load.nxv4f32(
338 ; DISABLED-NEXT: [[RES:%.*]] = tail call <vscale x 4 x float> @llvm.masked.load.nxv4f32.p0(ptr [[P:%.*]], i32 4, <vscale x 4 x i1> [[MASK:%.*]], <vscale x 4 x float> undef)
339 ; DISABLED-NEXT: ret <vscale x 4 x float> [[RES]]
341 %res = tail call <vscale x 4 x float> @llvm.masked.load.nxv4f32.p0(ptr %p, i32 4, <vscale x 4 x i1> %mask, <vscale x 4 x float> undef)
342 ret <vscale x 4 x float> %res
345 define void @scalable.store.nxv4f32(ptr %p, <vscale x 4 x float> %arg, <vscale x 4 x i1> %mask) sanitize_address {
346 ; CHECK-LABEL: @scalable.store.nxv4f32(
347 ; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.vscale.i64()
348 ; CHECK-NEXT: [[TMP2:%.*]] = mul i64 [[TMP1]], 4
349 ; CHECK-NEXT: br label [[DOTSPLIT:%.*]]
351 ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[TMP0:%.*]] ], [ [[IV_NEXT:%.*]], [[TMP7:%.*]] ]
352 ; CHECK-NEXT: [[TMP3:%.*]] = extractelement <vscale x 4 x i1> [[MASK:%.*]], i64 [[IV]]
353 ; CHECK-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP7]]
355 ; CHECK-NEXT: [[TMP5:%.*]] = getelementptr <vscale x 4 x float>, ptr [[P:%.*]], i64 0, i64 [[IV]]
356 ; CHECK-NEXT: [[TMP6:%.*]] = ptrtoint ptr [[TMP5]] to i64
357 ; CHECK-NEXT: call void @__asan_store4(i64 [[TMP6]])
358 ; CHECK-NEXT: br label [[TMP7]]
360 ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
361 ; CHECK-NEXT: [[IV_CHECK:%.*]] = icmp eq i64 [[IV_NEXT]], [[TMP2]]
362 ; CHECK-NEXT: br i1 [[IV_CHECK]], label [[DOTSPLIT_SPLIT:%.*]], label [[DOTSPLIT]]
363 ; CHECK: .split.split:
364 ; CHECK-NEXT: tail call void @llvm.masked.store.nxv4f32.p0(<vscale x 4 x float> [[ARG:%.*]], ptr [[P]], i32 4, <vscale x 4 x i1> [[MASK]])
365 ; CHECK-NEXT: ret void
367 ; DISABLED-LABEL: @scalable.store.nxv4f32(
368 ; DISABLED-NEXT: tail call void @llvm.masked.store.nxv4f32.p0(<vscale x 4 x float> [[ARG:%.*]], ptr [[P:%.*]], i32 4, <vscale x 4 x i1> [[MASK:%.*]])
369 ; DISABLED-NEXT: ret void
371 tail call void @llvm.masked.store.nxv4f32.p0(<vscale x 4 x float> %arg, ptr %p, i32 4, <vscale x 4 x i1> %mask)
375 ; Test masked.gather/scatter.
376 declare <vscale x 4 x float> @llvm.masked.gather.nxv4f32.nxv4p0(<vscale x 4 x ptr>, i32, <vscale x 4 x i1>, <vscale x 4 x float>)
377 declare void @llvm.masked.scatter.nxv4f32.nxv4p0(<vscale x 4 x float>, <vscale x 4 x ptr>, i32, <vscale x 4 x i1>)
379 define <vscale x 4 x float> @scalable.gather.nxv4f32(<vscale x 4 x ptr> %vp, <vscale x 4 x i1> %mask, i32 %evl) sanitize_address {
380 ; CHECK-LABEL: @scalable.gather.nxv4f32(
381 ; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.vscale.i64()
382 ; CHECK-NEXT: [[TMP2:%.*]] = mul i64 [[TMP1]], 4
383 ; CHECK-NEXT: br label [[DOTSPLIT:%.*]]
385 ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[TMP0:%.*]] ], [ [[IV_NEXT:%.*]], [[TMP7:%.*]] ]
386 ; CHECK-NEXT: [[TMP3:%.*]] = extractelement <vscale x 4 x i1> [[MASK:%.*]], i64 [[IV]]
387 ; CHECK-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP7]]
389 ; CHECK-NEXT: [[TMP5:%.*]] = extractelement <vscale x 4 x ptr> [[VP:%.*]], i64 [[IV]]
390 ; CHECK-NEXT: [[TMP6:%.*]] = ptrtoint ptr [[TMP5]] to i64
391 ; CHECK-NEXT: call void @__asan_load4(i64 [[TMP6]])
392 ; CHECK-NEXT: br label [[TMP7]]
394 ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
395 ; CHECK-NEXT: [[IV_CHECK:%.*]] = icmp eq i64 [[IV_NEXT]], [[TMP2]]
396 ; CHECK-NEXT: br i1 [[IV_CHECK]], label [[DOTSPLIT_SPLIT:%.*]], label [[DOTSPLIT]]
397 ; CHECK: .split.split:
398 ; CHECK-NEXT: [[RES:%.*]] = tail call <vscale x 4 x float> @llvm.masked.gather.nxv4f32.nxv4p0(<vscale x 4 x ptr> [[VP]], i32 4, <vscale x 4 x i1> [[MASK]], <vscale x 4 x float> undef)
399 ; CHECK-NEXT: ret <vscale x 4 x float> [[RES]]
401 ; DISABLED-LABEL: @scalable.gather.nxv4f32(
402 ; DISABLED-NEXT: [[RES:%.*]] = tail call <vscale x 4 x float> @llvm.masked.gather.nxv4f32.nxv4p0(<vscale x 4 x ptr> [[VP:%.*]], i32 4, <vscale x 4 x i1> [[MASK:%.*]], <vscale x 4 x float> undef)
403 ; DISABLED-NEXT: ret <vscale x 4 x float> [[RES]]
405 %res = tail call <vscale x 4 x float> @llvm.masked.gather.nxv4f32.nxv4p0(<vscale x 4 x ptr> %vp, i32 4, <vscale x 4 x i1> %mask, <vscale x 4 x float> undef)
406 ret <vscale x 4 x float> %res
409 define void @scalable.scatter.nxv4f32(<vscale x 4 x float> %val, <vscale x 4 x ptr> %vp, <vscale x 4 x i1> %mask, i32 %evl) sanitize_address {
410 ; CHECK-LABEL: @scalable.scatter.nxv4f32(
411 ; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.vscale.i64()
412 ; CHECK-NEXT: [[TMP2:%.*]] = mul i64 [[TMP1]], 4
413 ; CHECK-NEXT: br label [[DOTSPLIT:%.*]]
415 ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[TMP0:%.*]] ], [ [[IV_NEXT:%.*]], [[TMP7:%.*]] ]
416 ; CHECK-NEXT: [[TMP3:%.*]] = extractelement <vscale x 4 x i1> [[MASK:%.*]], i64 [[IV]]
417 ; CHECK-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP7]]
419 ; CHECK-NEXT: [[TMP5:%.*]] = extractelement <vscale x 4 x ptr> [[VP:%.*]], i64 [[IV]]
420 ; CHECK-NEXT: [[TMP6:%.*]] = ptrtoint ptr [[TMP5]] to i64
421 ; CHECK-NEXT: call void @__asan_store4(i64 [[TMP6]])
422 ; CHECK-NEXT: br label [[TMP7]]
424 ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
425 ; CHECK-NEXT: [[IV_CHECK:%.*]] = icmp eq i64 [[IV_NEXT]], [[TMP2]]
426 ; CHECK-NEXT: br i1 [[IV_CHECK]], label [[DOTSPLIT_SPLIT:%.*]], label [[DOTSPLIT]]
427 ; CHECK: .split.split:
428 ; CHECK-NEXT: tail call void @llvm.masked.scatter.nxv4f32.nxv4p0(<vscale x 4 x float> [[VAL:%.*]], <vscale x 4 x ptr> [[VP]], i32 4, <vscale x 4 x i1> [[MASK]])
429 ; CHECK-NEXT: ret void
431 ; DISABLED-LABEL: @scalable.scatter.nxv4f32(
432 ; DISABLED-NEXT: tail call void @llvm.masked.scatter.nxv4f32.nxv4p0(<vscale x 4 x float> [[VAL:%.*]], <vscale x 4 x ptr> [[VP:%.*]], i32 4, <vscale x 4 x i1> [[MASK:%.*]])
433 ; DISABLED-NEXT: ret void
435 tail call void @llvm.masked.scatter.nxv4f32.nxv4p0(<vscale x 4 x float> %val, <vscale x 4 x ptr> %vp, i32 4, <vscale x 4 x i1> %mask)
439 declare <vscale x 4 x float> @llvm.masked.expandload.nxv4f32(ptr, <vscale x 4 x i1>, <vscale x 4 x float>)
440 declare void @llvm.masked.compressstore.nxv4f32(<vscale x 4 x float>, ptr, <vscale x 4 x i1>)
442 define <vscale x 4 x float> @scalable.expandload.nxv4f32(ptr align 4 %p, <vscale x 4 x i1> %mask) sanitize_address {
443 ; CHECK-LABEL: @scalable.expandload.nxv4f32(
444 ; CHECK-NEXT: [[TMP1:%.*]] = zext <vscale x 4 x i1> [[MASK:%.*]] to <vscale x 4 x i64>
445 ; CHECK-NEXT: [[TMP2:%.*]] = call i64 @llvm.vector.reduce.add.nxv4i64(<vscale x 4 x i64> [[TMP1]])
446 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i64 [[TMP2]], 0
447 ; CHECK-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP13:%.*]]
449 ; CHECK-NEXT: [[TMP5:%.*]] = call i64 @llvm.vscale.i64()
450 ; CHECK-NEXT: [[TMP6:%.*]] = mul i64 [[TMP5]], 4
451 ; CHECK-NEXT: [[TMP7:%.*]] = call i64 @llvm.umin.i64(i64 [[TMP2]], i64 [[TMP6]])
452 ; CHECK-NEXT: br label [[DOTSPLIT:%.*]]
454 ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[TMP4]] ], [ [[IV_NEXT:%.*]], [[TMP12:%.*]] ]
455 ; CHECK-NEXT: [[TMP8:%.*]] = extractelement <vscale x 4 x i1> shufflevector (<vscale x 4 x i1> insertelement (<vscale x 4 x i1> poison, i1 true, i64 0), <vscale x 4 x i1> poison, <vscale x 4 x i32> zeroinitializer), i64 [[IV]]
456 ; CHECK-NEXT: br i1 [[TMP8]], label [[TMP9:%.*]], label [[TMP12]]
458 ; CHECK-NEXT: [[TMP10:%.*]] = getelementptr <vscale x 4 x float>, ptr [[P:%.*]], i64 0, i64 [[IV]]
459 ; CHECK-NEXT: [[TMP11:%.*]] = ptrtoint ptr [[TMP10]] to i64
460 ; CHECK-NEXT: call void @__asan_load4(i64 [[TMP11]])
461 ; CHECK-NEXT: br label [[TMP12]]
463 ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
464 ; CHECK-NEXT: [[IV_CHECK:%.*]] = icmp eq i64 [[IV_NEXT]], [[TMP7]]
465 ; CHECK-NEXT: br i1 [[IV_CHECK]], label [[DOTSPLIT_SPLIT:%.*]], label [[DOTSPLIT]]
466 ; CHECK: .split.split:
467 ; CHECK-NEXT: br label [[TMP13]]
469 ; CHECK-NEXT: [[RES:%.*]] = tail call <vscale x 4 x float> @llvm.masked.expandload.nxv4f32(ptr [[P]], <vscale x 4 x i1> [[MASK]], <vscale x 4 x float> undef)
470 ; CHECK-NEXT: ret <vscale x 4 x float> [[RES]]
472 ; DISABLED-LABEL: @scalable.expandload.nxv4f32(
473 ; DISABLED-NEXT: [[RES:%.*]] = tail call <vscale x 4 x float> @llvm.masked.expandload.nxv4f32(ptr [[P:%.*]], <vscale x 4 x i1> [[MASK:%.*]], <vscale x 4 x float> undef)
474 ; DISABLED-NEXT: ret <vscale x 4 x float> [[RES]]
476 %res = tail call <vscale x 4 x float> @llvm.masked.expandload.nxv4f32(ptr %p, <vscale x 4 x i1> %mask, <vscale x 4 x float> undef)
477 ret <vscale x 4 x float> %res
480 define void @scalable.compressstore.nxv4f32(ptr align 4 %p, <vscale x 4 x float> %arg, <vscale x 4 x i1> %mask) sanitize_address {
481 ; CHECK-LABEL: @scalable.compressstore.nxv4f32(
482 ; CHECK-NEXT: [[TMP1:%.*]] = zext <vscale x 4 x i1> [[MASK:%.*]] to <vscale x 4 x i64>
483 ; CHECK-NEXT: [[TMP2:%.*]] = call i64 @llvm.vector.reduce.add.nxv4i64(<vscale x 4 x i64> [[TMP1]])
484 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i64 [[TMP2]], 0
485 ; CHECK-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP13:%.*]]
487 ; CHECK-NEXT: [[TMP5:%.*]] = call i64 @llvm.vscale.i64()
488 ; CHECK-NEXT: [[TMP6:%.*]] = mul i64 [[TMP5]], 4
489 ; CHECK-NEXT: [[TMP7:%.*]] = call i64 @llvm.umin.i64(i64 [[TMP2]], i64 [[TMP6]])
490 ; CHECK-NEXT: br label [[DOTSPLIT:%.*]]
492 ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[TMP4]] ], [ [[IV_NEXT:%.*]], [[TMP12:%.*]] ]
493 ; CHECK-NEXT: [[TMP8:%.*]] = extractelement <vscale x 4 x i1> shufflevector (<vscale x 4 x i1> insertelement (<vscale x 4 x i1> poison, i1 true, i64 0), <vscale x 4 x i1> poison, <vscale x 4 x i32> zeroinitializer), i64 [[IV]]
494 ; CHECK-NEXT: br i1 [[TMP8]], label [[TMP9:%.*]], label [[TMP12]]
496 ; CHECK-NEXT: [[TMP10:%.*]] = getelementptr <vscale x 4 x float>, ptr [[P:%.*]], i64 0, i64 [[IV]]
497 ; CHECK-NEXT: [[TMP11:%.*]] = ptrtoint ptr [[TMP10]] to i64
498 ; CHECK-NEXT: call void @__asan_store4(i64 [[TMP11]])
499 ; CHECK-NEXT: br label [[TMP12]]
501 ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
502 ; CHECK-NEXT: [[IV_CHECK:%.*]] = icmp eq i64 [[IV_NEXT]], [[TMP7]]
503 ; CHECK-NEXT: br i1 [[IV_CHECK]], label [[DOTSPLIT_SPLIT:%.*]], label [[DOTSPLIT]]
504 ; CHECK: .split.split:
505 ; CHECK-NEXT: br label [[TMP13]]
507 ; CHECK-NEXT: tail call void @llvm.masked.compressstore.nxv4f32(<vscale x 4 x float> [[ARG:%.*]], ptr [[P]], <vscale x 4 x i1> [[MASK]])
508 ; CHECK-NEXT: ret void
510 ; DISABLED-LABEL: @scalable.compressstore.nxv4f32(
511 ; DISABLED-NEXT: tail call void @llvm.masked.compressstore.nxv4f32(<vscale x 4 x float> [[ARG:%.*]], ptr [[P:%.*]], <vscale x 4 x i1> [[MASK:%.*]])
512 ; DISABLED-NEXT: ret void
514 tail call void @llvm.masked.compressstore.nxv4f32(<vscale x 4 x float> %arg, ptr %p, <vscale x 4 x i1> %mask)