158
158
#include " llvm/ADT/SmallVector.h"
159
159
#include " llvm/ADT/StringExtras.h"
160
160
#include " llvm/ADT/StringRef.h"
161
+ #include " llvm/ADT/bit.h"
161
162
#include " llvm/Analysis/GlobalsModRef.h"
162
163
#include " llvm/Analysis/TargetLibraryInfo.h"
163
164
#include " llvm/Analysis/ValueTracking.h"
@@ -4272,6 +4273,25 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
4272
4273
setOrigin (&I, PtrSrcOrigin);
4273
4274
}
4274
4275
4276
+ void maskedCheckAVXIndexShadow (IRBuilder<> &IRB, Value *Idx, Instruction *I) {
4277
+ auto IdxVectorSize =
4278
+ cast<FixedVectorType>(Idx->getType ())->getNumElements ();
4279
+ assert (isPowerOf2_64 (IdxVectorSize));
4280
+ auto *IdxVectorElemType =
4281
+ cast<FixedVectorType>(Idx->getType ())->getElementType ();
4282
+ Constant *IndexBits =
4283
+ ConstantInt::get (IdxVectorElemType, IdxVectorSize - 1 );
4284
+ auto *IdxShadow = getShadow (Idx);
4285
+ // Only the low bits of Idx are used.
4286
+ Value *V = nullptr ;
4287
+ for (size_t i = 0 ; i < IdxVectorSize; ++i) {
4288
+ V = IRB.CreateExtractElement (IdxShadow, i);
4289
+ assert (V->getType () == IndexBits->getType ());
4290
+ V = IRB.CreateOr (V, IRB.CreateAnd (V, IndexBits));
4291
+ }
4292
+ insertShadowCheck (V, getOrigin (Idx), I);
4293
+ }
4294
+
4275
4295
// Instrument AVX permutation intrinsic.
4276
4296
// We apply the same permutation (argument index 1) to the shadow.
4277
4297
void handleAVXVpermilvar (IntrinsicInst &I) {
@@ -4289,6 +4309,39 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
4289
4309
setOriginForNaryOp (I);
4290
4310
}
4291
4311
4312
+ // Instrument AVX permutation intrinsic.
4313
+ // We apply the same permutation (argument index 1) to the shadows.
4314
+ void handleAVXVpermi2var (IntrinsicInst &I) {
4315
+ assert (I.arg_size () == 3 );
4316
+ assert (isa<FixedVectorType>(I.getArgOperand (0 )->getType ()));
4317
+ assert (isa<FixedVectorType>(I.getArgOperand (1 )->getType ()));
4318
+ assert (isa<FixedVectorType>(I.getArgOperand (2 )->getType ()));
4319
+ [[maybe_unused]] auto ArgVectorSize =
4320
+ cast<FixedVectorType>(I.getArgOperand (0 )->getType ())->getNumElements ();
4321
+ assert (cast<FixedVectorType>(I.getArgOperand (1 )->getType ())
4322
+ ->getNumElements () == ArgVectorSize);
4323
+ assert (cast<FixedVectorType>(I.getArgOperand (2 )->getType ())
4324
+ ->getNumElements () == ArgVectorSize);
4325
+ assert (I.getArgOperand (0 )->getType () == I.getArgOperand (2 )->getType ());
4326
+ assert (I.getType () == I.getArgOperand (0 )->getType ());
4327
+ assert (I.getArgOperand (1 )->getType ()->isIntOrIntVectorTy ());
4328
+ IRBuilder<> IRB (&I);
4329
+ Value *AShadow = getShadow (&I, 0 );
4330
+ Value *Idx = I.getArgOperand (1 );
4331
+ Value *BShadow = getShadow (&I, 2 );
4332
+
4333
+ maskedCheckAVXIndexShadow (IRB, Idx, &I);
4334
+
4335
+ // Shadows are integer-ish types but some intrinsics require a
4336
+ // different (e.g., floating-point) type.
4337
+ AShadow = IRB.CreateBitCast (AShadow, I.getArgOperand (0 )->getType ());
4338
+ BShadow = IRB.CreateBitCast (BShadow, I.getArgOperand (2 )->getType ());
4339
+ CallInst *CI = IRB.CreateIntrinsic (I.getType (), I.getIntrinsicID (),
4340
+ {AShadow, Idx, BShadow});
4341
+ setShadow (&I, IRB.CreateBitCast (CI, getShadowTy (&I)));
4342
+ setOriginForNaryOp (I);
4343
+ }
4344
+
4292
4345
// Instrument BMI / BMI2 intrinsics.
4293
4346
// All of these intrinsics are Z = I(X, Y)
4294
4347
// where the types of all operands and the result match, and are either i32 or
@@ -5244,6 +5297,27 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
5244
5297
break ;
5245
5298
}
5246
5299
5300
+ case Intrinsic::x86_avx512_vpermi2var_d_128:
5301
+ case Intrinsic::x86_avx512_vpermi2var_d_256:
5302
+ case Intrinsic::x86_avx512_vpermi2var_d_512:
5303
+ case Intrinsic::x86_avx512_vpermi2var_hi_128:
5304
+ case Intrinsic::x86_avx512_vpermi2var_hi_256:
5305
+ case Intrinsic::x86_avx512_vpermi2var_hi_512:
5306
+ case Intrinsic::x86_avx512_vpermi2var_pd_128:
5307
+ case Intrinsic::x86_avx512_vpermi2var_pd_256:
5308
+ case Intrinsic::x86_avx512_vpermi2var_pd_512:
5309
+ case Intrinsic::x86_avx512_vpermi2var_ps_128:
5310
+ case Intrinsic::x86_avx512_vpermi2var_ps_256:
5311
+ case Intrinsic::x86_avx512_vpermi2var_ps_512:
5312
+ case Intrinsic::x86_avx512_vpermi2var_q_128:
5313
+ case Intrinsic::x86_avx512_vpermi2var_q_256:
5314
+ case Intrinsic::x86_avx512_vpermi2var_q_512:
5315
+ case Intrinsic::x86_avx512_vpermi2var_qi_128:
5316
+ case Intrinsic::x86_avx512_vpermi2var_qi_256:
5317
+ case Intrinsic::x86_avx512_vpermi2var_qi_512:
5318
+ handleAVXVpermi2var (I);
5319
+ break ;
5320
+
5247
5321
case Intrinsic::x86_avx512fp16_mask_add_sh_round:
5248
5322
case Intrinsic::x86_avx512fp16_mask_sub_sh_round:
5249
5323
case Intrinsic::x86_avx512fp16_mask_mul_sh_round:
0 commit comments