[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