1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 12:41:49 +01:00

[MSAN] Pass Origin by parameter to __msan_warning functions

Summary:
Normally, the Origin is passed over TLS, which seems like it introduces unnecessary overhead. It's in the (extremely) cold path though, so the only overhead is in code size.

But with eager-checks, calls to __msan_warning functions are extremely common, so this becomes a useful optimization.

This can save ~5% code size.

Reviewers: eugenis, vitalybuka

Reviewed By: eugenis, vitalybuka

Subscribers: hiraditya, #sanitizers, llvm-commits

Tags: #sanitizers, #llvm

Differential Revision: https://reviews.llvm.org/D81700
This commit is contained in:
Gui Andrade 2020-06-15 15:17:00 -07:00 committed by Evgenii Stepanov
parent e746ac2167
commit bb38b0a59d
12 changed files with 64 additions and 73 deletions

View File

@ -543,10 +543,6 @@ private:
/// (x86_64-specific).
Value *VAArgOverflowSizeTLS;
/// Thread-local space used to pass origin value to the UMR reporting
/// function.
Value *OriginTLS;
/// Are the instrumentation callbacks set up?
bool CallbacksInitialized = false;
@ -715,10 +711,7 @@ void MemorySanitizer::createKernelApi(Module &M) {
VAArgTLS = nullptr;
VAArgOriginTLS = nullptr;
VAArgOverflowSizeTLS = nullptr;
// OriginTLS is unused in the kernel.
OriginTLS = nullptr;
// __msan_warning() in the kernel takes an origin.
WarningFn = M.getOrInsertFunction("__msan_warning", IRB.getVoidTy(),
IRB.getInt32Ty());
// Requests the per-task context state (kmsan_context_state*) from the
@ -773,12 +766,14 @@ static Constant *getOrInsertGlobal(Module &M, StringRef Name, Type *Ty) {
/// Insert declarations for userspace-specific functions and globals.
void MemorySanitizer::createUserspaceApi(Module &M) {
IRBuilder<> IRB(*C);
// Create the callback.
// FIXME: this function should have "Cold" calling conv,
// which is not yet implemented.
StringRef WarningFnName = Recover ? "__msan_warning"
: "__msan_warning_noreturn";
WarningFn = M.getOrInsertFunction(WarningFnName, IRB.getVoidTy());
StringRef WarningFnName = Recover ? "__msan_warning_with_origin"
: "__msan_warning_with_origin_noreturn";
WarningFn =
M.getOrInsertFunction(WarningFnName, IRB.getVoidTy(), IRB.getInt32Ty());
// Create the global TLS variables.
RetvalTLS =
@ -805,7 +800,6 @@ void MemorySanitizer::createUserspaceApi(Module &M) {
VAArgOverflowSizeTLS =
getOrInsertGlobal(M, "__msan_va_arg_overflow_size_tls", IRB.getInt64Ty());
OriginTLS = getOrInsertGlobal(M, "__msan_origin_tls", IRB.getInt32Ty());
for (size_t AccessSizeIndex = 0; AccessSizeIndex < kNumberOfAccessSizes;
AccessSizeIndex++) {
@ -1216,14 +1210,8 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
void insertWarningFn(IRBuilder<> &IRB, Value *Origin) {
if (!Origin)
Origin = (Value *)IRB.getInt32(0);
if (MS.CompileKernel) {
IRB.CreateCall(MS.WarningFn, Origin);
} else {
if (MS.TrackOrigins) {
IRB.CreateStore(Origin, MS.OriginTLS);
}
IRB.CreateCall(MS.WarningFn, {});
}
assert(Origin->getType()->isIntegerTy());
IRB.CreateCall(MS.WarningFn, Origin);
IRB.CreateCall(MS.EmptyAsm, {});
// FIXME: Insert UnreachableInst if !MS.Recover?
// This may invalidate some of the following checks and needs to be done

View File

@ -54,7 +54,7 @@ entry:
; CHECK: store { i32, i1 } zeroinitializer,
; CHECK: icmp
; CHECK: br
; CHECK: @__msan_warning
; CHECK: @__msan_warning_with_origin
; CHECK: cmpxchg {{.*}} seq_cst seq_cst
; CHECK: store i32 0, {{.*}} @__msan_retval_tls
; CHECK: ret i32
@ -73,7 +73,7 @@ entry:
; CHECK: store { i32, i1 } zeroinitializer,
; CHECK: icmp
; CHECK: br
; CHECK: @__msan_warning
; CHECK: @__msan_warning_with_origin
; CHECK: cmpxchg {{.*}} release monotonic
; CHECK: store i32 0, {{.*}} @__msan_retval_tls
; CHECK: ret i32

View File

@ -14,7 +14,7 @@ entry:
}
; CHECK-LABEL: @main
; CHECK: call void @__msan_warning_noreturn
; CHECK: call void @__msan_warning_with_origin_noreturn
; CHECK: ret i32 undef

View File

@ -45,7 +45,7 @@ entry:
; CHECK: icmp
; CHECK: br i1
; CHECK: {{^[0-9]+}}:
; CHECK: call void @__msan_warning_noreturn
; CHECK: call void @__msan_warning_with_origin_noreturn
; CHECK: {{^[0-9]+}}:
; CHECK: xor
; CHECK: store

View File

@ -28,7 +28,7 @@ entry:
; ADDR: %[[A:.*]] = load i64, i64* getelementptr inbounds {{.*}} @__msan_param_tls, i32 0, i32 0), align 8
; ADDR: %[[B:.*]] = icmp ne i64 %[[A]], 0
; ADDR: br i1 %[[B]], label {{.*}}, label
; ADDR: call void @__msan_warning_noreturn()
; ADDR: call void @__msan_warning_with_origin_noreturn(i32 0)
; ADDR: call void @llvm.x86.sse.stmxcsr(
; ADDR: ret void
@ -44,7 +44,7 @@ entry:
; CHECK: %[[A:.*]] = load i32, i32* %{{.*}}, align 1
; CHECK: %[[B:.*]] = icmp ne i32 %[[A]], 0
; CHECK: br i1 %[[B]], label {{.*}}, label
; CHECK: call void @__msan_warning_noreturn()
; CHECK: call void @__msan_warning_with_origin_noreturn(i32 0)
; CHECK: call void @llvm.x86.sse.ldmxcsr(
; CHECK: ret void
@ -52,6 +52,6 @@ entry:
; ADDR: %[[A:.*]] = load i64, i64* getelementptr inbounds {{.*}} @__msan_param_tls, i32 0, i32 0), align 8
; ADDR: %[[B:.*]] = icmp ne i64 %[[A]], 0
; ADDR: br i1 %[[B]], label {{.*}}, label
; ADDR: call void @__msan_warning_noreturn()
; ADDR: call void @__msan_warning_with_origin_noreturn(i32 0)
; ADDR: call void @llvm.x86.sse.ldmxcsr(
; ADDR: ret void

View File

@ -54,12 +54,12 @@ entry:
; ADDR: %[[ADDRBAD:.*]] = icmp ne i64 %[[ADDRSHADOW]], 0
; ADDR: br i1 %[[ADDRBAD]], label {{.*}}, label {{.*}}
; ADDR: call void @__msan_warning_noreturn()
; ADDR: call void @__msan_warning_with_origin_noreturn(i32 0)
; ADDR: %[[MASKSHADOWFLAT:.*]] = bitcast <4 x i1> %[[MASKSHADOW]] to i4
; ADDR: %[[MASKBAD:.*]] = icmp ne i4 %[[MASKSHADOWFLAT]], 0
; ADDR: br i1 %[[MASKBAD]], label {{.*}}, label {{.*}}
; ADDR: call void @__msan_warning_noreturn()
; ADDR: call void @__msan_warning_with_origin_noreturn(i32 0)
; ADDR: tail call void @llvm.masked.store.v4i64.p0v4i64(<4 x i64> %v, <4 x i64>* %p, i32 1, <4 x i1> %mask)
; ADDR: ret void
@ -94,12 +94,12 @@ entry:
; ADDR: %[[ADDRBAD:.*]] = icmp ne i64 %[[ADDRSHADOW]], 0
; ADDR: br i1 %[[ADDRBAD]], label {{.*}}, label {{.*}}
; ADDR: call void @__msan_warning_noreturn()
; ADDR: call void @__msan_warning_with_origin_noreturn(i32 0)
; ADDR: %[[MASKSHADOWFLAT:.*]] = bitcast <4 x i1> %[[MASKSHADOW]] to i4
; ADDR: %[[MASKBAD:.*]] = icmp ne i4 %[[MASKSHADOWFLAT]], 0
; ADDR: br i1 %[[MASKBAD]], label {{.*}}, label {{.*}}
; ADDR: call void @__msan_warning_noreturn()
; ADDR: call void @__msan_warning_with_origin_noreturn(i32 0)
; ADDR: = call <4 x double> @llvm.masked.load.v4f64.p0v4f64(<4 x double>* %p, i32 1, <4 x i1> %mask, <4 x double> %v)
; ADDR: ret <4 x double>

View File

@ -23,7 +23,6 @@ target triple = "x86_64-unknown-linux-gnu"
; CHECK: @__msan_param_origin_tls = external thread_local(initialexec) global [{{.*}}]
; CHECK: @__msan_va_arg_tls = external thread_local(initialexec) global [{{.*}}]
; CHECK: @__msan_va_arg_overflow_size_tls = external thread_local(initialexec) global i64
; CHECK: @__msan_origin_tls = external thread_local(initialexec) global i32
; Check instrumentation of stores
@ -72,7 +71,7 @@ entry:
; CHECK: ret void
; load followed by cmp: check that we load the shadow and call __msan_warning.
; load followed by cmp: check that we load the shadow and call __msan_warning_with_origin.
define void @LoadAndCmp(i32* nocapture %a) nounwind uwtable sanitize_memory {
entry:
%0 = load i32, i32* %a, align 4
@ -90,11 +89,15 @@ if.end: ; preds = %entry, %if.then
declare void @foo(...)
; CHECK-LABEL: @LoadAndCmp
; CHECK: %0 = load i32,
; CHECK: = load
; CHECK: = load
; CHECK: call void @__msan_warning_noreturn()
; CHECK-ORIGINS: %[[ORIGIN:.*]] = load
; CHECK: call void @__msan_warning_with_origin_noreturn(i32
; CHECK-ORIGINS-SAME %[[ORIGIN]])
; CHECK-CONT:
; CHECK-NEXT: call void asm sideeffect
; CHECK-NEXT: unreachable
; CHECK: br i1 %tobool
; CHECK: ret void
; Check that we store the shadow for the retval.
@ -417,7 +420,7 @@ entry:
; CHECK-LABEL: @Div
; CHECK: icmp
; CHECK: call void @__msan_warning
; CHECK: call void @__msan_warning_with_origin
; CHECK-NOT: icmp
; CHECK: udiv
; CHECK-NOT: icmp
@ -464,9 +467,9 @@ define zeroext i1 @ICmpSLTZero(i32 %x) nounwind uwtable readnone sanitize_memory
; CHECK-LABEL: @ICmpSLTZero
; CHECK: icmp slt
; CHECK-NOT: call void @__msan_warning
; CHECK-NOT: call void @__msan_warning_with_origin
; CHECK: icmp slt
; CHECK-NOT: call void @__msan_warning
; CHECK-NOT: call void @__msan_warning_with_origin
; CHECK: ret i1
define zeroext i1 @ICmpSGEZero(i32 %x) nounwind uwtable readnone sanitize_memory {
@ -476,9 +479,9 @@ define zeroext i1 @ICmpSGEZero(i32 %x) nounwind uwtable readnone sanitize_memory
; CHECK-LABEL: @ICmpSGEZero
; CHECK: icmp slt
; CHECK-NOT: call void @__msan_warning
; CHECK-NOT: call void @__msan_warning_with_origin
; CHECK: icmp sge
; CHECK-NOT: call void @__msan_warning
; CHECK-NOT: call void @__msan_warning_with_origin
; CHECK: ret i1
define zeroext i1 @ICmpSGTZero(i32 %x) nounwind uwtable readnone sanitize_memory {
@ -488,9 +491,9 @@ define zeroext i1 @ICmpSGTZero(i32 %x) nounwind uwtable readnone sanitize_memory
; CHECK-LABEL: @ICmpSGTZero
; CHECK: icmp slt
; CHECK-NOT: call void @__msan_warning
; CHECK-NOT: call void @__msan_warning_with_origin
; CHECK: icmp sgt
; CHECK-NOT: call void @__msan_warning
; CHECK-NOT: call void @__msan_warning_with_origin
; CHECK: ret i1
define zeroext i1 @ICmpSLEZero(i32 %x) nounwind uwtable readnone sanitize_memory {
@ -500,9 +503,9 @@ define zeroext i1 @ICmpSLEZero(i32 %x) nounwind uwtable readnone sanitize_memory
; CHECK-LABEL: @ICmpSLEZero
; CHECK: icmp slt
; CHECK-NOT: call void @__msan_warning
; CHECK-NOT: call void @__msan_warning_with_origin
; CHECK: icmp sle
; CHECK-NOT: call void @__msan_warning
; CHECK-NOT: call void @__msan_warning_with_origin
; CHECK: ret i1
@ -515,9 +518,9 @@ define zeroext i1 @ICmpSLTAllOnes(i32 %x) nounwind uwtable readnone sanitize_mem
; CHECK-LABEL: @ICmpSLTAllOnes
; CHECK: icmp slt
; CHECK-NOT: call void @__msan_warning
; CHECK-NOT: call void @__msan_warning_with_origin
; CHECK: icmp slt
; CHECK-NOT: call void @__msan_warning
; CHECK-NOT: call void @__msan_warning_with_origin
; CHECK: ret i1
define zeroext i1 @ICmpSGEAllOnes(i32 %x) nounwind uwtable readnone sanitize_memory {
@ -527,9 +530,9 @@ define zeroext i1 @ICmpSGEAllOnes(i32 %x) nounwind uwtable readnone sanitize_mem
; CHECK-LABEL: @ICmpSGEAllOnes
; CHECK: icmp slt
; CHECK-NOT: call void @__msan_warning
; CHECK-NOT: call void @__msan_warning_with_origin
; CHECK: icmp sge
; CHECK-NOT: call void @__msan_warning
; CHECK-NOT: call void @__msan_warning_with_origin
; CHECK: ret i1
define zeroext i1 @ICmpSGTAllOnes(i32 %x) nounwind uwtable readnone sanitize_memory {
@ -539,9 +542,9 @@ define zeroext i1 @ICmpSGTAllOnes(i32 %x) nounwind uwtable readnone sanitize_mem
; CHECK-LABEL: @ICmpSGTAllOnes
; CHECK: icmp slt
; CHECK-NOT: call void @__msan_warning
; CHECK-NOT: call void @__msan_warning_with_origin
; CHECK: icmp sgt
; CHECK-NOT: call void @__msan_warning
; CHECK-NOT: call void @__msan_warning_with_origin
; CHECK: ret i1
define zeroext i1 @ICmpSLEAllOnes(i32 %x) nounwind uwtable readnone sanitize_memory {
@ -551,9 +554,9 @@ define zeroext i1 @ICmpSLEAllOnes(i32 %x) nounwind uwtable readnone sanitize_mem
; CHECK-LABEL: @ICmpSLEAllOnes
; CHECK: icmp slt
; CHECK-NOT: call void @__msan_warning
; CHECK-NOT: call void @__msan_warning_with_origin
; CHECK: icmp sle
; CHECK-NOT: call void @__msan_warning
; CHECK-NOT: call void @__msan_warning_with_origin
; CHECK: ret i1
@ -567,9 +570,9 @@ define <2 x i1> @ICmpSLT_vector_Zero(<2 x i32*> %x) nounwind uwtable readnone sa
; CHECK-LABEL: @ICmpSLT_vector_Zero
; CHECK: icmp slt <2 x i64>
; CHECK-NOT: call void @__msan_warning
; CHECK-NOT: call void @__msan_warning_with_origin
; CHECK: icmp slt <2 x i32*>
; CHECK-NOT: call void @__msan_warning
; CHECK-NOT: call void @__msan_warning_with_origin
; CHECK: ret <2 x i1>
; Check that we propagate shadow for x<=-1, x>0, etc (i.e. sign bit tests)
@ -582,9 +585,9 @@ define <2 x i1> @ICmpSLT_vector_AllOnes(<2 x i32> %x) nounwind uwtable readnone
; CHECK-LABEL: @ICmpSLT_vector_AllOnes
; CHECK: icmp slt <2 x i32>
; CHECK-NOT: call void @__msan_warning
; CHECK-NOT: call void @__msan_warning_with_origin
; CHECK: icmp slt <2 x i32>
; CHECK-NOT: call void @__msan_warning
; CHECK-NOT: call void @__msan_warning_with_origin
; CHECK: ret <2 x i1>
@ -599,11 +602,11 @@ entry:
; CHECK-LABEL: @ICmpUGTConst
; CHECK: icmp ugt i32
; CHECK-NOT: call void @__msan_warning
; CHECK-NOT: call void @__msan_warning_with_origin
; CHECK: icmp ugt i32
; CHECK-NOT: call void @__msan_warning
; CHECK-NOT: call void @__msan_warning_with_origin
; CHECK: icmp ugt i32
; CHECK-NOT: call void @__msan_warning
; CHECK-NOT: call void @__msan_warning_with_origin
; CHECK: ret i1
@ -645,7 +648,7 @@ define i32 @ExtractElement(<4 x i32> %vec, i32 %idx) sanitize_memory {
; CHECK-LABEL: @ExtractElement
; CHECK: extractelement
; CHECK: call void @__msan_warning
; CHECK: call void @__msan_warning_with_origin
; CHECK: extractelement
; CHECK: ret i32
@ -656,7 +659,7 @@ define <4 x i32> @InsertElement(<4 x i32> %vec, i32 %idx, i32 %x) sanitize_memor
; CHECK-LABEL: @InsertElement
; CHECK: insertelement
; CHECK: call void @__msan_warning
; CHECK: call void @__msan_warning_with_origin
; CHECK: insertelement
; CHECK: ret <4 x i32>
@ -668,7 +671,7 @@ define <4 x i32> @ShuffleVector(<4 x i32> %vec, <4 x i32> %vec1) sanitize_memory
; CHECK-LABEL: @ShuffleVector
; CHECK: shufflevector
; CHECK-NOT: call void @__msan_warning
; CHECK-NOT: call void @__msan_warning_with_origin
; CHECK: shufflevector
; CHECK: ret <4 x i32>
@ -682,11 +685,11 @@ define i32 @BSwap(i32 %x) nounwind uwtable readnone sanitize_memory {
declare i32 @llvm.bswap.i32(i32) nounwind readnone
; CHECK-LABEL: @BSwap
; CHECK-NOT: call void @__msan_warning
; CHECK-NOT: call void @__msan_warning_with_origin
; CHECK: @llvm.bswap.i32
; CHECK-NOT: call void @__msan_warning
; CHECK-NOT: call void @__msan_warning_with_origin
; CHECK: @llvm.bswap.i32
; CHECK-NOT: call void @__msan_warning
; CHECK-NOT: call void @__msan_warning_with_origin
; CHECK: ret i32
; Test handling of vectors of pointers.
@ -752,7 +755,7 @@ entry:
}
; CHECK-LABEL: @VolatileStore
; CHECK-NOT: @__msan_warning
; CHECK-NOT: @__msan_warning_with_origin
; CHECK: ret void
@ -775,9 +778,9 @@ if.end: ; preds = %entry, %if.then
declare void @bar()
; CHECK-LABEL: @NoSanitizeMemory
; CHECK-NOT: @__msan_warning
; CHECK-NOT: @__msan_warning_with_origin
; CHECK: store i32 0, {{.*}} @__msan_retval_tls
; CHECK-NOT: @__msan_warning
; CHECK-NOT: @__msan_warning_with_origin
; CHECK: ret i32

View File

@ -18,7 +18,7 @@ entry:
}
; CHECK-LABEL: bar
; CHECK-NOT: call void @__msan_warning
; CHECK-NOT: call void @__msan_warning_with_origin
; Function Attrs: nounwind readnone
declare i1 @llvm.is.constant.i32(i32)

View File

@ -25,7 +25,7 @@ entry:
ret %class.Foo* %retval.0
}
; CHECK-NOT: call void @__msan_warning_noreturn
; CHECK-NOT: call void @__msan_warning_with_origin_noreturn
declare dso_local zeroext i1 @_Z2f1PPvb(i8**, i1 zeroext) local_unnamed_addr

View File

@ -14,7 +14,7 @@ entry:
ret i8* %0
}
; CHECK-NOT: call void @__msan_warning_noreturn
; CHECK-NOT: call void @__msan_warning_with_origin_noreturn
declare i8* @llvm.strip.invariant.group.p0i8(i8*)

View File

@ -16,5 +16,5 @@ declare i32 @f() sanitize_memory
; CHECK: call i32 @f()
; CHECK: store i32 0, {{.*}} @__msan_retval_tls
; CHECK: br i1
; CHECK: call void @__msan_warning_noreturn()
; CHECK: call void @__msan_warning_with_origin_noreturn(i32 0)
; CHECK: ret i32

View File

@ -22,7 +22,7 @@ entry:
; CHECK: [[S:%[_01-9a-z]+]] = extractelement <2 x i64> {{.*}}, i32 0
; CHECK: icmp ne {{.*}}[[S]], 0
; CHECK: br
; CHECK: call void @__msan_warning_noreturn
; CHECK: call void @__msan_warning_with_origin_noreturn
; CHECK: call i32 @llvm.x86.sse2.cvtsd2si
; CHECK: store i32 0, {{.*}} @__msan_retval_tls
; CHECK: ret i32
@ -41,7 +41,7 @@ entry:
; CHECK: [[S:%[_01-9a-z]+]] = or i32
; CHECK: icmp ne {{.*}}[[S]], 0
; CHECK: br
; CHECK: call void @__msan_warning_noreturn
; CHECK: call void @__msan_warning_with_origin_noreturn
; CHECK: call x86_mmx @llvm.x86.sse.cvtps2pi
; CHECK: store i64 0, {{.*}} @__msan_retval_tls
; CHECK: ret x86_mmx