https://github.com/dingxiangfei2009 updated 
https://github.com/llvm/llvm-project/pull/188001

>From 2f740fea6bd7613d3daff364bd850a98d95b1ea7 Mon Sep 17 00:00:00 2001
From: Xiangfei Ding <[email protected]>
Date: Thu, 19 Mar 2026 16:04:41 +0000
Subject: [PATCH 1/5] MSan: poison the default-init allocation before calling
 constructors

This change is to align with the standards pertaining to reserved global
placement `new`s in the default initialisation style.


Signed-off-by: Xiangfei Ding <[email protected]>
---
 clang/lib/CodeGen/CGExprCXX.cpp               | 94 +++++++++++++++++++
 .../test/CodeGenCXX/sanitize-default-init.cpp | 41 ++++++++
 2 files changed, 135 insertions(+)
 create mode 100644 clang/test/CodeGenCXX/sanitize-default-init.cpp

diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp
index c585523f2718f..c05ab0a7cdd31 100644
--- a/clang/lib/CodeGen/CGExprCXX.cpp
+++ b/clang/lib/CodeGen/CGExprCXX.cpp
@@ -17,8 +17,11 @@
 #include "CodeGenFunction.h"
 #include "ConstantEmitter.h"
 #include "TargetInfo.h"
+#include "clang/AST/ExprCXX.h"
 #include "clang/Basic/CodeGenOptions.h"
+#include "clang/Basic/Sanitizers.h"
 #include "clang/CodeGen/CGFunctionInfo.h"
+#include "llvm/IR/Constants.h"
 #include "llvm/IR/Intrinsics.h"
 
 using namespace clang;
@@ -1489,6 +1492,7 @@ class CallDeleteDuringNew final : public 
EHScopeStack::Cleanup {
     EmitNewDeleteCall(CGF, OperatorDelete, FPT, DeleteArgs);
   }
 };
+
 } // namespace
 
 /// Enter a cleanup to call 'operator delete' if the initializer in a
@@ -1553,6 +1557,86 @@ static void EnterNewDeleteCleanup(CodeGenFunction &CGF, 
const CXXNewExpr *E,
   CGF.initFullExprCleanup();
 }
 
