Skip to content

Commit 46639ce

Browse files
zhaomaosuaarongreig
authored andcommitted
[DevMSAN] Skip more unsupported memory access pattern (#16427)
UR: oneapi-src/unified-runtime#2484 --------- Co-authored-by: Aaron Greig <[email protected]>
1 parent eb8d2ae commit 46639ce

File tree

9 files changed

+157
-66
lines changed

9 files changed

+157
-66
lines changed

libdevice/include/sanitizer_defs.hpp

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//===----------------------------------------------------------------------===//
88
#pragma once
99

10+
#include "spir_global_var.hpp"
1011
#include <cstdint>
1112

1213
using uptr = uintptr_t;
@@ -19,6 +20,59 @@ using s16 = int16_t;
1920
using s32 = int32_t;
2021
using s64 = int64_t;
2122

23+
enum ADDRESS_SPACE : uint32_t {
24+
ADDRESS_SPACE_PRIVATE = 0,
25+
ADDRESS_SPACE_GLOBAL = 1,
26+
ADDRESS_SPACE_CONSTANT = 2,
27+
ADDRESS_SPACE_LOCAL = 3,
28+
ADDRESS_SPACE_GENERIC = 4,
29+
};
30+
2231
#define LIKELY(x) __builtin_expect(!!(x), 1)
2332
#define UNLIKELY(x) __builtin_expect(!!(x), 0)
2433
#define NORETURN __declspec(noreturn)
34+
35+
#if defined(__SPIR__) || defined(__SPIRV__)
36+
37+
#if defined(__SYCL_DEVICE_ONLY__)
38+
39+
#define __USE_SPIR_BUILTIN__ 1
40+
41+
#ifndef SYCL_EXTERNAL
42+
#define SYCL_EXTERNAL
43+
#endif // SYCL_EXTERNAL
44+
45+
#else // __SYCL_DEVICE_ONLY__
46+
47+
#define __USE_SPIR_BUILTIN__
48+
49+
#endif // __SYCL_DEVICE_ONLY__
50+
51+
#if __USE_SPIR_BUILTIN__
52+
extern SYCL_EXTERNAL int
53+
__spirv_ocl_printf(const __SYCL_CONSTANT__ char *Format, ...);
54+
55+
extern SYCL_EXTERNAL __SYCL_GLOBAL__ void *
56+
__spirv_GenericCastToPtrExplicit_ToGlobal(void *, int);
57+
extern SYCL_EXTERNAL __SYCL_LOCAL__ void *
58+
__spirv_GenericCastToPtrExplicit_ToLocal(void *, int);
59+
extern SYCL_EXTERNAL __SYCL_PRIVATE__ void *
60+
__spirv_GenericCastToPtrExplicit_ToPrivate(void *, int);
61+
62+
extern SYCL_EXTERNAL __attribute__((convergent)) void
63+
__spirv_ControlBarrier(uint32_t Execution, uint32_t Memory, uint32_t Semantics);
64+
65+
extern "C" SYCL_EXTERNAL void __devicelib_exit();
66+
#endif // __USE_SPIR_BUILTIN__
67+
68+
__SYCL_GLOBAL__ void *ToGlobal(void *ptr) {
69+
return __spirv_GenericCastToPtrExplicit_ToGlobal(ptr, 5);
70+
}
71+
__SYCL_LOCAL__ void *ToLocal(void *ptr) {
72+
return __spirv_GenericCastToPtrExplicit_ToLocal(ptr, 4);
73+
}
74+
__SYCL_PRIVATE__ void *ToPrivate(void *ptr) {
75+
return __spirv_GenericCastToPtrExplicit_ToPrivate(ptr, 7);
76+
}
77+
78+
#endif // __SPIR__ || __SPIRV__

libdevice/sanitizer/asan_rtl.cpp

Lines changed: 0 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -17,37 +17,6 @@ __SYCL_GLOBAL__ uptr *__SYCL_LOCAL__ __AsanLaunchInfo;
1717

1818
#if defined(__SPIR__) || defined(__SPIRV__)
1919

20-
#if defined(__SYCL_DEVICE_ONLY__)
21-
22-
#define __USE_SPIR_BUILTIN__ 1
23-
24-
#ifndef SYCL_EXTERNAL
25-
#define SYCL_EXTERNAL
26-
#endif // SYCL_EXTERNAL
27-
28-
#else // __SYCL_DEVICE_ONLY__
29-
30-
#define __USE_SPIR_BUILTIN__
31-
32-
#endif // __SYCL_DEVICE_ONLY__
33-
34-
#if __USE_SPIR_BUILTIN__
35-
extern SYCL_EXTERNAL int
36-
__spirv_ocl_printf(const __SYCL_CONSTANT__ char *Format, ...);
37-
38-
extern SYCL_EXTERNAL __SYCL_GLOBAL__ void *
39-
__spirv_GenericCastToPtrExplicit_ToGlobal(void *, int);
40-
extern SYCL_EXTERNAL __SYCL_LOCAL__ void *
41-
__spirv_GenericCastToPtrExplicit_ToLocal(void *, int);
42-
extern SYCL_EXTERNAL __SYCL_PRIVATE__ void *
43-
__spirv_GenericCastToPtrExplicit_ToPrivate(void *, int);
44-
45-
extern SYCL_EXTERNAL __attribute__((convergent)) void
46-
__spirv_ControlBarrier(uint32_t Execution, uint32_t Memory, uint32_t Semantics);
47-
48-
extern "C" SYCL_EXTERNAL void __devicelib_exit();
49-
#endif // __USE_SPIR_BUILTIN__
50-
5120
static const __SYCL_CONSTANT__ char __asan_shadow_value_start[] =
5221
"[kernel] %p(%d) -> %p:";
5322
static const __SYCL_CONSTANT__ char __asan_shadow_value[] = " %02X";
@@ -86,14 +55,6 @@ static __SYCL_CONSTANT__ const char __generic_to[] =
8655
} \
8756
} while (false)
8857

