Skip to content

Commit 8cf0f9a

Browse files
authored
[msan] Add conservative handling of vscale params (#90167)
Msan uses `__msan_param_tls` to pass shadow of arguments. Position of arguments is expected to be available during compile time, if size of the argument is know. This is not true for vscale. As work around we require that vscale parameters are always initialized, then we don't need to pass shadow. Ret val should work out of the box as we don't need to know size compile time.
1 parent eb3030a commit 8cf0f9a

File tree

2 files changed

+98
-2
lines changed

2 files changed

+98
-2
lines changed

llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1955,8 +1955,15 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
19551955
unsigned ArgOffset = 0;
19561956
const DataLayout &DL = F->getParent()->getDataLayout();
19571957
for (auto &FArg : F->args()) {
1958-
if (!FArg.getType()->isSized()) {
1959-
LLVM_DEBUG(dbgs() << "Arg is not sized\n");
1958+
if (!FArg.getType()->isSized() || FArg.getType()->isScalableTy()) {
1959+
LLVM_DEBUG(dbgs() << (FArg.getType()->isScalableTy()
1960+
? "vscale not fully supported\n"
1961+
: "Arg is not sized\n"));
1962+
if (A == &FArg) {
1963+
ShadowPtr = getCleanShadow(V);
1964+
setOrigin(A, getCleanOrigin());
1965+
break;
1966+
}
19601967
continue;
19611968
}
19621969

@@ -4198,6 +4205,14 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
41984205
LLVM_DEBUG(dbgs() << "Arg " << i << " is not sized: " << CB << "\n");
41994206
continue;
42004207
}
4208+
4209+
if (A->getType()->isScalableTy()) {
4210+
LLVM_DEBUG(dbgs() << "Arg " << i << " is vscale: " << CB << "\n");
4211+
// Handle as noundef, but don't reserve tls slots.
4212+
insertShadowCheck(A, &CB);
4213+
continue;
4214+
}
4215+
42014216
unsigned Size = 0;
42024217
const DataLayout &DL = F.getParent()->getDataLayout();
42034218

llvm/test/Instrumentation/MemorySanitizer/vscale.ll

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,3 +105,84 @@ define void @test_load_store_add_float(ptr %a, ptr %b) sanitize_memory {
105105
store <vscale x 2 x float> %2, ptr %b
106106
ret void
107107
}
108+
109+
define <vscale x 2 x float> @fn_ret(ptr %a) sanitize_memory {
110+
; CHECK-LABEL: define <vscale x 2 x float> @fn_ret(
111+
; CHECK-SAME: ptr [[A:%.*]]) #[[ATTR0]] {
112+
; CHECK-NEXT: call void @llvm.donothing()
113+
; CHECK-NEXT: [[TMP1:%.*]] = load <vscale x 2 x float>, ptr [[A]], align 8
114+
; CHECK-NEXT: [[TMP2:%.*]] = ptrtoint ptr [[A]] to i64
115+
; CHECK-NEXT: [[TMP3:%.*]] = xor i64 [[TMP2]], 87960930222080
116+
; CHECK-NEXT: [[TMP4:%.*]] = inttoptr i64 [[TMP3]] to ptr
117+
; CHECK-NEXT: [[_MSLD:%.*]] = load <vscale x 2 x i32>, ptr [[TMP4]], align 8
118+
; CHECK-NEXT: store <vscale x 2 x i32> [[_MSLD]], ptr @__msan_retval_tls, align 8
119+
; CHECK-NEXT: ret <vscale x 2 x float> [[TMP1]]
120+
;
121+
%1 = load <vscale x 2 x float>, ptr %a
122+
ret <vscale x 2 x float> %1
123+
}
124+
125+
define void @test_ret(ptr %a, ptr %b) sanitize_memory {
126+
; CHECK-LABEL: define void @test_ret(
127+
; CHECK-SAME: ptr [[A:%.*]], ptr [[B:%.*]]) #[[ATTR0]] {
128+
; CHECK-NEXT: [[TMP1:%.*]] = load i64, ptr @__msan_param_tls, align 8
129+
; CHECK-NEXT: call void @llvm.donothing()
130+
; CHECK-NEXT: store i64 [[TMP1]], ptr @__msan_param_tls, align 8
131+
; CHECK-NEXT: store <vscale x 2 x i32> zeroinitializer, ptr @__msan_retval_tls, align 8
132+
; CHECK-NEXT: [[TMP5:%.*]] = call <vscale x 2 x float> @fn_ret(ptr [[A]])
133+
; CHECK-NEXT: [[_MSRET:%.*]] = load <vscale x 2 x i32>, ptr @__msan_retval_tls, align 8
134+
; CHECK-NEXT: [[TMP2:%.*]] = ptrtoint ptr [[B]] to i64
135+
; CHECK-NEXT: [[TMP3:%.*]] = xor i64 [[TMP2]], 87960930222080
136+
; CHECK-NEXT: [[TMP4:%.*]] = inttoptr i64 [[TMP3]] to ptr
137+
; CHECK-NEXT: store <vscale x 2 x i32> [[_MSRET]], ptr [[TMP4]], align 8
138+
; CHECK-NEXT: store <vscale x 2 x float> [[TMP5]], ptr [[B]], align 8
139+
; CHECK-NEXT: ret void
140+
;
141+
%1 = call <vscale x 2 x float> @fn_ret(ptr %a)
142+
store <vscale x 2 x float> %1, ptr %b
143+
ret void
144+
}
145+
146+
define void @fn_param(<vscale x 2 x float> %a, ptr %b) sanitize_memory {
147+
; CHECK-LABEL: define void @fn_param(
148+
; CHECK-SAME: <vscale x 2 x float> [[A:%.*]], ptr [[B:%.*]]) #[[ATTR0]] {
149+
; CHECK-NEXT: call void @llvm.donothing()
150+
; CHECK-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[B]] to i64
151+
; CHECK-NEXT: [[TMP2:%.*]] = xor i64 [[TMP1]], 87960930222080
152+
; CHECK-NEXT: [[TMP3:%.*]] = inttoptr i64 [[TMP2]] to ptr
153+
; CHECK-NEXT: store <vscale x 2 x i32> zeroinitializer, ptr [[TMP3]], align 8
154+
; CHECK-NEXT: store <vscale x 2 x float> [[A]], ptr [[B]], align 8
155+
; CHECK-NEXT: ret void
156+
;
157+
store <vscale x 2 x float> %a, ptr %b
158+
ret void
159+
}
160+
161+
define void @test_param(ptr %a, ptr %b) sanitize_memory {
162+
; CHECK-LABEL: define void @test_param(
163+
; CHECK-SAME: ptr [[A:%.*]], ptr [[B:%.*]]) #[[ATTR0]] {
164+
; CHECK-NEXT: [[TMP1:%.*]] = load i64, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__msan_param_tls to i64), i64 8) to ptr), align 8
165+
; CHECK-NEXT: call void @llvm.donothing()
166+
; CHECK-NEXT: [[TMP2:%.*]] = load <vscale x 2 x float>, ptr [[A]], align 8
167+
; CHECK-NEXT: [[TMP3:%.*]] = ptrtoint ptr [[A]] to i64
168+
; CHECK-NEXT: [[TMP4:%.*]] = xor i64 [[TMP3]], 87960930222080
169+
; CHECK-NEXT: [[TMP5:%.*]] = inttoptr i64 [[TMP4]] to ptr
170+
; CHECK-NEXT: [[_MSLD:%.*]] = load <vscale x 2 x i32>, ptr [[TMP5]], align 8
171+
; CHECK-NEXT: store i64 [[TMP1]], ptr @__msan_param_tls, align 8
172+
; CHECK-NEXT: [[TMP6:%.*]] = call i32 @llvm.vector.reduce.or.nxv2i32(<vscale x 2 x i32> [[_MSLD]])
173+
; CHECK-NEXT: [[_MSCMP:%.*]] = icmp ne i32 [[TMP6]], 0
174+
; CHECK-NEXT: br i1 [[_MSCMP]], label [[TMP7:%.*]], label [[TMP8:%.*]], !prof [[PROF0:![0-9]+]]
175+
; CHECK: 7:
176+
; CHECK-NEXT: call void @__msan_warning_noreturn() #[[ATTR4:[0-9]+]]
177+
; CHECK-NEXT: unreachable
178+
; CHECK: 8:
179+
; CHECK-NEXT: call void @fn_param(<vscale x 2 x float> [[TMP2]], ptr [[B]])
180+
; CHECK-NEXT: ret void
181+
;
182+
%1 = load <vscale x 2 x float>, ptr %a
183+
call void @fn_param(<vscale x 2 x float> %1, ptr %b)
184+
ret void
185+
}
186+
;.
187+
; CHECK: [[PROF0]] = !{!"branch_weights", i32 1, i32 1048575}
188+
;.

0 commit comments

Comments
 (0)