Skip to content

Commit 0032148

Browse files
authored
[MSAN] handle permi2var (#146437)
1 parent 778f60d commit 0032148

File tree

5 files changed

+2852
-536
lines changed

5 files changed

+2852
-536
lines changed

llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@
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

Comments
 (0)