89-
enum ADDRESS_SPACE : uint32_t {
90-
ADDRESS_SPACE_PRIVATE = 0,
91-
ADDRESS_SPACE_GLOBAL = 1,
92-
ADDRESS_SPACE_CONSTANT = 2,
93-
ADDRESS_SPACE_LOCAL = 3,
94-
ADDRESS_SPACE_GENERIC = 4,
95-
};
96-
9758
namespace {
9859

9960
void __asan_report_unknown_device();

libdevice/sanitizer/msan_rtl.cpp

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@ constexpr int MSAN_REPORT_NONE = 0;
1818
constexpr int MSAN_REPORT_START = 1;
1919
constexpr int MSAN_REPORT_FINISH = 2;
2020

21-
static const uint64_t CleanShadow[16] = {};
22-
2321
static const __SYCL_CONSTANT__ char __msan_print_warning_return[] =
2422
"[kernel] !!! msan warning return\n";
2523

@@ -38,17 +36,10 @@ static const __SYCL_CONSTANT__ char __msan_print_report[] =
3836
static const __SYCL_CONSTANT__ char __msan_print_unsupport_device_type[] =
3937
"[kernel] Unsupport device type: %d\n";
4038

41-
#if defined(__SPIR__) || defined(__SPIRV__)
42-
43-
#if defined(__SYCL_DEVICE_ONLY__)
44-
#define __USE_SPIR_BUILTIN__ 1
45-
#endif
39+
static const __SYCL_CONSTANT__ char __msan_print_generic_to[] =
40+
"[kernel] %p(4) - %p(%d)\n";
4641

47-
#if __USE_SPIR_BUILTIN__
48-
extern SYCL_EXTERNAL int
49-
__spirv_ocl_printf(const __SYCL_CONSTANT__ char *Format, ...);
50-
extern "C" SYCL_EXTERNAL void __devicelib_exit();
51-
#endif
42+
#if defined(__SPIR__) || defined(__SPIRV__)
5243

5344
#define MSAN_DEBUG(X) \
5445
do { \
@@ -61,6 +52,21 @@ extern "C" SYCL_EXTERNAL void __devicelib_exit();
6152

6253
namespace {
6354

55+
inline void ConvertGenericPointer(uptr &addr, uint32_t &as) {
56+
auto old = addr;
57+
if ((addr = (uptr)ToPrivate((void *)old))) {
58+
as = ADDRESS_SPACE_PRIVATE;
59+
} else if ((addr = (uptr)ToLocal((void *)old))) {
60+
as = ADDRESS_SPACE_LOCAL;
61+
} else {
62+
// FIXME: I'm not sure if we need to check ADDRESS_SPACE_CONSTANT,
63+
// but this can really simplify the generic pointer conversion logic
64+
as = ADDRESS_SPACE_GLOBAL;
65+
addr = old;
66+
}
67+
MSAN_DEBUG(__spirv_ocl_printf(__msan_print_generic_to, old, addr, as));
68+
}
69+
6470
void __msan_internal_report_save(const uint32_t size,
6571
const char __SYCL_CONSTANT__ *file,
6672
const uint32_t line,
@@ -131,6 +137,13 @@ inline uptr __msan_get_shadow_cpu(uptr addr) {
131137
}
132138

133139
inline uptr __msan_get_shadow_pvc(uptr addr, uint32_t as) {
140+
if (as == ADDRESS_SPACE_GENERIC) {
141+
ConvertGenericPointer(addr, as);
142+
if (as != ADDRESS_SPACE_GLOBAL)
143+
return (uptr)((__SYCL_GLOBAL__ MsanLaunchInfo *)__MsanLaunchInfo.get())
144+
->CleanShadow;
145+
}
146+
134147
// Device USM only
135148
auto shadow_begin = ((__SYCL_GLOBAL__ MsanLaunchInfo *)__MsanLaunchInfo.get())
136149
->GlobalShadowOffset;
@@ -174,7 +187,9 @@ __msan_warning_noreturn(const char __SYCL_CONSTANT__ *file, uint32_t line,
174187

175188
DEVICE_EXTERN_C_NOINLINE uptr __msan_get_shadow(uptr addr, uint32_t as) {
176189
// Return clean shadow (0s) by default
177-
uptr shadow_ptr = (uptr)CleanShadow;
190+
uptr shadow_ptr =
191+
(uptr)((__SYCL_GLOBAL__ MsanLaunchInfo *)__MsanLaunchInfo.get())
192+
->CleanShadow;
178193

179194
if (UNLIKELY(!__MsanLaunchInfo)) {
180195
__spirv_ocl_printf(__msan_print_warning_nolaunchinfo);

llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -928,11 +928,21 @@ void MemorySanitizer::createKernelApi(Module &M, const TargetLibraryInfo &TLI) {
928928
}
929929

930930
static Constant *getOrInsertGlobal(Module &M, StringRef Name, Type *Ty) {
931-
return M.getOrInsertGlobal(Name, Ty, [&] {
932-
return new GlobalVariable(M, Ty, false, GlobalVariable::ExternalLinkage,
933-
nullptr, Name, nullptr,
934-
GlobalVariable::InitialExecTLSModel);
935-
});
931+
// FIXME: spirv target doesn't support TLS, need to handle it later.
932+
if (Triple(M.getTargetTriple()).isSPIROrSPIRV()) {
933+
return M.getOrInsertGlobal(Name, Ty, [&] {
934+
return new GlobalVariable(M, Ty, false, GlobalVariable::ExternalLinkage,
935+
Constant::getNullValue(Ty), Name, nullptr,
936+
GlobalVariable::NotThreadLocal,
937+
kSpirOffloadGlobalAS);
938+
});
939+
} else {
940+
return M.getOrInsertGlobal(Name, Ty, [&] {
941+
return new GlobalVariable(M, Ty, false, GlobalVariable::ExternalLinkage,
942+
nullptr, Name, nullptr,
943+
GlobalVariable::InitialExecTLSModel);
944+
});
945+
}
936946
}
937947

938948
/// Insert declarations for userspace-specific functions and globals.
@@ -1256,6 +1266,11 @@ static unsigned TypeSizeToSizeIndex(TypeSize TS) {
12561266
}
12571267

12581268
static bool isUnsupportedSPIRAccess(const Value *Addr, Instruction *I) {
1269+
if (isa<Instruction>(Addr) &&
1270+
cast<Instruction>(Addr)->getMetadata(LLVMContext::MD_nosanitize)) {
1271+
return true;
1272+
}
1273+
12591274
// Skip SPIR-V built-in varibles
12601275
auto *OrigValue = Addr->stripInBoundsOffsets();
12611276
assert(OrigValue != nullptr);
@@ -1266,8 +1281,9 @@ static bool isUnsupportedSPIRAccess(const Value *Addr, Instruction *I) {
12661281
switch (PtrTy->getPointerAddressSpace()) {
12671282
case kSpirOffloadPrivateAS:
12681283
case kSpirOffloadLocalAS:
1269-
case kSpirOffloadGenericAS:
12701284
return true;
1285+
case kSpirOffloadGenericAS:
1286+
return false;
12711287
}
12721288

12731289
return false;
@@ -1283,8 +1299,12 @@ static void setNoSanitizedMetadataSPIR(Instruction &I) {
12831299
Addr = RMW->getPointerOperand();
12841300
else if (const auto *XCHG = dyn_cast<AtomicCmpXchgInst>(&I))
12851301
Addr = XCHG->getPointerOperand();
1302+
else if (const auto *ASC = dyn_cast<AddrSpaceCastInst>(&I))
1303+
Addr = ASC->getPointerOperand();
12861304
else if (isa<MemCpyInst>(&I))
12871305
I.setNoSanitizeMetadata();
1306+
else if (isa<AllocaInst>(&I))
1307+
I.setNoSanitizeMetadata();
12881308
else if (const auto *CI = dyn_cast<CallInst>(&I)) {
12891309
auto *Func = CI->getCalledFunction();
12901310
if (Func) {
@@ -1308,6 +1328,11 @@ static void setNoSanitizedMetadataSPIR(Instruction &I) {
13081328
Addr = CI->getOperand(OpOffset);
13091329
break;
13101330
}
1331+
case Intrinsic::lifetime_start:
1332+
case Intrinsic::lifetime_end: {
1333+
I.setNoSanitizeMetadata();
1334+
break;
1335+
}
13111336
}
13121337
} else {
13131338
auto FuncName = Func->getName();
@@ -2243,7 +2268,10 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
22432268
unsigned ArgOffset = 0;
22442269
const DataLayout &DL = F->getDataLayout();
22452270
for (auto &FArg : F->args()) {
2246-
if (!FArg.getType()->isSized() || FArg.getType()->isScalableTy()) {
2271+
// FIXME: Need to find a reasonable way to handle byval arguments for
2272+
// spirv target.
2273+
if (!FArg.getType()->isSized() || FArg.getType()->isScalableTy() ||
2274+
(SpirOrSpirv && FArg.hasByValAttr())) {
22472275
LLVM_DEBUG(dbgs() << (FArg.getType()->isScalableTy()
22482276
? "vscale not fully supported\n"
22492277
: "Arg is not sized\n"));
@@ -3183,6 +3211,11 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
31833211

31843212
// Same as memcpy.
31853213
void visitMemSetInst(MemSetInst &I) {
3214+
if (SpirOrSpirv && isa<Instruction>(I.getArgOperand(0)) &&
3215+
cast<Instruction>(I.getArgOperand(0))
3216+
->getMetadata(LLVMContext::MD_nosanitize))
3217+
return;
3218+
31863219
IRBuilder<> IRB(&I);
31873220
IRB.CreateCall(
31883221
SpirOrSpirv ? MS.MemsetOffloadFn[cast<PointerType>(
@@ -4763,7 +4796,8 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
47634796
bool NoUndef = CB.paramHasAttr(i, Attribute::NoUndef);
47644797
bool EagerCheck = MayCheckCall && !ByVal && NoUndef;
47654798

4766-
if (EagerCheck) {
4799+
// Always do eager check for spirv target
4800+
if (EagerCheck || SpirOrSpirv) {
47674801
insertShadowCheck(A, &CB);
47684802
Size = DL.getTypeAllocSize(A->getType());
47694803
} else {
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
; RUN: opt < %s -passes=msan -msan-instrumentation-with-call-threshold=0 -msan-eager-checks=1 -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+
define spir_kernel void @MyKernel(ptr %__SYCLKernel) {
6+
; CHECK-LABEL: @MyKernel
7+
entry:
8+
%_arg_array1.addr = alloca ptr addrspace(1), i32 0, align 8
9+
; CHECK: %_arg_array1.addr = alloca ptr addrspace(1){{.*!nosanitize}}
10+
%_arg_array1.addr.ascast = addrspacecast ptr %_arg_array1.addr to ptr addrspace(4)
11+
; CHECK: %_arg_array1.addr.ascast = addrspacecast ptr %_arg_array1.addr to ptr addrspace(4){{.*!nosanitize}}
12+
call void @llvm.lifetime.start.p0(i64 64, ptr %__SYCLKernel)
13+
; CHECK: call void @llvm.lifetime.start.p0(i64 64, ptr %__SYCLKernel){{.*!nosanitize}}
14+
ret void
15+
}
16+
17+
; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
18+
declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #0
19+
20+
attributes #0 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
21+
Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
# commit fe6c83a3a40e69eaa0c4829c8ba99b03e05bb4e2
2-
# Merge: 93fc1331 cf0c9482
1+
# commit 13f5e52ac047bb81f478f0dbe9416a8bc179130a
2+
# Merge: fe6c83a3 fa1e678a
33
# Author: aarongreig <[email protected]>
4-
# Date: Fri Dec 27 17:39:52 2024 +0000
5-
# Merge pull request #2507 from AllanZyne/review/yang/fix_msan_shadow
6-
# [DeviceMSAN] Fix MemToShadow algorithm and VA reservation
7-
set(UNIFIED_RUNTIME_TAG fe6c83a3a40e69eaa0c4829c8ba99b03e05bb4e2)
4+
# Date: Mon Dec 30 15:14:19 2024 +0000
5+
# Merge pull request #2484 from zhaomaosu/move-clean-shadow-to-launchinfo
6+
# [DevMSAN] Move clean shadow into launch info
7+
set(UNIFIED_RUNTIME_TAG 13f5e52ac047bb81f478f0dbe9416a8bc179130a)

sycl/test-e2e/MemorySanitizer/check_buffer.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
// REQUIRES: linux, cpu || (gpu && level_zero)
2+
// RUN: %{build} %device_msan_flags -O0 -g -o %t2.out
3+
// RUN: %{run} not %t2.out 2>&1 | FileCheck %s
24
// RUN: %{build} %device_msan_flags -O1 -g -o %t2.out
35
// RUN: %{run} not %t2.out 2>&1 | FileCheck %s
46
// RUN: %{build} %device_msan_flags -O2 -g -o %t3.out

sycl/test-e2e/MemorySanitizer/check_call.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
// REQUIRES: linux, cpu || (gpu && level_zero)
2+
// RUN: %{build} %device_msan_flags -O0 -g -o %t2.out
3+
// RUN: %{run} not %t2.out 2>&1 | FileCheck %s
24
// RUN: %{build} %device_msan_flags -O1 -g -o %t2.out
35
// RUN: %{run} not %t2.out 2>&1 | FileCheck %s
46
// RUN: %{build} %device_msan_flags -O2 -g -o %t3.out

sycl/test-e2e/MemorySanitizer/check_divide.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
// REQUIRES: linux, cpu || (gpu && level_zero)
2+
// RUN: %{build} %device_msan_flags -O0 -g -o %t2.out
3+
// RUN: %{run} not %t2.out 2>&1 | FileCheck %s
24
// RUN: %{build} %device_msan_flags -O1 -g -o %t2.out
35
// RUN: %{run} not %t2.out 2>&1 | FileCheck %s
46
// RUN: %{build} %device_msan_flags -O2 -g -o %t3.out

0 commit comments

Comments
 (0)