Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 39 additions & 1 deletion llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ static const Align kMinOriginAlignment = Align(4);
static const Align kShadowTLSAlignment = Align(8);

// These constants must be kept in sync with the ones in msan.h.
// TODO: increase size to match SVE/SVE2/SME/SME2 limits
static const unsigned kParamTLSSize = 800;
static const unsigned kRetvalTLSSize = 800;

Expand Down Expand Up @@ -1544,6 +1545,22 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
}
}

static bool isAArch64SVCount(Type *Ty) {
if (TargetExtType *TTy = dyn_cast<TargetExtType>(Ty))
return TTy->getName() == "aarch64.svcount";
return false;
}

// This is intended to match the "AArch64 Predicate-as-Counter Type" (aka
// 'target("aarch64.svcount")', but not e.g., <vscale x 4 x i32>.
static bool isScalableNonVectorType(Type *Ty) {
if (!isAArch64SVCount(Ty))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we want to assert, or do we reasonably expect this to happen?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The not branch will happen if a similar predicate is introduced for RISC-V, Loongaarch, etc. Adding an assert would break them unnecessarily.

OTOH at the moment I am (willfully) unaware of such a predicate on other platforms; hence, the log message for debugging because it is somewhat unexpected.

LLVM_DEBUG(dbgs() << "isScalableNonVectorType: Unexpected type " << *Ty
<< "\n");

return Ty->isScalableTy() && !isa<VectorType>(Ty);
}

void materializeChecks() {
#ifndef NDEBUG
// For assert below.
Expand Down Expand Up @@ -1672,6 +1689,12 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
LLVM_DEBUG(dbgs() << "getShadowTy: " << *ST << " ===> " << *Res << "\n");
return Res;
}
if (isScalableNonVectorType(OrigTy)) {
LLVM_DEBUG(dbgs() << "getShadowTy: Scalable non-vector type: " << *OrigTy
<< "\n");
return OrigTy;
}

uint32_t TypeSize = DL.getTypeSizeInBits(OrigTy);
return IntegerType::get(*MS.C, TypeSize);
}
Expand Down Expand Up @@ -2185,8 +2208,14 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
<< *OrigIns << "\n");
return;
}
#ifndef NDEBUG