+namespace {
+void PoisonTrivialField(CodeGenFunction &CGF, QualType const &Ty,
+                        Address Dest) {
+  CharUnits Size = CGF.getContext().getTypeSizeInChars(Ty);
+  llvm::Value *SizeVal = CGF.CGM.getSize(Size);
+  llvm::Value *PoisonByte = llvm::PoisonValue::get(CGF.Builder.getInt8Ty());
+  CGF.Builder.CreateMemSet(Dest, PoisonByte, SizeVal, 
Ty.isVolatileQualified());
+}
+
+void PoisonArrayLValue(CodeGenFunction &CGF, QualType const &ElementQualTy,
+                       llvm::Type *ElementTy, LValue const &Dest,
+                       llvm::Value *numElements);
+
+void PoisonLValueRecursive(CodeGenFunction &CGF, QualType const &Ty,
+                           LValue const &Dest) {
+  if (Ty.isTriviallyCopyableType(CGF.getContext()) || Ty->isReferenceType()) {
+    return PoisonTrivialField(CGF, Ty, Dest.getAddress());
+  }
+
+  auto *RD = Ty->castAsCXXRecordDecl();
+  assert(RD &&
+         "type is not trivially copyable but it is not a record type either");
+  for (auto *FD : RD->fields()) {
+    // There is no need to poison unnamed fields.
+    if (FD->isUnnamedBitField()) {
+      continue;
+    }
+    QualType FieldTy = FD->getType();
+    LValue FieldLV = CGF.EmitLValueForField(Dest, FD);
+    if (FieldTy->isRecordType()) {
+      return PoisonLValueRecursive(CGF, FieldTy, FieldLV);
+    }
+    if (auto *AQualTy = dyn_cast<clang::ArrayType>(FieldTy)) {
+      if (auto *ATy =
+              dyn_cast<llvm::ArrayType>(CGF.ConvertTypeForMem(FieldTy))) {
+        if (uint64_t NumArrayElements = ATy->getNumElements()) {
+          PoisonArrayLValue(
+              CGF, AQualTy->getElementType(), ATy->getElementType(), FieldLV,
+              llvm::ConstantInt::get(CGF.SizeTy, NumArrayElements));
+        }
+      }
+      return;
+    }
+    // Every other case is trivial to poison.
+    PoisonTrivialField(CGF, FieldTy, FieldLV.getAddress());
+  }
+}
+
+void PoisonArrayLValue(CodeGenFunction &CGF, QualType const &ElementQualTy,
+                       llvm::Type *ElementTy, LValue const &Dest,
+                       llvm::Value *NumElements) {
+  auto ElementAlign = Dest.getAlignment().alignmentOfArrayElement(
+      CGF.getContext().getTypeSizeInChars(ElementQualTy));
+
+  auto &Builder = CGF.Builder;
+  llvm::Value *BeginPtr = Dest.emitRawPointer(CGF);
+  llvm::Value *EndPtr = Builder.CreateInBoundsGEP(
+      ElementTy, BeginPtr, NumElements, "arraypoison.end");
+  llvm::Value *One = llvm::ConstantInt::get(CGF.SizeTy, 1);
+  auto *EntryBB = Builder.GetInsertBlock();
+  // The loop head.
+  auto *BodyBB = CGF.createBasicBlock("arraypoison.body");
+  CGF.EmitBlock(BodyBB);
+  auto *CurElementPtr =
+      Builder.CreatePHI(BeginPtr->getType(), 2, "arraypoison.cur");
+  CurElementPtr->addIncoming(BeginPtr, EntryBB);
+  LValue ElementDest = CGF.MakeAddrLValue(
+      Address(CurElementPtr, ElementTy, ElementAlign), ElementQualTy);
+  PoisonLValueRecursive(CGF, ElementQualTy, ElementDest);
+  llvm::Value *NextElementPtr = Builder.CreateInBoundsGEP(
+      ElementTy, CurElementPtr, One, "arraypoison.next");
+  llvm::Value *Done =
+      Builder.CreateICmpEQ(NextElementPtr, EndPtr, "arraypoison.done");
+  auto *EndBB = CGF.createBasicBlock("arraypoison.end");
+  Builder.CreateCondBr(Done, EndBB, BodyBB);
+  CurElementPtr->addIncoming(NextElementPtr, Builder.GetInsertBlock());
+  CGF.EmitBlock(EndBB);
+}
+} // namespace
+
 llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
   // The element type being allocated.
   QualType allocType = getContext().getBaseElementType(E->getAllocatedType());
@@ -1611,6 +1695,16 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const 
CXXNewExpr *E) {
       allocatorArgs.add(RValue::get(allocation, *this), arg->getType());
     }
 
