Skip to content

Commit 9132666

Browse files
thurstondgithub-actions[bot]
authored andcommitted
Automerge: [msan] Handle AVX512 fpclass (floating-point classification) for packed double/float (#209652)
Each bit of the classifier constant specifies whether a particular classifier is enabled. If Classifiers == 0 (no classifiers are enabled), the output is trivially known to be zero, thus the output is fully initialized. Otherwise, each bit of the output is the bitwise OR of one or more classifications; we approximate each bit of the output shadow based on whether the corresponding input element is fully initialized (without which the classification is potentially unknown). This is only approximate, because some classifications do not rely on all the bits of the input element. This patch only handles packed double/single-precision floating-point. Handling the scalar equivalents is more complicated because those intrinsics encode a mask.
2 parents 9708449 + ce586b5 commit 9132666

2 files changed

Lines changed: 66 additions & 38 deletions

File tree

llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5292,6 +5292,50 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
52925292
setOriginForNaryOp(I);
52935293
}
52945294

5295+
// AVX512 Floating-Point Classification
5296+
//
5297+
// e.g.,
5298+
// - < 8 x i1> @llvm.x86.avx512.fpclass.pd.512
5299+
// (<8 x double> %input, i32 %classifiers)
5300+
// - <16 x i1> @llvm.x86.avx512.fpclass.ps.512
5301+
// (<16 x float> %input, i32 %classifiers)
5302+
void handleAVX512FPClass(IntrinsicInst &I) {
5303+
IRBuilder<> IRB(&I);
5304+
5305+
assert(I.arg_size() == 2);
5306+
5307+
Value *Input = I.getOperand(0);
5308+
assert(isFixedFPVector(Input));
5309+
FixedVectorType *InputType = cast<FixedVectorType>(Input->getType());
5310+
5311+
Value *Classifiers = I.getOperand(1);
5312+
assert(isa<ConstantInt>(Classifiers));
5313+
// No shadow check needed for constants
5314+
5315+
assert(isFixedIntVectorTy(I.getType()));
5316+
FixedVectorType *OutputType = cast<FixedVectorType>(I.getType());
5317+
assert(OutputType->getScalarSizeInBits() == 1);
5318+
5319+
assert(OutputType->getNumElements() == InputType->getNumElements());
5320+
5321+
Value *OutputShadow;
5322+
if (cast<ConstantInt>(Classifiers)->isZero())
5323+
// Each bit specifies whether a particular classifier is enabled.
5324+
// If Classifiers == 0, the output is trivially known to be zero, thus
5325+
// the output is fully initialized.
5326+
OutputShadow = getCleanShadow(OutputType);
5327+
else
5328+
// Approximate each bit of the output shadow based on whether the
5329+
// corresponding input element is fully initialized. It is only
5330+
// approximate because some classifications do not rely on all bits of
5331+
// the input element.
5332+
OutputShadow = IRB.CreateICmpNE(getShadow(Input), getCleanShadow(Input));
5333+
5334+
setShadow(&I, OutputShadow);
5335+
5336+
setOriginForNaryOp(I);
5337+
}
5338+
52955339
// For sh.* compiler intrinsics:
52965340
// llvm.x86.avx512fp16.mask.{add/sub/mul/div/max/min}.sh.round
52975341
// (<8 x half>, <8 x half>, <8 x half>, i8, i32)
@@ -7138,6 +7182,14 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
71387182
break;
71397183
}
71407184

7185+
// AVX512 Floating-Point Classification
7186+
// - <8 x i1> @llvm.x86.avx512.fpclass.pd.512(<8 x double>, i32)
7187+
// - <16 x i1> @llvm.x86.avx512.fpclass.ps.512(<16 x float>, i32)
7188+
case Intrinsic::x86_avx512_fpclass_pd_512:
7189+
case Intrinsic::x86_avx512_fpclass_ps_512:
7190+
handleAVX512FPClass(I);
7191+
break;
7192+
71417193
// AVX Galois Field New Instructions
71427194
case Intrinsic::x86_vgf2p8affineqb_128:
71437195
case Intrinsic::x86_vgf2p8affineqb_256:

llvm/test/Instrumentation/MemorySanitizer/X86/avx512dq-intrinsics.ll

