Skip to content

Commit c9446ff

Browse files
authored
[msan] Handle Arm NEON floating-point min/max (vector) (llvm#125778)
Apply handleVectorReduceIntrinsic() to Intrinsic::aarch64_neon_f{min,max}(mn)?v. Previously, these intrinsics were handled correctly (by maybeHandleSimpleNomemIntrinsic) if each parameter's type was the same as the return type; otherwise, they were handled suboptimally by visitInstruction(). Updates the tests from llvm#125729.
1 parent de5f643 commit c9446ff

File tree

2 files changed

+31
-105
lines changed

2 files changed

+31
-105
lines changed

llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4387,6 +4387,13 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
43874387
case Intrinsic::aarch64_neon_faddv:
43884388
case Intrinsic::aarch64_neon_saddv:
43894389
case Intrinsic::aarch64_neon_uaddv:
4390+
// Floating-point min/max (vector)
4391+
// The f{min,max}"nm"v variants handle NaN differently than f{min,max}v,
4392+
// but our shadow propagation is the same.
4393+
case Intrinsic::aarch64_neon_fmaxv:
4394+
case Intrinsic::aarch64_neon_fminv:
4395+
case Intrinsic::aarch64_neon_fmaxnmv:
4396+
case Intrinsic::aarch64_neon_fminnmv:
43904397
handleVectorReduceIntrinsic(I);
43914398
break;
43924399
case Intrinsic::vector_reduce_fadd:

llvm/test/Instrumentation/MemorySanitizer/AArch64/arm64-fminv.ll

Lines changed: 24 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,6 @@
22
; RUN: opt < %s -passes=msan -S | FileCheck %s
33
;
44
; 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
115

126
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
137
target triple = "aarch64--linux-android9001"
@@ -17,15 +11,9 @@ define float @test_fminv_v2f32(<2 x float> %in) #0 {
1711
; CHECK-SAME: <2 x float> [[IN:%.*]]) #[[ATTR0:[0-9]+]] {
1812
; CHECK-NEXT: [[TMP1:%.*]] = load <2 x i32>, ptr @__msan_param_tls, align 8
1913
; 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:
14+
; CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.vector.reduce.or.v2i32(<2 x i32> [[TMP1]])
2715
; 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
16+
; CHECK-NEXT: store i32 [[TMP2]], ptr @__msan_retval_tls, align 8
2917
; CHECK-NEXT: ret float [[MIN]]
3018
;
3119
%min = call float @llvm.aarch64.neon.fminv.f32.v2f32(<2 x float> %in)
@@ -37,15 +25,9 @@ define float @test_fminv_v4f32(<4 x float> %in) #0 {
3725
; CHECK-SAME: <4 x float> [[IN:%.*]]) #[[ATTR0]] {
3826
; CHECK-NEXT: [[TMP1:%.*]] = load <4 x i32>, ptr @__msan_param_tls, align 8
3927
; 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:
28+
; CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.vector.reduce.or.v4i32(<4 x i32> [[TMP1]])
4729
; 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
30+
; CHECK-NEXT: store i32 [[TMP2]], ptr @__msan_retval_tls, align 8
4931
; CHECK-NEXT: ret float [[MIN]]
5032
;
5133
%min = call float @llvm.aarch64.neon.fminv.f32.v4f32(<4 x float> %in)
@@ -57,15 +39,9 @@ define double @test_fminv_v2f64(<2 x double> %in) #0 {
5739
; CHECK-SAME: <2 x double> [[IN:%.*]]) #[[ATTR0]] {
5840
; CHECK-NEXT: [[TMP1:%.*]] = load <2 x i64>, ptr @__msan_param_tls, align 8
5941
; 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:
42+
; CHECK-NEXT: [[TMP2:%.*]] = call i64 @llvm.vector.reduce.or.v2i64(<2 x i64> [[TMP1]])
6743
; 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
44+
; CHECK-NEXT: store i64 [[TMP2]], ptr @__msan_retval_tls, align 8
6945
; CHECK-NEXT: ret double [[MIN]]
7046
;
7147
%min = call double @llvm.aarch64.neon.fminv.f64.v2f64(<2 x double> %in)
@@ -81,15 +57,9 @@ define float @test_fmaxv_v2f32(<2 x float> %in) #0 {
8157
; CHECK-SAME: <2 x float> [[IN:%.*]]) #[[ATTR0]] {
8258
; CHECK-NEXT: [[TMP1:%.*]] = load <2 x i32>, ptr @__msan_param_tls, align 8
8359
; 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:
60+
; CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.vector.reduce.or.v2i32(<2 x i32> [[TMP1]])
9161
; 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
62+
; CHECK-NEXT: store i32 [[TMP2]], ptr @__msan_retval_tls, align 8
9363
; CHECK-NEXT: ret float [[MAX]]
9464
;
9565
%max = call float @llvm.aarch64.neon.fmaxv.f32.v2f32(<2 x float> %in)
@@ -101,15 +71,9 @@ define float @test_fmaxv_v4f32(<4 x float> %in) #0 {
10171
; CHECK-SAME: <4 x float> [[IN:%.*]]) #[[ATTR0]] {
10272
; CHECK-NEXT: [[TMP1:%.*]] = load <4 x i32>, ptr @__msan_param_tls, align 8
10373
; 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:
74+
; CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.vector.reduce.or.v4i32(<4 x i32> [[TMP1]])
11175
; 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
76+
; CHECK-NEXT: store i32 [[TMP2]], ptr @__msan_retval_tls, align 8
11377
; CHECK-NEXT: ret float [[MAX]]
11478
;
11579
%max = call float @llvm.aarch64.neon.fmaxv.f32.v4f32(<4 x float> %in)
@@ -121,15 +85,9 @@ define double @test_fmaxv_v2f64(<2 x double> %shareholder_value) #0 {
12185
; CHECK-SAME: <2 x double> [[SHAREHOLDER_VALUE:%.*]]) #[[ATTR0]] {
12286
; CHECK-NEXT: [[TMP1:%.*]] = load <2 x i64>, ptr @__msan_param_tls, align 8
12387
; 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:
88+
; CHECK-NEXT: [[TMP2:%.*]] = call i64 @llvm.vector.reduce.or.v2i64(<2 x i64> [[TMP1]])
13189
; 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
90+
; CHECK-NEXT: store i64 [[TMP2]], ptr @__msan_retval_tls, align 8
13391
; CHECK-NEXT: ret double [[MAX]]
13492
;
13593
%max_sv = call double @llvm.aarch64.neon.fmaxv.f64.v2f64(<2 x double> %shareholder_value)
@@ -145,15 +103,9 @@ define float @test_fminnmv_v2f32(<2 x float> %in) #0 {
145103
; CHECK-SAME: <2 x float> [[IN:%.*]]) #[[ATTR0]] {
146104
; CHECK-NEXT: [[TMP1:%.*]] = load <2 x i32>, ptr @__msan_param_tls, align 8
147105
; 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:
106+
; CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.vector.reduce.or.v2i32(<2 x i32> [[TMP1]])
155107
; 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
108+
; CHECK-NEXT: store i32 [[TMP2]], ptr @__msan_retval_tls, align 8
157109
; CHECK-NEXT: ret float [[MINNM]]
158110
;
159111
%minnm = call float @llvm.aarch64.neon.fminnmv.f32.v2f32(<2 x float> %in)
@@ -165,15 +117,9 @@ define float @test_fminnmv_v4f32(<4 x float> %in) #0 {
165117
; CHECK-SAME: <4 x float> [[IN:%.*]]) #[[ATTR0]] {
166118
; CHECK-NEXT: [[TMP1:%.*]] = load <4 x i32>, ptr @__msan_param_tls, align 8
167119
; 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:
120+
; CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.vector.reduce.or.v4i32(<4 x i32> [[TMP1]])
175121
; 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
122+
; CHECK-NEXT: store i32 [[TMP2]], ptr @__msan_retval_tls, align 8
177123
; CHECK-NEXT: ret float [[MINNM]]
178124
;
179125
%minnm = call float @llvm.aarch64.neon.fminnmv.f32.v4f32(<4 x float> %in)
@@ -185,15 +131,9 @@ define double @test_fminnmv_v2f64(<2 x double> %in) #0 {
185131
; CHECK-SAME: <2 x double> [[IN:%.*]]) #[[ATTR0]] {
186132
; CHECK-NEXT: [[TMP1:%.*]] = load <2 x i64>, ptr @__msan_param_tls, align 8
187133
; 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:
134+
; CHECK-NEXT: [[TMP2:%.*]] = call i64 @llvm.vector.reduce.or.v2i64(<2 x i64> [[TMP1]])
195135
; 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
136+
; CHECK-NEXT: store i64 [[TMP2]], ptr @__msan_retval_tls, align 8
197137
; CHECK-NEXT: ret double [[MINNM]]
198138
;
199139
%minnm = call double @llvm.aarch64.neon.fminnmv.f64.v2f64(<2 x double> %in)
@@ -209,15 +149,9 @@ define float @test_fmaxnmv_v2f32(<2 x float> %in) #0 {
209149
; CHECK-SAME: <2 x float> [[IN:%.*]]) #[[ATTR0]] {
210150
; CHECK-NEXT: [[TMP1:%.*]] = load <2 x i32>, ptr @__msan_param_tls, align 8
211151
; 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:
152+
; CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.vector.reduce.or.v2i32(<2 x i32> [[TMP1]])
219153
; 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
154+
; CHECK-NEXT: store i32 [[TMP2]], ptr @__msan_retval_tls, align 8
221155
; CHECK-NEXT: ret float [[MAXNM]]
222156
;
223157
%maxnm = call float @llvm.aarch64.neon.fmaxnmv.f32.v2f32(<2 x float> %in)
@@ -229,15 +163,9 @@ define float @test_fmaxnmv_v4f32(<4 x float> %in) #0 {
229163
; CHECK-SAME: <4 x float> [[IN:%.*]]) #[[ATTR0]] {
230164
; CHECK-NEXT: [[TMP1:%.*]] = load <4 x i32>, ptr @__msan_param_tls, align 8
231165
; 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:
166+
; CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.vector.reduce.or.v4i32(<4 x i32> [[TMP1]])
239167
; 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
168+
; CHECK-NEXT: store i32 [[TMP2]], ptr @__msan_retval_tls, align 8
241169
; CHECK-NEXT: ret float [[MAXNM]]
242170
;
243171
%maxnm = call float @llvm.aarch64.neon.fmaxnmv.f32.v4f32(<4 x float> %in)
@@ -249,15 +177,9 @@ define double @test_fmaxnmv_v2f64(<2 x double> %in) #0 {
249177
; CHECK-SAME: <2 x double> [[IN:%.*]]) #[[ATTR0]] {
250178
; CHECK-NEXT: [[TMP1:%.*]] = load <2 x i64>, ptr @__msan_param_tls, align 8
251179
; 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:
180+
; CHECK-NEXT: [[TMP2:%.*]] = call i64 @llvm.vector.reduce.or.v2i64(<2 x i64> [[TMP1]])
259181
; 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
182+
; CHECK-NEXT: store i64 [[TMP2]], ptr @__msan_retval_tls, align 8
261183
; CHECK-NEXT: ret double [[MAXNM]]
262184
;
263185
%maxnm = call double @llvm.aarch64.neon.fmaxnmv.f64.v2f64(<2 x double> %in)
@@ -269,6 +191,3 @@ declare float @llvm.aarch64.neon.fmaxnmv.f32.v4f32(<4 x float>)
269191
declare double @llvm.aarch64.neon.fmaxnmv.f64.v2f64(<2 x double>)
270192

271193
attributes #0 = { sanitize_memory }
272-
;.
273-
; CHECK: [[PROF1]] = !{!"branch_weights", i32 1, i32 1048575}
274-
;.

0 commit comments

Comments
 (0)