+    if (E->getInitializationStyle() == CXXNewInitializationStyle::None &&
+        SanOpts.has(SanitizerKind::Memory)) {
+      auto *ElemTy = ConvertTypeForMem(allocType);
+      auto Dest = MakeAddrLValue(allocation.withElementType(ElemTy), 
allocType);
+      if (numElements) {
+        PoisonArrayLValue(*this, allocType, ElemTy, Dest, numElements);
+      } else {
+        PoisonLValueRecursive(*this, allocType, Dest);
+      }
+    }
   } else {
     const FunctionProtoType *allocatorType =
         allocator->getType()->castAs<FunctionProtoType>();
diff --git a/clang/test/CodeGenCXX/sanitize-default-init.cpp 
b/clang/test/CodeGenCXX/sanitize-default-init.cpp
new file mode 100644
index 0000000000000..fc3c2fd658fc6
--- /dev/null
+++ b/clang/test/CodeGenCXX/sanitize-default-init.cpp
@@ -0,0 +1,41 @@
+// RUN: %clang_cc1 -x c++ -fsanitize=memory -std=c++11 -triple=x86_64-pc-linux 
-emit-llvm -o - %s | FileCheck %s
+
+/// Sanitise the placement new with default initialisation style.
+
+namespace std {
+    using size_t = decltype(sizeof(0));
+}
+
+void *operator new(std::size_t, void *p) noexcept { return p; }
+
+struct Simple {
+    int x;
+};
+
+struct WithCtor {
+    int x;
+    int y[4];
+    WithCtor() {
+        bool flag = x > 0; /// This is UB
+    }
+};
+
+// CHECK-LABEL: define {{.*}} i32 @main()
+int main() {
+    {
+        Simple s;
+        // CHECK: [[S:%.+]] = alloca %struct.Simple, align 4
+        // CHECK: [[W:%.+]] = alloca %struct.WithCtor, align 4
+        s.x = 42;
+        // CHECK: {{%.+}} = call ptr @__msan_memset(ptr [[S]], i32 poison, i64 
4)
+        new (&s) Simple;
+        bool flag = s.x == 42; /// This is UB
+    }
+    {
+        WithCtor w;
+        w.x = 42;
+        // CHECK: {{%.+}} = call ptr @__msan_memset(ptr [[W]], i32 poison, i64 
20)
+        auto *ptr = new (&w) WithCtor; /// This is UB
+        // CHECK: call void @_ZN8WithCtorC1Ev
+    }
+}

>From cb45ffc8ef8d0446af9a860c110e3a8a29c43288 Mon Sep 17 00:00:00 2001
From: Xiangfei Ding <[email protected]>
Date: Wed, 25 Mar 2026 14:28:01 +0000
Subject: [PATCH 2/5] undef in msan

Signed-off-by: Xiangfei Ding <[email protected]>
---
 clang/lib/CodeGen/CGExprCXX.cpp               | 37 +++++++++----------
 .../test/CodeGenCXX/sanitize-default-init.cpp |  4 +-
 2 files changed, 20 insertions(+), 21 deletions(-)

diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp
index c05ab0a7cdd31..ac78a0e648099 100644
--- a/clang/lib/CodeGen/CGExprCXX.cpp
+++ b/clang/lib/CodeGen/CGExprCXX.cpp
@@ -1558,22 +1558,21 @@ static void EnterNewDeleteCleanup(CodeGenFunction &CGF, 
const CXXNewExpr *E,
 }
 
 namespace {
-void PoisonTrivialField(CodeGenFunction &CGF, QualType const &Ty,
-                        Address Dest) {
+void UndefTrivialField(CodeGenFunction &CGF, QualType const &Ty, Address Dest) 
{
   CharUnits Size = CGF.getContext().getTypeSizeInChars(Ty);
   llvm::Value *SizeVal = CGF.CGM.getSize(Size);
-  llvm::Value *PoisonByte = llvm::PoisonValue::get(CGF.Builder.getInt8Ty());
-  CGF.Builder.CreateMemSet(Dest, PoisonByte, SizeVal, 
Ty.isVolatileQualified());
+  llvm::Value *UndefByte = llvm::UndefValue::get(CGF.Builder.getInt8Ty());
+  CGF.Builder.CreateMemSet(Dest, UndefByte, SizeVal, Ty.isVolatileQualified());
 }
 
-void PoisonArrayLValue(CodeGenFunction &CGF, QualType const &ElementQualTy,
-                       llvm::Type *ElementTy, LValue const &Dest,
-                       llvm::Value *numElements);
+void UndefArrayLValue(CodeGenFunction &CGF, QualType const &ElementQualTy,
+                      llvm::Type *ElementTy, LValue const &Dest,
+                      llvm::Value *numElements);
 
-void PoisonLValueRecursive(CodeGenFunction &CGF, QualType const &Ty,
-                           LValue const &Dest) {
+void UndefLValueRecursive(CodeGenFunction &CGF, QualType const &Ty,
+                          LValue const &Dest) {
   if (Ty.isTriviallyCopyableType(CGF.getContext()) || Ty->isReferenceType()) {
-    return PoisonTrivialField(CGF, Ty, Dest.getAddress());
+    return UndefTrivialField(CGF, Ty, Dest.getAddress());
   }
 
   auto *RD = Ty->castAsCXXRecordDecl();
@@ -1587,13 +1586,13 @@ void PoisonLValueRecursive(CodeGenFunction &CGF, 
QualType const &Ty,
     QualType FieldTy = FD->getType();
     LValue FieldLV = CGF.EmitLValueForField(Dest, FD);
     if (FieldTy->isRecordType()) {
-      return PoisonLValueRecursive(CGF, FieldTy, FieldLV);
+      return UndefLValueRecursive(CGF, FieldTy, FieldLV);
     }
     if (auto *AQualTy = dyn_cast<clang::ArrayType>(FieldTy)) {
       if (auto *ATy =
               dyn_cast<llvm::ArrayType>(CGF.ConvertTypeForMem(FieldTy))) {
         if (uint64_t NumArrayElements = ATy->getNumElements()) {
-          PoisonArrayLValue(
+          UndefArrayLValue(
               CGF, AQualTy->getElementType(), ATy->getElementType(), FieldLV,
               llvm::ConstantInt::get(CGF.SizeTy, NumArrayElements));
         }
@@ -1601,13 +1600,13 @@ void PoisonLValueRecursive(CodeGenFunction &CGF, 
QualType const &Ty,
       return;
     }
     // Every other case is trivial to poison.
-    PoisonTrivialField(CGF, FieldTy, FieldLV.getAddress());
+    UndefTrivialField(CGF, FieldTy, FieldLV.getAddress());
   }
 }
 
-void PoisonArrayLValue(CodeGenFunction &CGF, QualType const &ElementQualTy,
-                       llvm::Type *ElementTy, LValue const &Dest,
-                       llvm::Value *NumElements) {
+void UndefArrayLValue(CodeGenFunction &CGF, QualType const &ElementQualTy,
+                      llvm::Type *ElementTy, LValue const &Dest,
+                      llvm::Value *NumElements) {
   auto ElementAlign = Dest.getAlignment().alignmentOfArrayElement(
       CGF.getContext().getTypeSizeInChars(ElementQualTy));
 
@@ -1625,7 +1624,7 @@ void PoisonArrayLValue(CodeGenFunction &CGF, QualType 
const &ElementQualTy,
   CurElementPtr->addIncoming(BeginPtr, EntryBB);
   LValue ElementDest = CGF.MakeAddrLValue(
       Address(CurElementPtr, ElementTy, ElementAlign), ElementQualTy);
-  PoisonLValueRecursive(CGF, ElementQualTy, ElementDest);
+  UndefLValueRecursive(CGF, ElementQualTy, ElementDest);
   llvm::Value *NextElementPtr = Builder.CreateInBoundsGEP(
       ElementTy, CurElementPtr, One, "arraypoison.next");
   llvm::Value *Done =
@@ -1700,9 +1699,9 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const 
CXXNewExpr *E) {
       auto *ElemTy = ConvertTypeForMem(allocType);
       auto Dest = MakeAddrLValue(allocation.withElementType(ElemTy), 
allocType);
       if (numElements) {
-        PoisonArrayLValue(*this, allocType, ElemTy, Dest, numElements);
+        UndefArrayLValue(*this, allocType, ElemTy, Dest, numElements);
       } else {
-        PoisonLValueRecursive(*this, allocType, Dest);
+        UndefLValueRecursive(*this, allocType, Dest);
       }
     }
   } else {
diff --git a/clang/test/CodeGenCXX/sanitize-default-init.cpp 
b/clang/test/CodeGenCXX/sanitize-default-init.cpp
index fc3c2fd658fc6..04245fdcf33bd 100644
--- a/clang/test/CodeGenCXX/sanitize-default-init.cpp
+++ b/clang/test/CodeGenCXX/sanitize-default-init.cpp
@@ -27,14 +27,14 @@ int main() {
         // CHECK: [[S:%.+]] = alloca %struct.Simple, align 4
         // CHECK: [[W:%.+]] = alloca %struct.WithCtor, align 4
         s.x = 42;
-        // CHECK: {{%.+}} = call ptr @__msan_memset(ptr [[S]], i32 poison, i64 
4)
+        // CHECK: {{%.+}} = call ptr @__msan_memset(ptr [[S]], i32 undef, i64 
4)
         new (&s) Simple;
         bool flag = s.x == 42; /// This is UB
     }
     {
         WithCtor w;
         w.x = 42;
-        // CHECK: {{%.+}} = call ptr @__msan_memset(ptr [[W]], i32 poison, i64 
20)
+        // CHECK: {{%.+}} = call ptr @__msan_memset(ptr [[W]], i32 undef, i64 
20)
         auto *ptr = new (&w) WithCtor; /// This is UB
         // CHECK: call void @_ZN8WithCtorC1Ev
     }

>From f836c2fac383b6e38ee39c625797debb2c3def96 Mon Sep 17 00:00:00 2001
From: Xiangfei Ding <[email protected]>
Date: Thu, 16 Apr 2026 20:02:20 +0000
Subject: [PATCH 3/5] old behaviour on undef memset

Signed-off-by: Xiangfei Ding <[email protected]>
---
 .../InstCombine/memset-load-forward.ll          | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)
 create mode 100644 llvm/test/Transforms/InstCombine/memset-load-forward.ll

diff --git a/llvm/test/Transforms/InstCombine/memset-load-forward.ll 
b/llvm/test/Transforms/InstCombine/memset-load-forward.ll
new file mode 100644
index 0000000000000..7989122ac25ac
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/memset-load-forward.ll
@@ -0,0 +1,17 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -passes=instcombine -S | FileCheck %s
+
+define i32 @test_load_forward(ptr %p) {
+; CHECK-LABEL: @test_load_forward(
+; CHECK-NEXT:    store i32 100, ptr [[P:%.*]], align 4
+; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr noundef nonnull align 1 
dereferenceable(4) [[P]], i8 undef, i64 4, i1 false)
+; CHECK-NEXT:    [[V:%.*]] = load i32, ptr [[P]], align 4
+; CHECK-NEXT:    ret i32 [[V]]
+;
+  store i32 100, ptr %p, align 4
+  call void @llvm.memset.p0.i64(ptr %p, i8 undef, i64 4, i1 false)
+  %v = load i32, ptr %p, align 4
+  ret i32 %v
+}
+
+declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1)

>From 1abeb11047ac02f194a8e86f9ebc5f5ad8c247bb Mon Sep 17 00:00:00 2001
From: Xiangfei Ding <[email protected]>
Date: Wed, 25 Mar 2026 14:28:01 +0000
Subject: [PATCH 4/5] preserve undef in middle-end

Signed-off-by: Xiangfei Ding <[email protected]>
---
 llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp       |  4 ++++
 llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp | 12 +++++++-----
 llvm/test/Transforms/InstCombine/memset.ll           |  2 ++
 3 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp 
b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 0b7d8b7946f99..ae9033ed5ca39 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -10082,6 +10082,10 @@ SDValue SelectionDAG::getMemset(SDValue Chain, const 
SDLoc &dl, SDValue Dst,
                                 const CallInst *CI,
                                 MachinePointerInfo DstPtrInfo,
                                 const AAMDNodes &AAInfo) {
+  // Optimize non-volatile memset with an undef value to a no-op.
+  if (Src.isUndef() && !isVol)
+    return Chain;
+
   // Check to see if we should lower the memset to stores first.
   // For cases within the target-specified limits, this is the best choice.
   ConstantSDNode *ConstantSize = dyn_cast<ConstantSDNode>(Size);
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp 
b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index a622e0248fce8..60d5873ff8660 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -239,11 +239,13 @@ Instruction 
*InstCombinerImpl::SimplifyAnyMemSet(AnyMemSetInst *MI) {
   // Remove memset with an undef value.
   // FIXME: This is technically incorrect because it might overwrite a poison
   // value. Change to PoisonValue once #52930 is resolved.
-  if (isa<UndefValue>(MI->getValue())) {
-    // Set the size of the copy to 0, it will be deleted on the next iteration.
-    MI->setLength((uint64_t)0);
-    return MI;
-  }
+  // Postponed to SelectionDAG lowering phase.
+  // if (isa<UndefValue>(MI->getValue())) {
+  //   // Set the size of the copy to 0, it will be deleted on the next 
iteration.
+  //   MI->setLength((uint64_t)0);
+  //   return MI;
+  // }
+
 
   // Extract the length and alignment and fill if they are constant.
   ConstantInt *LenC = dyn_cast<ConstantInt>(MI->getLength());
diff --git a/llvm/test/Transforms/InstCombine/memset.ll 
b/llvm/test/Transforms/InstCombine/memset.ll
index d593db040476f..b0935d6f5649e 100644
--- a/llvm/test/Transforms/InstCombine/memset.ll
+++ b/llvm/test/Transforms/InstCombine/memset.ll
@@ -31,6 +31,7 @@ define void @memset_to_constant() {
 ; value. Stop folding it once #52930 is resolved.
 define void @memset_undef(ptr %p) {
 ; CHECK-LABEL: @memset_undef(
+; CHECK-NEXT:    call void @llvm.memset.p0.i32(ptr noundef nonnull align 1 
dereferenceable(8) [[P:%.*]], i8 undef, i32 8, i1 false)
 ; CHECK-NEXT:    ret void
 ;
   call void @llvm.memset.p0.i32(ptr %p, i8 undef, i32 8, i1 false)
@@ -48,6 +49,7 @@ define void @memset_undef_volatile(ptr %p) {
 
 define void @memset_poison(ptr %p) {
 ; CHECK-LABEL: @memset_poison(
+; CHECK-NEXT:    call void @llvm.memset.p0.i32(ptr noundef nonnull align 1 
dereferenceable(8) [[P:%.*]], i8 poison, i32 8, i1 false)
 ; CHECK-NEXT:    ret void
 ;
   call void @llvm.memset.p0.i32(ptr %p, i8 poison, i32 8, i1 false)

>From ee85899304af55d4542d31ae94e4713d2f20eb35 Mon Sep 17 00:00:00 2001
From: Xiangfei Ding <[email protected]>
Date: Thu, 16 Apr 2026 20:43:13 +0000
Subject: [PATCH 5/5] new behaviour when undef memsets are preserved

Signed-off-by: Xiangfei Ding <[email protected]>
---
 .../test/CodeGenCXX/sanitize-default-init.cpp |  4 ++--
 .../Instrumentation/MemorySanitizer.cpp       | 21 +++++++++++++------
 .../InstCombine/memset-load-forward.ll        |  5 ++---
 3 files changed, 19 insertions(+), 11 deletions(-)

diff --git a/clang/test/CodeGenCXX/sanitize-default-init.cpp 
b/clang/test/CodeGenCXX/sanitize-default-init.cpp
index 04245fdcf33bd..551a402f33921 100644
--- a/clang/test/CodeGenCXX/sanitize-default-init.cpp
+++ b/clang/test/CodeGenCXX/sanitize-default-init.cpp
@@ -27,14 +27,14 @@ int main() {
         // CHECK: [[S:%.+]] = alloca %struct.Simple, align 4
         // CHECK: [[W:%.+]] = alloca %struct.WithCtor, align 4
         s.x = 42;
-        // CHECK: {{%.+}} = call ptr @__msan_memset(ptr [[S]], i32 undef, i64 
4)
+        // CHECK: call void @__msan_poison(ptr [[S]], i64 4)
         new (&s) Simple;
         bool flag = s.x == 42; /// This is UB
     }
     {
         WithCtor w;
         w.x = 42;
-        // CHECK: {{%.+}} = call ptr @__msan_memset(ptr [[W]], i32 undef, i64 
20)
+        // CHECK: call void @__msan_poison(ptr [[W]], i64 20)
         auto *ptr = new (&w) WithCtor; /// This is UB
         // CHECK: call void @_ZN8WithCtorC1Ev
     }
diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp 
b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
index f128ff5cfaab6..d7297d0299ac1 100644
--- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
@@ -716,7 +716,7 @@ class MemorySanitizer {
   FunctionCallee MsanSetOriginFn;
 
   /// MSan runtime replacements for memmove, memcpy and memset.
-  FunctionCallee MemmoveFn, MemcpyFn, MemsetFn;
+  FunctionCallee MemmoveFn, MemcpyFn, MemsetFn, MsanPoisonFn;
 
   /// KMSAN callback for task-local function argument shadow.
   StructType *MsanContextStateTy;
@@ -1015,6 +1015,8 @@ void MemorySanitizer::initializeCallbacks(Module &M,
   MemsetFn = M.getOrInsertFunction("__msan_memset",
                                    TLI.getAttrList(C, {1}, /*Signed=*/true),
                                    PtrTy, PtrTy, IRB.getInt32Ty(), IntptrTy);
+  MsanPoisonFn = M.getOrInsertFunction("__msan_poison", IRB.getVoidTy(), PtrTy,
+                                       IntptrTy);
 
   MsanInstrumentAsmStoreFn = M.getOrInsertFunction(
       "__msan_instrument_asm_store", IRB.getVoidTy(), PtrTy, IntptrTy);
@@ -3325,11 +3327,18 @@ struct MemorySanitizerVisitor : public 
InstVisitor<MemorySanitizerVisitor> {
   // Same as memcpy.
   void visitMemSetInst(MemSetInst &I) {
     IRBuilder<> IRB(&I);
-    IRB.CreateCall(
-        MS.MemsetFn,
-        {I.getArgOperand(0),
-         IRB.CreateIntCast(I.getArgOperand(1), IRB.getInt32Ty(), false),
-         IRB.CreateIntCast(I.getArgOperand(2), MS.IntptrTy, false)});
+    Value *Val = I.getArgOperand(1);
+    if (isa<UndefValue>(Val)) {
+      IRB.CreateCall(MS.MsanPoisonFn,
+                     {I.getArgOperand(0),
+                      IRB.CreateIntCast(I.getArgOperand(2), MS.IntptrTy, 
false)});
+    } else {
+      IRB.CreateCall(
+          MS.MemsetFn,
+          {I.getArgOperand(0),
+           IRB.CreateIntCast(Val, IRB.getInt32Ty(), false),
+           IRB.CreateIntCast(I.getArgOperand(2), MS.IntptrTy, false)});
+    }
     I.eraseFromParent();
   }
 
diff --git a/llvm/test/Transforms/InstCombine/memset-load-forward.ll 
b/llvm/test/Transforms/InstCombine/memset-load-forward.ll
index 7989122ac25ac..03765399eecc0 100644
--- a/llvm/test/Transforms/InstCombine/memset-load-forward.ll
+++ b/llvm/test/Transforms/InstCombine/memset-load-forward.ll
@@ -1,10 +1,9 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt < %s -passes=instcombine -S | FileCheck %s
+; RUN: opt < %s -passes="instcombine,dse" -S | FileCheck %s
 
 define i32 @test_load_forward(ptr %p) {
 ; CHECK-LABEL: @test_load_forward(
-; CHECK-NEXT:    store i32 100, ptr [[P:%.*]], align 4
-; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr noundef nonnull align 1 
dereferenceable(4) [[P]], i8 undef, i64 4, i1 false)
+; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr noundef nonnull align 1 
dereferenceable(4) [[P:%.*]], i8 undef, i64 4, i1 false)
 ; CHECK-NEXT:    [[V:%.*]] = load i32, ptr [[P]], align 4
 ; CHECK-NEXT:    ret i32 [[V]]
 ;

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to