@@ -4312,6 +4312,69 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
4312
4312
setOriginForNaryOp (I);
4313
4313
}
4314
4314
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
+
4315
4378
// Handle Arm NEON vector load intrinsics (vld*).
4316
4379
//
4317
4380
// The WithLane instructions (ld[234]lane) are similar to:
@@ -5041,6 +5104,16 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
5041
5104
break ;
5042
5105
}
5043
5106
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
+
5044
5117
case Intrinsic::fshl:
5045
5118
case Intrinsic::fshr:
5046
5119
handleFunnelShift (I);
0 commit comments