[llvm] [msan] Fix false negatives from partially undefined constant fixed-length vectors (PR #143837)
Thurston Dang via llvm-commits
llvm-commits at lists.llvm.org
Fri Jun 13 15:44:55 PDT 2025
https://github.com/thurstond updated https://github.com/llvm/llvm-project/pull/143837
>From 2f1c4b5107aec730b35fd8eae90f7be33a6e5cc2 Mon Sep 17 00:00:00 2001
From: Thurston Dang <thurston at google.com>
Date: Thu, 12 Jun 2025 06:01:16 +0000
Subject: [PATCH 1/7] [msan] Fix shadow computation for partially undefined
constant fixed-length vectors
For each element of the vector, the shadow is initialized iff the
element is not undefined/poisoned. Previously, partially undefined
constant fixed-length vectors always had fully initialized shadows,
which leads to false negatives.
Updates the tests from https://github.com/llvm/llvm-project/pull/143823
Note: since this patch corrects a false negative, MSan can now detect more bugs (corollary: code/tests that passed MSan may start failing).
---
.../Instrumentation/MemorySanitizer.cpp | 23 +++++++++++++++++--
.../MemorySanitizer/partial-poison.ll | 11 ++++-----
2 files changed, 26 insertions(+), 8 deletions(-)
diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
index d3c6a7151ec37..b345d9dc06654 100644
--- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
@@ -1989,6 +1989,8 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
}
return Shadow;
}
+ // Handle fully undefined values
+ // (partially undefined constant vectors are handled later)
if (UndefValue *U = dyn_cast<UndefValue>(V)) {
Value *AllOnes = (PropagateShadow && PoisonUndef) ? getPoisonedShadow(V)
: getCleanShadow(V);
@@ -2086,8 +2088,25 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
return ShadowPtr;
}
- // TODO: Partially undefined vectors are handled by the fall-through case
- // below (see partial-poison.ll); this causes false negatives.
+ // Check for partially undefined constant vectors
+ // TODO: scalable vectors (this is hard because we do not have IRBuilder)
+ if ( isa<FixedVectorType>(V->getType())
+ && isa<Constant>(V)
+ && (cast<Constant>(V))->containsUndefOrPoisonElement()
+ && PropagateShadow
+ && PoisonUndef) {
+ unsigned NumElems = (cast<FixedVectorType>(V->getType()))->getNumElements();
+ SmallVector<Constant *, 32> ShadowVector(NumElems);
+ for (unsigned i = 0; i != NumElems; ++i) {
+ Constant *Elem = (cast<Constant>(V))->getAggregateElement(i);
+ ShadowVector[i] = isa<UndefValue>(Elem) ? getPoisonedShadow(Elem) : getCleanShadow(Elem);
+ }
+
+ Value *ShadowConstant = ConstantVector::get(ShadowVector);
+ LLVM_DEBUG(dbgs() << "Partial undef constant vector: " << *V << " ==> " << *ShadowConstant << "\n");
+
+ return ShadowConstant;
+ }
// For everything else the shadow is zero.
return getCleanShadow(V);
diff --git a/llvm/test/Instrumentation/MemorySanitizer/partial-poison.ll b/llvm/test/Instrumentation/MemorySanitizer/partial-poison.ll
index 5164441c17e10..e058086b040ad 100644
--- a/llvm/test/Instrumentation/MemorySanitizer/partial-poison.ll
+++ b/llvm/test/Instrumentation/MemorySanitizer/partial-poison.ll
@@ -1,8 +1,7 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
; RUN: opt < %s -S -passes='msan' 2>&1 | FileCheck %s
;
-; Test case to show that MSan computes shadows for partially poisoned vectors
-; as fully initialized, resulting in false negatives.
+; Regression test case for computing shadows of partially poisoned vectors
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"
target triple = "x86_64-unknown-linux-gnu"
@@ -11,7 +10,7 @@ define <2 x i64> @left_poison(ptr %add.ptr) sanitize_memory {
; CHECK-LABEL: define <2 x i64> @left_poison(
; CHECK-SAME: ptr [[ADD_PTR:%.*]]) #[[ATTR0:[0-9]+]] {
; CHECK-NEXT: call void @llvm.donothing()
-; CHECK-NEXT: store <2 x i64> zeroinitializer, ptr @__msan_retval_tls, align 8
+; CHECK-NEXT: store <2 x i64> <i64 -1, i64 0>, ptr @__msan_retval_tls, align 8
; CHECK-NEXT: ret <2 x i64> <i64 poison, i64 42>
;
ret <2 x i64> <i64 poison, i64 42>
@@ -21,7 +20,7 @@ define <2 x i64> @right_poison(ptr %add.ptr) sanitize_memory {
; CHECK-LABEL: define <2 x i64> @right_poison(
; CHECK-SAME: ptr [[ADD_PTR:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: call void @llvm.donothing()
-; CHECK-NEXT: store <2 x i64> zeroinitializer, ptr @__msan_retval_tls, align 8
+; CHECK-NEXT: store <2 x i64> <i64 0, i64 -1>, ptr @__msan_retval_tls, align 8
; CHECK-NEXT: ret <2 x i64> <i64 42, i64 poison>
;
ret <2 x i64> <i64 42, i64 poison>
@@ -51,7 +50,7 @@ define <2 x i64> @left_undef(ptr %add.ptr) sanitize_memory {
; CHECK-LABEL: define <2 x i64> @left_undef(
; CHECK-SAME: ptr [[ADD_PTR:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: call void @llvm.donothing()
-; CHECK-NEXT: store <2 x i64> zeroinitializer, ptr @__msan_retval_tls, align 8
+; CHECK-NEXT: store <2 x i64> <i64 -1, i64 0>, ptr @__msan_retval_tls, align 8
; CHECK-NEXT: ret <2 x i64> <i64 undef, i64 42>
;
ret <2 x i64> <i64 undef, i64 42>
@@ -61,7 +60,7 @@ define <2 x i64> @right_undef(ptr %add.ptr) sanitize_memory {
; CHECK-LABEL: define <2 x i64> @right_undef(
; CHECK-SAME: ptr [[ADD_PTR:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: call void @llvm.donothing()
-; CHECK-NEXT: store <2 x i64> zeroinitializer, ptr @__msan_retval_tls, align 8
+; CHECK-NEXT: store <2 x i64> <i64 0, i64 -1>, ptr @__msan_retval_tls, align 8
; CHECK-NEXT: ret <2 x i64> <i64 42, i64 undef>
;
ret <2 x i64> <i64 42, i64 undef>
>From 2f3fa0b6815e8c1f86d4d12ad223206210b25aba Mon Sep 17 00:00:00 2001
From: Thurston Dang <thurston at google.com>
Date: Thu, 12 Jun 2025 06:11:24 +0000
Subject: [PATCH 2/7] clang-format
---
.../Instrumentation/MemorySanitizer.cpp | 17 +++++++++--------
1 file changed, 9 insertions(+), 8 deletions(-)
diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
index b345d9dc06654..9464a3918d4af 100644
--- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
@@ -2090,20 +2090,21 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
// Check for partially undefined constant vectors
// TODO: scalable vectors (this is hard because we do not have IRBuilder)
- if ( isa<FixedVectorType>(V->getType())
- && isa<Constant>(V)
- && (cast<Constant>(V))->containsUndefOrPoisonElement()
- && PropagateShadow
- && PoisonUndef) {
- unsigned NumElems = (cast<FixedVectorType>(V->getType()))->getNumElements();
+ if (isa<FixedVectorType>(V->getType()) && isa<Constant>(V) &&
+ (cast<Constant>(V))->containsUndefOrPoisonElement() &&
+ PropagateShadow && PoisonUndef) {
+ unsigned NumElems =
+ (cast<FixedVectorType>(V->getType()))->getNumElements();
SmallVector<Constant *, 32> ShadowVector(NumElems);
for (unsigned i = 0; i != NumElems; ++i) {
Constant *Elem = (cast<Constant>(V))->getAggregateElement(i);
- ShadowVector[i] = isa<UndefValue>(Elem) ? getPoisonedShadow(Elem) : getCleanShadow(Elem);
+ ShadowVector[i] = isa<UndefValue>(Elem) ? getPoisonedShadow(Elem)
+ : getCleanShadow(Elem);
}
Value *ShadowConstant = ConstantVector::get(ShadowVector);
- LLVM_DEBUG(dbgs() << "Partial undef constant vector: " << *V << " ==> " << *ShadowConstant << "\n");
+ LLVM_DEBUG(dbgs() << "Partial undef constant vector: " << *V << " ==> "
+ << *ShadowConstant << "\n");
return ShadowConstant;
}
>From 97bfb3444939d7f166fc4b48e7e3fd652ac69496 Mon Sep 17 00:00:00 2001
From: Thurston Dang <thurston at google.com>
Date: Thu, 12 Jun 2025 21:00:02 +0000
Subject: [PATCH 3/7] Add 'msan-poison-undef-vectors' for shitty compilers
Also update tests and TODOs
---
.../Instrumentation/MemorySanitizer.cpp | 16 +++++++-
.../MemorySanitizer/partial-poison.ll | 40 +++++++++++++++----
2 files changed, 47 insertions(+), 9 deletions(-)
diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
index 9464a3918d4af..7584bf9240e3c 100644
--- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
@@ -269,6 +269,14 @@ static cl::opt<bool> ClPoisonUndef("msan-poison-undef",
cl::desc("poison undef temps"), cl::Hidden,
cl::init(true));
+static cl::opt<bool> ClPoisonUndefVectors(
+ "msan-poison-undef-vectors",
+ cl::desc("Precisely poison partially undefined constant vectors. "
+ "If false (legacy behavior), the entire vector is "
+ "considered fully initialized, which may lead to false "
+ "negatives."),
+ cl::Hidden, cl::init(true));
+
static cl::opt<bool>
ClHandleICmp("msan-handle-icmp",
cl::desc("propagate shadow through ICmpEQ and ICmpNE"),
@@ -1181,6 +1189,7 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
bool PropagateShadow;
bool PoisonStack;
bool PoisonUndef;
+ bool PoisonUndefVectors;
struct ShadowOriginAndInsertPoint {
Value *Shadow;
@@ -1207,6 +1216,7 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
PropagateShadow = SanitizeFunction;
PoisonStack = SanitizeFunction && ClPoisonStack;
PoisonUndef = SanitizeFunction && ClPoisonUndef;
+ PoisonUndefVectors = SanitizeFunction && ClPoisonUndefVectors;
// In the presence of unreachable blocks, we may see Phi nodes with
// incoming nodes from such blocks. Since InstVisitor skips unreachable
@@ -2088,11 +2098,11 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
return ShadowPtr;
}
- // Check for partially undefined constant vectors
+ // Check for partially-undefined constant vectors
// TODO: scalable vectors (this is hard because we do not have IRBuilder)
if (isa<FixedVectorType>(V->getType()) && isa<Constant>(V) &&
(cast<Constant>(V))->containsUndefOrPoisonElement() &&
- PropagateShadow && PoisonUndef) {
+ PropagateShadow && PoisonUndefVectors) {
unsigned NumElems =
(cast<FixedVectorType>(V->getType()))->getNumElements();
SmallVector<Constant *, 32> ShadowVector(NumElems);
@@ -2109,6 +2119,8 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
return ShadowConstant;
}
+ // TODO: partially-undefined constant arrays, structures, and nested types
+
// For everything else the shadow is zero.
return getCleanShadow(V);
}
diff --git a/llvm/test/Instrumentation/MemorySanitizer/partial-poison.ll b/llvm/test/Instrumentation/MemorySanitizer/partial-poison.ll
index e058086b040ad..184794f124e5a 100644
--- a/llvm/test/Instrumentation/MemorySanitizer/partial-poison.ll
+++ b/llvm/test/Instrumentation/MemorySanitizer/partial-poison.ll
@@ -1,7 +1,9 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
-; RUN: opt < %s -S -passes='msan' 2>&1 | FileCheck %s
+; RUN: opt < %s -S -passes='msan' 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-PRECISE
+; RUN: opt < %s -S -passes='msan' -msan-poison-undef-vectors=false 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-IMPRECISE
;
-; Regression test case for computing shadows of partially poisoned vectors
+; Regression test case for computing shadows of partially poisoned vectors.
+; Partially poisoned structs and arrays are not correctly implemented.
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"
target triple = "x86_64-unknown-linux-gnu"
@@ -10,7 +12,8 @@ define <2 x i64> @left_poison(ptr %add.ptr) sanitize_memory {
; CHECK-LABEL: define <2 x i64> @left_poison(
; CHECK-SAME: ptr [[ADD_PTR:%.*]]) #[[ATTR0:[0-9]+]] {
; CHECK-NEXT: call void @llvm.donothing()
-; CHECK-NEXT: store <2 x i64> <i64 -1, i64 0>, ptr @__msan_retval_tls, align 8
+; CHECK-PRECISE: store <2 x i64> <i64 -1, i64 0>, ptr @__msan_retval_tls, align 8
+; CHECK-IMPRECISE: store <2 x i64> zeroinitializer, ptr @__msan_retval_tls, align 8
; CHECK-NEXT: ret <2 x i64> <i64 poison, i64 42>
;
ret <2 x i64> <i64 poison, i64 42>
@@ -20,7 +23,8 @@ define <2 x i64> @right_poison(ptr %add.ptr) sanitize_memory {
; CHECK-LABEL: define <2 x i64> @right_poison(
; CHECK-SAME: ptr [[ADD_PTR:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: call void @llvm.donothing()
-; CHECK-NEXT: store <2 x i64> <i64 0, i64 -1>, ptr @__msan_retval_tls, align 8
+; CHECK-PRECISE: store <2 x i64> <i64 0, i64 -1>, ptr @__msan_retval_tls, align 8
+; CHECK-IMPRECISE: store <2 x i64> zeroinitializer, ptr @__msan_retval_tls, align 8
; CHECK-NEXT: ret <2 x i64> <i64 42, i64 poison>
;
ret <2 x i64> <i64 42, i64 poison>
@@ -50,7 +54,8 @@ define <2 x i64> @left_undef(ptr %add.ptr) sanitize_memory {
; CHECK-LABEL: define <2 x i64> @left_undef(
; CHECK-SAME: ptr [[ADD_PTR:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: call void @llvm.donothing()
-; CHECK-NEXT: store <2 x i64> <i64 -1, i64 0>, ptr @__msan_retval_tls, align 8
+; CHECK-PRECISE: store <2 x i64> <i64 -1, i64 0>, ptr @__msan_retval_tls, align 8
+; CHECK-IMPRECISE: store <2 x i64> zeroinitializer, ptr @__msan_retval_tls, align 8
; CHECK-NEXT: ret <2 x i64> <i64 undef, i64 42>
;
ret <2 x i64> <i64 undef, i64 42>
@@ -60,7 +65,8 @@ define <2 x i64> @right_undef(ptr %add.ptr) sanitize_memory {
; CHECK-LABEL: define <2 x i64> @right_undef(
; CHECK-SAME: ptr [[ADD_PTR:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: call void @llvm.donothing()
-; CHECK-NEXT: store <2 x i64> <i64 0, i64 -1>, ptr @__msan_retval_tls, align 8
+; CHECK-PRECISE: store <2 x i64> <i64 0, i64 -1>, ptr @__msan_retval_tls, align 8
+; CHECK-IMPRECISE: store <2 x i64> zeroinitializer, ptr @__msan_retval_tls, align 8
; CHECK-NEXT: ret <2 x i64> <i64 42, i64 undef>
;
ret <2 x i64> <i64 42, i64 undef>
@@ -70,8 +76,28 @@ define <2 x i64> @full_undef(ptr %add.ptr) sanitize_memory {
; CHECK-LABEL: define <2 x i64> @full_undef(
; CHECK-SAME: ptr [[ADD_PTR:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: call void @llvm.donothing()
-; CHECK-NEXT: store <2 x i64> splat (i64 -1), ptr @__msan_retval_tls, align 8
+; CHECK: store <2 x i64> splat (i64 -1), ptr @__msan_retval_tls, align 8
; CHECK-NEXT: ret <2 x i64> undef
;
ret <2 x i64> <i64 undef, i64 undef>
}
+
+define {i64, i64} @struct_left_undef() sanitize_memory {
+; CHECK-LABEL: define { i64, i64 } @struct_left_undef(
+; CHECK-SAME: ) #[[ATTR0]] {
+; CHECK-NEXT: call void @llvm.donothing()
+; CHECK-NEXT: store { i64, i64 } zeroinitializer, ptr @__msan_retval_tls, align 8
+; CHECK-NEXT: ret { i64, i64 } { i64 undef, i64 42 }
+;
+ ret {i64, i64} { i64 undef, i64 42 }
+}
+
+define [2x i64] @array_right_undef() sanitize_memory {
+; CHECK-LABEL: define [2 x i64] @array_right_undef(
+; CHECK-SAME: ) #[[ATTR0]] {
+; CHECK-NEXT: call void @llvm.donothing()
+; CHECK-NEXT: store [2 x i64] zeroinitializer, ptr @__msan_retval_tls, align 8
+; CHECK-NEXT: ret [2 x i64] [i64 42, i64 undef]
+;
+ ret [2x i64] [ i64 42, i64 undef ]
+}
>From 09e88e65449cafd1c8148c62976908e8adddc087 Mon Sep 17 00:00:00 2001
From: Thurston Dang <thurston at google.com>
Date: Thu, 12 Jun 2025 21:01:46 +0000
Subject: [PATCH 4/7] Save money on parenthesis licensing fees
---
llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
index 7584bf9240e3c..020267c4582da 100644
--- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
@@ -2101,13 +2101,12 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
// Check for partially-undefined constant vectors
// TODO: scalable vectors (this is hard because we do not have IRBuilder)
if (isa<FixedVectorType>(V->getType()) && isa<Constant>(V) &&
- (cast<Constant>(V))->containsUndefOrPoisonElement() &&
- PropagateShadow && PoisonUndefVectors) {
- unsigned NumElems =
- (cast<FixedVectorType>(V->getType()))->getNumElements();
+ cast<Constant>(V)->containsUndefOrPoisonElement() && PropagateShadow &&
+ PoisonUndefVectors) {
+ unsigned NumElems = cast<FixedVectorType>(V->getType())->getNumElements();
SmallVector<Constant *, 32> ShadowVector(NumElems);
for (unsigned i = 0; i != NumElems; ++i) {
- Constant *Elem = (cast<Constant>(V))->getAggregateElement(i);
+ Constant *Elem = cast<Constant>(V)->getAggregateElement(i);
ShadowVector[i] = isa<UndefValue>(Elem) ? getPoisonedShadow(Elem)
: getCleanShadow(Elem);
}
>From 8db04fb22a9c98fdb2aa9f974e2956f626f9ff6d Mon Sep 17 00:00:00 2001
From: Thurston Dang <thurston at google.com>
Date: Thu, 12 Jun 2025 23:44:06 +0000
Subject: [PATCH 5/7] Clarify non-interaction of msan-poison-undef and
msan-poison-undef-vectors.
---
.../Transforms/Instrumentation/MemorySanitizer.cpp | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
index 020267c4582da..e3afa93b8a670 100644
--- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
@@ -265,16 +265,21 @@ static cl::opt<bool>
cl::desc("Print name of local stack variable"),
cl::Hidden, cl::init(true));
-static cl::opt<bool> ClPoisonUndef("msan-poison-undef",
- cl::desc("poison undef temps"), cl::Hidden,
- cl::init(true));
+static cl::opt<bool>
+ ClPoisonUndef("msan-poison-undef",
+ cl::desc("Poison fully undef temporary values. "
+ "Partially undefined constant vectors "
+ "are unaffected by this flag (see "
+ "-msan-poison-undef-vectors)."),
+ cl::Hidden, cl::init(true));
static cl::opt<bool> ClPoisonUndefVectors(
"msan-poison-undef-vectors",
cl::desc("Precisely poison partially undefined constant vectors. "
"If false (legacy behavior), the entire vector is "
"considered fully initialized, which may lead to false "
- "negatives."),
+ "negatives. Fully undefined constant vectors are "
+ "unaffected by this flag (see -msan-poison-undef)."),
cl::Hidden, cl::init(true));
static cl::opt<bool>
>From 4d4a8055ab51566f4fc31269a4c8863aa8191e6e Mon Sep 17 00:00:00 2001
From: Thurston Dang <thurston at google.com>
Date: Fri, 13 Jun 2025 05:27:26 +0000
Subject: [PATCH 6/7] Add back CHECK-NEXT
---
llvm/test/Instrumentation/MemorySanitizer/partial-poison.ll | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/test/Instrumentation/MemorySanitizer/partial-poison.ll b/llvm/test/Instrumentation/MemorySanitizer/partial-poison.ll
index 184794f124e5a..f0a6035608a25 100644
--- a/llvm/test/Instrumentation/MemorySanitizer/partial-poison.ll
+++ b/llvm/test/Instrumentation/MemorySanitizer/partial-poison.ll
@@ -76,7 +76,7 @@ define <2 x i64> @full_undef(ptr %add.ptr) sanitize_memory {
; CHECK-LABEL: define <2 x i64> @full_undef(
; CHECK-SAME: ptr [[ADD_PTR:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: call void @llvm.donothing()
-; CHECK: store <2 x i64> splat (i64 -1), ptr @__msan_retval_tls, align 8
+; CHECK-NEXT: store <2 x i64> splat (i64 -1), ptr @__msan_retval_tls, align 8
; CHECK-NEXT: ret <2 x i64> undef
;
ret <2 x i64> <i64 undef, i64 undef>
>From 82c463c65d66ee81be1e73846b325ed6023f39b2 Mon Sep 17 00:00:00 2001
From: Thurston Dang <thurston at google.com>
Date: Fri, 13 Jun 2025 22:44:23 +0000
Subject: [PATCH 7/7] Turn fix off by default
---
llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp | 2 +-
llvm/test/Instrumentation/MemorySanitizer/partial-poison.ll | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
index e3afa93b8a670..3941bed37ebaf 100644
--- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
@@ -280,7 +280,7 @@ static cl::opt<bool> ClPoisonUndefVectors(
"considered fully initialized, which may lead to false "
"negatives. Fully undefined constant vectors are "
"unaffected by this flag (see -msan-poison-undef)."),
- cl::Hidden, cl::init(true));
+ cl::Hidden, cl::init(false));
static cl::opt<bool>
ClHandleICmp("msan-handle-icmp",
diff --git a/llvm/test/Instrumentation/MemorySanitizer/partial-poison.ll b/llvm/test/Instrumentation/MemorySanitizer/partial-poison.ll
index f0a6035608a25..025317a53c8d1 100644
--- a/llvm/test/Instrumentation/MemorySanitizer/partial-poison.ll
+++ b/llvm/test/Instrumentation/MemorySanitizer/partial-poison.ll
@@ -1,5 +1,5 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
-; RUN: opt < %s -S -passes='msan' 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-PRECISE
+; RUN: opt < %s -S -passes='msan' -msan-poison-undef-vectors=true 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-PRECISE
; RUN: opt < %s -S -passes='msan' -msan-poison-undef-vectors=false 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-IMPRECISE
;
; Regression test case for computing shadows of partially poisoned vectors.
More information about the llvm-commits
mailing list