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 \
4 ; RUN: opt < %s -passes=asan -asan-instrumentation-with-call-threshold=0 -asan-instrument-reads=0 -asan-instrument-writes=0 -S \
5 ; RUN: | FileCheck %s -check-prefix=DISABLED
7 ; Support ASan instrumentation for constant-mask llvm.masked.{load,store}
9 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
11 ;;;;;;;;;;;;;;;; STORE
12 declare void @llvm.masked.store.v4f32.p0(<4 x float>, ptr, i32, <4 x i1>) argmemonly nounwind
13 declare void @llvm.masked.store.v8i32.p0(<8 x i32>, ptr, i32, <8 x i1>) argmemonly nounwind
14 declare void @llvm.masked.store.v4p0.p0(<4 x ptr>, ptr, i32, <4 x i1>) argmemonly nounwind
16 define void @store.v4f32.1110(ptr %p, <4 x float> %arg) sanitize_address {
17 ; CHECK-LABEL: @store.v4f32.1110(
18 ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr <4 x float>, ptr [[P:%.*]], i64 0, i64 0
19 ; CHECK-NEXT: [[TMP2:%.*]] = ptrtoint ptr [[TMP1]] to i64
20 ; CHECK-NEXT: call void @__asan_store4(i64 [[TMP2]])
21 ; CHECK-NEXT: [[TMP3:%.*]] = getelementptr <4 x float>, ptr [[P]], i64 0, i64 1
22 ; CHECK-NEXT: [[TMP4:%.*]] = ptrtoint ptr [[TMP3]] to i64
23 ; CHECK-NEXT: call void @__asan_store4(i64 [[TMP4]])
24 ; CHECK-NEXT: [[TMP5:%.*]] = getelementptr <4 x float>, ptr [[P]], i64 0, i64 2
25 ; CHECK-NEXT: [[TMP6:%.*]] = ptrtoint ptr [[TMP5]] to i64
26 ; CHECK-NEXT: call void @__asan_store4(i64 [[TMP6]])
27 ; 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>)
28 ; CHECK-NEXT: ret void
30 ; DISABLED-LABEL: @store.v4f32.1110(
31 ; 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>)
32 ; DISABLED-NEXT: ret void
34 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>)
38 define void @store.v8i32.10010110(ptr %p, <8 x i32> %arg) sanitize_address {
39 ; CHECK-LABEL: @store.v8i32.10010110(
40 ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr <8 x i32>, ptr [[P:%.*]], i64 0, i64 0
41 ; CHECK-NEXT: [[TMP2:%.*]] = ptrtoint ptr [[TMP1]] to i64
42 ; CHECK-NEXT: call void @__asan_store4(i64 [[TMP2]])
43 ; CHECK-NEXT: [[TMP3:%.*]] = getelementptr <8 x i32>, ptr [[P]], i64 0, i64 3
44 ; CHECK-NEXT: [[TMP4:%.*]] = ptrtoint ptr [[TMP3]] to i64
45 ; CHECK-NEXT: call void @__asan_store4(i64 [[TMP4]])
46 ; CHECK-NEXT: [[TMP5:%.*]] = getelementptr <8 x i32>, ptr [[P]], i64 0, i64 5
47 ; CHECK-NEXT: [[TMP6:%.*]] = ptrtoint ptr [[TMP5]] to i64
48 ; CHECK-NEXT: call void @__asan_store4(i64 [[TMP6]])
49 ; CHECK-NEXT: [[TMP7:%.*]] = getelementptr <8 x i32>, ptr [[P]], i64 0, i64 6
50 ; CHECK-NEXT: [[TMP8:%.*]] = ptrtoint ptr [[TMP7]] to i64
51 ; CHECK-NEXT: call void @__asan_store4(i64 [[TMP8]])
52 ; 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>)
53 ; CHECK-NEXT: ret void
55 ; DISABLED-LABEL: @store.v8i32.10010110(
56 ; 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>)
57 ; DISABLED-NEXT: ret void
59 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>)
63 define void @store.v4i64.0001(ptr %p, <4 x ptr> %arg) sanitize_address {
64 ; CHECK-LABEL: @store.v4i64.0001(
65 ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr <4 x ptr>, ptr [[P:%.*]], i64 0, i64 3
66 ; CHECK-NEXT: [[TMP2:%.*]] = ptrtoint ptr [[TMP1]] to i64
67 ; CHECK-NEXT: call void @__asan_store8(i64 [[TMP2]])
68 ; 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>)
69 ; CHECK-NEXT: ret void
71 ; DISABLED-LABEL: @store.v4i64.0001(
72 ; 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>)
73 ; DISABLED-NEXT: ret void
75 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>)
79 define void @store.v4f32.variable(ptr %p, <4 x float> %arg, <4 x i1> %mask) sanitize_address {
80 ; CHECK-LABEL: @store.v4f32.variable(
81 ; CHECK-NEXT: [[TMP1:%.*]] = extractelement <4 x i1> [[MASK:%.*]], i64 0
82 ; CHECK-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP5:%.*]]
84 ; CHECK-NEXT: [[TMP3:%.*]] = getelementptr <4 x float>, ptr [[P:%.*]], i64 0, i64 0
85 ; CHECK-NEXT: [[TMP4:%.*]] = ptrtoint ptr [[TMP3]] to i64
86 ; CHECK-NEXT: call void @__asan_store4(i64 [[TMP4]])
87 ; CHECK-NEXT: br label [[TMP5]]
89 ; CHECK-NEXT: [[TMP6:%.*]] = extractelement <4 x i1> [[MASK]], i64 1
90 ; CHECK-NEXT: br i1 [[TMP6]], label [[TMP7:%.*]], label [[TMP10:%.*]]
92 ; CHECK-NEXT: [[TMP8:%.*]] = getelementptr <4 x float>, ptr [[P]], i64 0, i64 1
93 ; CHECK-NEXT: [[TMP9:%.*]] = ptrtoint ptr [[TMP8]] to i64
94 ; CHECK-NEXT: call void @__asan_store4(i64 [[TMP9]])
95 ; CHECK-NEXT: br label [[TMP10]]
97 ; CHECK-NEXT: [[TMP11:%.*]] = extractelement <4 x i1> [[MASK]], i64 2
98 ; CHECK-NEXT: br i1 [[TMP11]], label [[TMP12:%.*]], label [[TMP15:%.*]]
100 ; CHECK-NEXT: [[TMP13:%.*]] = getelementptr <4 x float>, ptr [[P]], i64 0, i64 2
101 ; CHECK-NEXT: [[TMP14:%.*]] = ptrtoint ptr [[TMP13]] to i64
102 ; CHECK-NEXT: call void @__asan_store4(i64 [[TMP14]])
103 ; CHECK-NEXT: br label [[TMP15]]
105 ; CHECK-NEXT: [[TMP16:%.*]] = extractelement <4 x i1> [[MASK]], i64 3
106 ; CHECK-NEXT: br i1 [[TMP16]], label [[TMP17:%.*]], label [[TMP20:%.*]]
108 ; CHECK-NEXT: [[TMP18:%.*]] = getelementptr <4 x float>, ptr [[P]], i64 0, i64 3
109 ; CHECK-NEXT: [[TMP19:%.*]] = ptrtoint ptr [[TMP18]] to i64
110 ; CHECK-NEXT: call void @__asan_store4(i64 [[TMP19]])
111 ; CHECK-NEXT: br label [[TMP20]]
113 ; CHECK-NEXT: tail call void @llvm.masked.store.v4f32.p0(<4 x float> [[ARG:%.*]], ptr [[P]], i32 4, <4 x i1> [[MASK]])
114 ; CHECK-NEXT: ret void
116 ; DISABLED-LABEL: @store.v4f32.variable(
117 ; DISABLED-NEXT: tail call void @llvm.masked.store.v4f32.p0(<4 x float> [[ARG:%.*]], ptr [[P:%.*]], i32 4, <4 x i1> [[MASK:%.*]])
118 ; DISABLED-NEXT: ret void
120 tail call void @llvm.masked.store.v4f32.p0(<4 x float> %arg, ptr %p, i32 4, <4 x i1> %mask)
124 ;; Store using two masked.stores, which should instrument them both.
125 define void @store.v4f32.1010.split(ptr %p, <4 x float> %arg) sanitize_address {
126 ; CHECK-LABEL: @store.v4f32.1010.split(
127 ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr <4 x float>, ptr [[P:%.*]], i64 0, i64 2
128 ; CHECK-NEXT: [[TMP2:%.*]] = ptrtoint ptr [[TMP1]] to i64
129 ; CHECK-NEXT: call void @__asan_store4(i64 [[TMP2]])
130 ; 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>)
131 ; CHECK-NEXT: ret void
133 ; DISABLED-LABEL: @store.v4f32.1010.split(
134 ; 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>)
135 ; DISABLED-NEXT: ret void
137 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>)
141 ;; Store using a masked.store after a full store. Shouldn't instrument the second one.
142 define void @store.v4f32.0010.after.full.store(ptr %p, <4 x float> %arg) sanitize_address {
143 ; CHECK-LABEL: @store.v4f32.0010.after.full.store(
144 ; CHECK-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[P:%.*]] to i64
145 ; CHECK-NEXT: call void @__asan_store16(i64 [[TMP1]])
146 ; CHECK-NEXT: store <4 x float> [[ARG:%.*]], ptr [[P]], align 16
147 ; 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>)
148 ; CHECK-NEXT: ret void
150 ; DISABLED-LABEL: @store.v4f32.0010.after.full.store(
151 ; DISABLED-NEXT: store <4 x float> [[ARG:%.*]], ptr [[P:%.*]], align 16
152 ; 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>)
153 ; DISABLED-NEXT: ret void
155 store <4 x float> %arg, ptr %p
156 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>)
160 ;;;;;;;;;;;;;;;; LOAD
161 declare <4 x float> @llvm.masked.load.v4f32.p0(ptr, i32, <4 x i1>, <4 x float>) argmemonly nounwind
162 declare <8 x i32> @llvm.masked.load.v8i32.p0(ptr, i32, <8 x i1>, <8 x i32>) argmemonly nounwind
163 declare <4 x ptr> @llvm.masked.load.v4p0.p0(ptr, i32, <4 x i1>, <4 x ptr>) argmemonly nounwind
165 define <8 x i32> @load.v8i32.11100001(ptr %p, <8 x i32> %arg) sanitize_address {
166 ; CHECK-LABEL: @load.v8i32.11100001(
167 ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr <8 x i32>, ptr [[P:%.*]], i64 0, i64 0
168 ; CHECK-NEXT: [[TMP2:%.*]] = ptrtoint ptr [[TMP1]] to i64
169 ; CHECK-NEXT: call void @__asan_load4(i64 [[TMP2]])
170 ; CHECK-NEXT: [[TMP3:%.*]] = getelementptr <8 x i32>, ptr [[P]], i64 0, i64 1
171 ; CHECK-NEXT: [[TMP4:%.*]] = ptrtoint ptr [[TMP3]] to i64
172 ; CHECK-NEXT: call void @__asan_load4(i64 [[TMP4]])
173 ; CHECK-NEXT: [[TMP5:%.*]] = getelementptr <8 x i32>, ptr [[P]], i64 0, i64 2
174 ; CHECK-NEXT: [[TMP6:%.*]] = ptrtoint ptr [[TMP5]] to i64
175 ; CHECK-NEXT: call void @__asan_load4(i64 [[TMP6]])
176 ; CHECK-NEXT: [[TMP7:%.*]] = getelementptr <8 x i32>, ptr [[P]], i64 0, i64 7
177 ; CHECK-NEXT: [[TMP8:%.*]] = ptrtoint ptr [[TMP7]] to i64
178 ; CHECK-NEXT: call void @__asan_load4(i64 [[TMP8]])
179 ; 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:%.*]])
180 ; CHECK-NEXT: ret <8 x i32> [[RES]]
182 ; DISABLED-LABEL: @load.v8i32.11100001(
183 ; 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:%.*]])
184 ; DISABLED-NEXT: ret <8 x i32> [[RES]]
186 %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)
190 define <4 x float> @load.v4f32.1001(ptr %p, <4 x float> %arg) sanitize_address {
191 ; CHECK-LABEL: @load.v4f32.1001(
192 ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr <4 x float>, ptr [[P:%.*]], i64 0, i64 0
193 ; CHECK-NEXT: [[TMP2:%.*]] = ptrtoint ptr [[TMP1]] to i64
194 ; CHECK-NEXT: call void @__asan_load4(i64 [[TMP2]])
195 ; CHECK-NEXT: [[TMP3:%.*]] = getelementptr <4 x float>, ptr [[P]], i64 0, i64 3
196 ; CHECK-NEXT: [[TMP4:%.*]] = ptrtoint ptr [[TMP3]] to i64
197 ; CHECK-NEXT: call void @__asan_load4(i64 [[TMP4]])
198 ; 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:%.*]])
199 ; CHECK-NEXT: ret <4 x float> [[RES]]
201 ; DISABLED-LABEL: @load.v4f32.1001(
202 ; 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:%.*]])
203 ; DISABLED-NEXT: ret <4 x float> [[RES]]
205 %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)
209 define <4 x ptr> @load.v4i64.0001(ptr %p, <4 x ptr> %arg) sanitize_address {
210 ; CHECK-LABEL: @load.v4i64.0001(
211 ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr <4 x ptr>, ptr [[P:%.*]], i64 0, i64 3
212 ; CHECK-NEXT: [[TMP2:%.*]] = ptrtoint ptr [[TMP1]] to i64
213 ; CHECK-NEXT: call void @__asan_load8(i64 [[TMP2]])
214 ; 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:%.*]])
215 ; CHECK-NEXT: ret <4 x ptr> [[RES]]
217 ; DISABLED-LABEL: @load.v4i64.0001(
218 ; 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:%.*]])
219 ; DISABLED-NEXT: ret <4 x ptr> [[RES]]
221 %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)
225 define <4 x float> @load.v4f32.variable(ptr %p, <4 x float> %arg, <4 x i1> %mask) sanitize_address {
226 ; CHECK-LABEL: @load.v4f32.variable(
227 ; CHECK-NEXT: [[TMP1:%.*]] = extractelement <4 x i1> [[MASK:%.*]], i64 0
228 ; CHECK-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP5:%.*]]
230 ; CHECK-NEXT: [[TMP3:%.*]] = getelementptr <4 x float>, ptr [[P:%.*]], i64 0, i64 0
231 ; CHECK-NEXT: [[TMP4:%.*]] = ptrtoint ptr [[TMP3]] to i64
232 ; CHECK-NEXT: call void @__asan_load4(i64 [[TMP4]])
233 ; CHECK-NEXT: br label [[TMP5]]
235 ; CHECK-NEXT: [[TMP6:%.*]] = extractelement <4 x i1> [[MASK]], i64 1
236 ; CHECK-NEXT: br i1 [[TMP6]], label [[TMP7:%.*]], label [[TMP10:%.*]]
238 ; CHECK-NEXT: [[TMP8:%.*]] = getelementptr <4 x float>, ptr [[P]], i64 0, i64 1
239 ; CHECK-NEXT: [[TMP9:%.*]] = ptrtoint ptr [[TMP8]] to i64
240 ; CHECK-NEXT: call void @__asan_load4(i64 [[TMP9]])
241 ; CHECK-NEXT: br label [[TMP10]]
243 ; CHECK-NEXT: [[TMP11:%.*]] = extractelement <4 x i1> [[MASK]], i64 2
244 ; CHECK-NEXT: br i1 [[TMP11]], label [[TMP12:%.*]], label [[TMP15:%.*]]
246 ; CHECK-NEXT: [[TMP13:%.*]] = getelementptr <4 x float>, ptr [[P]], i64 0, i64 2
247 ; CHECK-NEXT: [[TMP14:%.*]] = ptrtoint ptr [[TMP13]] to i64
248 ; CHECK-NEXT: call void @__asan_load4(i64 [[TMP14]])
249 ; CHECK-NEXT: br label [[TMP15]]
251 ; CHECK-NEXT: [[TMP16:%.*]] = extractelement <4 x i1> [[MASK]], i64 3
252 ; CHECK-NEXT: br i1 [[TMP16]], label [[TMP17:%.*]], label [[TMP20:%.*]]
254 ; CHECK-NEXT: [[TMP18:%.*]] = getelementptr <4 x float>, ptr [[P]], i64 0, i64 3
255 ; CHECK-NEXT: [[TMP19:%.*]] = ptrtoint ptr [[TMP18]] to i64
256 ; CHECK-NEXT: call void @__asan_load4(i64 [[TMP19]])
257 ; CHECK-NEXT: br label [[TMP20]]
259 ; 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:%.*]])
260 ; CHECK-NEXT: ret <4 x float> [[RES]]
262 ; DISABLED-LABEL: @load.v4f32.variable(
263 ; 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:%.*]])
264 ; DISABLED-NEXT: ret <4 x float> [[RES]]
266 %res = tail call <4 x float> @llvm.masked.load.v4f32.p0(ptr %p, i32 4, <4 x i1> %mask, <4 x float> %arg)
270 ;; Load using two masked.loads, which should instrument them both.
271 define <4 x float> @load.v4f32.1001.split(ptr %p, <4 x float> %arg) sanitize_address {
272 ; CHECK-LABEL: @load.v4f32.1001.split(
273 ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr <4 x float>, ptr [[P:%.*]], i64 0, i64 0
274 ; CHECK-NEXT: [[TMP2:%.*]] = ptrtoint ptr [[TMP1]] to i64
275 ; CHECK-NEXT: call void @__asan_load4(i64 [[TMP2]])
276 ; 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:%.*]])
277 ; CHECK-NEXT: [[TMP3:%.*]] = getelementptr <4 x float>, ptr [[P]], i64 0, i64 3
278 ; CHECK-NEXT: [[TMP4:%.*]] = ptrtoint ptr [[TMP3]] to i64
279 ; CHECK-NEXT: call void @__asan_load4(i64 [[TMP4]])
280 ; 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]])
281 ; CHECK-NEXT: ret <4 x float> [[RES2]]
283 ; DISABLED-LABEL: @load.v4f32.1001.split(
284 ; 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:%.*]])
285 ; 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]])
286 ; DISABLED-NEXT: ret <4 x float> [[RES2]]
288 %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)
289 %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)
290 ret <4 x float> %res2
293 ;; Load using a masked.load after a full load. Shouldn't instrument the second one.
294 define <4 x float> @load.v4f32.1001.after.full.load(ptr %p, <4 x float> %arg) sanitize_address {
295 ; CHECK-LABEL: @load.v4f32.1001.after.full.load(
296 ; CHECK-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[P:%.*]] to i64
297 ; CHECK-NEXT: call void @__asan_load16(i64 [[TMP1]])
298 ; CHECK-NEXT: [[RES:%.*]] = load <4 x float>, ptr [[P]], align 16
299 ; 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:%.*]])
300 ; CHECK-NEXT: ret <4 x float> [[RES2]]
302 ; DISABLED-LABEL: @load.v4f32.1001.after.full.load(
303 ; DISABLED-NEXT: [[RES:%.*]] = load <4 x float>, ptr [[P:%.*]], align 16
304 ; 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:%.*]])
305 ; DISABLED-NEXT: ret <4 x float> [[RES2]]
307 %res = load <4 x float>, ptr %p
308 %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)
309 ret <4 x float> %res2
312 ;; Scalable vector tests
313 ;; ---------------------------
314 declare <vscale x 4 x float> @llvm.masked.load.nxv4f32.p0(ptr, i32, <vscale x 4 x i1>, <vscale x 4 x float>)
315 declare void @llvm.masked.store.nxv4f32.p0(<vscale x 4 x float>, ptr, i32, <vscale x 4 x i1>)
317 define <vscale x 4 x float> @scalable.load.nxv4f32(ptr %p, <vscale x 4 x i1> %mask) sanitize_address {
318 ; CHECK-LABEL: @scalable.load.nxv4f32(
319 ; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.vscale.i64()
320 ; CHECK-NEXT: [[TMP2:%.*]] = mul i64 [[TMP1]], 4
321 ; CHECK-NEXT: br label [[DOTSPLIT:%.*]]
323 ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[TMP0:%.*]] ], [ [[IV_NEXT:%.*]], [[TMP7:%.*]] ]
324 ; CHECK-NEXT: [[TMP3:%.*]] = extractelement <vscale x 4 x i1> [[MASK:%.*]], i64 [[IV]]
325 ; CHECK-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP7]]
327 ; CHECK-NEXT: [[TMP5:%.*]] = getelementptr <vscale x 4 x float>, ptr [[P:%.*]], i64 0, i64 [[IV]]
328 ; CHECK-NEXT: [[TMP6:%.*]] = ptrtoint ptr [[TMP5]] to i64
329 ; CHECK-NEXT: call void @__asan_load4(i64 [[TMP6]])
330 ; CHECK-NEXT: br label [[TMP7]]
332 ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
333 ; CHECK-NEXT: [[IV_CHECK:%.*]] = icmp eq i64 [[IV_NEXT]], [[TMP2]]
334 ; CHECK-NEXT: br i1 [[IV_CHECK]], label [[DOTSPLIT_SPLIT:%.*]], label [[DOTSPLIT]]
335 ; CHECK: .split.split:
336 ; 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)
337 ; CHECK-NEXT: ret <vscale x 4 x float> [[RES]]
339 ; DISABLED-LABEL: @scalable.load.nxv4f32(
340 ; 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)
341 ; DISABLED-NEXT: ret <vscale x 4 x float> [[RES]]
343 %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)
344 ret <vscale x 4 x float> %res
347 define void @scalable.store.nxv4f32(ptr %p, <vscale x 4 x float> %arg, <vscale x 4 x i1> %mask) sanitize_address {
348 ; CHECK-LABEL: @scalable.store.nxv4f32(
349 ; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.vscale.i64()
350 ; CHECK-NEXT: [[TMP2:%.*]] = mul i64 [[TMP1]], 4
351 ; CHECK-NEXT: br label [[DOTSPLIT:%.*]]
353 ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[TMP0:%.*]] ], [ [[IV_NEXT:%.*]], [[TMP7:%.*]] ]
354 ; CHECK-NEXT: [[TMP3:%.*]] = extractelement <vscale x 4 x i1> [[MASK:%.*]], i64 [[IV]]
355 ; CHECK-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP7]]
357 ; CHECK-NEXT: [[TMP5:%.*]] = getelementptr <vscale x 4 x float>, ptr [[P:%.*]], i64 0, i64 [[IV]]
358 ; CHECK-NEXT: [[TMP6:%.*]] = ptrtoint ptr [[TMP5]] to i64
359 ; CHECK-NEXT: call void @__asan_store4(i64 [[TMP6]])
360 ; CHECK-NEXT: br label [[TMP7]]
362 ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
363 ; CHECK-NEXT: [[IV_CHECK:%.*]] = icmp eq i64 [[IV_NEXT]], [[TMP2]]
364 ; CHECK-NEXT: br i1 [[IV_CHECK]], label [[DOTSPLIT_SPLIT:%.*]], label [[DOTSPLIT]]
365 ; CHECK: .split.split:
366 ; 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]])
367 ; CHECK-NEXT: ret void
369 ; DISABLED-LABEL: @scalable.store.nxv4f32(
370 ; 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:%.*]])
371 ; DISABLED-NEXT: ret void
373 tail call void @llvm.masked.store.nxv4f32.p0(<vscale x 4 x float> %arg, ptr %p, i32 4, <vscale x 4 x i1> %mask)
377 ; Test masked.gather/scatter.
378 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>)
379 declare void @llvm.masked.scatter.nxv4f32.nxv4p0(<vscale x 4 x float>, <vscale x 4 x ptr>, i32, <vscale x 4 x i1>)
381 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 {
382 ; CHECK-LABEL: @scalable.gather.nxv4f32(
383 ; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.vscale.i64()
384 ; CHECK-NEXT: [[TMP2:%.*]] = mul i64 [[TMP1]], 4
385 ; CHECK-NEXT: br label [[DOTSPLIT:%.*]]
387 ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[TMP0:%.*]] ], [ [[IV_NEXT:%.*]], [[TMP7:%.*]] ]
388 ; CHECK-NEXT: [[TMP3:%.*]] = extractelement <vscale x 4 x i1> [[MASK:%.*]], i64 [[IV]]
389 ; CHECK-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP7]]
391 ; CHECK-NEXT: [[TMP5:%.*]] = extractelement <vscale x 4 x ptr> [[VP:%.*]], i64 [[IV]]
392 ; CHECK-NEXT: [[TMP6:%.*]] = ptrtoint ptr [[TMP5]] to i64
393 ; CHECK-NEXT: call void @__asan_load4(i64 [[TMP6]])
394 ; CHECK-NEXT: br label [[TMP7]]
396 ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
397 ; CHECK-NEXT: [[IV_CHECK:%.*]] = icmp eq i64 [[IV_NEXT]], [[TMP2]]
398 ; CHECK-NEXT: br i1 [[IV_CHECK]], label [[DOTSPLIT_SPLIT:%.*]], label [[DOTSPLIT]]
399 ; CHECK: .split.split:
400 ; 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)
401 ; CHECK-NEXT: ret <vscale x 4 x float> [[RES]]
403 ; DISABLED-LABEL: @scalable.gather.nxv4f32(
404 ; 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)
405 ; DISABLED-NEXT: ret <vscale x 4 x float> [[RES]]
407 %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)
408 ret <vscale x 4 x float> %res
411 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 {
412 ; CHECK-LABEL: @scalable.scatter.nxv4f32(
413 ; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.vscale.i64()
414 ; CHECK-NEXT: [[TMP2:%.*]] = mul i64 [[TMP1]], 4
415 ; CHECK-NEXT: br label [[DOTSPLIT:%.*]]
417 ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[TMP0:%.*]] ], [ [[IV_NEXT:%.*]], [[TMP7:%.*]] ]
418 ; CHECK-NEXT: [[TMP3:%.*]] = extractelement <vscale x 4 x i1> [[MASK:%.*]], i64 [[IV]]
419 ; CHECK-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP7]]
421 ; CHECK-NEXT: [[TMP5:%.*]] = extractelement <vscale x 4 x ptr> [[VP:%.*]], i64 [[IV]]
422 ; CHECK-NEXT: [[TMP6:%.*]] = ptrtoint ptr [[TMP5]] to i64
423 ; CHECK-NEXT: call void @__asan_store4(i64 [[TMP6]])
424 ; CHECK-NEXT: br label [[TMP7]]
426 ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
427 ; CHECK-NEXT: [[IV_CHECK:%.*]] = icmp eq i64 [[IV_NEXT]], [[TMP2]]
428 ; CHECK-NEXT: br i1 [[IV_CHECK]], label [[DOTSPLIT_SPLIT:%.*]], label [[DOTSPLIT]]
429 ; CHECK: .split.split:
430 ; 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]])
431 ; CHECK-NEXT: ret void
433 ; DISABLED-LABEL: @scalable.scatter.nxv4f32(
434 ; 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:%.*]])
435 ; DISABLED-NEXT: ret void
437 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)
441 declare <vscale x 4 x float> @llvm.masked.expandload.nxv4f32(ptr, <vscale x 4 x i1>, <vscale x 4 x float>)
442 declare void @llvm.masked.compressstore.nxv4f32(<vscale x 4 x float>, ptr, <vscale x 4 x i1>)
444 define <vscale x 4 x float> @scalable.expandload.nxv4f32(ptr align 4 %p, <vscale x 4 x i1> %mask) sanitize_address {
445 ; CHECK-LABEL: @scalable.expandload.nxv4f32(
446 ; CHECK-NEXT: [[TMP1:%.*]] = zext <vscale x 4 x i1> [[MASK:%.*]] to <vscale x 4 x i64>
447 ; CHECK-NEXT: [[TMP2:%.*]] = call i64 @llvm.vector.reduce.add.nxv4i64(<vscale x 4 x i64> [[TMP1]])
448 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i64 [[TMP2]], 0
449 ; CHECK-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP13:%.*]]
451 ; CHECK-NEXT: [[TMP5:%.*]] = call i64 @llvm.vscale.i64()
452 ; CHECK-NEXT: [[TMP6:%.*]] = mul i64 [[TMP5]], 4
453 ; CHECK-NEXT: [[TMP7:%.*]] = call i64 @llvm.umin.i64(i64 [[TMP2]], i64 [[TMP6]])
454 ; CHECK-NEXT: br label [[DOTSPLIT:%.*]]
456 ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[TMP4]] ], [ [[IV_NEXT:%.*]], [[TMP12:%.*]] ]
457 ; 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]]
458 ; CHECK-NEXT: br i1 [[TMP8]], label [[TMP9:%.*]], label [[TMP12]]
460 ; CHECK-NEXT: [[TMP10:%.*]] = getelementptr <vscale x 4 x float>, ptr [[P:%.*]], i64 0, i64 [[IV]]
461 ; CHECK-NEXT: [[TMP11:%.*]] = ptrtoint ptr [[TMP10]] to i64
462 ; CHECK-NEXT: call void @__asan_load4(i64 [[TMP11]])
463 ; CHECK-NEXT: br label [[TMP12]]
465 ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
466 ; CHECK-NEXT: [[IV_CHECK:%.*]] = icmp eq i64 [[IV_NEXT]], [[TMP7]]
467 ; CHECK-NEXT: br i1 [[IV_CHECK]], label [[DOTSPLIT_SPLIT:%.*]], label [[DOTSPLIT]]
468 ; CHECK: .split.split:
469 ; CHECK-NEXT: br label [[TMP13]]
471 ; 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)
472 ; CHECK-NEXT: ret <vscale x 4 x float> [[RES]]
474 ; DISABLED-LABEL: @scalable.expandload.nxv4f32(
475 ; 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)
476 ; DISABLED-NEXT: ret <vscale x 4 x float> [[RES]]
478 %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)
479 ret <vscale x 4 x float> %res
482 define void @scalable.compressstore.nxv4f32(ptr align 4 %p, <vscale x 4 x float> %arg, <vscale x 4 x i1> %mask) sanitize_address {
483 ; CHECK-LABEL: @scalable.compressstore.nxv4f32(
484 ; CHECK-NEXT: [[TMP1:%.*]] = zext <vscale x 4 x i1> [[MASK:%.*]] to <vscale x 4 x i64>
485 ; CHECK-NEXT: [[TMP2:%.*]] = call i64 @llvm.vector.reduce.add.nxv4i64(<vscale x 4 x i64> [[TMP1]])
486 ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i64 [[TMP2]], 0
487 ; CHECK-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP13:%.*]]
489 ; CHECK-NEXT: [[TMP5:%.*]] = call i64 @llvm.vscale.i64()
490 ; CHECK-NEXT: [[TMP6:%.*]] = mul i64 [[TMP5]], 4
491 ; CHECK-NEXT: [[TMP7:%.*]] = call i64 @llvm.umin.i64(i64 [[TMP2]], i64 [[TMP6]])
492 ; CHECK-NEXT: br label [[DOTSPLIT:%.*]]
494 ; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[TMP4]] ], [ [[IV_NEXT:%.*]], [[TMP12:%.*]] ]
495 ; 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]]
496 ; CHECK-NEXT: br i1 [[TMP8]], label [[TMP9:%.*]], label [[TMP12]]
498 ; CHECK-NEXT: [[TMP10:%.*]] = getelementptr <vscale x 4 x float>, ptr [[P:%.*]], i64 0, i64 [[IV]]
499 ; CHECK-NEXT: [[TMP11:%.*]] = ptrtoint ptr [[TMP10]] to i64
500 ; CHECK-NEXT: call void @__asan_store4(i64 [[TMP11]])
501 ; CHECK-NEXT: br label [[TMP12]]
503 ; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
504 ; CHECK-NEXT: [[IV_CHECK:%.*]] = icmp eq i64 [[IV_NEXT]], [[TMP7]]
505 ; CHECK-NEXT: br i1 [[IV_CHECK]], label [[DOTSPLIT_SPLIT:%.*]], label [[DOTSPLIT]]
506 ; CHECK: .split.split:
507 ; CHECK-NEXT: br label [[TMP13]]
509 ; CHECK-NEXT: tail call void @llvm.masked.compressstore.nxv4f32(<vscale x 4 x float> [[ARG:%.*]], ptr [[P]], <vscale x 4 x i1> [[MASK]])
510 ; CHECK-NEXT: ret void
512 ; DISABLED-LABEL: @scalable.compressstore.nxv4f32(
513 ; DISABLED-NEXT: tail call void @llvm.masked.compressstore.nxv4f32(<vscale x 4 x float> [[ARG:%.*]], ptr [[P:%.*]], <vscale x 4 x i1> [[MASK:%.*]])
514 ; DISABLED-NEXT: ret void
516 tail call void @llvm.masked.compressstore.nxv4f32(<vscale x 4 x float> %arg, ptr %p, <vscale x 4 x i1> %mask)