[llvm-commits] [llvm] r168876 - /llvm/trunk/lib/Transforms/Instrumentation/MemorySanitizer.cpp

Evgeniy Stepanov eugeni.stepanov at gmail.com
Thu Nov 29 04:49:04 PST 2012


Author: eugenis
Date: Thu Nov 29 06:49:04 2012
New Revision: 168876

URL: http://llvm.org/viewvc/llvm-project?rev=168876&view=rev
Log:
[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.

Modified:
    llvm/trunk/lib/Transforms/Instrumentation/MemorySanitizer.cpp

Modified: llvm/trunk/lib/Transforms/Instrumentation/MemorySanitizer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Instrumentation/MemorySanitizer.cpp?rev=168876&r1=168875&r2=168876&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Instrumentation/MemorySanitizer.cpp (original)
+++ llvm/trunk/lib/Transforms/Instrumentation/MemorySanitizer.cpp Thu Nov 29 06:49:04 2012
@@ -170,8 +170,8 @@
   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 @@
   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 @@
   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<PointerType>(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 @@
   /// 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 @@
     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);
   }





More information about the llvm-commits mailing list