Lines changed: 14 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@
2020
; (<2 x double>, <2 x double>, <2 x double>, i8, i32, i32)
2121
; - <4 x float> @llvm.x86.avx512.mask.reduce.ss
2222
; (<4 x float>, <4 x float>, <4 x float>, i8, i32, i32)
23-
; - <8 x i1> @llvm.x86.avx512.fpclass.pd.512(<8 x double>, i32)
24-
; - <16 x i1> @llvm.x86.avx512.fpclass.ps.512(<16 x float>, i32)
2523
; - i8 @llvm.x86.avx512.mask.fpclass.sd(<2 x double>, i32, i8)
2624
; - i8 @llvm.x86.avx512.mask.fpclass.ss(<4 x float>, i32, i8)
2725
; - <8 x double> @llvm.x86.avx512.sitofp.round(<8 x i64>, i32)
@@ -1235,28 +1233,17 @@ define i8 @test_int_x86_avx512_fpclass_pd_512(<8 x double> %x0) sanitize_memory
12351233
; CHECK-SAME: <8 x double> [[X0:%.*]]) #[[ATTR2]] {
12361234
; CHECK-NEXT: [[TMP1:%.*]] = load <8 x i64>, ptr @__msan_param_tls, align 8
12371235
; CHECK-NEXT: call void @llvm.donothing()
1238-
; CHECK-NEXT: [[TMP2:%.*]] = bitcast <8 x i64> [[TMP1]] to i512
1239-
; CHECK-NEXT: [[_MSCMP:%.*]] = icmp ne i512 [[TMP2]], 0
1240-
; CHECK-NEXT: br i1 [[_MSCMP]], label %[[BB3:.*]], label %[[BB4:.*]], !prof [[PROF1]]
1241-
; CHECK: [[BB3]]:
1242-
; CHECK-NEXT: call void @__msan_warning_noreturn() #[[ATTR5]]
1243-
; CHECK-NEXT: unreachable
1244-
; CHECK: [[BB4]]:
1236+
; CHECK-NEXT: [[TMP2:%.*]] = icmp ne <8 x i64> [[TMP1]], zeroinitializer
12451237
; CHECK-NEXT: [[RES:%.*]] = call <8 x i1> @llvm.x86.avx512.fpclass.pd.512(<8 x double> [[X0]], i32 4)
1246-
; CHECK-NEXT: [[TMP5:%.*]] = bitcast <8 x i64> [[TMP1]] to i512
1247-
; CHECK-NEXT: [[_MSCMP1:%.*]] = icmp ne i512 [[TMP5]], 0
1248-
; CHECK-NEXT: br i1 [[_MSCMP1]], label %[[BB6:.*]], label %[[BB7:.*]], !prof [[PROF1]]
1249-
; CHECK: [[BB6]]:
1250-
; CHECK-NEXT: call void @__msan_warning_noreturn() #[[ATTR5]]
1251-
; CHECK-NEXT: unreachable
1252-
; CHECK: [[BB7]]:
1238+
; CHECK-NEXT: [[TMP3:%.*]] = icmp ne <8 x i64> [[TMP1]], zeroinitializer
12531239
; CHECK-NEXT: [[RES1:%.*]] = call <8 x i1> @llvm.x86.avx512.fpclass.pd.512(<8 x double> [[X0]], i32 2)
1254-
; CHECK-NEXT: [[TMP8:%.*]] = and <8 x i1> [[RES1]], zeroinitializer
1255-
; CHECK-NEXT: [[TMP9:%.*]] = and <8 x i1> zeroinitializer, [[RES]]
1256-
; CHECK-NEXT: [[TMP10:%.*]] = or <8 x i1> zeroinitializer, [[TMP8]]
1240+
; CHECK-NEXT: [[TMP10:%.*]] = and <8 x i1> [[TMP3]], [[TMP2]]
1241+
; CHECK-NEXT: [[TMP9:%.*]] = and <8 x i1> [[RES1]], [[TMP2]]
1242+
; CHECK-NEXT: [[TMP6:%.*]] = and <8 x i1> [[TMP3]], [[RES]]
12571243
; CHECK-NEXT: [[TMP11:%.*]] = or <8 x i1> [[TMP10]], [[TMP9]]
1244+
; CHECK-NEXT: [[TMP8:%.*]] = or <8 x i1> [[TMP11]], [[TMP6]]
12581245
; CHECK-NEXT: [[TMP12:%.*]] = and <8 x i1> [[RES1]], [[RES]]
1259-
; CHECK-NEXT: [[TMP13:%.*]] = bitcast <8 x i1> [[TMP11]] to i8
1246+
; CHECK-NEXT: [[TMP13:%.*]] = bitcast <8 x i1> [[TMP8]] to i8
12601247
; CHECK-NEXT: [[TMP14:%.*]] = bitcast <8 x i1> [[TMP12]] to i8
12611248
; CHECK-NEXT: store i8 [[TMP13]], ptr @__msan_retval_tls, align 8
12621249
; CHECK-NEXT: ret i8 [[TMP14]]
@@ -1274,28 +1261,17 @@ define i16@test_int_x86_avx512_fpclass_ps_512(<16 x float> %x0) sanitize_memory
12741261
; CHECK-SAME: <16 x float> [[X0:%.*]]) #[[ATTR2]] {
12751262
; CHECK-NEXT: [[TMP1:%.*]] = load <16 x i32>, ptr @__msan_param_tls, align 8
12761263
; CHECK-NEXT: call void @llvm.donothing()
1277-
; CHECK-NEXT: [[TMP2:%.*]] = bitcast <16 x i32> [[TMP1]] to i512
1278-
; CHECK-NEXT: [[_MSCMP:%.*]] = icmp ne i512 [[TMP2]], 0
1279-
; CHECK-NEXT: br i1 [[_MSCMP]], label %[[BB3:.*]], label %[[BB4:.*]], !prof [[PROF1]]
1280-
; CHECK: [[BB3]]:
1281-
; CHECK-NEXT: call void @__msan_warning_noreturn() #[[ATTR5]]
1282-
; CHECK-NEXT: unreachable
1283-
; CHECK: [[BB4]]:
1264+
; CHECK-NEXT: [[TMP2:%.*]] = icmp ne <16 x i32> [[TMP1]], zeroinitializer
12841265
; CHECK-NEXT: [[RES:%.*]] = call <16 x i1> @llvm.x86.avx512.fpclass.ps.512(<16 x float> [[X0]], i32 4)
1285-
; CHECK-NEXT: [[TMP5:%.*]] = bitcast <16 x i32> [[TMP1]] to i512
1286-
; CHECK-NEXT: [[_MSCMP1:%.*]] = icmp ne i512 [[TMP5]], 0
1287-
; CHECK-NEXT: br i1 [[_MSCMP1]], label %[[BB6:.*]], label %[[BB7:.*]], !prof [[PROF1]]
1288-
; CHECK: [[BB6]]:
1289-
; CHECK-NEXT: call void @__msan_warning_noreturn() #[[ATTR5]]
1290-
; CHECK-NEXT: unreachable
1291-
; CHECK: [[BB7]]:
1266+
; CHECK-NEXT: [[TMP3:%.*]] = icmp ne <16 x i32> [[TMP1]], zeroinitializer
12921267
; CHECK-NEXT: [[RES1:%.*]] = call <16 x i1> @llvm.x86.avx512.fpclass.ps.512(<16 x float> [[X0]], i32 2)
1293-
; CHECK-NEXT: [[TMP8:%.*]] = and <16 x i1> [[RES1]], zeroinitializer
1294-
; CHECK-NEXT: [[TMP9:%.*]] = and <16 x i1> zeroinitializer, [[RES]]
1295-
; CHECK-NEXT: [[TMP10:%.*]] = or <16 x i1> zeroinitializer, [[TMP8]]
1268+
; CHECK-NEXT: [[TMP10:%.*]] = and <16 x i1> [[TMP3]], [[TMP2]]
1269+
; CHECK-NEXT: [[TMP9:%.*]] = and <16 x i1> [[RES1]], [[TMP2]]
1270+
; CHECK-NEXT: [[TMP6:%.*]] = and <16 x i1> [[TMP3]], [[RES]]
12961271
; CHECK-NEXT: [[TMP11:%.*]] = or <16 x i1> [[TMP10]], [[TMP9]]
1272+
; CHECK-NEXT: [[TMP8:%.*]] = or <16 x i1> [[TMP11]], [[TMP6]]
12971273
; CHECK-NEXT: [[TMP12:%.*]] = and <16 x i1> [[RES1]], [[RES]]
1298-
; CHECK-NEXT: [[TMP13:%.*]] = bitcast <16 x i1> [[TMP11]] to i16
1274+
; CHECK-NEXT: [[TMP13:%.*]] = bitcast <16 x i1> [[TMP8]] to i16
12991275
; CHECK-NEXT: [[TMP14:%.*]] = bitcast <16 x i1> [[TMP12]] to i16
13001276
; CHECK-NEXT: store i16 [[TMP13]], ptr @__msan_retval_tls, align 8
13011277
; CHECK-NEXT: ret i16 [[TMP14]]

0 commit comments

Comments
 (0)