Skip to content

Commit 54ad114

Browse files
authored
[msan][NFC] Add tests for Arm NEON umaxv/uminv (#129661)
This patch precommits tests for the umaxv/uminv intrinsics, which are currently handled suboptimally by visitInstruction. Future work will update MSan to apply handleVectorReduceIntrinsic.
1 parent 180e305 commit 54ad114

File tree

2 files changed

+683
-0
lines changed

2 files changed

+683
-0
lines changed
Lines changed: 342 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,342 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2+
; RUN: opt < %s -passes=msan -S | FileCheck %s
3+
;
4+
; Forked from llvm/test/CodeGen/AArch64/arm64-umaxv.ll
5+
;
6+
; Handled suboptimally (visitInstruction):
7+
; - llvm.aarch64.neon.umaxv.i32.v16i8
8+
; - llvm.aarch64.neon.umaxv.i32.v2i32
9+
; - llvm.aarch64.neon.umaxv.i32.v4i16
10+
; - llvm.aarch64.neon.umaxv.i32.v4i32
11+
; - llvm.aarch64.neon.umaxv.i32.v8i16
12+
; - llvm.aarch64.neon.umaxv.i32.v8i8
13+
14+
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
15+
target triple = "aarch64--linux-android9001"
16+
17+
define i32 @vmax_u8x8(<8 x i8> %a) nounwind ssp {
18+
; CHECK-LABEL: define i32 @vmax_u8x8(
19+
; CHECK-SAME: <8 x i8> [[A:%.*]]) #[[ATTR0:[0-9]+]] {
20+
; CHECK-NEXT: [[ENTRY:.*]]:
21+
; CHECK-NEXT: call void @llvm.donothing()
22+
; CHECK-NEXT: [[VMAXV_I:%.*]] = tail call i32 @llvm.aarch64.neon.umaxv.i32.v8i8(<8 x i8> [[A]]) #[[ATTR3:[0-9]+]]
23+
; CHECK-NEXT: [[TMP:%.*]] = trunc i32 [[VMAXV_I]] to i8
24+
; CHECK-NEXT: [[TMP0:%.*]] = xor i8 [[TMP]], 0
25+
; CHECK-NEXT: [[TMP1:%.*]] = and i8 -1, [[TMP0]]
26+
; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[TMP1]], 0
27+
; CHECK-NEXT: [[_MSPROP_ICMP:%.*]] = and i1 false, [[TMP2]]
28+
; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i8 [[TMP]], 0
29+
; CHECK-NEXT: br i1 [[TOBOOL]], label %[[RETURN:.*]], label %[[IF_THEN:.*]]
30+
; CHECK: [[IF_THEN]]:
31+
; CHECK-NEXT: store i32 0, ptr @__msan_retval_tls, align 8
32+
; CHECK-NEXT: [[CALL1:%.*]] = tail call i32 @bar() #[[ATTR3]]
33+
; CHECK-NEXT: [[_MSRET:%.*]] = load i32, ptr @__msan_retval_tls, align 8
34+
; CHECK-NEXT: br label %[[RETURN]]
35+
; CHECK: [[RETURN]]:
36+
; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i32 [ [[CALL1]], %[[IF_THEN]] ], [ 0, %[[ENTRY]] ]
37+
; CHECK-NEXT: store i32 0, ptr @__msan_retval_tls, align 8
38+
; CHECK-NEXT: ret i32 [[RETVAL_0]]
39+
;
40+
entry:
41+
%vmaxv.i = tail call i32 @llvm.aarch64.neon.umaxv.i32.v8i8(<8 x i8> %a) nounwind
42+
%tmp = trunc i32 %vmaxv.i to i8
43+
%tobool = icmp eq i8 %tmp, 0
44+
br i1 %tobool, label %return, label %if.then
45+
46+
if.then:
47+
%call1 = tail call i32 @bar() nounwind
48+
br label %return
49+
50+
return:
51+
%retval.0 = phi i32 [ %call1, %if.then ], [ 0, %entry ]
52+
ret i32 %retval.0
53+
}
54+
55+
declare i32 @bar(...)
56+
57+
define i32 @vmax_u4x16(<4 x i16> %a) nounwind ssp {
58+
; CHECK-LABEL: define i32 @vmax_u4x16(
59+
; CHECK-SAME: <4 x i16> [[A:%.*]]) #[[ATTR0]] {
60+
; CHECK-NEXT: [[ENTRY:.*]]:
61+
; CHECK-NEXT: call void @llvm.donothing()
62+
; CHECK-NEXT: [[VMAXV_I:%.*]] = tail call i32 @llvm.aarch64.neon.umaxv.i32.v4i16(<4 x i16> [[A]]) #[[ATTR3]]
63+
; CHECK-NEXT: [[TMP:%.*]] = trunc i32 [[VMAXV_I]] to i16
64+
; CHECK-NEXT: [[TMP0:%.*]] = xor i16 [[TMP]], 0
65+
; CHECK-NEXT: [[TMP1:%.*]] = and i16 -1, [[TMP0]]
66+
; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i16 [[TMP1]], 0
67+
; CHECK-NEXT: [[_MSPROP_ICMP:%.*]] = and i1 false, [[TMP2]]
68+
; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i16 [[TMP]], 0
69+
; CHECK-NEXT: br i1 [[TOBOOL]], label %[[RETURN:.*]], label %[[IF_THEN:.*]]
70+
; CHECK: [[IF_THEN]]:
71+
; CHECK-NEXT: store i32 0, ptr @__msan_retval_tls, align 8
72+
; CHECK-NEXT: [[CALL1:%.*]] = tail call i32 @bar() #[[ATTR3]]
73+
; CHECK-NEXT: [[_MSRET:%.*]] = load i32, ptr @__msan_retval_tls, align 8
74+
; CHECK-NEXT: br label %[[RETURN]]
75+
; CHECK: [[RETURN]]:
76+
; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i32 [ [[CALL1]], %[[IF_THEN]] ], [ 0, %[[ENTRY]] ]
77+
; CHECK-NEXT: store i32 0, ptr @__msan_retval_tls, align 8
78+
; CHECK-NEXT: ret i32 [[RETVAL_0]]
79+
;
80+
entry:
81+
%vmaxv.i = tail call i32 @llvm.aarch64.neon.umaxv.i32.v4i16(<4 x i16> %a) nounwind
82+
%tmp = trunc i32 %vmaxv.i to i16
83+
%tobool = icmp eq i16 %tmp, 0
84+
br i1 %tobool, label %return, label %if.then
85+
86+
if.then:
87+
%call1 = tail call i32 @bar() nounwind
88+
br label %return
89+
90+
return:
91+
%retval.0 = phi i32 [ %call1, %if.then ], [ 0, %entry ]
92+
ret i32 %retval.0
93+
}
94+
95+
define i32 @vmax_u8x16(<8 x i16> %a) nounwind ssp {
96+
; CHECK-LABEL: define i32 @vmax_u8x16(
97+
; CHECK-SAME: <8 x i16> [[A:%.*]]) #[[ATTR0]] {
98+
; CHECK-NEXT: [[ENTRY:.*]]:
99+
; CHECK-NEXT: call void @llvm.donothing()
100+
; CHECK-NEXT: [[VMAXV_I:%.*]] = tail call i32 @llvm.aarch64.neon.umaxv.i32.v8i16(<8 x i16> [[A]]) #[[ATTR3]]
101+
; CHECK-NEXT: [[TMP:%.*]] = trunc i32 [[VMAXV_I]] to i16
102+
; CHECK-NEXT: [[TMP0:%.*]] = xor i16 [[TMP]], 0
103+
; CHECK-NEXT: [[TMP1:%.*]] = and i16 -1, [[TMP0]]
104+
; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i16 [[TMP1]], 0
105+
; CHECK-NEXT: [[_MSPROP_ICMP:%.*]] = and i1 false, [[TMP2]]
106+
; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i16 [[TMP]], 0
107+
; CHECK-NEXT: br i1 [[TOBOOL]], label %[[RETURN:.*]], label %[[IF_THEN:.*]]
108+
; CHECK: [[IF_THEN]]:
109+
; CHECK-NEXT: store i32 0, ptr @__msan_retval_tls, align 8
110+
; CHECK-NEXT: [[CALL1:%.*]] = tail call i32 @bar() #[[ATTR3]]
111+
; CHECK-NEXT: [[_MSRET:%.*]] = load i32, ptr @__msan_retval_tls, align 8
112+
; CHECK-NEXT: br label %[[RETURN]]
113+
; CHECK: [[RETURN]]:
114+
; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i32 [ [[CALL1]], %[[IF_THEN]] ], [ 0, %[[ENTRY]] ]
115+
; CHECK-NEXT: store i32 0, ptr @__msan_retval_tls, align 8
116+
; CHECK-NEXT: ret i32 [[RETVAL_0]]
117+
;
118+
entry:
119+
%vmaxv.i = tail call i32 @llvm.aarch64.neon.umaxv.i32.v8i16(<8 x i16> %a) nounwind
120+
%tmp = trunc i32 %vmaxv.i to i16
121+
%tobool = icmp eq i16 %tmp, 0
122+
br i1 %tobool, label %return, label %if.then
123+
124+
if.then:
125+
%call1 = tail call i32 @bar() nounwind
126+
br label %return
127+
128+
return:
129+
%retval.0 = phi i32 [ %call1, %if.then ], [ 0, %entry ]
130+
ret i32 %retval.0
131+
}
132+
133+
define i32 @vmax_u16x8(<16 x i8> %a) nounwind ssp {
134+
; CHECK-LABEL: define i32 @vmax_u16x8(
135+
; CHECK-SAME: <16 x i8> [[A:%.*]]) #[[ATTR0]] {
136+
; CHECK-NEXT: [[ENTRY:.*]]:
137+
; CHECK-NEXT: call void @llvm.donothing()
138+
; CHECK-NEXT: [[VMAXV_I:%.*]] = tail call i32 @llvm.aarch64.neon.umaxv.i32.v16i8(<16 x i8> [[A]]) #[[ATTR3]]
139+
; CHECK-NEXT: [[TMP:%.*]] = trunc i32 [[VMAXV_I]] to i8
140+
; CHECK-NEXT: [[TMP0:%.*]] = xor i8 [[TMP]], 0
141+
; CHECK-NEXT: [[TMP1:%.*]] = and i8 -1, [[TMP0]]
142+
; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[TMP1]], 0
143+
; CHECK-NEXT: [[_MSPROP_ICMP:%.*]] = and i1 false, [[TMP2]]
144+
; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i8 [[TMP]], 0
145+
; CHECK-NEXT: br i1 [[TOBOOL]], label %[[RETURN:.*]], label %[[IF_THEN:.*]]
146+
; CHECK: [[IF_THEN]]:
147+
; CHECK-NEXT: store i32 0, ptr @__msan_retval_tls, align 8
148+
; CHECK-NEXT: [[CALL1:%.*]] = tail call i32 @bar() #[[ATTR3]]
149+
; CHECK-NEXT: [[_MSRET:%.*]] = load i32, ptr @__msan_retval_tls, align 8
150+
; CHECK-NEXT: br label %[[RETURN]]
151+
; CHECK: [[RETURN]]:
152+
; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i32 [ [[CALL1]], %[[IF_THEN]] ], [ 0, %[[ENTRY]] ]
153+
; CHECK-NEXT: store i32 0, ptr @__msan_retval_tls, align 8
154+
; CHECK-NEXT: ret i32 [[RETVAL_0]]
155+
;
156+
entry:
157+
%vmaxv.i = tail call i32 @llvm.aarch64.neon.umaxv.i32.v16i8(<16 x i8> %a) nounwind
158+
%tmp = trunc i32 %vmaxv.i to i8
159+
%tobool = icmp eq i8 %tmp, 0
160+
br i1 %tobool, label %return, label %if.then
161+
162+
if.then:
163+
%call1 = tail call i32 @bar() nounwind
164+
br label %return
165+
166+
return:
167+
%retval.0 = phi i32 [ %call1, %if.then ], [ 0, %entry ]
168+
ret i32 %retval.0
169+
}
170+
171+
define <8 x i8> @test_vmaxv_u8_used_by_laneop(<8 x i8> %a1, <8 x i8> %a2) #0 {
172+
; CHECK-LABEL: define <8 x i8> @test_vmaxv_u8_used_by_laneop(
173+
; CHECK-SAME: <8 x i8> [[A1:%.*]], <8 x i8> [[A2:%.*]]) #[[ATTR1:[0-9]+]] {
174+
; CHECK-NEXT: [[ENTRY:.*:]]
175+
; CHECK-NEXT: [[TMP0:%.*]] = load <8 x i8>, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_param_tls to i64), i64 8) to ptr), align 8
176+
; CHECK-NEXT: [[TMP1:%.*]] = load <8 x i8>, ptr @__msan_param_tls, align 8
177+
; CHECK-NEXT: call void @llvm.donothing()
178+
; CHECK-NEXT: [[TMP2:%.*]] = bitcast <8 x i8> [[TMP0]] to i64
179+
; CHECK-NEXT: [[_MSCMP:%.*]] = icmp ne i64 [[TMP2]], 0
180+
; CHECK-NEXT: br i1 [[_MSCMP]], label %[[BB3:.*]], label %[[BB4:.*]], !prof [[PROF1:![0-9]+]]
181+
; CHECK: [[BB3]]:
182+
; CHECK-NEXT: call void @__msan_warning_noreturn() #[[ATTR4:[0-9]+]]
183+
; CHECK-NEXT: unreachable
184+
; CHECK: [[BB4]]:
185+
; CHECK-NEXT: [[TMP5:%.*]] = tail call i32 @llvm.aarch64.neon.umaxv.i32.v8i8(<8 x i8> [[A2]])
186+
; CHECK-NEXT: [[TMP6:%.*]] = trunc i32 [[TMP5]] to i8
187+
; CHECK-NEXT: [[_MSPROP:%.*]] = insertelement <8 x i8> [[TMP1]], i8 0, i32 3
188+
; CHECK-NEXT: [[TMP7:%.*]] = insertelement <8 x i8> [[A1]], i8 [[TMP6]], i32 3
189+
; CHECK-NEXT: store <8 x i8> [[_MSPROP]], ptr @__msan_retval_tls, align 8
190+
; CHECK-NEXT: ret <8 x i8> [[TMP7]]
191+
;
192+
entry:
193+
%0 = tail call i32 @llvm.aarch64.neon.umaxv.i32.v8i8(<8 x i8> %a2)
194+
%1 = trunc i32 %0 to i8
195+
%2 = insertelement <8 x i8> %a1, i8 %1, i32 3
196+
ret <8 x i8> %2
197+
}
198+
199+
define <4 x i16> @test_vmaxv_u16_used_by_laneop(<4 x i16> %a1, <4 x i16> %a2) #0 {
200+
; CHECK-LABEL: define <4 x i16> @test_vmaxv_u16_used_by_laneop(
201+
; CHECK-SAME: <4 x i16> [[A1:%.*]], <4 x i16> [[A2:%.*]]) #[[ATTR1]] {
202+
; CHECK-NEXT: [[ENTRY:.*:]]
203+
; CHECK-NEXT: [[TMP0:%.*]] = load <4 x i16>, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_param_tls to i64), i64 8) to ptr), align 8
204+
; CHECK-NEXT: [[TMP1:%.*]] = load <4 x i16>, ptr @__msan_param_tls, align 8
205+
; CHECK-NEXT: call void @llvm.donothing()
206+
; CHECK-NEXT: [[TMP2:%.*]] = bitcast <4 x i16> [[TMP0]] to i64
207+
; CHECK-NEXT: [[_MSCMP:%.*]] = icmp ne i64 [[TMP2]], 0
208+
; CHECK-NEXT: br i1 [[_MSCMP]], label %[[BB3:.*]], label %[[BB4:.*]], !prof [[PROF1]]
209+
; CHECK: [[BB3]]:
210+
; CHECK-NEXT: call void @__msan_warning_noreturn() #[[ATTR4]]
211+
; CHECK-NEXT: unreachable
212+
; CHECK: [[BB4]]:
213+
; CHECK-NEXT: [[TMP5:%.*]] = tail call i32 @llvm.aarch64.neon.umaxv.i32.v4i16(<4 x i16> [[A2]])
214+
; CHECK-NEXT: [[TMP6:%.*]] = trunc i32 [[TMP5]] to i16
215+
; CHECK-NEXT: [[_MSPROP:%.*]] = insertelement <4 x i16> [[TMP1]], i16 0, i32 3
216+
; CHECK-NEXT: [[TMP7:%.*]] = insertelement <4 x i16> [[A1]], i16 [[TMP6]], i32 3
217+
; CHECK-NEXT: store <4 x i16> [[_MSPROP]], ptr @__msan_retval_tls, align 8
218+
; CHECK-NEXT: ret <4 x i16> [[TMP7]]
219+
;
220+
entry:
221+
%0 = tail call i32 @llvm.aarch64.neon.umaxv.i32.v4i16(<4 x i16> %a2)
222+
%1 = trunc i32 %0 to i16
223+
%2 = insertelement <4 x i16> %a1, i16 %1, i32 3
224+
ret <4 x i16> %2
225+
}
226+
227+
define <2 x i32> @test_vmaxv_u32_used_by_laneop(<2 x i32> %a1, <2 x i32> %a2) #0 {
228+
; CHECK-LABEL: define <2 x i32> @test_vmaxv_u32_used_by_laneop(
229+
; CHECK-SAME: <2 x i32> [[A1:%.*]], <2 x i32> [[A2:%.*]]) #[[ATTR1]] {
230+
; CHECK-NEXT: [[ENTRY:.*:]]
231+
; CHECK-NEXT: [[TMP0:%.*]] = load <2 x i32>, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_param_tls to i64), i64 8) to ptr), align 8
232+
; CHECK-NEXT: [[TMP1:%.*]] = load <2 x i32>, ptr @__msan_param_tls, align 8
233+
; CHECK-NEXT: call void @llvm.donothing()
234+
; CHECK-NEXT: [[TMP2:%.*]] = bitcast <2 x i32> [[TMP0]] to i64
235+
; CHECK-NEXT: [[_MSCMP:%.*]] = icmp ne i64 [[TMP2]], 0
236+
; CHECK-NEXT: br i1 [[_MSCMP]], label %[[BB3:.*]], label %[[BB4:.*]], !prof [[PROF1]]
237+
; CHECK: [[BB3]]:
238+
; CHECK-NEXT: call void @__msan_warning_noreturn() #[[ATTR4]]
239+
; CHECK-NEXT: unreachable
240+
; CHECK: [[BB4]]:
241+
; CHECK-NEXT: [[TMP5:%.*]] = tail call i32 @llvm.aarch64.neon.umaxv.i32.v2i32(<2 x i32> [[A2]])
242+
; CHECK-NEXT: [[_MSPROP:%.*]] = insertelement <2 x i32> [[TMP1]], i32 0, i32 1
243+
; CHECK-NEXT: [[TMP6:%.*]] = insertelement <2 x i32> [[A1]], i32 [[TMP5]], i32 1
244+
; CHECK-NEXT: store <2 x i32> [[_MSPROP]], ptr @__msan_retval_tls, align 8
245+
; CHECK-NEXT: ret <2 x i32> [[TMP6]]
246+
;
247+
entry:
248+
%0 = tail call i32 @llvm.aarch64.neon.umaxv.i32.v2i32(<2 x i32> %a2)
249+
%1 = insertelement <2 x i32> %a1, i32 %0, i32 1
250+
ret <2 x i32> %1
251+
}
252+
253+
define <16 x i8> @test_vmaxvq_u8_used_by_laneop(<16 x i8> %a1, <16 x i8> %a2) #0 {
254+
; CHECK-LABEL: define <16 x i8> @test_vmaxvq_u8_used_by_laneop(
255+
; CHECK-SAME: <16 x i8> [[A1:%.*]], <16 x i8> [[A2:%.*]]) #[[ATTR1]] {
256+
; CHECK-NEXT: [[ENTRY:.*:]]
257+
; CHECK-NEXT: [[TMP0:%.*]] = load <16 x i8>, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_param_tls to i64), i64 16) to ptr), align 8
258+
; CHECK-NEXT: [[TMP1:%.*]] = load <16 x i8>, ptr @__msan_param_tls, align 8
259+
; CHECK-NEXT: call void @llvm.donothing()
260+
; CHECK-NEXT: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP0]] to i128
261+
; CHECK-NEXT: [[_MSCMP:%.*]] = icmp ne i128 [[TMP2]], 0
262+
; CHECK-NEXT: br i1 [[_MSCMP]], label %[[BB3:.*]], label %[[BB4:.*]], !prof [[PROF1]]
263+
; CHECK: [[BB3]]:
264+
; CHECK-NEXT: call void @__msan_warning_noreturn() #[[ATTR4]]
265+
; CHECK-NEXT: unreachable
266+
; CHECK: [[BB4]]:
267+
; CHECK-NEXT: [[TMP5:%.*]] = tail call i32 @llvm.aarch64.neon.umaxv.i32.v16i8(<16 x i8> [[A2]])
268+
; CHECK-NEXT: [[TMP6:%.*]] = trunc i32 [[TMP5]] to i8
269+
; CHECK-NEXT: [[_MSPROP:%.*]] = insertelement <16 x i8> [[TMP1]], i8 0, i32 3
270+
; CHECK-NEXT: [[TMP7:%.*]] = insertelement <16 x i8> [[A1]], i8 [[TMP6]], i32 3
271+
; CHECK-NEXT: store <16 x i8> [[_MSPROP]], ptr @__msan_retval_tls, align 8
272+
; CHECK-NEXT: ret <16 x i8> [[TMP7]]
273+
;
274+
entry:
275+
%0 = tail call i32 @llvm.aarch64.neon.umaxv.i32.v16i8(<16 x i8> %a2)
276+
%1 = trunc i32 %0 to i8
277+
%2 = insertelement <16 x i8> %a1, i8 %1, i32 3
278+
ret <16 x i8> %2
279+
}
280+
281+
define <8 x i16> @test_vmaxvq_u16_used_by_laneop(<8 x i16> %a1, <8 x i16> %a2) #0 {
282+
; CHECK-LABEL: define <8 x i16> @test_vmaxvq_u16_used_by_laneop(
283+
; CHECK-SAME: <8 x i16> [[A1:%.*]], <8 x i16> [[A2:%.*]]) #[[ATTR1]] {
284+
; CHECK-NEXT: [[ENTRY:.*:]]
285+
; CHECK-NEXT: [[TMP0:%.*]] = load <8 x i16>, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_param_tls to i64), i64 16) to ptr), align 8
286+
; CHECK-NEXT: [[TMP1:%.*]] = load <8 x i16>, ptr @__msan_param_tls, align 8
287+
; CHECK-NEXT: call void @llvm.donothing()
288+
; CHECK-NEXT: [[TMP2:%.*]] = bitcast <8 x i16> [[TMP0]] to i128
289+
; CHECK-NEXT: [[_MSCMP:%.*]] = icmp ne i128 [[TMP2]], 0
290+
; CHECK-NEXT: br i1 [[_MSCMP]], label %[[BB3:.*]], label %[[BB4:.*]], !prof [[PROF1]]
291+
; CHECK: [[BB3]]:
292+
; CHECK-NEXT: call void @__msan_warning_noreturn() #[[ATTR4]]
293+
; CHECK-NEXT: unreachable
294+
; CHECK: [[BB4]]:
295+
; CHECK-NEXT: [[TMP5:%.*]] = tail call i32 @llvm.aarch64.neon.umaxv.i32.v8i16(<8 x i16> [[A2]])
296+
; CHECK-NEXT: [[TMP6:%.*]] = trunc i32 [[TMP5]] to i16
297+
; CHECK-NEXT: [[_MSPROP:%.*]] = insertelement <8 x i16> [[TMP1]], i16 0, i32 3
298+
; CHECK-NEXT: [[TMP7:%.*]] = insertelement <8 x i16> [[A1]], i16 [[TMP6]], i32 3
299+
; CHECK-NEXT: store <8 x i16> [[_MSPROP]], ptr @__msan_retval_tls, align 8
300+
; CHECK-NEXT: ret <8 x i16> [[TMP7]]
301+
;
302+
entry:
303+
%0 = tail call i32 @llvm.aarch64.neon.umaxv.i32.v8i16(<8 x i16> %a2)
304+
%1 = trunc i32 %0 to i16
305+
%2 = insertelement <8 x i16> %a1, i16 %1, i32 3
306+
ret <8 x i16> %2
307+
}
308+
309+
define <4 x i32> @test_vmaxvq_u32_used_by_laneop(<4 x i32> %a1, <4 x i32> %a2) #0 {
310+
; CHECK-LABEL: define <4 x i32> @test_vmaxvq_u32_used_by_laneop(
311+
; CHECK-SAME: <4 x i32> [[A1:%.*]], <4 x i32> [[A2:%.*]]) #[[ATTR1]] {
312+
; CHECK-NEXT: [[ENTRY:.*:]]
313+
; CHECK-NEXT: [[TMP0:%.*]] = load <4 x i32>, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_param_tls to i64), i64 16) to ptr), align 8
314+
; CHECK-NEXT: [[TMP1:%.*]] = load <4 x i32>, ptr @__msan_param_tls, align 8
315+
; CHECK-NEXT: call void @llvm.donothing()
316+
; CHECK-NEXT: [[TMP2:%.*]] = bitcast <4 x i32> [[TMP0]] to i128
317+
; CHECK-NEXT: [[_MSCMP:%.*]] = icmp ne i128 [[TMP2]], 0
318+
; CHECK-NEXT: br i1 [[_MSCMP]], label %[[BB3:.*]], label %[[BB4:.*]], !prof [[PROF1]]
319+
; CHECK: [[BB3]]:
320+
; CHECK-NEXT: call void @__msan_warning_noreturn() #[[ATTR4]]
321+
; CHECK-NEXT: unreachable
322+
; CHECK: [[BB4]]:
323+
; CHECK-NEXT: [[TMP5:%.*]] = tail call i32 @llvm.aarch64.neon.umaxv.i32.v4i32(<4 x i32> [[A2]])
324+
; CHECK-NEXT: [[_MSPROP:%.*]] = insertelement <4 x i32> [[TMP1]], i32 0, i32 3
325+
; CHECK-NEXT: [[TMP6:%.*]] = insertelement <4 x i32> [[A1]], i32 [[TMP5]], i32 3
326+
; CHECK-NEXT: store <4 x i32> [[_MSPROP]], ptr @__msan_retval_tls, align 8
327+
; CHECK-NEXT: ret <4 x i32> [[TMP6]]
328+
;
329+
entry:
330+
%0 = tail call i32 @llvm.aarch64.neon.umaxv.i32.v4i32(<4 x i32> %a2)
331+
%1 = insertelement <4 x i32> %a1, i32 %0, i32 3
332+
ret <4 x i32> %1
333+
}
334+
335+
declare i32 @llvm.aarch64.neon.umaxv.i32.v16i8(<16 x i8>) nounwind readnone
336+
declare i32 @llvm.aarch64.neon.umaxv.i32.v8i16(<8 x i16>) nounwind readnone
337+
declare i32 @llvm.aarch64.neon.umaxv.i32.v4i16(<4 x i16>) nounwind readnone
338+
declare i32 @llvm.aarch64.neon.umaxv.i32.v8i8(<8 x i8>) nounwind readnone
339+
declare i32 @llvm.aarch64.neon.umaxv.i32.v2i32(<2 x i32>) nounwind readnone
340+
declare i32 @llvm.aarch64.neon.umaxv.i32.v4i32(<4 x i32>) nounwind readnone
341+
342+
attributes #0 = { sanitize_memory }

0 commit comments

Comments
 (0)