@@ -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