Type *ShadowTy = Shadow->getType();
if (isScalableNonVectorType(ShadowTy)) {
LLVM_DEBUG(dbgs() << "Skipping check of scalable non-vector " << *Shadow
<< " before " << *OrigIns << "\n");
return;
}
#ifndef NDEBUG
assert((isa<IntegerType>(ShadowTy) || isa<VectorType>(ShadowTy) ||
isa<StructType>(ShadowTy) || isa<ArrayType>(ShadowTy)) &&
"Can only insert checks for integer, vector, and aggregate shadow "
Expand Down Expand Up @@ -6972,6 +7001,15 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
// an extra "select". This results in much more compact IR.
// Sa = select Sb, poisoned, (select b, Sc, Sd)
Sa1 = getPoisonedShadow(getShadowTy(I.getType()));
} else if (isScalableNonVectorType(I.getType())) {
// This is intended to handle target("aarch64.svcount"), which can't be
// handled in the else branch because of incompatibility with CreateXor
// ("The supported LLVM operations on this type are limited to load,
// store, phi, select and alloca instructions").

// TODO: this currently underapproximates. Use Arm SVE EOR in the else
// branch as needed instead.
Sa1 = getCleanShadow(getShadowTy(I.getType()));
} else {
// Sa = select Sb, [ (c^d) | Sc | Sd ], [ b ? Sc : Sd ]
// If Sb (condition is poisoned), look for bits in c and d that are equal
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -S -passes=msan -mattr=+sme -o - %s

; XFAIL: *
; RUN: opt -S -passes=msan -mattr=+sme -o - %s | FileCheck %s

; Forked from llvm/test/CodeGen/AArch64/sme-aarch64-svcount.ll
; Manually minimized to show MSan leads to a compiler crash

target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
target triple = "aarch64--linux-android9001"

define target("aarch64.svcount") @test_return_arg1(target("aarch64.svcount") %arg0, target("aarch64.svcount") %arg1) nounwind {
; CHECK-LABEL: @test_return_arg1(
; CHECK-NEXT: call void @llvm.donothing()
; CHECK-NEXT: store target("aarch64.svcount") zeroinitializer, ptr @__msan_retval_tls, align 8
; CHECK-NEXT: ret target("aarch64.svcount") [[ARG1:%.*]]
;
ret target("aarch64.svcount") %arg1
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -S -passes=msan -mattr=+sme -o - %s

; XFAIL: *
; RUN: opt -S -passes=msan -mattr=+sme -o - %s | FileCheck %s

; Forked from llvm/test/CodeGen/AArch64/sme-aarch64-svcount.ll

Expand All @@ -12,16 +10,49 @@ target triple = "aarch64--linux-android9001"
; Test simple loads, stores and return.
;
define target("aarch64.svcount") @test_load(ptr %ptr) nounwind {
; CHECK-LABEL: @test_load(
; CHECK-NEXT: call void @llvm.donothing()
; CHECK-NEXT: [[RES:%.*]] = load target("aarch64.svcount"), ptr [[PTR:%.*]], align 2
; CHECK-NEXT: store target("aarch64.svcount") zeroinitializer, ptr @__msan_retval_tls, align 8
; CHECK-NEXT: ret target("aarch64.svcount") [[RES]]
;
%res = load target("aarch64.svcount"), ptr %ptr
ret target("aarch64.svcount") %res
}

define void @test_store(ptr %ptr, target("aarch64.svcount") %val) nounwind {
; CHECK-LABEL: @test_store(
; CHECK-NEXT: call void @llvm.donothing()
; CHECK-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[PTR:%.*]] to i64
; CHECK-NEXT: [[TMP2:%.*]] = xor i64 [[TMP1]], 193514046488576
; CHECK-NEXT: [[TMP3:%.*]] = inttoptr i64 [[TMP2]] to ptr
; CHECK-NEXT: store target("aarch64.svcount") zeroinitializer, ptr [[TMP3]], align 2
; CHECK-NEXT: store target("aarch64.svcount") [[VAL:%.*]], ptr [[PTR]], align 2
; CHECK-NEXT: ret void
;
store target("aarch64.svcount") %val, ptr %ptr
ret void
}

define target("aarch64.svcount") @test_alloca_store_reload(target("aarch64.svcount") %val) nounwind {
; CHECK-LABEL: @test_alloca_store_reload(
; CHECK-NEXT: call void @llvm.donothing()
; CHECK-NEXT: [[PTR:%.*]] = alloca target("aarch64.svcount"), align 1
; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.vscale.i64()
; CHECK-NEXT: [[TMP2:%.*]] = mul nuw i64 [[TMP1]], 2
; CHECK-NEXT: [[TMP3:%.*]] = ptrtoint ptr [[PTR]] to i64
; CHECK-NEXT: [[TMP4:%.*]] = xor i64 [[TMP3]], 193514046488576
; CHECK-NEXT: [[TMP5:%.*]] = inttoptr i64 [[TMP4]] to ptr
; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP5]], i8 0, i64 [[TMP2]], i1 false)
; CHECK-NEXT: [[TMP6:%.*]] = ptrtoint ptr [[PTR]] to i64
; CHECK-NEXT: [[TMP7:%.*]] = xor i64 [[TMP6]], 193514046488576
; CHECK-NEXT: [[TMP8:%.*]] = inttoptr i64 [[TMP7]] to ptr
; CHECK-NEXT: store target("aarch64.svcount") zeroinitializer, ptr [[TMP8]], align 2
; CHECK-NEXT: store target("aarch64.svcount") [[VAL:%.*]], ptr [[PTR]], align 2
; CHECK-NEXT: [[RES:%.*]] = load target("aarch64.svcount"), ptr [[PTR]], align 2
; CHECK-NEXT: store target("aarch64.svcount") zeroinitializer, ptr @__msan_retval_tls, align 8
; CHECK-NEXT: ret target("aarch64.svcount") [[RES]]
;
%ptr = alloca target("aarch64.svcount"), align 1
store target("aarch64.svcount") %val, ptr %ptr
%res = load target("aarch64.svcount"), ptr %ptr
Expand All @@ -33,10 +64,20 @@ define target("aarch64.svcount") @test_alloca_store_reload(target("aarch64.svcou
;

define target("aarch64.svcount") @test_return_arg1(target("aarch64.svcount") %arg0, target("aarch64.svcount") %arg1) nounwind {
; CHECK-LABEL: @test_return_arg1(
; CHECK-NEXT: call void @llvm.donothing()
; CHECK-NEXT: store target("aarch64.svcount") zeroinitializer, ptr @__msan_retval_tls, align 8
; CHECK-NEXT: ret target("aarch64.svcount") [[ARG1:%.*]]
;
ret target("aarch64.svcount") %arg1
}

define target("aarch64.svcount") @test_return_arg4(target("aarch64.svcount") %arg0, target("aarch64.svcount") %arg1, target("aarch64.svcount") %arg2, target("aarch64.svcount") %arg3, target("aarch64.svcount") %arg4) nounwind {
; CHECK-LABEL: @test_return_arg4(
; CHECK-NEXT: call void @llvm.donothing()
; CHECK-NEXT: store target("aarch64.svcount") zeroinitializer, ptr @__msan_retval_tls, align 8
; CHECK-NEXT: ret target("aarch64.svcount") [[ARG4:%.*]]
;
ret target("aarch64.svcount") %arg4
}

Expand All @@ -46,22 +87,58 @@ define target("aarch64.svcount") @test_return_arg4(target("aarch64.svcount") %ar

declare void @take_svcount_1(target("aarch64.svcount") %arg)
define void @test_pass_1arg(target("aarch64.svcount") %arg) nounwind {
; CHECK-LABEL: @test_pass_1arg(
; CHECK-NEXT: call void @llvm.donothing()
; CHECK-NEXT: call void @take_svcount_1(target("aarch64.svcount") [[ARG:%.*]])
; CHECK-NEXT: ret void
;
call void @take_svcount_1(target("aarch64.svcount") %arg)
ret void
}

declare void @take_svcount_5(target("aarch64.svcount") %arg0, target("aarch64.svcount") %arg1, target("aarch64.svcount") %arg2, target("aarch64.svcount") %arg3, target("aarch64.svcount") %arg4)
define void @test_pass_5args(target("aarch64.svcount") %arg) nounwind {
; CHECK-LABEL: @test_pass_5args(
; CHECK-NEXT: call void @llvm.donothing()
; CHECK-NEXT: call void @take_svcount_5(target("aarch64.svcount") [[ARG:%.*]], target("aarch64.svcount") [[ARG]], target("aarch64.svcount") [[ARG]], target("aarch64.svcount") [[ARG]], target("aarch64.svcount") [[ARG]])
; CHECK-NEXT: ret void
;
call void @take_svcount_5(target("aarch64.svcount") %arg, target("aarch64.svcount") %arg, target("aarch64.svcount") %arg, target("aarch64.svcount") %arg, target("aarch64.svcount") %arg)
ret void
}

define target("aarch64.svcount") @test_sel(target("aarch64.svcount") %x, target("aarch64.svcount") %y, i1 %cmp) sanitize_memory {
; CHECK-LABEL: @test_sel(
; CHECK-NEXT: [[TMP1:%.*]] = load i1, ptr @__msan_param_tls, align 8
; CHECK-NEXT: call void @llvm.donothing()
; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[CMP:%.*]], target("aarch64.svcount") zeroinitializer, target("aarch64.svcount") zeroinitializer
; CHECK-NEXT: [[_MSPROP_SELECT:%.*]] = select i1 [[TMP1]], target("aarch64.svcount") zeroinitializer, target("aarch64.svcount") [[TMP2]]
; CHECK-NEXT: [[X_Y:%.*]] = select i1 [[CMP]], target("aarch64.svcount") [[X:%.*]], target("aarch64.svcount") [[Y:%.*]]
; CHECK-NEXT: store target("aarch64.svcount") [[_MSPROP_SELECT]], ptr @__msan_retval_tls, align 8
; CHECK-NEXT: ret target("aarch64.svcount") [[X_Y]]
;
%x.y = select i1 %cmp, target("aarch64.svcount") %x, target("aarch64.svcount") %y
ret target("aarch64.svcount") %x.y
}

define target("aarch64.svcount") @test_sel_cc(target("aarch64.svcount") %x, target("aarch64.svcount") %y, i32 %k) sanitize_memory {
; CHECK-LABEL: @test_sel_cc(
; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr @__msan_param_tls, align 8
; CHECK-NEXT: call void @llvm.donothing()
; CHECK-NEXT: [[TMP2:%.*]] = xor i32 [[K:%.*]], -2147483648
; CHECK-NEXT: [[TMP3:%.*]] = xor i32 [[TMP1]], -1
; CHECK-NEXT: [[TMP4:%.*]] = and i32 [[TMP2]], [[TMP3]]
; CHECK-NEXT: [[TMP5:%.*]] = or i32 [[TMP2]], [[TMP1]]
; CHECK-NEXT: [[TMP6:%.*]] = icmp ugt i32 [[TMP4]], -2147483606
; CHECK-NEXT: [[TMP7:%.*]] = icmp ugt i32 [[TMP5]], -2147483606
; CHECK-NEXT: [[TMP8:%.*]] = xor i1 [[TMP6]], [[TMP7]]
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[K]], 42
; CHECK-NEXT: [[TMP9:%.*]] = select i1 [[CMP]], target("aarch64.svcount") zeroinitializer, target("aarch64.svcount") zeroinitializer
; CHECK-NEXT: [[_MSPROP_SELECT:%.*]] = select i1 [[TMP8]], target("aarch64.svcount") zeroinitializer, target("aarch64.svcount") [[TMP9]]
; CHECK-NEXT: [[X_Y:%.*]] = select i1 [[CMP]], target("aarch64.svcount") [[X:%.*]], target("aarch64.svcount") [[Y:%.*]]
; CHECK-NEXT: store target("aarch64.svcount") [[_MSPROP_SELECT]], ptr @__msan_retval_tls, align 8
; CHECK-NEXT: ret target("aarch64.svcount") [[X_Y]]
;
%cmp = icmp sgt i32 %k, 42
%x.y = select i1 %cmp, target("aarch64.svcount") %x, target("aarch64.svcount") %y
ret target("aarch64.svcount") %x.y
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -S -passes=msan -mattr=+sme2 -mattr=+sme-i16i64 -mattr=+sme-f64f64 -o - %s

; XFAIL: *
; RUN: opt -S -passes=msan -mattr=+sme2 -mattr=+sme-i16i64 -mattr=+sme-f64f64 -o - %s | FileCheck %s

; Forked from llvm/test/CodeGen/AArch64/sme2-intrinsics-add.ll
; Manually reduced to show MSan leads to a compiler crash
Expand All @@ -10,6 +8,19 @@ target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
target triple = "aarch64--linux-android9001"

define void @multi_vector_add_za_vg1x4_f32_tuple(i64 %stride, ptr %ptr) sanitize_memory {
; CHECK-LABEL: @multi_vector_add_za_vg1x4_f32_tuple(
; CHECK-NEXT: [[TMP1:%.*]] = load i64, ptr getelementptr (i8, ptr @__msan_param_tls, i64 8), align 8
; CHECK-NEXT: call void @llvm.donothing()
; CHECK-NEXT: [[TMP2:%.*]] = tail call target("aarch64.svcount") @llvm.aarch64.sve.ptrue.c8()
; CHECK-NEXT: [[_MSCMP:%.*]] = icmp ne i64 [[TMP1]], 0
; CHECK-NEXT: br i1 [[_MSCMP]], label [[TMP3:%.*]], label [[TMP4:%.*]], !prof [[PROF1:![0-9]+]]
; CHECK: 3:
; CHECK-NEXT: call void @__msan_warning_noreturn() #[[ATTR5:[0-9]+]]
; CHECK-NEXT: unreachable
; CHECK: 4:
; CHECK-NEXT: [[TMP5:%.*]] = tail call { <vscale x 4 x float>, <vscale x 4 x float>, <vscale x 4 x float>, <vscale x 4 x float> } @llvm.aarch64.sve.ld1.pn.x4.nxv4f32(target("aarch64.svcount") [[TMP2]], ptr [[PTR:%.*]])
; CHECK-NEXT: ret void
;
%1 = tail call target("aarch64.svcount") @llvm.aarch64.sve.ptrue.c8()
%2 = tail call { <vscale x 4 x float>, <vscale x 4 x float>, <vscale x 4 x float>, <vscale x 4 x float> } @llvm.aarch64.sve.ld1.pn.x4.nxv4f32(target("aarch64.svcount") %1, ptr %ptr)
ret void
Expand Down
Loading