Skip to content

Commit d913ea3

Browse files
authored
[msan] Implement support for avx512fp16.mask.{add/sub/mul/div/max/min}.sh.round (#137441)
This adds a handler, visitGenericScalarHalfwordInst, which works for mask.{add/sub/mul/div/max/min}.sh.round. Updates the tests in #136260
1 parent 1fc0a14 commit d913ea3

File tree

2 files changed

+307
-220
lines changed

2 files changed

+307
-220
lines changed

llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp

+73
Original file line numberDiff line numberDiff line change
@@ -4312,6 +4312,69 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
43124312
setOriginForNaryOp(I);
43134313
}
43144314

4315+
Value *extractLowerShadow(IRBuilder<> &IRB, Value *V) {
4316+
assert(isa<FixedVectorType>(V->getType()));
4317+
assert(cast<FixedVectorType>(V->getType())->getNumElements() > 0);
4318+
Value *Shadow = getShadow(V);
4319+
return IRB.CreateExtractElement(Shadow,
4320+
ConstantInt::get(IRB.getInt32Ty(), 0));
4321+
}
4322+
4323+
// For sh.* compiler intrinsics:
4324+
// llvm.x86.avx512fp16.mask.{add/sub/mul/div/max/min}.sh.round
4325+
// (<8 x half>, <8 x half>, <8 x half>, i8, i32)
4326+
// A B WriteThru Mask RoundingMode
4327+
//
4328+
// DstShadow[0] = Mask[0] ? (AShadow[0] | BShadow[0]) : WriteThruShadow[0]
4329+
// DstShadow[1..7] = AShadow[1..7]
4330+
void visitGenericScalarHalfwordInst(IntrinsicInst &I) {
4331+
IRBuilder<> IRB(&I);
4332+
4333+
assert(I.arg_size() == 5);
4334+
Value *A = I.getOperand(0);
4335+
Value *B = I.getOperand(1);
4336+
Value *WriteThrough = I.getOperand(2);
4337+
Value *Mask = I.getOperand(3);
4338+
Value *RoundingMode = I.getOperand(4);
4339+
4340+
// Technically, we could probably just check whether the LSB is
4341+
// initialized, but intuitively it feels like a partly uninitialized mask
4342+
// is unintended, and we should warn the user immediately.
4343+
insertShadowCheck(Mask, &I);
4344+
insertShadowCheck(RoundingMode, &I);
4345+
4346+
assert(isa<FixedVectorType>(A->getType()));
4347+
unsigned NumElements =
4348+
cast<FixedVectorType>(A->getType())->getNumElements();
4349+
assert(NumElements == 8);
4350+
assert(A->getType() == B->getType());
4351+
assert(B->getType() == WriteThrough->getType());
4352+
assert(Mask->getType()->getPrimitiveSizeInBits() == NumElements);
4353+
assert(RoundingMode->getType()->isIntegerTy());
4354+
4355+
Value *ALowerShadow = extractLowerShadow(IRB, A);
4356+
Value *BLowerShadow = extractLowerShadow(IRB, B);
4357+
4358+
Value *ABLowerShadow = IRB.CreateOr(ALowerShadow, BLowerShadow);
4359+
4360+
Value *WriteThroughLowerShadow = extractLowerShadow(IRB, WriteThrough);
4361+
4362+
Mask = IRB.CreateBitCast(
4363+
Mask, FixedVectorType::get(IRB.getInt1Ty(), NumElements));
4364+
Value *MaskLower =
4365+
IRB.CreateExtractElement(Mask, ConstantInt::get(IRB.getInt32Ty(), 0));
4366+
4367+
Value *AShadow = getShadow(A);
4368+
Value *DstLowerShadow =
4369+
IRB.CreateSelect(MaskLower, ABLowerShadow, WriteThroughLowerShadow);
4370+
Value *DstShadow = IRB.CreateInsertElement(
4371+
AShadow, DstLowerShadow, ConstantInt::get(IRB.getInt32Ty(), 0),
4372+
"_msprop");
4373+
4374+
setShadow(&I, DstShadow);
4375+
setOriginForNaryOp(I);
4376+
}
4377+
43154378
// Handle Arm NEON vector load intrinsics (vld*).
43164379
//
43174380
// The WithLane instructions (ld[234]lane) are similar to:
@@ -5041,6 +5104,16 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
50415104
break;
50425105
}
50435106

5107+
case Intrinsic::x86_avx512fp16_mask_add_sh_round:
5108+
case Intrinsic::x86_avx512fp16_mask_sub_sh_round:
5109+
case Intrinsic::x86_avx512fp16_mask_mul_sh_round:
5110+
case Intrinsic::x86_avx512fp16_mask_div_sh_round:
5111+
case Intrinsic::x86_avx512fp16_mask_max_sh_round:
5112+
case Intrinsic::x86_avx512fp16_mask_min_sh_round: {
5113+
visitGenericScalarHalfwordInst(I);
5114+
break;
5115+
}
5116+
50445117
case Intrinsic::fshl:
50455118
case Intrinsic::fshr:
50465119
handleFunnelShift(I);

0 commit comments

Comments
 (0)