diff options
author | Evgenii Stepanov <eugenis@google.com> | 2020-01-24 11:08:49 -0800 |
---|---|---|
committer | Hans Wennborg <hans@chromium.org> | 2020-01-27 15:17:30 +0100 |
commit | f234f5c2b1ed6486fe578744fe673912ef68b945 (patch) | |
tree | 415661b26bba9a99c8352413d70d9a21081bf1b2 /llvm/lib/Transforms | |
parent | 23d93923900834dd873cde2ea54f7c3a0e071802 (diff) | |
download | bcm5719-llvm-f234f5c2b1ed6486fe578744fe673912ef68b945.tar.gz bcm5719-llvm-f234f5c2b1ed6486fe578744fe673912ef68b945.zip |
[msan] Instrument x86.pclmulqdq* intrinsics.
Summary:
These instructions ignore parts of the input vectors which makes the
default MSan handling too strict and causes false positive reports.
Reviewers: vitalybuka, RKSimon, thakis
Subscribers: hiraditya, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D73374
(cherry picked from commit 1df8549b26892198ddf77dfd627eb9f979d45b7e)
Diffstat (limited to 'llvm/lib/Transforms')
-rw-r--r-- | llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp index 80acab30757..f581142df8f 100644 --- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp @@ -3005,6 +3005,43 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> { setOriginForNaryOp(I); } + Constant *getPclmulMask(IRBuilder<> &IRB, unsigned Width, bool OddElements) { + SmallVector<Constant *, 8> Mask; + for (unsigned X = OddElements ? 1 : 0; X < Width; X += 2) { + Constant *C = ConstantInt::get(IRB.getInt32Ty(), X); + Mask.push_back(C); + Mask.push_back(C); + } + return ConstantVector::get(Mask); + } + + // Instrument pclmul intrinsics. + // These intrinsics operate either on odd or on even elements of the input + // vectors, depending on the constant in the 3rd argument, ignoring the rest. + // Replace the unused elements with copies of the used ones, ex: + // (0, 1, 2, 3) -> (0, 0, 2, 2) (even case) + // or + // (0, 1, 2, 3) -> (1, 1, 3, 3) (odd case) + // and then apply the usual shadow combining logic. + void handlePclmulIntrinsic(IntrinsicInst &I) { + IRBuilder<> IRB(&I); + Type *ShadowTy = getShadowTy(&I); + unsigned Width = I.getArgOperand(0)->getType()->getVectorNumElements(); + assert(isa<ConstantInt>(I.getArgOperand(2)) && + "pclmul 3rd operand must be a constant"); + unsigned Imm = cast<ConstantInt>(I.getArgOperand(2))->getZExtValue(); + Value *Shuf0 = + IRB.CreateShuffleVector(getShadow(&I, 0), UndefValue::get(ShadowTy), + getPclmulMask(IRB, Width, Imm & 0x01)); + Value *Shuf1 = + IRB.CreateShuffleVector(getShadow(&I, 1), UndefValue::get(ShadowTy), + getPclmulMask(IRB, Width, Imm & 0x10)); + ShadowAndOriginCombiner SOC(this, IRB); + SOC.Add(Shuf0, getOrigin(&I, 0)); + SOC.Add(Shuf1, getOrigin(&I, 1)); + SOC.Done(&I); + } + void visitIntrinsicInst(IntrinsicInst &I) { switch (I.getIntrinsicID()) { case Intrinsic::lifetime_start: @@ -3238,6 +3275,12 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> { handleBmiIntrinsic(I); break; + case Intrinsic::x86_pclmulqdq: + case Intrinsic::x86_pclmulqdq_256: + case Intrinsic::x86_pclmulqdq_512: + handlePclmulIntrinsic(I); + break; + case Intrinsic::is_constant: // The result of llvm.is.constant() is always defined. setShadow(&I, getCleanShadow(&I)); |