[llvm] [Sanitizer] Make sanitizer passes idempotent (PR #99439)

via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 26 03:02:33 PDT 2024


https://github.com/skc7 updated https://github.com/llvm/llvm-project/pull/99439

>From 8a2a63ba5e2005fb2bf03b24610dc0e19130a978 Mon Sep 17 00:00:00 2001
From: skc7 <Krishna.Sankisa at amd.com>
Date: Thu, 18 Jul 2024 11:49:24 +0530
Subject: [PATCH 1/6] [ASAN] Make asan pass idempotent.

---
 .../Instrumentation/AddressSanitizer.cpp      | 11 ++++
 .../AddressSanitizer/asan-pass-second-run.ll  | 56 +++++++++++++++++++
 2 files changed, 67 insertions(+)
 create mode 100644 llvm/test/Instrumentation/AddressSanitizer/asan-pass-second-run.ll

diff --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
index 9fb1df7ab2b79..3cc14515d6b15 100644
--- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
@@ -1249,8 +1249,19 @@ AddressSanitizerPass::AddressSanitizerPass(
       UseOdrIndicator(UseOdrIndicator), DestructorKind(DestructorKind),
       ConstructorKind(ConstructorKind) {}
 
+static bool hasAsanModuleCtor(Module &M) {
+  if (M.getFunction(kAsanModuleCtorName))
+    return true;
+  return false;
+}
+
 PreservedAnalyses AddressSanitizerPass::run(Module &M,
                                             ModuleAnalysisManager &MAM) {
+  // Return early if asan.module_ctor is already present in the module.
+  // This implies that asan pass has already run before.
+  if (hasAsanModuleCtor(M))
+    return PreservedAnalyses::all();
+
   ModuleAddressSanitizer ModuleSanitizer(
       M, Options.InsertVersionCheck, Options.CompileKernel, Options.Recover,
       UseGlobalGC, UseOdrIndicator, DestructorKind, ConstructorKind);
diff --git a/llvm/test/Instrumentation/AddressSanitizer/asan-pass-second-run.ll b/llvm/test/Instrumentation/AddressSanitizer/asan-pass-second-run.ll
new file mode 100644
index 0000000000000..65d72a72f605b
--- /dev/null
+++ b/llvm/test/Instrumentation/AddressSanitizer/asan-pass-second-run.ll
@@ -0,0 +1,56 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals all --version 5
+; This test checks in the second run, function is not instrumented again.
+; RUN: opt < %s -passes=asan,asan -S | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; Function with sanitize_address is instrumented.
+; Function Attrs: nounwind uwtable
+;.
+; CHECK: @llvm.used = appending global [1 x ptr] [ptr @asan.module_ctor], section "llvm.metadata"
+; CHECK: @___asan_globals_registered = common hidden global i64 0
+; CHECK: @__start_asan_globals = extern_weak hidden global i64
+; CHECK: @__stop_asan_globals = extern_weak hidden global i64
+; CHECK: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 1, ptr @asan.module_ctor, ptr @asan.module_ctor }]
+;.
+define void @instr_sa(ptr %a) sanitize_address {
+; CHECK-LABEL: define void @instr_sa(
+; CHECK-SAME: ptr [[A:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP0:%.*]] = ptrtoint ptr [[A]] to i64
+; CHECK-NEXT:    [[TMP1:%.*]] = lshr i64 [[TMP0]], 3
+; CHECK-NEXT:    [[TMP2:%.*]] = add i64 [[TMP1]], 2147450880
+; CHECK-NEXT:    [[TMP3:%.*]] = inttoptr i64 [[TMP2]] to ptr
+; CHECK-NEXT:    [[TMP4:%.*]] = load i8, ptr [[TMP3]], align 1
+; CHECK-NEXT:    [[TMP5:%.*]] = icmp ne i8 [[TMP4]], 0
+; CHECK-NEXT:    br i1 [[TMP5]], label %[[BB6:.*]], label %[[BB12:.*]], !prof [[PROF0:![0-9]+]]
+; CHECK:       [[BB6]]:
+; CHECK-NEXT:    [[TMP7:%.*]] = and i64 [[TMP0]], 7
+; CHECK-NEXT:    [[TMP8:%.*]] = add i64 [[TMP7]], 3
+; CHECK-NEXT:    [[TMP9:%.*]] = trunc i64 [[TMP8]] to i8
+; CHECK-NEXT:    [[TMP10:%.*]] = icmp sge i8 [[TMP9]], [[TMP4]]
+; CHECK-NEXT:    br i1 [[TMP10]], label %[[BB11:.*]], label %[[BB12]]
+; CHECK:       [[BB11]]:
+; CHECK-NEXT:    call void @__asan_report_load4(i64 [[TMP0]]) #[[ATTR3:[0-9]+]]
+; CHECK-NEXT:    unreachable
+; CHECK:       [[BB12]]:
+; CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[A]], align 4
+; CHECK-NEXT:    [[TMP2:%.*]] = add i32 [[TMP1]], 1
+; CHECK-NEXT:    store i32 [[TMP2]], ptr [[A]], align 4
+; CHECK-NEXT:    ret void
+;
+entry:
+  %tmp1 = load i32, ptr %a, align 4
+  %tmp2 = add i32 %tmp1,  1
+  store i32 %tmp2, ptr %a, align 4
+  ret void
+}
+;.
+; CHECK: attributes #[[ATTR0]] = { sanitize_address }
+; CHECK: attributes #[[ATTR1:[0-9]+]] = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
+; CHECK: attributes #[[ATTR2:[0-9]+]] = { nounwind }
+; CHECK: attributes #[[ATTR3]] = { nomerge }
+;.
+; CHECK: [[PROF0]] = !{!"branch_weights", i32 1, i32 1048575}
+;.

>From 6552d844ab844b60fb29b1dcaf70905484075dbd Mon Sep 17 00:00:00 2001
From: skc7 <Krishna.Sankisa at amd.com>
Date: Mon, 22 Jul 2024 15:41:25 +0530
Subject: [PATCH 2/6] [ASAN] Use nosanitize module flag.

---
 .../Instrumentation/AddressSanitizer.cpp          | 12 ++++--------
 .../AddressSanitizer/asan-pass-second-run.ll      | 15 +++++++--------
 .../AddressSanitizer/missing_dbg.ll               |  2 +-
 3 files changed, 12 insertions(+), 17 deletions(-)

diff --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
index 3cc14515d6b15..a985aa1df101b 100644
--- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
@@ -1249,17 +1249,11 @@ AddressSanitizerPass::AddressSanitizerPass(
       UseOdrIndicator(UseOdrIndicator), DestructorKind(DestructorKind),
       ConstructorKind(ConstructorKind) {}
 
-static bool hasAsanModuleCtor(Module &M) {
-  if (M.getFunction(kAsanModuleCtorName))
-    return true;
-  return false;
-}
-
 PreservedAnalyses AddressSanitizerPass::run(Module &M,
                                             ModuleAnalysisManager &MAM) {
-  // Return early if asan.module_ctor is already present in the module.
+  // Return early if nosanitize module flag is present for the module.
   // This implies that asan pass has already run before.
-  if (hasAsanModuleCtor(M))
+  if (M.getModuleFlag("nosanitize"))
     return PreservedAnalyses::all();
 
   ModuleAddressSanitizer ModuleSanitizer(
@@ -1278,6 +1272,8 @@ PreservedAnalyses AddressSanitizerPass::run(Module &M,
     Modified |= FunctionSanitizer.instrumentFunction(F, &TLI);
   }
   Modified |= ModuleSanitizer.instrumentModule(M);
+  if (Modified)
+    M.addModuleFlag(Module::ModFlagBehavior::Override, "nosanitize", 1);
   if (!Modified)
     return PreservedAnalyses::all();
 
diff --git a/llvm/test/Instrumentation/AddressSanitizer/asan-pass-second-run.ll b/llvm/test/Instrumentation/AddressSanitizer/asan-pass-second-run.ll
index 65d72a72f605b..d3089870e3893 100644
--- a/llvm/test/Instrumentation/AddressSanitizer/asan-pass-second-run.ll
+++ b/llvm/test/Instrumentation/AddressSanitizer/asan-pass-second-run.ll
@@ -1,4 +1,4 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals all --version 5
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-attributes --check-globals all --version 5
 ; This test checks in the second run, function is not instrumented again.
 ; RUN: opt < %s -passes=asan,asan -S | FileCheck %s
 
@@ -8,13 +8,12 @@ target triple = "x86_64-unknown-linux-gnu"
 ; Function with sanitize_address is instrumented.
 ; Function Attrs: nounwind uwtable
 ;.
-; CHECK: @llvm.used = appending global [1 x ptr] [ptr @asan.module_ctor], section "llvm.metadata"
 ; CHECK: @___asan_globals_registered = common hidden global i64 0
 ; CHECK: @__start_asan_globals = extern_weak hidden global i64
 ; CHECK: @__stop_asan_globals = extern_weak hidden global i64
-; CHECK: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 1, ptr @asan.module_ctor, ptr @asan.module_ctor }]
 ;.
 define void @instr_sa(ptr %a) sanitize_address {
+; CHECK: Function Attrs: sanitize_address
 ; CHECK-LABEL: define void @instr_sa(
 ; CHECK-SAME: ptr [[A:%.*]]) #[[ATTR0:[0-9]+]] {
 ; CHECK-NEXT:  [[ENTRY:.*:]]
@@ -24,7 +23,7 @@ define void @instr_sa(ptr %a) sanitize_address {
 ; CHECK-NEXT:    [[TMP3:%.*]] = inttoptr i64 [[TMP2]] to ptr
 ; CHECK-NEXT:    [[TMP4:%.*]] = load i8, ptr [[TMP3]], align 1
 ; CHECK-NEXT:    [[TMP5:%.*]] = icmp ne i8 [[TMP4]], 0
-; CHECK-NEXT:    br i1 [[TMP5]], label %[[BB6:.*]], label %[[BB12:.*]], !prof [[PROF0:![0-9]+]]
+; CHECK-NEXT:    br i1 [[TMP5]], label %[[BB6:.*]], label %[[BB12:.*]], !prof [[PROF1:![0-9]+]]
 ; CHECK:       [[BB6]]:
 ; CHECK-NEXT:    [[TMP7:%.*]] = and i64 [[TMP0]], 7
 ; CHECK-NEXT:    [[TMP8:%.*]] = add i64 [[TMP7]], 3
@@ -32,7 +31,7 @@ define void @instr_sa(ptr %a) sanitize_address {
 ; CHECK-NEXT:    [[TMP10:%.*]] = icmp sge i8 [[TMP9]], [[TMP4]]
 ; CHECK-NEXT:    br i1 [[TMP10]], label %[[BB11:.*]], label %[[BB12]]
 ; CHECK:       [[BB11]]:
-; CHECK-NEXT:    call void @__asan_report_load4(i64 [[TMP0]]) #[[ATTR3:[0-9]+]]
+; CHECK-NEXT:    call void @__asan_report_load4(i64 [[TMP0]]) #[[ATTR2:[0-9]+]]
 ; CHECK-NEXT:    unreachable
 ; CHECK:       [[BB12]]:
 ; CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[A]], align 4
@@ -49,8 +48,8 @@ entry:
 ;.
 ; CHECK: attributes #[[ATTR0]] = { sanitize_address }
 ; CHECK: attributes #[[ATTR1:[0-9]+]] = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
-; CHECK: attributes #[[ATTR2:[0-9]+]] = { nounwind }
-; CHECK: attributes #[[ATTR3]] = { nomerge }
+; CHECK: attributes #[[ATTR2]] = { nomerge }
 ;.
-; CHECK: [[PROF0]] = !{!"branch_weights", i32 1, i32 1048575}
+; CHECK: [[META0:![0-9]+]] = !{i32 4, !"nosanitize", i32 1}
+; CHECK: [[PROF1]] = !{!"branch_weights", i32 1, i32 1048575}
 ;.
diff --git a/llvm/test/Instrumentation/AddressSanitizer/missing_dbg.ll b/llvm/test/Instrumentation/AddressSanitizer/missing_dbg.ll
index 762f91c156dd8..f6553322fd678 100644
--- a/llvm/test/Instrumentation/AddressSanitizer/missing_dbg.ll
+++ b/llvm/test/Instrumentation/AddressSanitizer/missing_dbg.ll
@@ -34,4 +34,4 @@ entry:
 !4 = !DISubroutineType(types: !5)
 !5 = !{}
 
-; CHECK:       [[DBG]] = !DILocation(line: 0, scope: !3)
+; CHECK:       [[DBG]] = !DILocation(line: 0, scope: !4)

>From 1b0b12fa02a65a6e11306f82344250c806061f9f Mon Sep 17 00:00:00 2001
From: skc7 <Krishna.Sankisa at amd.com>
Date: Thu, 25 Jul 2024 15:16:08 +0530
Subject: [PATCH 3/6] [Sanitizer] Make hwsan, msan, dfsan passes idempotent.

---
 .../Instrumentation/DataFlowSanitizer.cpp     |  4 ++
 .../Instrumentation/HWAddressSanitizer.cpp    |  4 ++
 .../Instrumentation/MemorySanitizer.cpp       |  5 +++
 .../dfsan-pass-second-run.ll                  | 17 ++++++++
 .../hwasan-pass-second-run.ll                 | 41 ++++++++++++++++++
 .../MemorySanitizer/msan-pass-second-run.ll   | 43 +++++++++++++++++++
 6 files changed, 114 insertions(+)
 create mode 100644 llvm/test/Instrumentation/DataFlowSanitizer/dfsan-pass-second-run.ll
 create mode 100644 llvm/test/Instrumentation/HWAddressSanitizer/hwasan-pass-second-run.ll
 create mode 100644 llvm/test/Instrumentation/MemorySanitizer/msan-pass-second-run.ll

diff --git a/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
index 113d39b4f2af7..77e8a830d10f1 100644
--- a/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
@@ -3473,6 +3473,9 @@ void DFSanVisitor::visitPHINode(PHINode &PN) {
 
 PreservedAnalyses DataFlowSanitizerPass::run(Module &M,
                                              ModuleAnalysisManager &AM) {
+  // Return early if nosanitize module flag is present for the module.
+  if (M.getModuleFlag("nosanitize"))
+    return PreservedAnalyses::all();
   auto GetTLI = [&](Function &F) -> TargetLibraryInfo & {
     auto &FAM =
         AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
@@ -3486,5 +3489,6 @@ PreservedAnalyses DataFlowSanitizerPass::run(Module &M,
   // explicitly invalidated; PreservedAnalyses::none() is not enough. Sanitizers
   // make changes that require GlobalsAA to be invalidated.
   PA.abandon<GlobalsAA>();
+  M.addModuleFlag(Module::ModFlagBehavior::Override, "nosanitize", 1);
   return PA;
 }
diff --git a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
index a0e63bf12400e..0fc33e28cd29b 100644
--- a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
@@ -455,6 +455,9 @@ class HWAddressSanitizer {
 
 PreservedAnalyses HWAddressSanitizerPass::run(Module &M,
                                               ModuleAnalysisManager &MAM) {
+  // Return early if nosanitize module flag is present for the module.
+  if (M.getModuleFlag("nosanitize"))
+    return PreservedAnalyses::all();
   const StackSafetyGlobalInfo *SSI = nullptr;
   auto TargetTriple = llvm::Triple(M.getTargetTriple());
   if (shouldUseStackSafetyAnalysis(TargetTriple, Options.DisableOptimization))
@@ -476,6 +479,7 @@ PreservedAnalyses HWAddressSanitizerPass::run(Module &M,
   // explicitly invalidated; PreservedAnalyses::none() is not enough. Sanitizers
   // make changes that require GlobalsAA to be invalidated.
   PA.abandon<GlobalsAA>();
+  M.addModuleFlag(Module::ModFlagBehavior::Override, "nosanitize", 1);
   return PA;
 }
 void HWAddressSanitizerPass::printPipeline(
diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
index c979e81ac1a3f..65b36dfbde32a 100644
--- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
@@ -706,6 +706,9 @@ MemorySanitizerOptions::MemorySanitizerOptions(int TO, bool R, bool K,
 
 PreservedAnalyses MemorySanitizerPass::run(Module &M,
                                            ModuleAnalysisManager &AM) {
+  // Return early if nosanitize module flag is present for the module.
+  if (M.getModuleFlag("nosanitize"))
+    return PreservedAnalyses::all();
   bool Modified = false;
   if (!Options.Kernel) {
     insertModuleCtor(M);
@@ -721,6 +724,8 @@ PreservedAnalyses MemorySanitizerPass::run(Module &M,
         Msan.sanitizeFunction(F, FAM.getResult<TargetLibraryAnalysis>(F));
   }
 
+  if (Modified)
+    M.addModuleFlag(Module::ModFlagBehavior::Override, "nosanitize", 1);
   if (!Modified)
     return PreservedAnalyses::all();
 
diff --git a/llvm/test/Instrumentation/DataFlowSanitizer/dfsan-pass-second-run.ll b/llvm/test/Instrumentation/DataFlowSanitizer/dfsan-pass-second-run.ll
new file mode 100644
index 0000000000000..d812367cfe9b6
--- /dev/null
+++ b/llvm/test/Instrumentation/DataFlowSanitizer/dfsan-pass-second-run.ll
@@ -0,0 +1,17 @@
+; RUN: opt < %s -passes=dfsan,dfsan -S | FileCheck %s
+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"
+
+define i8 @add(i8 %a, i8 %b) {
+  ; CHECK: @add.dfsan
+  ; CHECK-DAG: %[[#ALABEL:]] = load i8, ptr @__dfsan_arg_tls, align [[ALIGN:2]]
+  ; CHECK-DAG: %[[#BLABEL:]] = load i8, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__dfsan_arg_tls to i64), i64 2) to ptr), align [[ALIGN]]
+  ; CHECK: %[[#UNION:]] = or i8 %[[#ALABEL]], %[[#BLABEL]]
+  ; CHECK: %c = add i8 %a, %b
+  ; CHECK: store i8 %[[#UNION]], ptr @__dfsan_retval_tls, align [[ALIGN]]
+  ; CHECK: ret i8 %c
+  %c = add i8 %a, %b
+  ret i8 %c
+}
+
+; CHECK: [[META0:![0-9]+]] = !{i32 4, !"nosanitize", i32 1}
diff --git a/llvm/test/Instrumentation/HWAddressSanitizer/hwasan-pass-second-run.ll b/llvm/test/Instrumentation/HWAddressSanitizer/hwasan-pass-second-run.ll
new file mode 100644
index 0000000000000..6276480536303
--- /dev/null
+++ b/llvm/test/Instrumentation/HWAddressSanitizer/hwasan-pass-second-run.ll
@@ -0,0 +1,41 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-attributes --check-globals --version 2
+; Test basic address sanitizer instrumentation.
+;
+; RUN: opt < %s -passes=hwasan,hwasan -S | FileCheck %s
+
+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"
+
+;.
+; CHECK: @llvm.used = appending global [1 x ptr] [ptr @hwasan.module_ctor], section "llvm.metadata"
+; CHECK: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 0, ptr @hwasan.module_ctor, ptr @hwasan.module_ctor }]
+; CHECK: @__start_hwasan_globals = external hidden constant [0 x i8]
+; CHECK: @__stop_hwasan_globals = external hidden constant [0 x i8]
+; CHECK: @hwasan.note = private constant { i32, i32, i32, [8 x i8], i32, i32 } { i32 8, i32 8, i32 3, [8 x i8] c"LLVM\00\00\00\00", i32 trunc (i64 sub (i64 ptrtoint (ptr @__start_hwasan_globals to i64), i64 ptrtoint (ptr @hwasan.note to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (ptr @__stop_hwasan_globals to i64), i64 ptrtoint (ptr @hwasan.note to i64)) to i32) }, section ".note.hwasan.globals", comdat($hwasan.module_ctor), align 4
+; CHECK: @hwasan.dummy.global = private constant [0 x i8] zeroinitializer, section "hwasan_globals", comdat($hwasan.module_ctor), !associated [[META0:![0-9]+]]
+; CHECK: @__hwasan_tls = external thread_local(initialexec) global i64
+; CHECK: @llvm.compiler.used = appending global [3 x ptr] [ptr @hwasan.note, ptr @hwasan.dummy.global, ptr @__hwasan_tls], section "llvm.metadata"
+; CHECK: @__hwasan_shadow = external global [0 x i8]
+;.
+define i8 @test_load8(ptr %a) sanitize_hwaddress {
+; CHECK: Function Attrs: sanitize_hwaddress
+; CHECK-LABEL: define i8 @test_load8
+; CHECK-SAME: (ptr [[A:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[DOTHWASAN_SHADOW:%.*]] = call ptr asm "", "=r,0"(ptr null)
+; CHECK-NEXT:    [[TMP0:%.*]] = ptrtoint ptr [[A]] to i64
+; CHECK-NEXT:    call void @__hwasan_load1(i64 [[TMP0]])
+; CHECK-NEXT:    [[B:%.*]] = load i8, ptr [[A]], align 4
+; CHECK-NEXT:    ret i8 [[B]]
+;
+entry:
+  %b = load i8, ptr %a, align 4
+  ret i8 %b
+}
+;.
+; CHECK: attributes #[[ATTR0]] = { sanitize_hwaddress }
+; CHECK: attributes #[[ATTR1:[0-9]+]] = { nounwind }
+;.
+; CHECK: [[META0]] = !{ptr @hwasan.note}
+; CHECK: [[META1:![0-9]+]] = !{i32 4, !"nosanitize", i32 1}
+;.
diff --git a/llvm/test/Instrumentation/MemorySanitizer/msan-pass-second-run.ll b/llvm/test/Instrumentation/MemorySanitizer/msan-pass-second-run.ll
new file mode 100644
index 0000000000000..2633222399650
--- /dev/null
+++ b/llvm/test/Instrumentation/MemorySanitizer/msan-pass-second-run.ll
@@ -0,0 +1,43 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-attributes --check-globals all --version 5
+; This test checks in the second run, function is not instrumented again.
+; RUN: opt < %s -msan-check-access-address=0 -S -passes=msan,msan | FileCheck %s
+
+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"
+
+;.
+; CHECK: @llvm.used = appending global [1 x ptr] [ptr @msan.module_ctor], section "llvm.metadata"
+; CHECK: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 0, ptr @msan.module_ctor, ptr null }]
+; CHECK: @__msan_retval_tls = external thread_local(initialexec) global [100 x i64]
+; CHECK: @__msan_retval_origin_tls = external thread_local(initialexec) global i32
+; CHECK: @__msan_param_tls = external thread_local(initialexec) global [100 x i64]
+; CHECK: @__msan_param_origin_tls = external thread_local(initialexec) global [200 x i32]
+; CHECK: @__msan_va_arg_tls = external thread_local(initialexec) global [100 x i64]
+; CHECK: @__msan_va_arg_origin_tls = external thread_local(initialexec) global [200 x i32]
+; CHECK: @__msan_va_arg_overflow_size_tls = external thread_local(initialexec) global i64
+;.
+define void @array() sanitize_memory {
+; CHECK: Function Attrs: sanitize_memory
+; CHECK-LABEL: define void @array(
+; CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    call void @llvm.donothing()
+; CHECK-NEXT:    [[X:%.*]] = alloca i32, i64 5, align 4
+; CHECK-NEXT:    [[TMP0:%.*]] = ptrtoint ptr [[X]] to i64
+; CHECK-NEXT:    [[TMP1:%.*]] = xor i64 [[TMP0]], 87960930222080
+; CHECK-NEXT:    [[TMP2:%.*]] = inttoptr i64 [[TMP1]] to ptr
+; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr align 4 [[TMP2]], i8 -1, i64 20, i1 false)
+; CHECK-NEXT:    ret void
+;
+entry:
+  %x = alloca i32, i64 5, align 4
+  ret void
+}
+;.
+; CHECK: attributes #[[ATTR0]] = { sanitize_memory }
+; CHECK: attributes #[[ATTR1:[0-9]+]] = { nounwind }
+; CHECK: attributes #[[ATTR2:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(none) }
+; CHECK: attributes #[[ATTR3:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: write) }
+;.
+; CHECK: [[META0:![0-9]+]] = !{i32 4, !"nosanitize", i32 1}
+;.

>From 82d49f05040d38f47b544fc46d609f8db631c808 Mon Sep 17 00:00:00 2001
From: skc7 <Krishna.Sankisa at amd.com>
Date: Fri, 26 Jul 2024 11:03:21 +0530
Subject: [PATCH 4/6] [Sanitizer] Use separate module flag for every sanitizer.

---
 llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp      | 4 ++--
 llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp     | 4 ++--
 llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp    | 4 ++--
 llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp       | 4 ++--
 .../Instrumentation/AddressSanitizer/asan-pass-second-run.ll  | 2 +-
 .../DataFlowSanitizer/dfsan-pass-second-run.ll                | 2 +-
 .../HWAddressSanitizer/hwasan-pass-second-run.ll              | 2 +-
 .../Instrumentation/MemorySanitizer/msan-pass-second-run.ll   | 2 +-
 8 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
index a985aa1df101b..c1e3e805fe63b 100644
--- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
@@ -1253,7 +1253,7 @@ PreservedAnalyses AddressSanitizerPass::run(Module &M,
                                             ModuleAnalysisManager &MAM) {
   // Return early if nosanitize module flag is present for the module.
   // This implies that asan pass has already run before.
-  if (M.getModuleFlag("nosanitize"))
+  if (M.getModuleFlag("nosanitize_address"))
     return PreservedAnalyses::all();
 
   ModuleAddressSanitizer ModuleSanitizer(
@@ -1273,7 +1273,7 @@ PreservedAnalyses AddressSanitizerPass::run(Module &M,
   }
   Modified |= ModuleSanitizer.instrumentModule(M);
   if (Modified)
-    M.addModuleFlag(Module::ModFlagBehavior::Override, "nosanitize", 1);
+    M.addModuleFlag(Module::ModFlagBehavior::Override, "nosanitize_address", 1);
   if (!Modified)
     return PreservedAnalyses::all();
 
diff --git a/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
index 77e8a830d10f1..32ee16a7bf159 100644
--- a/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
@@ -3474,7 +3474,7 @@ void DFSanVisitor::visitPHINode(PHINode &PN) {
 PreservedAnalyses DataFlowSanitizerPass::run(Module &M,
                                              ModuleAnalysisManager &AM) {
   // Return early if nosanitize module flag is present for the module.
-  if (M.getModuleFlag("nosanitize"))
+  if (M.getModuleFlag("nosanitize_dataflow"))
     return PreservedAnalyses::all();
   auto GetTLI = [&](Function &F) -> TargetLibraryInfo & {
     auto &FAM =
@@ -3489,6 +3489,6 @@ PreservedAnalyses DataFlowSanitizerPass::run(Module &M,
   // explicitly invalidated; PreservedAnalyses::none() is not enough. Sanitizers
   // make changes that require GlobalsAA to be invalidated.
   PA.abandon<GlobalsAA>();
-  M.addModuleFlag(Module::ModFlagBehavior::Override, "nosanitize", 1);
+  M.addModuleFlag(Module::ModFlagBehavior::Override, "nosanitize_dataflow", 1);
   return PA;
 }
diff --git a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
index 0fc33e28cd29b..e550b2644f4a0 100644
--- a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
@@ -456,7 +456,7 @@ class HWAddressSanitizer {
 PreservedAnalyses HWAddressSanitizerPass::run(Module &M,
                                               ModuleAnalysisManager &MAM) {
   // Return early if nosanitize module flag is present for the module.
-  if (M.getModuleFlag("nosanitize"))
+  if (M.getModuleFlag("nosanitize_hwaddress"))
     return PreservedAnalyses::all();
   const StackSafetyGlobalInfo *SSI = nullptr;
   auto TargetTriple = llvm::Triple(M.getTargetTriple());
@@ -479,7 +479,7 @@ PreservedAnalyses HWAddressSanitizerPass::run(Module &M,
   // explicitly invalidated; PreservedAnalyses::none() is not enough. Sanitizers
   // make changes that require GlobalsAA to be invalidated.
   PA.abandon<GlobalsAA>();
-  M.addModuleFlag(Module::ModFlagBehavior::Override, "nosanitize", 1);
+  M.addModuleFlag(Module::ModFlagBehavior::Override, "nosanitize_hwaddress", 1);
   return PA;
 }
 void HWAddressSanitizerPass::printPipeline(
diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
index 65b36dfbde32a..be10278658b2c 100644
--- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
@@ -707,7 +707,7 @@ MemorySanitizerOptions::MemorySanitizerOptions(int TO, bool R, bool K,
 PreservedAnalyses MemorySanitizerPass::run(Module &M,
                                            ModuleAnalysisManager &AM) {
   // Return early if nosanitize module flag is present for the module.
-  if (M.getModuleFlag("nosanitize"))
+  if (M.getModuleFlag("nosanitize_memory"))
     return PreservedAnalyses::all();
   bool Modified = false;
   if (!Options.Kernel) {
@@ -725,7 +725,7 @@ PreservedAnalyses MemorySanitizerPass::run(Module &M,
   }
 
   if (Modified)
-    M.addModuleFlag(Module::ModFlagBehavior::Override, "nosanitize", 1);
+    M.addModuleFlag(Module::ModFlagBehavior::Override, "nosanitize_memory", 1);
   if (!Modified)
     return PreservedAnalyses::all();
 
diff --git a/llvm/test/Instrumentation/AddressSanitizer/asan-pass-second-run.ll b/llvm/test/Instrumentation/AddressSanitizer/asan-pass-second-run.ll
index d3089870e3893..60ef1079624d7 100644
--- a/llvm/test/Instrumentation/AddressSanitizer/asan-pass-second-run.ll
+++ b/llvm/test/Instrumentation/AddressSanitizer/asan-pass-second-run.ll
@@ -50,6 +50,6 @@ entry:
 ; CHECK: attributes #[[ATTR1:[0-9]+]] = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
 ; CHECK: attributes #[[ATTR2]] = { nomerge }
 ;.
-; CHECK: [[META0:![0-9]+]] = !{i32 4, !"nosanitize", i32 1}
+; CHECK: [[META0:![0-9]+]] = !{i32 4, !"nosanitize_address", i32 1}
 ; CHECK: [[PROF1]] = !{!"branch_weights", i32 1, i32 1048575}
 ;.
diff --git a/llvm/test/Instrumentation/DataFlowSanitizer/dfsan-pass-second-run.ll b/llvm/test/Instrumentation/DataFlowSanitizer/dfsan-pass-second-run.ll
index d812367cfe9b6..7da647be24bbc 100644
--- a/llvm/test/Instrumentation/DataFlowSanitizer/dfsan-pass-second-run.ll
+++ b/llvm/test/Instrumentation/DataFlowSanitizer/dfsan-pass-second-run.ll
@@ -14,4 +14,4 @@ define i8 @add(i8 %a, i8 %b) {
   ret i8 %c
 }
 
-; CHECK: [[META0:![0-9]+]] = !{i32 4, !"nosanitize", i32 1}
+; CHECK: [[META0:![0-9]+]] = !{i32 4, !"nosanitize_dataflow", i32 1}
diff --git a/llvm/test/Instrumentation/HWAddressSanitizer/hwasan-pass-second-run.ll b/llvm/test/Instrumentation/HWAddressSanitizer/hwasan-pass-second-run.ll
index 6276480536303..00614b603fe79 100644
--- a/llvm/test/Instrumentation/HWAddressSanitizer/hwasan-pass-second-run.ll
+++ b/llvm/test/Instrumentation/HWAddressSanitizer/hwasan-pass-second-run.ll
@@ -37,5 +37,5 @@ entry:
 ; CHECK: attributes #[[ATTR1:[0-9]+]] = { nounwind }
 ;.
 ; CHECK: [[META0]] = !{ptr @hwasan.note}
-; CHECK: [[META1:![0-9]+]] = !{i32 4, !"nosanitize", i32 1}
+; CHECK: [[META1:![0-9]+]] = !{i32 4, !"nosanitize_hwaddress", i32 1}
 ;.
diff --git a/llvm/test/Instrumentation/MemorySanitizer/msan-pass-second-run.ll b/llvm/test/Instrumentation/MemorySanitizer/msan-pass-second-run.ll
index 2633222399650..5c135d63e56fd 100644
--- a/llvm/test/Instrumentation/MemorySanitizer/msan-pass-second-run.ll
+++ b/llvm/test/Instrumentation/MemorySanitizer/msan-pass-second-run.ll
@@ -39,5 +39,5 @@ entry:
 ; CHECK: attributes #[[ATTR2:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(none) }
 ; CHECK: attributes #[[ATTR3:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: write) }
 ;.
-; CHECK: [[META0:![0-9]+]] = !{i32 4, !"nosanitize", i32 1}
+; CHECK: [[META0:![0-9]+]] = !{i32 4, !"nosanitize_memory", i32 1}
 ;.

>From e782d91032e6e00274f75dcd074e48f97aa9260c Mon Sep 17 00:00:00 2001
From: skc7 <Krishna.Sankisa at amd.com>
Date: Fri, 26 Jul 2024 11:36:36 +0530
Subject: [PATCH 5/6] [Sanitizer] Set module flag after check.

---
 llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp   | 3 +--
 llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp  | 2 +-
 llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp | 2 +-
 llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp    | 3 +--
 4 files changed, 4 insertions(+), 6 deletions(-)

diff --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
index c1e3e805fe63b..f7513a2f22c5a 100644
--- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
@@ -1255,6 +1255,7 @@ PreservedAnalyses AddressSanitizerPass::run(Module &M,
   // This implies that asan pass has already run before.
   if (M.getModuleFlag("nosanitize_address"))
     return PreservedAnalyses::all();
+  M.addModuleFlag(Module::ModFlagBehavior::Override, "nosanitize_address", 1);
 
   ModuleAddressSanitizer ModuleSanitizer(
       M, Options.InsertVersionCheck, Options.CompileKernel, Options.Recover,
@@ -1272,8 +1273,6 @@ PreservedAnalyses AddressSanitizerPass::run(Module &M,
     Modified |= FunctionSanitizer.instrumentFunction(F, &TLI);
   }
   Modified |= ModuleSanitizer.instrumentModule(M);
-  if (Modified)
-    M.addModuleFlag(Module::ModFlagBehavior::Override, "nosanitize_address", 1);
   if (!Modified)
     return PreservedAnalyses::all();
 
diff --git a/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
index 32ee16a7bf159..16af27297b5f2 100644
--- a/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
@@ -3476,6 +3476,7 @@ PreservedAnalyses DataFlowSanitizerPass::run(Module &M,
   // Return early if nosanitize module flag is present for the module.
   if (M.getModuleFlag("nosanitize_dataflow"))
     return PreservedAnalyses::all();
+  M.addModuleFlag(Module::ModFlagBehavior::Override, "nosanitize_dataflow", 1);
   auto GetTLI = [&](Function &F) -> TargetLibraryInfo & {
     auto &FAM =
         AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
@@ -3489,6 +3490,5 @@ PreservedAnalyses DataFlowSanitizerPass::run(Module &M,
   // explicitly invalidated; PreservedAnalyses::none() is not enough. Sanitizers
   // make changes that require GlobalsAA to be invalidated.
   PA.abandon<GlobalsAA>();
-  M.addModuleFlag(Module::ModFlagBehavior::Override, "nosanitize_dataflow", 1);
   return PA;
 }
diff --git a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
index e550b2644f4a0..c92a2dea68e83 100644
--- a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
@@ -458,6 +458,7 @@ PreservedAnalyses HWAddressSanitizerPass::run(Module &M,
   // Return early if nosanitize module flag is present for the module.
   if (M.getModuleFlag("nosanitize_hwaddress"))
     return PreservedAnalyses::all();
+  M.addModuleFlag(Module::ModFlagBehavior::Override, "nosanitize_hwaddress", 1);
   const StackSafetyGlobalInfo *SSI = nullptr;
   auto TargetTriple = llvm::Triple(M.getTargetTriple());
   if (shouldUseStackSafetyAnalysis(TargetTriple, Options.DisableOptimization))
@@ -479,7 +480,6 @@ PreservedAnalyses HWAddressSanitizerPass::run(Module &M,
   // explicitly invalidated; PreservedAnalyses::none() is not enough. Sanitizers
   // make changes that require GlobalsAA to be invalidated.
   PA.abandon<GlobalsAA>();
-  M.addModuleFlag(Module::ModFlagBehavior::Override, "nosanitize_hwaddress", 1);
   return PA;
 }
 void HWAddressSanitizerPass::printPipeline(
diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
index be10278658b2c..76f1aba470644 100644
--- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
@@ -709,6 +709,7 @@ PreservedAnalyses MemorySanitizerPass::run(Module &M,
   // Return early if nosanitize module flag is present for the module.
   if (M.getModuleFlag("nosanitize_memory"))
     return PreservedAnalyses::all();
+  M.addModuleFlag(Module::ModFlagBehavior::Override, "nosanitize_memory", 1);
   bool Modified = false;
   if (!Options.Kernel) {
     insertModuleCtor(M);
@@ -724,8 +725,6 @@ PreservedAnalyses MemorySanitizerPass::run(Module &M,
         Msan.sanitizeFunction(F, FAM.getResult<TargetLibraryAnalysis>(F));
   }
 
-  if (Modified)
-    M.addModuleFlag(Module::ModFlagBehavior::Override, "nosanitize_memory", 1);
   if (!Modified)
     return PreservedAnalyses::all();
 

>From 044d7b816a83d2cce29640abe4fbf2f35a36721a Mon Sep 17 00:00:00 2001
From: skc7 <Krishna.Sankisa at amd.com>
Date: Fri, 26 Jul 2024 15:31:28 +0530
Subject: [PATCH 6/6] [Sanitizer] Add module nosanitize flag for tsan-module.

---
 .../Instrumentation/AddressSanitizer.cpp      |  2 +-
 .../Instrumentation/DataFlowSanitizer.cpp     |  2 +-
 .../Instrumentation/HWAddressSanitizer.cpp    |  2 +-
 .../Instrumentation/MemorySanitizer.cpp       |  2 +-
 .../Instrumentation/ThreadSanitizer.cpp       |  4 +++
 .../ThreadSanitizer/tsan-pass-second-run.ll   | 28 +++++++++++++++++++
 6 files changed, 36 insertions(+), 4 deletions(-)
 create mode 100644 llvm/test/Instrumentation/ThreadSanitizer/tsan-pass-second-run.ll

diff --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
index f7513a2f22c5a..bed43db1cc487 100644
--- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
@@ -1251,7 +1251,7 @@ AddressSanitizerPass::AddressSanitizerPass(
 
 PreservedAnalyses AddressSanitizerPass::run(Module &M,
                                             ModuleAnalysisManager &MAM) {
-  // Return early if nosanitize module flag is present for the module.
+  // Return early if nosanitize_address module flag is present for the module.
   // This implies that asan pass has already run before.
   if (M.getModuleFlag("nosanitize_address"))
     return PreservedAnalyses::all();
diff --git a/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
index 16af27297b5f2..1fe8ef9e61284 100644
--- a/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
@@ -3473,7 +3473,7 @@ void DFSanVisitor::visitPHINode(PHINode &PN) {
 
 PreservedAnalyses DataFlowSanitizerPass::run(Module &M,
                                              ModuleAnalysisManager &AM) {
-  // Return early if nosanitize module flag is present for the module.
+  // Return early if nosanitize_dataflow module flag is present for the module.
   if (M.getModuleFlag("nosanitize_dataflow"))
     return PreservedAnalyses::all();
   M.addModuleFlag(Module::ModFlagBehavior::Override, "nosanitize_dataflow", 1);
diff --git a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
index c92a2dea68e83..5693d35101211 100644
--- a/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
@@ -455,7 +455,7 @@ class HWAddressSanitizer {
 
 PreservedAnalyses HWAddressSanitizerPass::run(Module &M,
                                               ModuleAnalysisManager &MAM) {
-  // Return early if nosanitize module flag is present for the module.
+  // Return early if nosanitize_hwaddress module flag is present for the module.
   if (M.getModuleFlag("nosanitize_hwaddress"))
     return PreservedAnalyses::all();
   M.addModuleFlag(Module::ModFlagBehavior::Override, "nosanitize_hwaddress", 1);
diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
index 76f1aba470644..da6477b0a6250 100644
--- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
@@ -706,7 +706,7 @@ MemorySanitizerOptions::MemorySanitizerOptions(int TO, bool R, bool K,
 
 PreservedAnalyses MemorySanitizerPass::run(Module &M,
                                            ModuleAnalysisManager &AM) {
-  // Return early if nosanitize module flag is present for the module.
+  // Return early if nosanitize_memory module flag is present for the module.
   if (M.getModuleFlag("nosanitize_memory"))
     return PreservedAnalyses::all();
   M.addModuleFlag(Module::ModFlagBehavior::Override, "nosanitize_memory", 1);
diff --git a/llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp
index 92e533d2281af..dd47a529e007c 100644
--- a/llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp
@@ -191,6 +191,10 @@ PreservedAnalyses ThreadSanitizerPass::run(Function &F,
 
 PreservedAnalyses ModuleThreadSanitizerPass::run(Module &M,
                                                  ModuleAnalysisManager &MAM) {
+  // Return early if nosanitize_thread module flag is present for the module.
+  if (M.getModuleFlag("nosanitize_thread"))
+    return PreservedAnalyses::all();
+  M.addModuleFlag(Module::ModFlagBehavior::Override, "nosanitize_thread", 1);
   insertModuleCtor(M);
   return PreservedAnalyses::none();
 }
diff --git a/llvm/test/Instrumentation/ThreadSanitizer/tsan-pass-second-run.ll b/llvm/test/Instrumentation/ThreadSanitizer/tsan-pass-second-run.ll
new file mode 100644
index 0000000000000..9614a418480ec
--- /dev/null
+++ b/llvm/test/Instrumentation/ThreadSanitizer/tsan-pass-second-run.ll
@@ -0,0 +1,28 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-attributes --check-globals --version 2
+; RUN: opt < %s -passes=tsan-module,tsan-module -S | FileCheck %s
+
+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"
+
+declare void @can_throw()
+declare void @cannot_throw() nounwind
+
+;.
+; CHECK: @llvm.used = appending global [1 x ptr] [ptr @tsan.module_ctor], section "llvm.metadata"
+; CHECK: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 0, ptr @tsan.module_ctor, ptr null }]
+;.
+define i32 @func1() sanitize_thread {
+; CHECK: Function Attrs: sanitize_thread
+; CHECK-LABEL: define i32 @func1
+; CHECK-SAME: () #[[ATTR1:[0-9]+]] {
+; CHECK-NEXT:    call void @can_throw()
+; CHECK-NEXT:    ret i32 0
+;
+  call void @can_throw()
+  ret i32 0
+}
+;.
+; CHECK: attributes #[[ATTR0:[0-9]+]] = { nounwind }
+; CHECK: attributes #[[ATTR1]] = { sanitize_thread }
+;.
+; CHECK: [[META0:![0-9]+]] = !{i32 4, !"nosanitize_thread", i32 1}
+;.



More information about the llvm-commits mailing list