Skip to content

Commit 97630ed

Browse files
committed
[DevSAN] Skip instrumentation if module has esimd kernel for MSAN/TSAN
Device sanitizer doesn't support esimd kernel now.
1 parent 3e94066 commit 97630ed

File tree

7 files changed

+130
-43
lines changed

7 files changed

+130
-43
lines changed

llvm/include/llvm/Transforms/Instrumentation/SPIRVSanitizerCommonUtils.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "llvm/ADT/SmallString.h"
1616
#include "llvm/IR/Constants.h"
1717
#include "llvm/IR/DerivedTypes.h"
18+
#include "llvm/IR/Module.h"
1819
#include "llvm/IR/Type.h"
1920
#include "llvm/IR/Value.h"
2021

@@ -42,6 +43,8 @@ SmallString<128>
4243
computeKernelMetadataUniqueId(StringRef Prefix,
4344
SmallVectorImpl<uint8_t> &KernelNamesBytes);
4445

46+
bool hasESIMDKernel(Module &M);
47+
4548
// Sync with sanitizer_common/sanitizer_common.hpp
4649
enum SanitizedKernelFlags : uint32_t {
4750
NO_CHECK = 0,

llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1624,13 +1624,7 @@ PreservedAnalyses AddressSanitizerPass::run(Module &M,
16241624
AsanSpirv->initializeCallbacks();
16251625

16261626
// FIXME: W/A skip instrumentation if this module has ESIMD
1627-
bool HasESIMD = false;
1628-
for (auto &F : M) {
1629-
if (F.hasMetadata("sycl_explicit_simd")) {
1630-
HasESIMD = true;
1631-
break;
1632-
}
1633-
}
1627+
bool HasESIMD = hasESIMDKernel(M);
16341628

16351629
// Make sure "__AsanKernelMetadata" always exists
16361630
ExtendSpirKernelArgs(M, FAM, HasESIMD);

llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp

Lines changed: 32 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -800,6 +800,7 @@ class MemorySanitizerOnSpirv {
800800
: M(M), C(M.getContext()), DL(M.getDataLayout()) {
801801
const auto &TargetTriple = Triple(M.getTargetTriple());
802802
IsSPIRV = TargetTriple.isSPIROrSPIRV();
803+
HasESIMD = hasESIMDKernel(M);
803804

804805
IntptrTy = DL.getIntPtrType(C);
805806
Int32Ty = Type::getInt32Ty(C);
@@ -812,6 +813,8 @@ class MemorySanitizerOnSpirv {
812813
Constant *getOrCreateGlobalString(StringRef Name, StringRef Value,
813814
unsigned AddressSpace);
814815

816+
bool hasESIMD() { return HasESIMD; }
817+
815818
static bool isSupportedBuiltIn(StringRef Name);
816819

817820
operator bool() const { return IsSPIRV; }
@@ -834,6 +837,7 @@ class MemorySanitizerOnSpirv {
834837
LLVMContext &C;
835838
const DataLayout &DL;
836839
bool IsSPIRV;
840+
bool HasESIMD;
837841
Type *IntptrTy;
838842
Type *Int32Ty;
839843

@@ -1242,34 +1246,35 @@ void MemorySanitizerOnSpirv::instrumentKernelsMetadata(int TrackOrigins) {
12421246
// uptr unmangled_kernel_name_size
12431247
// uptr sanitized_flags
12441248
StructType *StructTy = StructType::get(IntptrTy, IntptrTy, IntptrTy);
1245-
for (Function &F : M) {
1246-
if (F.getCallingConv() != CallingConv::SPIR_KERNEL)
1247-
continue;
1249+
if (!HasESIMD)
1250+
for (Function &F : M) {
1251+
if (F.getCallingConv() != CallingConv::SPIR_KERNEL)
1252+
continue;
12481253

1249-
if (!F.hasFnAttribute(Attribute::SanitizeMemory) ||
1250-
F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation))
1251-
continue;
1254+
if (!F.hasFnAttribute(Attribute::SanitizeMemory) ||
1255+
F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation))
1256+
continue;
12521257

1253-
auto KernelName = F.getName();
1254-
KernelNamesBytes.append(KernelName.begin(), KernelName.end());
1255-
auto *KernelNameGV = getOrCreateGlobalString("__msan_kernel", KernelName,
1256-
kSpirOffloadConstantAS);
1258+
auto KernelName = F.getName();
1259+
KernelNamesBytes.append(KernelName.begin(), KernelName.end());
1260+
auto *KernelNameGV = getOrCreateGlobalString("__msan_kernel", KernelName,
1261+
kSpirOffloadConstantAS);
12571262

1258-
uintptr_t SanitizerFlags = 0;
1259-
SanitizerFlags |= ClSpirOffloadLocals ? SanitizedKernelFlags::CHECK_LOCALS
1260-
: SanitizedKernelFlags::NO_CHECK;
1261-
SanitizerFlags |= ClSpirOffloadPrivates
1262-
? SanitizedKernelFlags::CHECK_PRIVATES
1263-
: SanitizedKernelFlags::NO_CHECK;
1264-
SanitizerFlags |= TrackOrigins != 0
1265-
? SanitizedKernelFlags::MSAN_TRACK_ORIGINS
1266-
: SanitizedKernelFlags::NO_CHECK;
1263+
uintptr_t SanitizerFlags = 0;
1264+
SanitizerFlags |= ClSpirOffloadLocals ? SanitizedKernelFlags::CHECK_LOCALS
1265+
: SanitizedKernelFlags::NO_CHECK;
1266+
SanitizerFlags |= ClSpirOffloadPrivates
1267+
? SanitizedKernelFlags::CHECK_PRIVATES
1268+
: SanitizedKernelFlags::NO_CHECK;
1269+
SanitizerFlags |= TrackOrigins != 0
1270+
? SanitizedKernelFlags::MSAN_TRACK_ORIGINS
1271+
: SanitizedKernelFlags::NO_CHECK;
12671272

1268-
SpirKernelsMetadata.emplace_back(ConstantStruct::get(
1269-
StructTy, ConstantExpr::getPointerCast(KernelNameGV, IntptrTy),
1270-
ConstantInt::get(IntptrTy, KernelName.size()),
1271-
ConstantInt::get(IntptrTy, SanitizerFlags)));
1272-
}
1273+
SpirKernelsMetadata.emplace_back(ConstantStruct::get(
1274+
StructTy, ConstantExpr::getPointerCast(KernelNameGV, IntptrTy),
1275+
ConstantInt::get(IntptrTy, KernelName.size()),
1276+
ConstantInt::get(IntptrTy, SanitizerFlags)));
1277+
}
12731278

12741279
// Create global variable to record spirv kernels' information
12751280
ArrayType *ArrayTy = ArrayType::get(StructTy, SpirKernelsMetadata.size());
@@ -1361,6 +1366,9 @@ PreservedAnalyses MemorySanitizerPass::run(Module &M,
13611366

13621367
MemorySanitizerOnSpirv MsanSpirv(M);
13631368
Modified |= MsanSpirv.instrumentModule(Options.TrackOrigins);
1369+
// FIXME: W/A skip instrumentation if this module has ESIMD
1370+
if (MsanSpirv.hasESIMD())
1371+
return PreservedAnalyses::none();
13641372

13651373
auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
13661374
for (Function &F : M) {

llvm/lib/Transforms/Instrumentation/SPIRVSanitizerCommonUtils.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,4 +81,11 @@ computeKernelMetadataUniqueId(StringRef Prefix,
8181
return UniqueId;
8282
}
8383

84+
bool hasESIMDKernel(Module &M) {
85+
for (auto &F : M)
86+
if (F.hasMetadata("sycl_explicit_simd"))
87+
return true;
88+
return false;
89+
}
90+
8491
} // namespace llvm

llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ struct ThreadSanitizerOnSpirv {
117117
ThreadSanitizerOnSpirv(Module &M)
118118
: M(M), C(M.getContext()), DL(M.getDataLayout()) {
119119
IntptrTy = DL.getIntPtrType(C);
120+
HasESIMD = hasESIMDKernel(M);
120121
}
121122

122123
void initialize();
@@ -134,6 +135,8 @@ struct ThreadSanitizerOnSpirv {
134135

135136
bool isUnsupportedSPIRAccess(Value *Addr, Instruction *Inst);
136137

138+
bool hasESIMD() { return HasESIMD; }
139+
137140
private:
138141
void instrumentGlobalVariables();
139142

@@ -154,6 +157,7 @@ struct ThreadSanitizerOnSpirv {
154157
Module &M;
155158
LLVMContext &C;
156159
const DataLayout &DL;
160+
bool HasESIMD;
157161
Type *IntptrTy;
158162

159163
StringMap<GlobalVariable *> GlobalStringMap;
@@ -695,20 +699,21 @@ void ThreadSanitizerOnSpirv::instrumentKernelsMetadata() {
695699
// uptr unmangled_kernel_name_size
696700
StructType *StructTy = StructType::get(IntptrTy, IntptrTy);
697701

698-
for (Function &F : M) {
699-
if (F.getCallingConv() != CallingConv::SPIR_KERNEL)
700-
continue;
702+
if (!HasESIMD)
703+
for (Function &F : M) {
704+
if (F.getCallingConv() != CallingConv::SPIR_KERNEL)
705+
continue;
701706

702-
if (isSupportedSPIRKernel(F)) {
703-
auto KernelName = F.getName();
704-
KernelNamesBytes.append(KernelName.begin(), KernelName.end());
705-
auto *KernelNameGV = GetOrCreateGlobalString("__tsan_kernel", KernelName,
706-
kSpirOffloadConstantAS);
707-
SpirKernelsMetadata.emplace_back(ConstantStruct::get(
708-
StructTy, ConstantExpr::getPointerCast(KernelNameGV, IntptrTy),
709-
ConstantInt::get(IntptrTy, KernelName.size())));
707+
if (isSupportedSPIRKernel(F)) {
708+
auto KernelName = F.getName();
709+
KernelNamesBytes.append(KernelName.begin(), KernelName.end());
710+
auto *KernelNameGV = GetOrCreateGlobalString(
711+
"__tsan_kernel", KernelName, kSpirOffloadConstantAS);
712+
SpirKernelsMetadata.emplace_back(ConstantStruct::get(
713+
StructTy, ConstantExpr::getPointerCast(KernelNameGV, IntptrTy),
714+
ConstantInt::get(IntptrTy, KernelName.size())));
715+
}
710716
}
711-
}
712717

713718
// Create global variable to record spirv kernels' information
714719
ArrayType *ArrayTy = ArrayType::get(StructTy, SpirKernelsMetadata.size());
@@ -1076,6 +1081,10 @@ bool ThreadSanitizer::sanitizeFunction(Function &F,
10761081
bool SanitizeFunction = F.hasFnAttribute(Attribute::SanitizeThread);
10771082
const DataLayout &DL = F.getDataLayout();
10781083

1084+
// FIXME: W/A skip instrumentation if this module has ESIMD
1085+
if (Spirv && Spirv->hasESIMD())
1086+
return false;
1087+
10791088
// Traverse all instructions, collect loads/stores/returns, check for calls.
10801089
for (auto &BB : F) {
10811090
for (auto &Inst : BB) {
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
; RUN: opt < %s -passes=msan -msan-instrumentation-with-call-threshold=0 -msan-eager-checks=1 -msan-spir-privates=0 -S | FileCheck %s
2+
3+
target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64-G1"
4+
target triple = "spir64-unknown-unknown"
5+
6+
;CHECK: @__MsanKernelMetadata
7+
;CHECK-SAME: [0 x { i64, i64, i64 }]
8+
9+
define spir_kernel void @test(ptr addrspace(1) noundef align 4 %_arg_array) sanitize_memory {
10+
; CHECK-LABEL: define spir_kernel void @test
11+
entry:
12+
%0 = load i32, ptr addrspace(1) %_arg_array, align 4
13+
%call = call spir_func i32 @foo(i32 %0)
14+
store i32 %call, ptr addrspace(1) %_arg_array, align 4
15+
; CHECK-NOT: call void @__msan_maybe_warning
16+
ret void
17+
}
18+
19+
define spir_kernel void @test_esimd(ptr addrspace(1) noundef align 4 %_arg_array) sanitize_memory !sycl_explicit_simd !0 {
20+
; CHECK-LABEL: define spir_kernel void @test_esimd
21+
entry:
22+
%0 = load i32, ptr addrspace(1) %_arg_array, align 4
23+
%call = call spir_func i32 @foo(i32 %0)
24+
store i32 %call, ptr addrspace(1) %_arg_array, align 4
25+
; CHECK-NOT: call void @__msan_maybe_warning
26+
ret void
27+
}
28+
29+
define spir_func i32 @foo(i32 %data) sanitize_memory {
30+
entry:
31+
ret i32 %data
32+
}
33+
34+
!0 = !{}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
; RUN: opt < %s -passes='function(tsan),module(tsan-module)' -tsan-instrument-func-entry-exit=0 -tsan-instrument-memintrinsics=0 -S | FileCheck %s
2+
target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64-G1"
3+
target triple = "spir64-unknown-unknown"
4+
5+
; CHECK: @__TsanKernelMetadata
6+
; CHECK-SAME: [0 x { i64, i64 }]
7+
8+
; Function Attrs: sanitize_thread
9+
define spir_kernel void @test(ptr addrspace(4) %a) #0 {
10+
; CHECK-LABEL: void @test
11+
entry:
12+
%tmp1 = load i8, ptr addrspace(4) %a, align 1
13+
%inc = add i8 %tmp1, 1
14+
; CHECK-NOT: call void @__tsan_write
15+
store i8 %inc, ptr addrspace(4) %a, align 1
16+
ret void
17+
}
18+
19+
; Function Attrs: sanitize_thread
20+
define spir_kernel void @test_esimd(ptr addrspace(4) %a) #0 !sycl_explicit_simd !0 {
21+
; CHECK-LABEL: void @test_esimd
22+
entry:
23+
%tmp1 = load i16, ptr addrspace(4) %a, align 2
24+
%inc = add i16 %tmp1, 1
25+
; CHECK-NOT: call void @__tsan_write
26+
store i16 %inc, ptr addrspace(4) %a, align 2
27+
ret void
28+
}
29+
30+
attributes #0 = { sanitize_thread }
31+
32+
!0 = !{}

0 commit comments

Comments
 (0)