158158#include " llvm/ADT/SmallVector.h"
159159#include " llvm/ADT/StringExtras.h"
160160#include " llvm/ADT/StringRef.h"
161+ #include " llvm/ADT/bit.h"
161162#include " llvm/Analysis/GlobalsModRef.h"
162163#include " llvm/Analysis/TargetLibraryInfo.h"
163164#include " llvm/Analysis/ValueTracking.h"
@@ -4272,6 +4273,25 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
42724273 setOrigin (&I, PtrSrcOrigin);
42734274 }
42744275
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+
42754295 // Instrument AVX permutation intrinsic.
42764296 // We apply the same permutation (argument index 1) to the shadow.
42774297 void handleAVXVpermilvar (IntrinsicInst &I) {
@@ -4289,6 +4309,39 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
42894309 setOriginForNaryOp (I);
42904310 }
42914311
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+
42924345 // Instrument BMI / BMI2 intrinsics.
42934346 // All of these intrinsics are Z = I(X, Y)
42944347 // where the types of all operands and the result match, and are either i32 or
@@ -5244,6 +5297,27 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
52445297 break ;
52455298 }
52465299
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+
52475321 case Intrinsic::x86_avx512fp16_mask_add_sh_round:
52485322 case Intrinsic::x86_avx512fp16_mask_sub_sh_round:
52495323 case Intrinsic::x86_avx512fp16_mask_mul_sh_round:
0 commit comments