[llvm-commits] [PATCH] [msan] Heuristic handling of unknown intrinsics
Evgeniy Stepanov
eugenis at google.com
Thu Dec 13 06:37:55 PST 2012
A different approach.
Detect and instrument several narrow classes of intrinsics where we have more confidence in what we are doing.
This version adds support for SSE-like loads and stores only. There are FIXMEs for some of the other important classes.
This way the code seems cleaner and more predictable.
Hi kcc, chandlerc,
http://llvm-reviews.chandlerc.com/D184
CHANGE SINCE LAST DIFF
http://llvm-reviews.chandlerc.com/D184?vs=507&id=518#toc
Files:
lib/Transforms/Instrumentation/MemorySanitizer.cpp
test/Instrumentation/MemorySanitizer/msan_basic.ll
Index: lib/Transforms/Instrumentation/MemorySanitizer.cpp
===================================================================
--- lib/Transforms/Instrumentation/MemorySanitizer.cpp
+++ lib/Transforms/Instrumentation/MemorySanitizer.cpp
@@ -1143,6 +1143,104 @@
VAHelper->visitVACopyInst(I);
}
+ enum IntrinsicKind {
+ IK_DoesNotAccessMemory,
+ IK_OnlyReadsMemory,
+ IK_WritesMemory
+ };
+
+ static IntrinsicKind getIntrinsicKind(Intrinsic::ID iid) {
+ const int DoesNotAccessMemory = IK_DoesNotAccessMemory;
+ const int OnlyReadsArgumentPointees = IK_OnlyReadsMemory;
+ const int OnlyReadsMemory = IK_OnlyReadsMemory;
+ const int OnlyAccessesArgumentPointees = IK_WritesMemory;
+ const int UnknownModRefBehavior = IK_WritesMemory;
+#define GET_INTRINSIC_MODREF_BEHAVIOR
+#define ModRefBehavior IntrinsicKind
+#include "llvm/Intrinsics.gen"
+#undef ModRefBehavior
+#undef GET_INTRINSIC_MODREF_BEHAVIOR
+ }
+
+ bool handleVectorStoreIntrinsic(IntrinsicInst &I) {
+ IRBuilder<> IRB(&I);
+ Value* Addr = I.getArgOperand(0);
+ Value *Shadow = getShadow(&I, 1);
+ Value *ShadowPtr = getShadowPtr(Addr, Shadow->getType(), IRB);
+
+ // We don't know the pointer alignment (could be unaligned SSE store!).
+ // Have to assume to worst case.
+ IRB.CreateAlignedStore(Shadow, ShadowPtr, 1);
+
+ if (ClCheckAccessAddress)
+ insertCheck(Addr, &I);
+
+ // FIXME: use ClStoreCleanOrigin
+ // FIXME: factor out common code from materializeStores
+ if (ClTrackOrigins)
+ IRB.CreateStore(getOrigin(&I, 1), getOriginPtr(Addr, IRB));
+ return true;
+ }
+
+ bool handleVectorLoadIntrinsic(IntrinsicInst &I) {
+ IRBuilder<> IRB(&I);
+ Value *Addr = I.getArgOperand(0);
+
+ Type *ShadowTy = getShadowTy(&I);
+ Value *ShadowPtr = getShadowPtr(Addr, ShadowTy, IRB);
+ // We don't know the pointer alignment (could be unaligned SSE load!).
+ // Have to assume to worst case.
+ setShadow(&I, IRB.CreateAlignedLoad(ShadowPtr, 1, "_msld"));
+
+ if (ClCheckAccessAddress)
+ insertCheck(Addr, &I);
+
+ if (ClTrackOrigins)
+ setOrigin(&I, IRB.CreateLoad(getOriginPtr(Addr, IRB)));
+ return true;
+ }
+
+ /// \brief Heuristically instrument unknown intrinsics.
+ ///
+ /// The main purpose of this code is to do something reasonable with all
+ /// random intrinsics we might encounter, most importantly - SIMD intrinsics.
+ /// We recognize several classes of intrinsics by their argument types and
+ /// ModRefBehaviour and apply special intrumentation when we are reasonably
+ /// sure that we know what the intrinsic does.
+ ///
+ /// We special-case intrinsics where this approach fails. See llvm.bswap
+ /// handling as an example of that.
+ bool handleUnknownIntrinsic(IntrinsicInst &I) {
+ if (I.getNumArgOperands() == 0)
+ return false;
+
+ Intrinsic::ID iid = I.getIntrinsicID();
+ IntrinsicKind IK = getIntrinsicKind(iid);
+ bool ReadsMemory = IK == IK_OnlyReadsMemory;
+ bool WritesMemory = IK == IK_WritesMemory;
+
+ if (I.getNumArgOperands() == 2 &&
+ I.getArgOperand(0)->getType()->isPointerTy() &&
+ I.getArgOperand(1)->getType()->isVectorTy() &&
+ I.getType()->isVoidTy() &&
+ WritesMemory) {
+ // This looks like a vector store.
+ return handleVectorStoreIntrinsic(I);
+ }
+
+ if (I.getNumArgOperands() == 1 &&
+ I.getArgOperand(0)->getType()->isPointerTy() &&
+ I.getType()->isVectorTy() &&
+ ReadsMemory) {
+ // This looks like a vector load.
+ return handleVectorLoadIntrinsic(I);
+ }
+
+ // FIXME: detect and handle NoMem, no pointers, vector manipulation SIMD.
+ // FIXME: detect and handle SSE maskstore/maskload
+ return false;
+ }
+
void handleBswap(IntrinsicInst &I) {
IRBuilder<> IRB(&I);
Value *Op = I.getArgOperand(0);
@@ -1158,7 +1256,9 @@
case llvm::Intrinsic::bswap:
handleBswap(I); break;
default:
- visitInstruction(I); break;
+ if (!handleUnknownIntrinsic(I))
+ visitInstruction(I);
+ break;
}
}
Index: test/Instrumentation/MemorySanitizer/msan_basic.ll
===================================================================
--- test/Instrumentation/MemorySanitizer/msan_basic.ll
+++ test/Instrumentation/MemorySanitizer/msan_basic.ll
@@ -1,5 +1,5 @@
-; RUN: opt < %s -msan -S | FileCheck %s
-; RUN: opt < %s -msan -msan-track-origins=1 -S | FileCheck -check-prefix=CHECK-ORIGINS %s
+; RUN: opt < %s -msan -msan-check-access-address=0 -S | FileCheck %s
+; RUN: opt < %s -msan -msan-check-access-address=0 -msan-track-origins=1 -S | FileCheck -check-prefix=CHECK-ORIGINS %s
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
; Check the presence of __msan_init
@@ -378,6 +378,7 @@
; CHECK: shufflevector
; CHECK: ret <4 x i32>
+
; Test bswap intrinsic instrumentation
define i32 @BSwap(i32 %x) nounwind uwtable readnone {
%y = tail call i32 @llvm.bswap.i32(i32 %x)
@@ -393,3 +394,44 @@
; CHECK: @llvm.bswap.i32
; CHECK-NOT: call void @__msan_warning
; CHECK: ret i32
+
+
+; Store intrinsic.
+
+define void @StoreIntrinsic(i8* %p, <4 x float> %x) nounwind uwtable {
+ call void @llvm.x86.sse.storeu.ps(i8* %p, <4 x float> %x)
+ ret void
+}
+
+declare void @llvm.x86.sse.storeu.ps(i8*, <4 x float>) nounwind
+
+; CHECK: @StoreIntrinsic
+; CHECK-NOT: br
+; CHECK-NOT: = or
+; CHECK: store <4 x i32> {{.*}} align 1
+; CHECK: call void @llvm.x86.sse.storeu.ps
+; CHECK: ret void
+
+
+; Load intrinsic.
+
+define <16 x i8> @LoadIntrinsic(i8* %p) nounwind uwtable {
+ %call = call <16 x i8> @llvm.x86.sse3.ldu.dq(i8* %p)
+ ret <16 x i8> %call
+}
+
+declare <16 x i8> @llvm.x86.sse3.ldu.dq(i8* %p) nounwind
+
+; CHECK: @LoadIntrinsic
+; CHECK: load <16 x i8>* {{.*}} align 1
+; CHECK-NOT: br
+; CHECK-NOT: = or
+; CHECK: call <16 x i8> @llvm.x86.sse3.ldu.dq
+; CHECK: store <16 x i8> {{.*}} @__msan_retval_tls
+; CHECK: ret <16 x i8>
+
+; CHECK-ORIGINS: @LoadIntrinsic
+; CHECK-ORIGINS: [[ORIGIN:%[01-9a-z]+]] = load i32* {{.*}}
+; CHECK-ORIGINS: call <16 x i8> @llvm.x86.sse3.ldu.dq
+; CHECK-ORIGINS: store i32 {{.*}}[[ORIGIN]], i32* @__msan_retval_origin_tls
+; CHECK-ORIGINS: ret <16 x i8>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D184.4.patch
Type: text/x-patch
Size: 6331 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20121213/d6e6a2a6/attachment.bin>
More information about the llvm-commits
mailing list