From 2e815e7cf4f31c53ad64059192e70828d476680e Mon Sep 17 00:00:00 2001 From: Evgeniy Stepanov Date: Thu, 29 Nov 2012 12:49:04 +0000 Subject: [PATCH] [msan] Transform memcpy and memset to library calls. This was already done for memmove, where it is required for correctness. This change improves performance by avoiding copyingthe same memory twice. Also, the library functions are given __msan_ prefix to prevent instcombine pass from converting them back to intrinsics. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@168876 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Instrumentation/MemorySanitizer.cpp | 69 ++++++++++--------- 1 file changed, 35 insertions(+), 34 deletions(-) diff --git a/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/lib/Transforms/Instrumentation/MemorySanitizer.cpp index bc9e709fd47..74334093450 100644 --- a/lib/Transforms/Instrumentation/MemorySanitizer.cpp +++ b/lib/Transforms/Instrumentation/MemorySanitizer.cpp @@ -170,8 +170,8 @@ private: Value *MsanSetAllocaOriginFn; /// \brief Run-time helper that poisons stack on function entry. Value *MsanPoisonStackFn; - /// \brief The actual "memmove" function. - Value *MemmoveFn; + /// \brief MSan runtime replacements for memmove, memcpy and memset. + Value *MemmoveFn, *MemcpyFn, *MemsetFn; /// \brief Address mask used in application-to-shadow address calculation. /// ShadowAddr is computed as ApplicationAddr & ~ShadowMask. @@ -266,7 +266,13 @@ bool MemorySanitizer::doInitialization(Module &M) { MsanPoisonStackFn = M.getOrInsertFunction( "__msan_poison_stack", IRB.getVoidTy(), IRB.getInt8PtrTy(), IntptrTy, NULL); MemmoveFn = M.getOrInsertFunction( - "memmove", IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), + "__msan_memmove", IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), + IntptrTy, NULL); + MemcpyFn = M.getOrInsertFunction( + "__msan_memcpy", IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), + IntptrTy, NULL); + MemsetFn = M.getOrInsertFunction( + "__msan_memset", IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), IRB.getInt32Ty(), IntptrTy, NULL); // Create globals. @@ -969,35 +975,6 @@ struct MemorySanitizerVisitor : public InstVisitor { void visitAShr(BinaryOperator &I) { handleShift(I); } void visitLShr(BinaryOperator &I) { handleShift(I); } - void visitMemSetInst(MemSetInst &I) { - IRBuilder<> IRB(&I); - Value *Ptr = I.getArgOperand(0); - Value *Val = I.getArgOperand(1); - Value *ShadowPtr = getShadowPtr(Ptr, Val->getType(), IRB); - Value *ShadowVal = getCleanShadow(Val); - Value *Size = I.getArgOperand(2); - unsigned Align = I.getAlignment(); - bool isVolatile = I.isVolatile(); - - IRB.CreateMemSet(ShadowPtr, ShadowVal, Size, Align, isVolatile); - } - - void visitMemCpyInst(MemCpyInst &I) { - IRBuilder<> IRB(&I); - Value *Dst = I.getArgOperand(0); - Value *Src = I.getArgOperand(1); - Type *ElementType = dyn_cast(Dst->getType())->getElementType(); - Value *ShadowDst = getShadowPtr(Dst, ElementType, IRB); - Value *ShadowSrc = getShadowPtr(Src, ElementType, IRB); - Value *Size = I.getArgOperand(2); - unsigned Align = I.getAlignment(); - bool isVolatile = I.isVolatile(); - - IRB.CreateMemCpy(ShadowDst, ShadowSrc, Size, Align, isVolatile); - if (ClTrackOrigins) - IRB.CreateCall3(MS.MsanCopyOriginFn, Dst, Src, Size); - } - /// \brief Instrument llvm.memmove /// /// At this point we don't know if llvm.memmove will be inlined or not. @@ -1007,8 +984,7 @@ struct MemorySanitizerVisitor : public InstVisitor { /// we will memove the shadow twice: which is bad in case /// of overlapping regions. So, we simply lower the intrinsic to a call. /// - /// Similar situation exists for memcpy and memset, but for those functions - /// calling instrumentation twice does not lead to incorrect results. + /// Similar situation exists for memcpy and memset. void visitMemMoveInst(MemMoveInst &I) { IRBuilder<> IRB(&I); IRB.CreateCall3( @@ -1019,6 +995,31 @@ struct MemorySanitizerVisitor : public InstVisitor { I.eraseFromParent(); } + // Similar to memmove: avoid copying shadow twice. + // This is somewhat unfortunate as it may slowdown small constant memcpys. + // FIXME: consider doing manual inline for small constant sizes and proper + // alignment. + void visitMemCpyInst(MemCpyInst &I) { + IRBuilder<> IRB(&I); + IRB.CreateCall3( + MS.MemcpyFn, + IRB.CreatePointerCast(I.getArgOperand(0), IRB.getInt8PtrTy()), + IRB.CreatePointerCast(I.getArgOperand(1), IRB.getInt8PtrTy()), + IRB.CreateIntCast(I.getArgOperand(2), MS.IntptrTy, false)); + I.eraseFromParent(); + } + + // Same as memcpy. + void visitMemSetInst(MemSetInst &I) { + IRBuilder<> IRB(&I); + IRB.CreateCall3( + MS.MemsetFn, + IRB.CreatePointerCast(I.getArgOperand(0), IRB.getInt8PtrTy()), + IRB.CreateIntCast(I.getArgOperand(1), IRB.getInt32Ty(), false), + IRB.CreateIntCast(I.getArgOperand(2), MS.IntptrTy, false)); + I.eraseFromParent(); + } + void visitVAStartInst(VAStartInst &I) { VAHelper->visitVAStartInst(I); }