Skip to content

Commit 7002ecb

Browse files
authored
[msan] Convert vector shadow to scalar before zext (#96722)
zext does not allow converting vector shadow to scalar, so we must manually convert it prior to calling zext in materializeOneCheck, for which the 'ConvertedShadow' parameter isn't actually guaranteed to be scalar (1). Note that it is safe/no-op to call convertShadowToScalar on a shadow that is already scalar. In contrast, the storeOrigin function already converts the (potentially vector) shadow to scalar; we add a comment to note why it is load bearing. (1) In materializeInstructionChecks(): "// Disable combining in some cases. TrackOrigins checks each shadow to pick // correct origin. bool Combine = !MS.TrackOrigins; ... if (!Combine) { materializeOneCheck(IRB, ConvertedShadow, ShadowData.Origin); continue; }"
1 parent c02e8f7 commit 7002ecb

File tree

3 files changed

+29
-42
lines changed

3 files changed

+29
-42
lines changed

llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -1283,6 +1283,7 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
12831283
const DataLayout &DL = F.getDataLayout();
12841284
const Align OriginAlignment = std::max(kMinOriginAlignment, Alignment);
12851285
TypeSize StoreSize = DL.getTypeStoreSize(Shadow->getType());
1286+
// ZExt cannot convert between vector and scalar
12861287
Value *ConvertedShadow = convertShadowToScalar(Shadow, IRB);
12871288
if (auto *ConstantShadow = dyn_cast<Constant>(ConvertedShadow)) {
12881289
if (!ClCheckConstantShadow || ConstantShadow->isZeroValue()) {
@@ -1398,6 +1399,8 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
13981399
if (instrumentWithCalls(ConvertedShadow) &&
13991400
SizeIndex < kNumberOfAccessSizes && !MS.CompileKernel) {
14001401
FunctionCallee Fn = MS.MaybeWarningFn[SizeIndex];
1402+
// ZExt cannot convert between vector and scalar
1403+
ConvertedShadow = convertShadowToScalar(ConvertedShadow, IRB);
14011404
Value *ConvertedShadow2 =
14021405
IRB.CreateZExt(ConvertedShadow, IRB.getIntNTy(8 * (1 << SizeIndex)));
14031406
CallBase *CB = IRB.CreateCall(

llvm/test/Instrumentation/MemorySanitizer/vector-track-origins-neon.ll

+17-28
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,11 @@
1-
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --tool build-release/bin/opt --version 5
2-
; RUN: opt < %s -S -passes="msan<eager-checks;track-origins=2>" -msan-instrumentation-with-call-threshold=0 -disable-verify | FileCheck %s
3-
;
4-
; UNSUPPORTED: target={{.*}}
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --tool build/bin/opt --version 5
2+
; RUN: opt < %s -S -passes="msan<eager-checks;track-origins=2>" -msan-instrumentation-with-call-threshold=0 | FileCheck %s
53
;
64
; This test illustrates a bug in MemorySanitizer that will shortly be fixed
75
; (https://github.com/llvm/llvm-project/pull/96722).
86
;
97
; '-msan-instrumentation-with-call-threshold=0' makes it possible to detect the
108
; bug with a short test case.
11-
;
12-
; '-disable-verify' with a release build is needed to avoid a compiler crash
13-
; (e.g., to autogenerate the assertions).
14-
;
159

1610
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32"
1711
target triple = "aarch64-grtev4-linux-gnu"
@@ -28,36 +22,31 @@ define dso_local void @_Z1cv() local_unnamed_addr #0 {
2822
; CHECK-NEXT: br label %[[FOR_COND:.*]]
2923
; CHECK: [[FOR_COND]]:
3024
; CHECK-NEXT: [[_MSPHI_S:%.*]] = phi <4 x i16> [ [[_MSLD]], %[[ENTRY]] ], [ [[_MSLD3:%.*]], %[[FOR_COND]] ]
31-
; CHECK-NEXT: [[_MSPHI_O:%.*]] = phi i32 [ [[TMP0]], %[[ENTRY]] ], [ [[TMP15:%.*]], %[[FOR_COND]] ]
25+
; CHECK-NEXT: [[_MSPHI_O:%.*]] = phi i32 [ [[TMP0]], %[[ENTRY]] ], [ [[TMP11:%.*]], %[[FOR_COND]] ]
3226
; CHECK-NEXT: [[TMP1:%.*]] = phi <4 x i16> [ [[DOTPRE]], %[[ENTRY]] ], [ [[TMP5:%.*]], %[[FOR_COND]] ]
3327
; CHECK-NEXT: [[_MSPHI_S1:%.*]] = phi <4 x i16> [ <i16 -1, i16 -1, i16 -1, i16 -1>, %[[ENTRY]] ], [ [[_MSLD3]], %[[FOR_COND]] ]
34-
; CHECK-NEXT: [[_MSPHI_O2:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[TMP15]], %[[FOR_COND]] ]
28+
; CHECK-NEXT: [[_MSPHI_O2:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[TMP11]], %[[FOR_COND]] ]
3529
; CHECK-NEXT: [[E_0:%.*]] = phi <4 x i16> [ undef, %[[ENTRY]] ], [ [[TMP5]], %[[FOR_COND]] ]
3630
; CHECK-NEXT: [[_MSPROP:%.*]] = shufflevector <4 x i16> [[_MSPHI_S1]], <4 x i16> <i16 -1, i16 -1, i16 -1, i16 -1>, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
3731
; CHECK-NEXT: [[LANE:%.*]] = shufflevector <4 x i16> [[E_0]], <4 x i16> poison, <4 x i32> <i32 1, i32 1, i32 1, i32 1>
38-
;
39-
; Editor's note: the following zext instructions are invalid
40-
; ('zext source and destination must both be a vector or neither')
41-
;
42-
; CHECK-NEXT: [[TMP2:%.*]] = zext <4 x i16> [[_MSPHI_S]] to i64
32+
; CHECK-NEXT: [[TMP2:%.*]] = bitcast <4 x i16> [[_MSPHI_S]] to i64
4333
; CHECK-NEXT: call void @__msan_maybe_warning_8(i64 zeroext [[TMP2]], i32 zeroext [[_MSPHI_O]])
44-
; CHECK-NEXT: [[TMP3:%.*]] = zext <4 x i16> [[_MSPROP]] to i64
45-
;
34+
; CHECK-NEXT: [[TMP3:%.*]] = bitcast <4 x i16> [[_MSPROP]] to i64
4635
; CHECK-NEXT: call void @__msan_maybe_warning_8(i64 zeroext [[TMP3]], i32 zeroext [[_MSPHI_O2]])
4736
; CHECK-NEXT: [[CALL:%.*]] = tail call noundef i32 @_Z1b11__Int16x4_tS_(<4 x i16> noundef [[TMP1]], <4 x i16> noundef [[LANE]])
4837
; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[CALL]] to i64
49-
; CHECK-NEXT: [[TMP8:%.*]] = inttoptr i64 [[CONV]] to ptr
50-
; CHECK-NEXT: [[TMP5]] = load <4 x i16>, ptr [[TMP8]], align 8, !tbaa [[TBAA0]]
51-
; CHECK-NEXT: [[TMP10:%.*]] = ptrtoint ptr [[TMP8]] to i64
52-
; CHECK-NEXT: [[TMP11:%.*]] = xor i64 [[TMP10]], 193514046488576
53-
; CHECK-NEXT: [[TMP12:%.*]] = inttoptr i64 [[TMP11]] to ptr
54-
; CHECK-NEXT: [[TMP13:%.*]] = add i64 [[TMP11]], 35184372088832
55-
; CHECK-NEXT: [[TMP14:%.*]] = inttoptr i64 [[TMP13]] to ptr
56-
; CHECK-NEXT: [[_MSLD3]] = load <4 x i16>, ptr [[TMP12]], align 8
57-
; CHECK-NEXT: [[TMP15]] = load i32, ptr [[TMP14]], align 8
38+
; CHECK-NEXT: [[TMP4:%.*]] = inttoptr i64 [[CONV]] to ptr
39+
; CHECK-NEXT: [[TMP5]] = load <4 x i16>, ptr [[TMP4]], align 8, !tbaa [[TBAA0]]
40+
; CHECK-NEXT: [[TMP6:%.*]] = ptrtoint ptr [[TMP4]] to i64
41+
; CHECK-NEXT: [[TMP7:%.*]] = xor i64 [[TMP6]], 193514046488576
42+
; CHECK-NEXT: [[TMP8:%.*]] = inttoptr i64 [[TMP7]] to ptr
43+
; CHECK-NEXT: [[TMP9:%.*]] = add i64 [[TMP7]], 35184372088832
44+
; CHECK-NEXT: [[TMP10:%.*]] = inttoptr i64 [[TMP9]] to ptr
45+
; CHECK-NEXT: [[_MSLD3]] = load <4 x i16>, ptr [[TMP8]], align 8
46+
; CHECK-NEXT: [[TMP11]] = load i32, ptr [[TMP10]], align 8
5847
; CHECK-NEXT: store <4 x i16> [[_MSLD3]], ptr inttoptr (i64 xor (i64 ptrtoint (ptr @_Z1cv to i64), i64 193514046488576) to ptr), align 8
59-
; CHECK-NEXT: [[TMP16:%.*]] = bitcast <4 x i16> [[_MSLD3]] to i64
60-
; CHECK-NEXT: call void @__msan_maybe_store_origin_8(i64 zeroext [[TMP16]], ptr @_Z1cv, i32 zeroext [[TMP15]])
48+
; CHECK-NEXT: [[TMP12:%.*]] = bitcast <4 x i16> [[_MSLD3]] to i64
49+
; CHECK-NEXT: call void @__msan_maybe_store_origin_8(i64 zeroext [[TMP12]], ptr @_Z1cv, i32 zeroext [[TMP11]])
6150
; CHECK-NEXT: store <4 x i16> [[TMP5]], ptr @_Z1cv, align 8, !tbaa [[TBAA0]]
6251
; CHECK-NEXT: br label %[[FOR_COND]], !llvm.loop [[LOOP3:![0-9]+]]
6352
;

llvm/test/Instrumentation/MemorySanitizer/vector-track-origins-struct.ll

+9-14
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,12 @@
1-
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --tool build-release/bin/opt --version 5
2-
; RUN: opt < %s -S -passes="msan<eager-checks;track-origins=2>" -msan-instrumentation-with-call-threshold=0 -disable-verify | FileCheck %s
3-
;
4-
; UNSUPPORTED: target={{.*}}
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --tool build/bin/opt --version 5
2+
; RUN: opt < %s -S -passes="msan<eager-checks;track-origins=2>" -msan-instrumentation-with-call-threshold=0 | FileCheck %s
53
;
64
; This test illustrates a bug in MemorySanitizer that will shortly be fixed
75
; (https://github.com/llvm/llvm-project/pull/96722).
86
;
97
; '-msan-instrumentation-with-call-threshold=0' makes it possible to detect the
108
; bug with a short test case.
119
;
12-
; '-disable-verify' with a release build is needed to avoid a compiler crash
13-
; (e.g., to autogenerate the assertions).
14-
;
1510
; This is based on check-struct.ll.
1611

1712
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"
@@ -31,13 +26,13 @@ define { i32, i8 } @main() sanitize_memory {
3126
; CHECK-NEXT: [[_MSLD:%.*]] = load { i32, i8 }, ptr [[TMP3]], align 4
3227
; CHECK-NEXT: [[TMP6:%.*]] = load i32, ptr [[TMP5]], align 4
3328
; CHECK-NEXT: store { i32, i8 } zeroinitializer, ptr @__msan_retval_tls, align 8
34-
;
35-
; Editor's note: the following zext instruction is invalid
36-
; ('ZExt only operates on integer')
37-
;
38-
; CHECK-NEXT: [[TMP7:%.*]] = zext { i32, i8 } [[_MSLD]] to i64
39-
;
40-
; CHECK-NEXT: call void @__msan_maybe_warning_8(i64 zeroext [[TMP7]], i32 zeroext [[TMP6]])
29+
; CHECK-NEXT: [[TMP7:%.*]] = extractvalue { i32, i8 } [[_MSLD]], 0
30+
; CHECK-NEXT: [[TMP8:%.*]] = icmp ne i32 [[TMP7]], 0
31+
; CHECK-NEXT: [[TMP9:%.*]] = extractvalue { i32, i8 } [[_MSLD]], 1
32+
; CHECK-NEXT: [[TMP10:%.*]] = icmp ne i8 [[TMP9]], 0
33+
; CHECK-NEXT: [[TMP11:%.*]] = or i1 [[TMP8]], [[TMP10]]
34+
; CHECK-NEXT: [[TMP12:%.*]] = zext i1 [[TMP11]] to i64
35+
; CHECK-NEXT: call void @__msan_maybe_warning_8(i64 zeroext [[TMP12]], i32 zeroext [[TMP6]])
4136
; CHECK-NEXT: ret { i32, i8 } [[O]]
4237
;
4338
%p = inttoptr i64 0 to ptr

0 commit comments

Comments
 (0)