Skip to content

Commit c9fccbd

Browse files
authored
[msan][NFCI] Add tests for Arm NEON floating-point min/max (vector) (#125729)
Currently handled (suboptimally) by handleUnknownInstruction: - llvm.aarch64.neon.fmaxv (Floating-point Maximum (vector)) - llvm.aarch64.neon.fminv - llvm.aarch64.neon.fmaxnmv (Floating-point Maximum Number across Vector) - llvm.aarch64.neon.fminnmv (not to be mistaken with llvm.aarch64.neon.f{max,min}, which are correctly handled by `maybeHandleSimpleNomemIntrinsic`) Forked from llvm/test/CodeGen/AArch64/arm64-fminv.ll
1 parent 806e351 commit c9fccbd

File tree

1 file changed

+274
-0
lines changed

1 file changed

+274
-0
lines changed
Lines changed: 274 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,274 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
2+
; RUN: opt < %s -passes=msan -S | FileCheck %s
3+
;
4+
; Forked from llvm/test/CodeGen/AArch64/arm64-fminv.ll
5+
;
6+
; Currently handled (suboptimally) by handleUnknownInstruction:
7+
; - llvm.aarch64.neon.fmaxv
8+
; - llvm.aarch64.neon.fminv
9+
; - llvm.aarch64.neon.fmaxnmv
10+
; - llvm.aarch64.neon.fminnmv
11+
12+
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
13+
target triple = "aarch64--linux-android9001"
14+
15+
define float @test_fminv_v2f32(<2 x float> %in) #0 {
16+
; CHECK-LABEL: define float @test_fminv_v2f32(
17+
; CHECK-SAME: <2 x float> [[IN:%.*]]) #[[ATTR0:[0-9]+]] {
18+
; CHECK-NEXT: [[TMP1:%.*]] = load <2 x i32>, ptr @__msan_param_tls, align 8
19+
; CHECK-NEXT: call void @llvm.donothing()
20+
; CHECK-NEXT: [[TMP2:%.*]] = bitcast <2 x i32> [[TMP1]] to i64
21+
; CHECK-NEXT: [[_MSCMP:%.*]] = icmp ne i64 [[TMP2]], 0
22+
; CHECK-NEXT: br i1 [[_MSCMP]], label [[TMP3:%.*]], label [[TMP4:%.*]], !prof [[PROF1:![0-9]+]]
23+
; CHECK: 3:
24+
; CHECK-NEXT: call void @__msan_warning_noreturn() #[[ATTR3:[0-9]+]]
25+
; CHECK-NEXT: unreachable
26+
; CHECK: 4:
27+
; CHECK-NEXT: [[MIN:%.*]] = call float @llvm.aarch64.neon.fminv.f32.v2f32(<2 x float> [[IN]])
28+
; CHECK-NEXT: store i32 0, ptr @__msan_retval_tls, align 8
29+
; CHECK-NEXT: ret float [[MIN]]
30+
;
31+
%min = call float @llvm.aarch64.neon.fminv.f32.v2f32(<2 x float> %in)
32+
ret float %min
33+
}
34+
35+
define float @test_fminv_v4f32(<4 x float> %in) #0 {
36+
; CHECK-LABEL: define float @test_fminv_v4f32(
37+
; CHECK-SAME: <4 x float> [[IN:%.*]]) #[[ATTR0]] {
38+
; CHECK-NEXT: [[TMP1:%.*]] = load <4 x i32>, ptr @__msan_param_tls, align 8
39+
; CHECK-NEXT: call void @llvm.donothing()
40+
; CHECK-NEXT: [[TMP2:%.*]] = bitcast <4 x i32> [[TMP1]] to i128
41+
; CHECK-NEXT: [[_MSCMP:%.*]] = icmp ne i128 [[TMP2]], 0
42+
; CHECK-NEXT: br i1 [[_MSCMP]], label [[TMP3:%.*]], label [[TMP4:%.*]], !prof [[PROF1]]
43+
; CHECK: 3:
44+
; CHECK-NEXT: call void @__msan_warning_noreturn() #[[ATTR3]]
45+
; CHECK-NEXT: unreachable
46+
; CHECK: 4:
47+
; CHECK-NEXT: [[MIN:%.*]] = call float @llvm.aarch64.neon.fminv.f32.v4f32(<4 x float> [[IN]])
48+
; CHECK-NEXT: store i32 0, ptr @__msan_retval_tls, align 8
49+
; CHECK-NEXT: ret float [[MIN]]
50+
;
51+
%min = call float @llvm.aarch64.neon.fminv.f32.v4f32(<4 x float> %in)
52+
ret float %min
53+
}
54+
55+
define double @test_fminv_v2f64(<2 x double> %in) #0 {
56+
; CHECK-LABEL: define double @test_fminv_v2f64(
57+
; CHECK-SAME: <2 x double> [[IN:%.*]]) #[[ATTR0]] {
58+
; CHECK-NEXT: [[TMP1:%.*]] = load <2 x i64>, ptr @__msan_param_tls, align 8
59+
; CHECK-NEXT: call void @llvm.donothing()
60+
; CHECK-NEXT: [[TMP2:%.*]] = bitcast <2 x i64> [[TMP1]] to i128
61+
; CHECK-NEXT: [[_MSCMP:%.*]] = icmp ne i128 [[TMP2]], 0
62+
; CHECK-NEXT: br i1 [[_MSCMP]], label [[TMP3:%.*]], label [[TMP4:%.*]], !prof [[PROF1]]
63+
; CHECK: 3:
64+
; CHECK-NEXT: call void @__msan_warning_noreturn() #[[ATTR3]]
65+
; CHECK-NEXT: unreachable
66+
; CHECK: 4:
67+
; CHECK-NEXT: [[MIN:%.*]] = call double @llvm.aarch64.neon.fminv.f64.v2f64(<2 x double> [[IN]])
68+
; CHECK-NEXT: store i64 0, ptr @__msan_retval_tls, align 8
69+
; CHECK-NEXT: ret double [[MIN]]
70+
;
71+
%min = call double @llvm.aarch64.neon.fminv.f64.v2f64(<2 x double> %in)
72+
ret double %min
73+
}
74+
75+
declare float @llvm.aarch64.neon.fminv.f32.v2f32(<2 x float>)
76+
declare float @llvm.aarch64.neon.fminv.f32.v4f32(<4 x float>)
77+
declare double @llvm.aarch64.neon.fminv.f64.v2f64(<2 x double>)
78+
79+
define float @test_fmaxv_v2f32(<2 x float> %in) #0 {
80+
; CHECK-LABEL: define float @test_fmaxv_v2f32(
81+
; CHECK-SAME: <2 x float> [[IN:%.*]]) #[[ATTR0]] {
82+
; CHECK-NEXT: [[TMP1:%.*]] = load <2 x i32>, ptr @__msan_param_tls, align 8
83+
; CHECK-NEXT: call void @llvm.donothing()
84+
; CHECK-NEXT: [[TMP2:%.*]] = bitcast <2 x i32> [[TMP1]] to i64
85+
; CHECK-NEXT: [[_MSCMP:%.*]] = icmp ne i64 [[TMP2]], 0
86+
; CHECK-NEXT: br i1 [[_MSCMP]], label [[TMP3:%.*]], label [[TMP4:%.*]], !prof [[PROF1]]
87+
; CHECK: 3:
88+
; CHECK-NEXT: call void @__msan_warning_noreturn() #[[ATTR3]]
89+
; CHECK-NEXT: unreachable
90+
; CHECK: 4:
91+
; CHECK-NEXT: [[MAX:%.*]] = call float @llvm.aarch64.neon.fmaxv.f32.v2f32(<2 x float> [[IN]])
92+
; CHECK-NEXT: store i32 0, ptr @__msan_retval_tls, align 8
93+
; CHECK-NEXT: ret float [[MAX]]
94+
;
95+
%max = call float @llvm.aarch64.neon.fmaxv.f32.v2f32(<2 x float> %in)
96+
ret float %max
97+
}
98+
99+
define float @test_fmaxv_v4f32(<4 x float> %in) #0 {
100+
; CHECK-LABEL: define float @test_fmaxv_v4f32(
101+
; CHECK-SAME: <4 x float> [[IN:%.*]]) #[[ATTR0]] {
102+
; CHECK-NEXT: [[TMP1:%.*]] = load <4 x i32>, ptr @__msan_param_tls, align 8
103+
; CHECK-NEXT: call void @llvm.donothing()
104+
; CHECK-NEXT: [[TMP2:%.*]] = bitcast <4 x i32> [[TMP1]] to i128
105+
; CHECK-NEXT: [[_MSCMP:%.*]] = icmp ne i128 [[TMP2]], 0
106+
; CHECK-NEXT: br i1 [[_MSCMP]], label [[TMP3:%.*]], label [[TMP4:%.*]], !prof [[PROF1]]
107+
; CHECK: 3:
108+
; CHECK-NEXT: call void @__msan_warning_noreturn() #[[ATTR3]]
109+
; CHECK-NEXT: unreachable
110+
; CHECK: 4:
111+
; CHECK-NEXT: [[MAX:%.*]] = call float @llvm.aarch64.neon.fmaxv.f32.v4f32(<4 x float> [[IN]])
112+
; CHECK-NEXT: store i32 0, ptr @__msan_retval_tls, align 8
113+
; CHECK-NEXT: ret float [[MAX]]
114+
;
115+
%max = call float @llvm.aarch64.neon.fmaxv.f32.v4f32(<4 x float> %in)
116+
ret float %max
117+
}
118+
119+
define double @test_fmaxv_v2f64(<2 x double> %shareholder_value) #0 {
120+
; CHECK-LABEL: define double @test_fmaxv_v2f64(
121+
; CHECK-SAME: <2 x double> [[SHAREHOLDER_VALUE:%.*]]) #[[ATTR0]] {
122+
; CHECK-NEXT: [[TMP1:%.*]] = load <2 x i64>, ptr @__msan_param_tls, align 8
123+
; CHECK-NEXT: call void @llvm.donothing()
124+
; CHECK-NEXT: [[TMP2:%.*]] = bitcast <2 x i64> [[TMP1]] to i128
125+
; CHECK-NEXT: [[_MSCMP:%.*]] = icmp ne i128 [[TMP2]], 0
126+
; CHECK-NEXT: br i1 [[_MSCMP]], label [[TMP3:%.*]], label [[TMP4:%.*]], !prof [[PROF1]]
127+
; CHECK: 3:
128+
; CHECK-NEXT: call void @__msan_warning_noreturn() #[[ATTR3]]
129+
; CHECK-NEXT: unreachable
130+
; CHECK: 4:
131+
; CHECK-NEXT: [[MAX:%.*]] = call double @llvm.aarch64.neon.fmaxv.f64.v2f64(<2 x double> [[SHAREHOLDER_VALUE]])
132+
; CHECK-NEXT: store i64 0, ptr @__msan_retval_tls, align 8
133+
; CHECK-NEXT: ret double [[MAX]]
134+
;
135+
%max_sv = call double @llvm.aarch64.neon.fmaxv.f64.v2f64(<2 x double> %shareholder_value)
136+
ret double %max_sv
137+
}
138+
139+
declare float @llvm.aarch64.neon.fmaxv.f32.v2f32(<2 x float>)
140+
declare float @llvm.aarch64.neon.fmaxv.f32.v4f32(<4 x float>)
141+
declare double @llvm.aarch64.neon.fmaxv.f64.v2f64(<2 x double>)
142+
143+
define float @test_fminnmv_v2f32(<2 x float> %in) #0 {
144+
; CHECK-LABEL: define float @test_fminnmv_v2f32(
145+
; CHECK-SAME: <2 x float> [[IN:%.*]]) #[[ATTR0]] {
146+
; CHECK-NEXT: [[TMP1:%.*]] = load <2 x i32>, ptr @__msan_param_tls, align 8
147+
; CHECK-NEXT: call void @llvm.donothing()
148+
; CHECK-NEXT: [[TMP2:%.*]] = bitcast <2 x i32> [[TMP1]] to i64
149+
; CHECK-NEXT: [[_MSCMP:%.*]] = icmp ne i64 [[TMP2]], 0
150+
; CHECK-NEXT: br i1 [[_MSCMP]], label [[TMP3:%.*]], label [[TMP4:%.*]], !prof [[PROF1]]
151+
; CHECK: 3:
152+
; CHECK-NEXT: call void @__msan_warning_noreturn() #[[ATTR3]]
153+
; CHECK-NEXT: unreachable
154+
; CHECK: 4:
155+
; CHECK-NEXT: [[MINNM:%.*]] = call float @llvm.aarch64.neon.fminnmv.f32.v2f32(<2 x float> [[IN]])
156+
; CHECK-NEXT: store i32 0, ptr @__msan_retval_tls, align 8
157+
; CHECK-NEXT: ret float [[MINNM]]
158+
;
159+
%minnm = call float @llvm.aarch64.neon.fminnmv.f32.v2f32(<2 x float> %in)
160+
ret float %minnm
161+
}
162+
163+
define float @test_fminnmv_v4f32(<4 x float> %in) #0 {
164+
; CHECK-LABEL: define float @test_fminnmv_v4f32(
165+
; CHECK-SAME: <4 x float> [[IN:%.*]]) #[[ATTR0]] {
166+
; CHECK-NEXT: [[TMP1:%.*]] = load <4 x i32>, ptr @__msan_param_tls, align 8
167+
; CHECK-NEXT: call void @llvm.donothing()
168+
; CHECK-NEXT: [[TMP2:%.*]] = bitcast <4 x i32> [[TMP1]] to i128
169+
; CHECK-NEXT: [[_MSCMP:%.*]] = icmp ne i128 [[TMP2]], 0
170+
; CHECK-NEXT: br i1 [[_MSCMP]], label [[TMP3:%.*]], label [[TMP4:%.*]], !prof [[PROF1]]
171+
; CHECK: 3:
172+
; CHECK-NEXT: call void @__msan_warning_noreturn() #[[ATTR3]]
173+
; CHECK-NEXT: unreachable
174+
; CHECK: 4:
175+
; CHECK-NEXT: [[MINNM:%.*]] = call float @llvm.aarch64.neon.fminnmv.f32.v4f32(<4 x float> [[IN]])
176+
; CHECK-NEXT: store i32 0, ptr @__msan_retval_tls, align 8
177+
; CHECK-NEXT: ret float [[MINNM]]
178+
;
179+
%minnm = call float @llvm.aarch64.neon.fminnmv.f32.v4f32(<4 x float> %in)
180+
ret float %minnm
181+
}
182+
183+
define double @test_fminnmv_v2f64(<2 x double> %in) #0 {
184+
; CHECK-LABEL: define double @test_fminnmv_v2f64(
185+
; CHECK-SAME: <2 x double> [[IN:%.*]]) #[[ATTR0]] {
186+
; CHECK-NEXT: [[TMP1:%.*]] = load <2 x i64>, ptr @__msan_param_tls, align 8
187+
; CHECK-NEXT: call void @llvm.donothing()
188+
; CHECK-NEXT: [[TMP2:%.*]] = bitcast <2 x i64> [[TMP1]] to i128
189+
; CHECK-NEXT: [[_MSCMP:%.*]] = icmp ne i128 [[TMP2]], 0
190+
; CHECK-NEXT: br i1 [[_MSCMP]], label [[TMP3:%.*]], label [[TMP4:%.*]], !prof [[PROF1]]
191+
; CHECK: 3:
192+
; CHECK-NEXT: call void @__msan_warning_noreturn() #[[ATTR3]]
193+
; CHECK-NEXT: unreachable
194+
; CHECK: 4:
195+
; CHECK-NEXT: [[MINNM:%.*]] = call double @llvm.aarch64.neon.fminnmv.f64.v2f64(<2 x double> [[IN]])
196+
; CHECK-NEXT: store i64 0, ptr @__msan_retval_tls, align 8
197+
; CHECK-NEXT: ret double [[MINNM]]
198+
;
199+
%minnm = call double @llvm.aarch64.neon.fminnmv.f64.v2f64(<2 x double> %in)
200+
ret double %minnm
201+
}
202+
203+
declare float @llvm.aarch64.neon.fminnmv.f32.v2f32(<2 x float>)
204+
declare float @llvm.aarch64.neon.fminnmv.f32.v4f32(<4 x float>)
205+
declare double @llvm.aarch64.neon.fminnmv.f64.v2f64(<2 x double>)
206+
207+
define float @test_fmaxnmv_v2f32(<2 x float> %in) #0 {
208+
; CHECK-LABEL: define float @test_fmaxnmv_v2f32(
209+
; CHECK-SAME: <2 x float> [[IN:%.*]]) #[[ATTR0]] {
210+
; CHECK-NEXT: [[TMP1:%.*]] = load <2 x i32>, ptr @__msan_param_tls, align 8
211+
; CHECK-NEXT: call void @llvm.donothing()
212+
; CHECK-NEXT: [[TMP2:%.*]] = bitcast <2 x i32> [[TMP1]] to i64
213+
; CHECK-NEXT: [[_MSCMP:%.*]] = icmp ne i64 [[TMP2]], 0
214+
; CHECK-NEXT: br i1 [[_MSCMP]], label [[TMP3:%.*]], label [[TMP4:%.*]], !prof [[PROF1]]
215+
; CHECK: 3:
216+
; CHECK-NEXT: call void @__msan_warning_noreturn() #[[ATTR3]]
217+
; CHECK-NEXT: unreachable
218+
; CHECK: 4:
219+
; CHECK-NEXT: [[MAXNM:%.*]] = call float @llvm.aarch64.neon.fmaxnmv.f32.v2f32(<2 x float> [[IN]])
220+
; CHECK-NEXT: store i32 0, ptr @__msan_retval_tls, align 8
221+
; CHECK-NEXT: ret float [[MAXNM]]
222+
;
223+
%maxnm = call float @llvm.aarch64.neon.fmaxnmv.f32.v2f32(<2 x float> %in)
224+
ret float %maxnm
225+
}
226+
227+
define float @test_fmaxnmv_v4f32(<4 x float> %in) #0 {
228+
; CHECK-LABEL: define float @test_fmaxnmv_v4f32(
229+
; CHECK-SAME: <4 x float> [[IN:%.*]]) #[[ATTR0]] {
230+
; CHECK-NEXT: [[TMP1:%.*]] = load <4 x i32>, ptr @__msan_param_tls, align 8
231+
; CHECK-NEXT: call void @llvm.donothing()
232+
; CHECK-NEXT: [[TMP2:%.*]] = bitcast <4 x i32> [[TMP1]] to i128
233+
; CHECK-NEXT: [[_MSCMP:%.*]] = icmp ne i128 [[TMP2]], 0
234+
; CHECK-NEXT: br i1 [[_MSCMP]], label [[TMP3:%.*]], label [[TMP4:%.*]], !prof [[PROF1]]
235+
; CHECK: 3:
236+
; CHECK-NEXT: call void @__msan_warning_noreturn() #[[ATTR3]]
237+
; CHECK-NEXT: unreachable
238+
; CHECK: 4:
239+
; CHECK-NEXT: [[MAXNM:%.*]] = call float @llvm.aarch64.neon.fmaxnmv.f32.v4f32(<4 x float> [[IN]])
240+
; CHECK-NEXT: store i32 0, ptr @__msan_retval_tls, align 8
241+
; CHECK-NEXT: ret float [[MAXNM]]
242+
;
243+
%maxnm = call float @llvm.aarch64.neon.fmaxnmv.f32.v4f32(<4 x float> %in)
244+
ret float %maxnm
245+
}
246+
247+
define double @test_fmaxnmv_v2f64(<2 x double> %in) #0 {
248+
; CHECK-LABEL: define double @test_fmaxnmv_v2f64(
249+
; CHECK-SAME: <2 x double> [[IN:%.*]]) #[[ATTR0]] {
250+
; CHECK-NEXT: [[TMP1:%.*]] = load <2 x i64>, ptr @__msan_param_tls, align 8
251+
; CHECK-NEXT: call void @llvm.donothing()
252+
; CHECK-NEXT: [[TMP2:%.*]] = bitcast <2 x i64> [[TMP1]] to i128
253+
; CHECK-NEXT: [[_MSCMP:%.*]] = icmp ne i128 [[TMP2]], 0
254+
; CHECK-NEXT: br i1 [[_MSCMP]], label [[TMP3:%.*]], label [[TMP4:%.*]], !prof [[PROF1]]
255+
; CHECK: 3:
256+
; CHECK-NEXT: call void @__msan_warning_noreturn() #[[ATTR3]]
257+
; CHECK-NEXT: unreachable
258+
; CHECK: 4:
259+
; CHECK-NEXT: [[MAXNM:%.*]] = call double @llvm.aarch64.neon.fmaxnmv.f64.v2f64(<2 x double> [[IN]])
260+
; CHECK-NEXT: store i64 0, ptr @__msan_retval_tls, align 8
261+
; CHECK-NEXT: ret double [[MAXNM]]
262+
;
263+
%maxnm = call double @llvm.aarch64.neon.fmaxnmv.f64.v2f64(<2 x double> %in)
264+
ret double %maxnm
265+
}
266+
267+
declare float @llvm.aarch64.neon.fmaxnmv.f32.v2f32(<2 x float>)
268+
declare float @llvm.aarch64.neon.fmaxnmv.f32.v4f32(<4 x float>)
269+
declare double @llvm.aarch64.neon.fmaxnmv.f64.v2f64(<2 x double>)
270+
271+
attributes #0 = { sanitize_memory }
272+
;.
273+
; CHECK: [[PROF1]] = !{!"branch_weights", i32 1, i32 1048575}
274+
;.

0 commit comments

Comments
 (0)