[compiler-rt] dbe8c2c - Use-after-return sanitizer binary metadata

Dmitry Vyukov via llvm-commits llvm-commits at lists.llvm.org
Mon Dec 5 05:40:39 PST 2022


Author: Dmitry Vyukov
Date: 2022-12-05T14:40:31+01:00
New Revision: dbe8c2c316c40b25a0a37b91f1a1a02a55182378

URL: https://github.com/llvm/llvm-project/commit/dbe8c2c316c40b25a0a37b91f1a1a02a55182378
DIFF: https://github.com/llvm/llvm-project/commit/dbe8c2c316c40b25a0a37b91f1a1a02a55182378.diff

LOG: Use-after-return sanitizer binary metadata

Currently per-function metadata consists of:
(start-pc, size, features)

This adds a new UAR feature and if it's set an additional element:
(start-pc, size, features, stack-args-size)

Reviewed By: melver

Differential Revision: https://reviews.llvm.org/D136078

Added: 
    compiler-rt/test/metadata/CMakeLists.txt
    compiler-rt/test/metadata/common.h
    compiler-rt/test/metadata/covered.cpp
    compiler-rt/test/metadata/lit.cfg.py
    compiler-rt/test/metadata/lit.site.cfg.py.in
    compiler-rt/test/metadata/uar.cpp
    llvm/lib/CodeGen/SanitizerBinaryMetadata.cpp

Modified: 
    clang/include/clang/Basic/CodeGenOptions.def
    clang/include/clang/Basic/CodeGenOptions.h
    clang/include/clang/Driver/Options.td
    clang/lib/CodeGen/BackendUtil.cpp
    clang/lib/Driver/SanitizerArgs.cpp
    compiler-rt/test/CMakeLists.txt
    llvm/include/llvm/CodeGen/CodeGenPassBuilder.h
    llvm/include/llvm/CodeGen/MachinePassRegistry.def
    llvm/include/llvm/CodeGen/Passes.h
    llvm/include/llvm/InitializePasses.h
    llvm/include/llvm/Transforms/Instrumentation.h
    llvm/include/llvm/Transforms/Instrumentation/SanitizerBinaryMetadata.h
    llvm/lib/CodeGen/CMakeLists.txt
    llvm/lib/CodeGen/CodeGen.cpp
    llvm/lib/CodeGen/TargetPassConfig.cpp
    llvm/lib/Transforms/Instrumentation/SanitizerBinaryMetadata.cpp
    llvm/test/CodeGen/AArch64/O0-pipeline.ll
    llvm/test/CodeGen/AArch64/O3-pipeline.ll
    llvm/test/CodeGen/AMDGPU/llc-pipeline.ll
    llvm/test/CodeGen/ARM/O3-pipeline.ll
    llvm/test/CodeGen/M68k/pipeline.ll
    llvm/test/CodeGen/PowerPC/O3-pipeline.ll
    llvm/test/CodeGen/RISCV/O0-pipeline.ll
    llvm/test/CodeGen/RISCV/O3-pipeline.ll
    llvm/test/CodeGen/X86/O0-pipeline.ll
    llvm/test/CodeGen/X86/opt-pipeline.ll

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def
index 43521b76652db..81d5ccd4856d4 100644
--- a/clang/include/clang/Basic/CodeGenOptions.def
+++ b/clang/include/clang/Basic/CodeGenOptions.def
@@ -288,6 +288,8 @@ CODEGENOPT(SanitizeCoverageTraceLoads, 1, 0) ///< Enable tracing of loads.
 CODEGENOPT(SanitizeCoverageTraceStores, 1, 0) ///< Enable tracing of stores.
 CODEGENOPT(SanitizeBinaryMetadataCovered, 1, 0) ///< Emit PCs for covered functions.
 CODEGENOPT(SanitizeBinaryMetadataAtomics, 1, 0) ///< Emit PCs for atomic operations.
+CODEGENOPT(SanitizeBinaryMetadataUAR, 1, 0) ///< Emit PCs for start of functions
+                                            ///< that are subject for use-after-return checking.
 CODEGENOPT(SanitizeStats     , 1, 0) ///< Collect statistics for sanitizers.
 CODEGENOPT(SimplifyLibCalls  , 1, 1) ///< Set when -fbuiltin is enabled.
 CODEGENOPT(SoftFloat         , 1, 0) ///< -soft-float.

diff  --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h
index 24cc56c8e05df..d34ed1d6d4919 100644
--- a/clang/include/clang/Basic/CodeGenOptions.h
+++ b/clang/include/clang/Basic/CodeGenOptions.h
@@ -497,7 +497,8 @@ class CodeGenOptions : public CodeGenOptionsBase {
 
   // Check if any one of SanitizeBinaryMetadata* is enabled.
   bool hasSanitizeBinaryMetadata() const {
-    return SanitizeBinaryMetadataCovered || SanitizeBinaryMetadataAtomics;
+    return SanitizeBinaryMetadataCovered || SanitizeBinaryMetadataAtomics ||
+           SanitizeBinaryMetadataUAR;
   }
 };
 

diff  --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 11f6253db7445..c888d4f6194ab 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -5582,6 +5582,10 @@ def fexperimental_sanitize_metadata_EQ_atomics
     : Flag<["-"], "fexperimental-sanitize-metadata=atomics">,
       HelpText<"Emit PCs for atomic operations used by binary analysis sanitizers">,
       MarshallingInfoFlag<CodeGenOpts<"SanitizeBinaryMetadataAtomics">>;
+def fexperimental_sanitize_metadata_EQ_uar
+    : Flag<["-"], "fexperimental-sanitize-metadata=uar">,
+      HelpText<"Emit PCs for start of functions that are subject for use-after-return checking.">,
+      MarshallingInfoFlag<CodeGenOpts<"SanitizeBinaryMetadataUAR">>;
 def fpatchable_function_entry_offset_EQ
     : Joined<["-"], "fpatchable-function-entry-offset=">, MetaVarName<"<M>">,
       HelpText<"Generate M NOPs before function entry">,

diff  --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp
index b18ead066c6d2..16b48c6dc1d18 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -235,6 +235,7 @@ getSanitizerBinaryMetadataOptions(const CodeGenOptions &CGOpts) {
   SanitizerBinaryMetadataOptions Opts;
   Opts.Covered = CGOpts.SanitizeBinaryMetadataCovered;
   Opts.Atomics = CGOpts.SanitizeBinaryMetadataAtomics;
+  Opts.UAR = CGOpts.SanitizeBinaryMetadataUAR;
   return Opts;
 }
 

diff  --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp
index af27dbc92c8e6..96a701366e37b 100644
--- a/clang/lib/Driver/SanitizerArgs.cpp
+++ b/clang/lib/Driver/SanitizerArgs.cpp
@@ -104,6 +104,7 @@ enum CoverageFeature {
 enum BinaryMetadataFeature {
   BinaryMetadataCovered = 1 << 0,
   BinaryMetadataAtomics = 1 << 1,
+  BinaryMetadataUAR = 1 << 2,
 };
 
 /// Parse a -fsanitize= or -fno-sanitize= argument's values, diagnosing any
@@ -1133,7 +1134,8 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
   // flags. Does not depend on any other sanitizers.
   const std::pair<int, std::string> BinaryMetadataFlags[] = {
       std::make_pair(BinaryMetadataCovered, "covered"),
-      std::make_pair(BinaryMetadataAtomics, "atomics")};
+      std::make_pair(BinaryMetadataAtomics, "atomics"),
+      std::make_pair(BinaryMetadataUAR, "uar")};
   for (const auto &F : BinaryMetadataFlags) {
     if (BinaryMetadataFeatures & F.first)
       CmdArgs.push_back(
@@ -1399,6 +1401,7 @@ int parseBinaryMetadataFeatures(const Driver &D, const llvm::opt::Arg *A,
     int F = llvm::StringSwitch<int>(Value)
                 .Case("covered", BinaryMetadataCovered)
                 .Case("atomics", BinaryMetadataAtomics)
+                .Case("uar", BinaryMetadataUAR)
                 .Case("all", ~0)
                 .Default(0);
     if (F == 0 && DiagnoseErrors)

diff  --git a/compiler-rt/test/CMakeLists.txt b/compiler-rt/test/CMakeLists.txt
index 4fc51e0b41e6e..04ff819c6e5af 100644
--- a/compiler-rt/test/CMakeLists.txt
+++ b/compiler-rt/test/CMakeLists.txt
@@ -105,6 +105,8 @@ if(COMPILER_RT_CAN_EXECUTE_TESTS)
   # ShadowCallStack does not yet provide a runtime with compiler-rt, the tests
   # include their own minimal runtime
   add_subdirectory(shadowcallstack)
+  # These tests are self-contained and don't need an additional runtime.
+  add_subdirectory(metadata)
 endif()
 
 if(COMPILER_RT_STANDALONE_BUILD)

diff  --git a/compiler-rt/test/metadata/CMakeLists.txt b/compiler-rt/test/metadata/CMakeLists.txt
new file mode 100644
index 0000000000000..b3765d7dd0885
--- /dev/null
+++ b/compiler-rt/test/metadata/CMakeLists.txt
@@ -0,0 +1,15 @@
+set(TEST_ARCH ${X86_64})
+
+set(METADATA_LIT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
+set(METADATA_LIT_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
+
+set(SANITIZER_COMMON_TEST_TARGET_ARCH ${X86_64})
+get_test_cc_for_arch(${X86_64} METADATA_TEST_TARGET_CC METADATA_TEST_TARGET_CFLAGS)
+configure_lit_site_cfg(
+  ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.py.in
+  ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg.py)
+
+add_lit_testsuite(check-sanmd "Running the SanitizerBinaryMetadata tests"
+  ${CMAKE_CURRENT_BINARY_DIR}
+  DEPENDS ${SANITIZER_COMMON_LIT_TEST_DEPS})
+set_target_properties(check-sanmd PROPERTIES FOLDER "Compiler-RT Misc")

diff  --git a/compiler-rt/test/metadata/common.h b/compiler-rt/test/metadata/common.h
new file mode 100644
index 0000000000000..b121e871718e9
--- /dev/null
+++ b/compiler-rt/test/metadata/common.h
@@ -0,0 +1,75 @@
+#include <assert.h>
+#include <stdint.h>
+#include <stdio.h>
+
+int main() { printf("main\n"); }
+
+typedef unsigned long uptr;
+
+#define FN(X)                                                                  \
+  if (pc == reinterpret_cast<uptr>(X))                                         \
+  return #X
+
+const char *symbolize(uptr pc) {
+  FUNCTIONS;
+  return nullptr;
+}
+
+template <typename T> T consume(const char *&pos, const char *end) {
+  T v = *reinterpret_cast<const T *>(pos);
+  pos += sizeof(T);
+  assert(pos <= end);
+  return v;
+}
+
+uint32_t meta_version;
+const char *meta_start;
+const char *meta_end;
+
+extern "C" {
+void __sanitizer_metadata_covered_add(uint32_t version, const char *start,
+                                      const char *end) {
+  printf("metadata add version %u\n", version);
+  for (const char *pos = start; pos < end;) {
+    const uptr base = reinterpret_cast<uptr>(pos);
+    const long offset = (version & (1 << 16)) ? consume<long>(pos, end)
+                                              : consume<int>(pos, end);
+    const uint32_t size = consume<uint32_t>(pos, end);
+    const uint32_t features = consume<uint32_t>(pos, end);
+    uint32_t stack_args = 0;
+    if (features & (1 << 1))
+      stack_args = consume<uint32_t>(pos, end);
+    if (const char *name = symbolize(base + offset))
+      printf("%s: features=%x stack_args=%u\n", name, features, stack_args);
+  }
+  meta_version = version;
+  meta_start = start;
+  meta_end = end;
+}
+
+void __sanitizer_metadata_covered_del(uint32_t version, const char *start,
+                                      const char *end) {
+  assert(version == meta_version);
+  assert(start == meta_start);
+  assert(end == meta_end);
+}
+
+const char *atomics_start;
+const char *atomics_end;
+
+void __sanitizer_metadata_atomics_add(uint32_t version, const char *start,
+                                      const char *end) {
+  assert(version == meta_version);
+  assert(start);
+  assert(end >= end);
+  atomics_start = start;
+  atomics_end = end;
+}
+
+void __sanitizer_metadata_atomics_del(uint32_t version, const char *start,
+                                      const char *end) {
+  assert(version == meta_version);
+  assert(atomics_start == start);
+  assert(atomics_end == end);
+}
+}

diff  --git a/compiler-rt/test/metadata/covered.cpp b/compiler-rt/test/metadata/covered.cpp
new file mode 100644
index 0000000000000..d00f970c795c9
--- /dev/null
+++ b/compiler-rt/test/metadata/covered.cpp
@@ -0,0 +1,75 @@
+// RUN: %clangxx %s -o %t && %t | FileCheck %s
+// RUN: %clangxx %s -o %t -fexperimental-sanitize-metadata=covered && %t | FileCheck -check-prefix=CHECK-C %s
+// RUN: %clangxx %s -o %t -fexperimental-sanitize-metadata=atomics && %t | FileCheck -check-prefix=CHECK-A %s
+// RUN: %clangxx %s -o %t -fexperimental-sanitize-metadata=uar && %t | FileCheck -check-prefix=CHECK-U %s
+// RUN: %clangxx %s -o %t -fexperimental-sanitize-metadata=covered,atomics && %t | FileCheck -check-prefix=CHECK-CA %s
+// RUN: %clangxx %s -o %t -fexperimental-sanitize-metadata=covered,uar && %t | FileCheck -check-prefix=CHECK-CU %s
+// RUN: %clangxx %s -o %t -fexperimental-sanitize-metadata=atomics,uar && %t | FileCheck -check-prefix=CHECK-AU %s
+// RUN: %clangxx %s -o %t -fexperimental-sanitize-metadata=covered,atomics,uar && %t | FileCheck -check-prefix=CHECK-CAU %s
+
+// CHECK-NOT: metadata add
+// CHECK: main
+// CHECK-NOT: metadata del
+
+// CHECK-C:      empty: features=0
+// CHECK-A-NOT:  empty:
+// CHECK-U-NOT:  empty:
+// CHECK-CA:     empty: features=1
+// CHECK-CU:     empty: features=0
+// CHECK-AU-NOT: empty:
+// CHECK-CAU:    empty: features=1
+void empty() {}
+
+// CHECK-C:  normal: features=0
+// CHECK-A:  normal: features=1
+// CHECK-U:  normal: features=2
+// CHECK-CA: normal: features=1
+// CHECK-CU: normal: features=2
+// CHECK-AU: normal: features=3
+// CHECK-CAU:normal: features=3
+void normal() {
+  volatile int x;
+  x = 0;
+}
+
+// CHECK-C:   with_atomic: features=0
+// CHECK-A:   with_atomic: features=1
+// CHECK-U:   with_atomic: features=2
+// CHECK-CA:  with_atomic: features=1
+// CHECK-CU:  with_atomic: features=2
+// CHECK-AU:  with_atomic: features=3
+// CHECK-CAU: with_atomic: features=3
+int with_atomic(int *p) { return __atomic_load_n(p, __ATOMIC_RELAXED); }
+
+// CHECK-C:     ellipsis: features=0
+// CHECK-A:     ellipsis: features=1
+// CHECK-U-NOT: ellipsis:
+// CHECK-CA:    ellipsis: features=1
+// CHECK-CU:    ellipsis: features=0
+// CHECK-AU:    ellipsis: features=1
+// CHECK-CAU:   ellipsis: features=1
+void ellipsis(int *p, ...) {
+  volatile int x;
+  x = 0;
+}
+
+// CHECK-C:     ellipsis_with_atomic: features=0
+// CHECK-A:     ellipsis_with_atomic: features=1
+// CHECK-U-NOT: ellipsis_with_atomic:
+// CHECK-CA:    ellipsis_with_atomic: features=1
+// CHECK-CU:    ellipsis_with_atomic: features=0
+// CHECK-AU:    ellipsis_with_atomic: features=1
+// CHECK-CAU:   ellipsis_with_atomic: features=1
+int ellipsis_with_atomic(int *p, ...) {
+  return __atomic_load_n(p, __ATOMIC_RELAXED);
+}
+
+#define FUNCTIONS                                                              \
+  FN(empty);                                                                   \
+  FN(normal);                                                                  \
+  FN(with_atomic);                                                             \
+  FN(ellipsis);                                                                \
+  FN(ellipsis_with_atomic);                                                    \
+  /**/
+
+#include "common.h"

diff  --git a/compiler-rt/test/metadata/lit.cfg.py b/compiler-rt/test/metadata/lit.cfg.py
new file mode 100644
index 0000000000000..aefc97f09ed92
--- /dev/null
+++ b/compiler-rt/test/metadata/lit.cfg.py
@@ -0,0 +1,9 @@
+import os
+
+config.name = 'SanitizerBinaryMetadata'
+config.test_source_root = os.path.dirname(__file__)
+config.suffixes = ['.cpp']
+# Binary metadata is currently emited only for ELF binaries
+# and sizes of stack arguments depend on the arch.
+if config.host_os not in ['Linux'] or config.target_arch not in ['x86_64']:
+   config.unsupported = True

diff  --git a/compiler-rt/test/metadata/lit.site.cfg.py.in b/compiler-rt/test/metadata/lit.site.cfg.py.in
new file mode 100644
index 0000000000000..7b95b4b0fb73d
--- /dev/null
+++ b/compiler-rt/test/metadata/lit.site.cfg.py.in
@@ -0,0 +1,14 @@
+ at LIT_SITE_CFG_IN_HEADER@
+
+# Tool-specific config options.
+config.clang = "@METADATA_TEST_TARGET_CC@"
+config.target_cflags = "@METADATA_TEST_TARGET_CFLAGS@"
+config.target_arch = "x86_64"
+
+# Load common config for all compiler-rt lit tests.
+lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/test/lit.common.configured")
+
+# Load tool-specific config that would do the real work.
+lit_config.load_config(config, "@METADATA_LIT_SOURCE_DIR@/lit.cfg.py")
+
+config.substitutions.append(("%clangxx ", " " + config.clang + " " + config.target_cflags + " "))

diff  --git a/compiler-rt/test/metadata/uar.cpp b/compiler-rt/test/metadata/uar.cpp
new file mode 100644
index 0000000000000..dc6abdf63ab45
--- /dev/null
+++ b/compiler-rt/test/metadata/uar.cpp
@@ -0,0 +1,59 @@
+// RUN: %clangxx %s -o %t -fexperimental-sanitize-metadata=covered,uar && %t | FileCheck %s
+
+// CHECK: metadata add version 1
+
+// CHECK: empty: features=0 stack_args=0
+void empty() {}
+
+// CHECK: ellipsis: features=0 stack_args=0
+void ellipsis(const char *fmt, ...) {
+  volatile int x;
+  x = 1;
+}
+
+// CHECK: non_empty_function: features=2 stack_args=0
+void non_empty_function() {
+  // Completely empty functions don't get uar metadata.
+  volatile int x;
+  x = 1;
+}
+
+// CHECK: no_stack_args: features=2 stack_args=0
+void no_stack_args(long a0, long a1, long a2, long a3, long a4, long a5) {
+  volatile int x;
+  x = 1;
+}
+
+// CHECK: stack_args: features=2 stack_args=16
+void stack_args(long a0, long a1, long a2, long a3, long a4, long a5, long a6) {
+  volatile int x;
+  x = 1;
+}
+
+// CHECK: more_stack_args: features=2 stack_args=32
+void more_stack_args(long a0, long a1, long a2, long a3, long a4, long a5,
+                     long a6, long a7, long a8) {
+  volatile int x;
+  x = 1;
+}
+
+// CHECK: struct_stack_args: features=2 stack_args=144
+struct large {
+  char x[131];
+};
+void struct_stack_args(large a) {
+  volatile int x;
+  x = 1;
+}
+
+#define FUNCTIONS                                                              \
+  FN(empty);                                                                   \
+  FN(ellipsis);                                                                \
+  FN(non_empty_function);                                                      \
+  FN(no_stack_args);                                                           \
+  FN(stack_args);                                                              \
+  FN(more_stack_args);                                                         \
+  FN(struct_stack_args);                                                       \
+  /**/
+
+#include "common.h"

diff  --git a/llvm/include/llvm/CodeGen/CodeGenPassBuilder.h b/llvm/include/llvm/CodeGen/CodeGenPassBuilder.h
index 48aa4b034fee0..fbaa1b229f55a 100644
--- a/llvm/include/llvm/CodeGen/CodeGenPassBuilder.h
+++ b/llvm/include/llvm/CodeGen/CodeGenPassBuilder.h
@@ -926,6 +926,7 @@ Error CodeGenPassBuilder<Derived>::addMachinePasses(
 
   addPass(StackMapLivenessPass());
   addPass(LiveDebugValuesPass());
+  addPass(MachineSanitizerBinaryMetadata());
 
   if (TM.Options.EnableMachineOutliner && getOptLevel() != CodeGenOpt::None &&
       Opt.EnableMachineOutliner != RunOutliner::NeverOutline) {

diff  --git a/llvm/include/llvm/CodeGen/MachinePassRegistry.def b/llvm/include/llvm/CodeGen/MachinePassRegistry.def
index c1ceff9680d67..e5799a12a6dfe 100644
--- a/llvm/include/llvm/CodeGen/MachinePassRegistry.def
+++ b/llvm/include/llvm/CodeGen/MachinePassRegistry.def
@@ -203,4 +203,5 @@ DUMMY_MACHINE_FUNCTION_PASS("instruction-select", InstructionSelectPass, ())
 DUMMY_MACHINE_FUNCTION_PASS("reset-machine-function", ResetMachineFunctionPass, ())
 DUMMY_MACHINE_FUNCTION_PASS("machineverifier", MachineVerifierPass, ())
 DUMMY_MACHINE_FUNCTION_PASS("print-machine-cycles", MachineCycleInfoPrinterPass, ())
+DUMMY_MACHINE_FUNCTION_PASS("machine-sanmd", MachineSanitizerBinaryMetadata, ())
 #undef DUMMY_MACHINE_FUNCTION_PASS

diff  --git a/llvm/include/llvm/CodeGen/Passes.h b/llvm/include/llvm/CodeGen/Passes.h
index 5701dd13e152c..06cf550ed12c7 100644
--- a/llvm/include/llvm/CodeGen/Passes.h
+++ b/llvm/include/llvm/CodeGen/Passes.h
@@ -409,6 +409,10 @@ namespace llvm {
   /// the intrinsic for later emission to the StackMap.
   extern char &StackMapLivenessID;
 
+  // MachineSanitizerBinaryMetadata - appends/finalizes sanitizer binary
+  // metadata after llvm SanitizerBinaryMetadata pass.
+  extern char &MachineSanitizerBinaryMetadataID;
+
   /// RemoveRedundantDebugValues pass.
   extern char &RemoveRedundantDebugValuesID;
 

diff  --git a/llvm/include/llvm/InitializePasses.h b/llvm/include/llvm/InitializePasses.h
index 0c69ff3166d68..fd52c529bb4e6 100644
--- a/llvm/include/llvm/InitializePasses.h
+++ b/llvm/include/llvm/InitializePasses.h
@@ -276,6 +276,7 @@ void initializeMachineOutlinerPass(PassRegistry&);
 void initializeMachinePipelinerPass(PassRegistry&);
 void initializeMachinePostDominatorTreePass(PassRegistry&);
 void initializeMachineRegionInfoPassPass(PassRegistry&);
+void initializeMachineSanitizerBinaryMetadataPass(PassRegistry &);
 void initializeMachineSchedulerPass(PassRegistry&);
 void initializeMachineSinkingPass(PassRegistry&);
 void initializeMachineTraceMetricsPass(PassRegistry&);

diff  --git a/llvm/include/llvm/Transforms/Instrumentation.h b/llvm/include/llvm/Transforms/Instrumentation.h
index 2497b3d40d0b0..392983a198444 100644
--- a/llvm/include/llvm/Transforms/Instrumentation.h
+++ b/llvm/include/llvm/Transforms/Instrumentation.h
@@ -150,13 +150,6 @@ struct SanitizerCoverageOptions {
   SanitizerCoverageOptions() = default;
 };
 
-/// Options for SanitizerBinaryMetadata.
-struct SanitizerBinaryMetadataOptions {
-  bool Covered = false;
-  bool Atomics = false;
-  SanitizerBinaryMetadataOptions() = default;
-};
-
 /// Calculate what to divide by to scale counts.
 ///
 /// Given the maximum count, calculate a divisor that will scale all the

diff  --git a/llvm/include/llvm/Transforms/Instrumentation/SanitizerBinaryMetadata.h b/llvm/include/llvm/Transforms/Instrumentation/SanitizerBinaryMetadata.h
index a54801309c1d8..67e22d1aa6818 100644
--- a/llvm/include/llvm/Transforms/Instrumentation/SanitizerBinaryMetadata.h
+++ b/llvm/include/llvm/Transforms/Instrumentation/SanitizerBinaryMetadata.h
@@ -19,6 +19,27 @@
 
 namespace llvm {
 
+struct SanitizerBinaryMetadataOptions {
+  bool Covered = false;
+  bool Atomics = false;
+  bool UAR = false;
+  SanitizerBinaryMetadataOptions() = default;
+};
+
+inline constexpr int kSanitizerBinaryMetadataAtomicsBit = 0;
+inline constexpr int kSanitizerBinaryMetadataUARBit = 1;
+
+inline constexpr uint32_t kSanitizerBinaryMetadataNone = 0;
+inline constexpr uint32_t kSanitizerBinaryMetadataAtomics =
+    1 << kSanitizerBinaryMetadataAtomicsBit;
+inline constexpr uint32_t kSanitizerBinaryMetadataUAR =
+    1 << kSanitizerBinaryMetadataUARBit;
+
+inline constexpr char kSanitizerBinaryMetadataCoveredSection[] =
+    "sanmd_covered";
+inline constexpr char kSanitizerBinaryMetadataAtomicsSection[] =
+    "sanmd_atomics";
+
 /// Public interface to the SanitizerBinaryMetadata module pass for emitting
 /// metadata for binary analysis sanitizers.
 //

diff  --git a/llvm/lib/CodeGen/CMakeLists.txt b/llvm/lib/CodeGen/CMakeLists.txt
index db3b6183b5fd2..75b77ee7cd5fe 100644
--- a/llvm/lib/CodeGen/CMakeLists.txt
+++ b/llvm/lib/CodeGen/CMakeLists.txt
@@ -197,6 +197,7 @@ add_llvm_component_library(LLVMCodeGen
   RegisterBankInfo.cpp
   SafeStack.cpp
   SafeStackLayout.cpp
+  SanitizerBinaryMetadata.cpp
   ScheduleDAG.cpp
   ScheduleDAGInstrs.cpp
   ScheduleDAGPrinter.cpp

diff  --git a/llvm/lib/CodeGen/CodeGen.cpp b/llvm/lib/CodeGen/CodeGen.cpp
index a8bde3b700970..82581e262f843 100644
--- a/llvm/lib/CodeGen/CodeGen.cpp
+++ b/llvm/lib/CodeGen/CodeGen.cpp
@@ -84,6 +84,7 @@ void llvm::initializeCodeGen(PassRegistry &Registry) {
   initializeMachineOptimizationRemarkEmitterPassPass(Registry);
   initializeMachineOutlinerPass(Registry);
   initializeMachinePipelinerPass(Registry);
+  initializeMachineSanitizerBinaryMetadataPass(Registry);
   initializeModuloScheduleTestPass(Registry);
   initializeMachinePostDominatorTreePass(Registry);
   initializeMachineRegionInfoPassPass(Registry);

diff  --git a/llvm/lib/CodeGen/SanitizerBinaryMetadata.cpp b/llvm/lib/CodeGen/SanitizerBinaryMetadata.cpp
new file mode 100644
index 0000000000000..f9e608fe0f107
--- /dev/null
+++ b/llvm/lib/CodeGen/SanitizerBinaryMetadata.cpp
@@ -0,0 +1,78 @@
+//===- SanitizerBinaryMetadata.cpp
+//----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of SanitizerBinaryMetadata.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Transforms/Instrumentation/SanitizerBinaryMetadata.h"
+#include "llvm/CodeGen/MachineFrameInfo.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/MDBuilder.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Pass.h"
+#include <algorithm>
+
+using namespace llvm;
+
+class MachineSanitizerBinaryMetadata : public MachineFunctionPass {
+public:
+  static char ID;
+
+  MachineSanitizerBinaryMetadata();
+  bool runOnMachineFunction(MachineFunction &F) override;
+};
+
+INITIALIZE_PASS(MachineSanitizerBinaryMetadata, "machine-sanmd",
+                "Machine Sanitizer Binary Metadata", false, false)
+
+char MachineSanitizerBinaryMetadata::ID = 0;
+char &llvm::MachineSanitizerBinaryMetadataID =
+    MachineSanitizerBinaryMetadata::ID;
+
+MachineSanitizerBinaryMetadata::MachineSanitizerBinaryMetadata()
+    : MachineFunctionPass(ID) {
+  initializeMachineSanitizerBinaryMetadataPass(
+      *PassRegistry::getPassRegistry());
+}
+
+bool MachineSanitizerBinaryMetadata::runOnMachineFunction(MachineFunction &MF) {
+  MDNode *MD = MF.getFunction().getMetadata(LLVMContext::MD_pcsections);
+  if (!MD)
+    return false;
+  const auto &Section = *cast<MDString>(MD->getOperand(0));
+  if (!Section.getString().equals(kSanitizerBinaryMetadataCoveredSection))
+    return false;
+  auto &AuxMDs = *cast<MDTuple>(MD->getOperand(1));
+  // Assume it currently only has features.
+  assert(AuxMDs.getNumOperands() == 1);
+  auto *Features = cast<ConstantAsMetadata>(AuxMDs.getOperand(0))->getValue();
+  if (!Features->getUniqueInteger()[kSanitizerBinaryMetadataUARBit])
+    return false;
+  // Calculate size of stack args for the function.
+  int64_t Size = 0;
+  uint64_t Align = 0;
+  const MachineFrameInfo &MFI = MF.getFrameInfo();
+  for (int i = -1; i >= (int)-MFI.getNumFixedObjects(); --i) {
+    Size = std::max(Size, MFI.getObjectOffset(i) + MFI.getObjectSize(i));
+    Align = std::max(Align, MFI.getObjectAlign(i).value());
+  }
+  Size = (Size + Align - 1) & ~(Align - 1);
+  auto &F = MF.getFunction();
+  IRBuilder<> IRB(F.getContext());
+  MDBuilder MDB(F.getContext());
+  // Keep the features and append size of stack args to the metadata.
+  F.setMetadata(LLVMContext::MD_pcsections,
+                MDB.createPCSections(
+                    {{Section.getString(), {Features, IRB.getInt32(Size)}}}));
+  return false;
+}

diff  --git a/llvm/lib/CodeGen/TargetPassConfig.cpp b/llvm/lib/CodeGen/TargetPassConfig.cpp
index 59e714c4f2801..78195bc3d7a4c 100644
--- a/llvm/lib/CodeGen/TargetPassConfig.cpp
+++ b/llvm/lib/CodeGen/TargetPassConfig.cpp
@@ -1270,6 +1270,7 @@ void TargetPassConfig::addMachinePasses() {
 
   addPass(&StackMapLivenessID);
   addPass(&LiveDebugValuesID);
+  addPass(&MachineSanitizerBinaryMetadataID);
 
   if (TM->Options.EnableMachineOutliner && getOptLevel() != CodeGenOpt::None &&
       EnableMachineOutliner != RunOutliner::NeverOutline) {

diff  --git a/llvm/lib/Transforms/Instrumentation/SanitizerBinaryMetadata.cpp b/llvm/lib/Transforms/Instrumentation/SanitizerBinaryMetadata.cpp
index 169e87625c254..e8eaa9439c474 100644
--- a/llvm/lib/Transforms/Instrumentation/SanitizerBinaryMetadata.cpp
+++ b/llvm/lib/Transforms/Instrumentation/SanitizerBinaryMetadata.cpp
@@ -67,14 +67,16 @@ class MetadataInfo {
 private:
   // Forbid construction elsewhere.
   explicit constexpr MetadataInfo(StringRef FunctionPrefix,
-                                  StringRef SectionSuffix, int Feature)
+                                  StringRef SectionSuffix, uint32_t Feature)
       : FunctionPrefix(FunctionPrefix), SectionSuffix(SectionSuffix),
-        FeatureMask(Feature != -1 ? (1u << Feature) : 0) {}
+        FeatureMask(Feature) {}
 };
 const MetadataInfo MetadataInfo::Covered{"__sanitizer_metadata_covered",
-                                         "sanmd_covered", -1};
+                                         kSanitizerBinaryMetadataCoveredSection,
+                                         kSanitizerBinaryMetadataNone};
 const MetadataInfo MetadataInfo::Atomics{"__sanitizer_metadata_atomics",
-                                         "sanmd_atomics", 0};
+                                         kSanitizerBinaryMetadataAtomicsSection,
+                                         kSanitizerBinaryMetadataAtomics};
 
 // The only instances of MetadataInfo are the constants above, so a set of
 // them may simply store pointers to them. To deterministically generate code,
@@ -89,11 +91,16 @@ cl::opt<bool> ClEmitCovered("sanitizer-metadata-covered",
 cl::opt<bool> ClEmitAtomics("sanitizer-metadata-atomics",
                             cl::desc("Emit PCs for atomic operations."),
                             cl::Hidden, cl::init(false));
+cl::opt<bool> ClEmitUAR("sanitizer-metadata-uar",
+                        cl::desc("Emit PCs for start of functions that are "
+                                 "subject for use-after-return checking"),
+                        cl::Hidden, cl::init(false));
 
 //===--- Statistics -------------------------------------------------------===//
 
 STATISTIC(NumMetadataCovered, "Metadata attached to covered functions");
 STATISTIC(NumMetadataAtomics, "Metadata attached to atomics");
+STATISTIC(NumMetadataUAR, "Metadata attached to UAR functions");
 
 //===----------------------------------------------------------------------===//
 
@@ -102,6 +109,7 @@ SanitizerBinaryMetadataOptions &&
 transformOptionsFromCl(SanitizerBinaryMetadataOptions &&Opts) {
   Opts.Covered |= ClEmitCovered;
   Opts.Atomics |= ClEmitAtomics;
+  Opts.UAR |= ClEmitUAR;
   return std::move(Opts);
 }
 
@@ -142,7 +150,8 @@ class SanitizerBinaryMetadata {
   // function with memory operations (atomic or not) requires covered metadata
   // to determine if a memory operation is atomic or not in modules compiled
   // with SanitizerBinaryMetadata.
-  bool runOn(Instruction &I, MetadataInfoSet &MIS, MDBuilder &MDB);
+  bool runOn(Instruction &I, MetadataInfoSet &MIS, MDBuilder &MDB,
+             uint32_t &FeatureMask);
 
   // Get start/end section marker pointer.
   GlobalVariable *getSectionMarker(const Twine &MarkerName, Type *Ty);
@@ -227,36 +236,58 @@ void SanitizerBinaryMetadata::runOn(Function &F, MetadataInfoSet &MIS) {
 
   // The metadata features enabled for this function, stored along covered
   // metadata (if enabled).
-  uint32_t PerInstrFeatureMask = getEnabledPerInstructionFeature();
+  uint32_t FeatureMask = getEnabledPerInstructionFeature();
   // Don't emit unnecessary covered metadata for all functions to save space.
   bool RequiresCovered = false;
-  if (PerInstrFeatureMask) {
+  // We can only understand if we need to set UAR feature after looking
+  // at the instructions. So we need to check instructions even if FeatureMask
+  // is empty.
+  if (FeatureMask || Options.UAR) {
     for (BasicBlock &BB : F)
       for (Instruction &I : BB)
-        RequiresCovered |= runOn(I, MIS, MDB);
+        RequiresCovered |= runOn(I, MIS, MDB, FeatureMask);
   }
 
+  if (F.isVarArg())
+    FeatureMask &= ~kSanitizerBinaryMetadataUAR;
+  if (FeatureMask & kSanitizerBinaryMetadataUAR)
+    NumMetadataUAR++;
+
   // Covered metadata is always emitted if explicitly requested, otherwise only
   // if some other metadata requires it to unambiguously interpret it for
   // modules compiled with SanitizerBinaryMetadata.
-  if (Options.Covered || RequiresCovered) {
+  if (Options.Covered || (FeatureMask && RequiresCovered)) {
     NumMetadataCovered++;
     const auto *MI = &MetadataInfo::Covered;
     MIS.insert(MI);
     const StringRef Section = getSectionName(MI->SectionSuffix);
     // The feature mask will be placed after the size (32 bit) of the function,
     // so in total one covered entry will use `sizeof(void*) + 4 + 4`.
-    Constant *CFM = IRB.getInt32(PerInstrFeatureMask);
+    Constant *CFM = IRB.getInt32(FeatureMask);
     F.setMetadata(LLVMContext::MD_pcsections,
                   MDB.createPCSections({{Section, {CFM}}}));
   }
 }
 
 bool SanitizerBinaryMetadata::runOn(Instruction &I, MetadataInfoSet &MIS,
-                                    MDBuilder &MDB) {
+                                    MDBuilder &MDB, uint32_t &FeatureMask) {
   SmallVector<const MetadataInfo *, 1> InstMetadata;
   bool RequiresCovered = false;
 
+  if (Options.UAR) {
+    for (unsigned i = 0; i < I.getNumOperands(); ++i) {
+      const Value *V = I.getOperand(i);
+      // TODO(dvyukov): check if V is an address of alloca/function arg.
+      // See isSafeAndProfitableToSinkLoad for addr-taken allocas
+      // and DeadArgumentEliminationPass::removeDeadStuffFromFunction
+      // for iteration over function args.
+      if (V) {
+        RequiresCovered = true;
+        FeatureMask |= kSanitizerBinaryMetadataUAR;
+      }
+    }
+  }
+
   if (Options.Atomics && I.mayReadOrWriteMemory()) {
     auto SSID = getAtomicSyncScopeID(&I);
     if (SSID.has_value() && SSID.value() != SyncScope::SingleThread) {

diff  --git a/llvm/test/CodeGen/AArch64/O0-pipeline.ll b/llvm/test/CodeGen/AArch64/O0-pipeline.ll
index 595343979f9b7..8d4556c6bda1c 100644
--- a/llvm/test/CodeGen/AArch64/O0-pipeline.ll
+++ b/llvm/test/CodeGen/AArch64/O0-pipeline.ll
@@ -71,6 +71,7 @@
 ; CHECK-NEXT:       Contiguously Lay Out Funclets
 ; CHECK-NEXT:       StackMap Liveness Analysis
 ; CHECK-NEXT:       Live DEBUG_VALUE analysis
+; CHECK-NEXT:       Machine Sanitizer Binary Metadata
 ; CHECK-NEXT:       Insert CFI remember/restore state instructions
 ; CHECK-NEXT:       Unpack machine instruction bundles
 ; CHECK-NEXT:       Lazy Machine Block Frequency Analysis

diff  --git a/llvm/test/CodeGen/AArch64/O3-pipeline.ll b/llvm/test/CodeGen/AArch64/O3-pipeline.ll
index 90cf49e8ed8fc..8d697c8b647db 100644
--- a/llvm/test/CodeGen/AArch64/O3-pipeline.ll
+++ b/llvm/test/CodeGen/AArch64/O3-pipeline.ll
@@ -219,6 +219,7 @@
 ; CHECK-NEXT:       Contiguously Lay Out Funclets
 ; CHECK-NEXT:       StackMap Liveness Analysis
 ; CHECK-NEXT:       Live DEBUG_VALUE analysis
+; CHECK-NEXT:       Machine Sanitizer Binary Metadata
 ; CHECK-NEXT:     Machine Outliner
 ; CHECK-NEXT:     FunctionPass Manager
 ; CHECK-NEXT:       Insert CFI remember/restore state instructions

diff  --git a/llvm/test/CodeGen/AMDGPU/llc-pipeline.ll b/llvm/test/CodeGen/AMDGPU/llc-pipeline.ll
index 8ceb5ec1ed8ab..c4e4f36df5980 100644
--- a/llvm/test/CodeGen/AMDGPU/llc-pipeline.ll
+++ b/llvm/test/CodeGen/AMDGPU/llc-pipeline.ll
@@ -140,6 +140,7 @@
 ; GCN-O0-NEXT:        Branch relaxation pass
 ; GCN-O0-NEXT:        Register Usage Information Collector Pass
 ; GCN-O0-NEXT:        Live DEBUG_VALUE analysis
+; GCN-O0-NEXT:        Machine Sanitizer Binary Metadata
 ; GCN-O0-NEXT:    Function register usage analysis
 ; GCN-O0-NEXT:    FunctionPass Manager
 ; GCN-O0-NEXT:      Lazy Machine Block Frequency Analysis
@@ -404,6 +405,7 @@
 ; GCN-O1-NEXT:        Branch relaxation pass
 ; GCN-O1-NEXT:        Register Usage Information Collector Pass
 ; GCN-O1-NEXT:        Live DEBUG_VALUE analysis
+; GCN-O1-NEXT:        Machine Sanitizer Binary Metadata
 ; GCN-O1-NEXT:    Function register usage analysis
 ; GCN-O1-NEXT:    FunctionPass Manager
 ; GCN-O1-NEXT:      Lazy Machine Block Frequency Analysis
@@ -700,6 +702,7 @@
 ; GCN-O1-OPTS-NEXT:        Branch relaxation pass
 ; GCN-O1-OPTS-NEXT:        Register Usage Information Collector Pass
 ; GCN-O1-OPTS-NEXT:        Live DEBUG_VALUE analysis
+; GCN-O1-OPTS-NEXT:        Machine Sanitizer Binary Metadata
 ; GCN-O1-OPTS-NEXT:    Function register usage analysis
 ; GCN-O1-OPTS-NEXT:    FunctionPass Manager
 ; GCN-O1-OPTS-NEXT:      Lazy Machine Block Frequency Analysis
@@ -999,6 +1002,7 @@
 ; GCN-O2-NEXT:        Branch relaxation pass
 ; GCN-O2-NEXT:        Register Usage Information Collector Pass
 ; GCN-O2-NEXT:        Live DEBUG_VALUE analysis
+; GCN-O2-NEXT:        Machine Sanitizer Binary Metadata
 ; GCN-O2-NEXT:    Function register usage analysis
 ; GCN-O2-NEXT:    FunctionPass Manager
 ; GCN-O2-NEXT:      Lazy Machine Block Frequency Analysis
@@ -1310,6 +1314,7 @@
 ; GCN-O3-NEXT:        Branch relaxation pass
 ; GCN-O3-NEXT:        Register Usage Information Collector Pass
 ; GCN-O3-NEXT:        Live DEBUG_VALUE analysis
+; GCN-O3-NEXT:        Machine Sanitizer Binary Metadata
 ; GCN-O3-NEXT:    Function register usage analysis
 ; GCN-O3-NEXT:    FunctionPass Manager
 ; GCN-O3-NEXT:      Lazy Machine Block Frequency Analysis

diff  --git a/llvm/test/CodeGen/ARM/O3-pipeline.ll b/llvm/test/CodeGen/ARM/O3-pipeline.ll
index 253e17cdd303e..853aab572d58e 100644
--- a/llvm/test/CodeGen/ARM/O3-pipeline.ll
+++ b/llvm/test/CodeGen/ARM/O3-pipeline.ll
@@ -190,6 +190,7 @@
 ; CHECK-NEXT:      Contiguously Lay Out Funclets
 ; CHECK-NEXT:      StackMap Liveness Analysis
 ; CHECK-NEXT:      Live DEBUG_VALUE analysis
+; CHECK-NEXT:      Machine Sanitizer Binary Metadata
 ; CHECK-NEXT:    Machine Outliner
 ; CHECK-NEXT:    FunctionPass Manager
 ; CHECK-NEXT:      ReachingDefAnalysis

diff  --git a/llvm/test/CodeGen/M68k/pipeline.ll b/llvm/test/CodeGen/M68k/pipeline.ll
index f1dba29cf4cf7..93c1e102ebfaf 100644
--- a/llvm/test/CodeGen/M68k/pipeline.ll
+++ b/llvm/test/CodeGen/M68k/pipeline.ll
@@ -131,6 +131,7 @@
 ; CHECK-NEXT:      Contiguously Lay Out Funclets
 ; CHECK-NEXT:      StackMap Liveness Analysis
 ; CHECK-NEXT:      Live DEBUG_VALUE analysis
+; CHECK-NEXT:      Machine Sanitizer Binary Metadata
 ; CHECK-NEXT:      Lazy Machine Block Frequency Analysis
 ; CHECK-NEXT:      Machine Optimization Remark Emitter
 ; CHECK-NEXT:      M68k Assembly Printer

diff  --git a/llvm/test/CodeGen/PowerPC/O3-pipeline.ll b/llvm/test/CodeGen/PowerPC/O3-pipeline.ll
index 6b87f605dd8b7..9f1703e238eb6 100644
--- a/llvm/test/CodeGen/PowerPC/O3-pipeline.ll
+++ b/llvm/test/CodeGen/PowerPC/O3-pipeline.ll
@@ -207,6 +207,7 @@
 ; CHECK-NEXT:       Contiguously Lay Out Funclets
 ; CHECK-NEXT:       StackMap Liveness Analysis
 ; CHECK-NEXT:       Live DEBUG_VALUE analysis
+; CHECK-NEXT:       Machine Sanitizer Binary Metadata
 ; CHECK-NEXT:       PowerPC Expand Atomic
 ; CHECK-NEXT:       PowerPC Branch Selector
 ; CHECK-NEXT:       Lazy Machine Block Frequency Analysis

diff  --git a/llvm/test/CodeGen/RISCV/O0-pipeline.ll b/llvm/test/CodeGen/RISCV/O0-pipeline.ll
index ea5bfb0bdc86b..beb2ace4b809e 100644
--- a/llvm/test/CodeGen/RISCV/O0-pipeline.ll
+++ b/llvm/test/CodeGen/RISCV/O0-pipeline.ll
@@ -57,6 +57,7 @@
 ; CHECK-NEXT:       Contiguously Lay Out Funclets
 ; CHECK-NEXT:       StackMap Liveness Analysis
 ; CHECK-NEXT:       Live DEBUG_VALUE analysis
+; CHECK-NEXT:       Machine Sanitizer Binary Metadata
 ; CHECK-NEXT:       RISCV pseudo instruction expansion pass
 ; CHECK-NEXT:       RISCV atomic pseudo instruction expansion pass
 ; CHECK-NEXT:       Lazy Machine Block Frequency Analysis

diff  --git a/llvm/test/CodeGen/RISCV/O3-pipeline.ll b/llvm/test/CodeGen/RISCV/O3-pipeline.ll
index 73853d614fcea..64ffdb75b0eb3 100644
--- a/llvm/test/CodeGen/RISCV/O3-pipeline.ll
+++ b/llvm/test/CodeGen/RISCV/O3-pipeline.ll
@@ -164,6 +164,7 @@
 ; CHECK-NEXT:       Contiguously Lay Out Funclets
 ; CHECK-NEXT:       StackMap Liveness Analysis
 ; CHECK-NEXT:       Live DEBUG_VALUE analysis
+; CHECK-NEXT:       Machine Sanitizer Binary Metadata
 ; CHECK-NEXT:     Machine Outliner
 ; CHECK-NEXT:     FunctionPass Manager
 ; CHECK-NEXT:       RISCV pseudo instruction expansion pass

diff  --git a/llvm/test/CodeGen/X86/O0-pipeline.ll b/llvm/test/CodeGen/X86/O0-pipeline.ll
index 8ef0202a16536..959add648245f 100644
--- a/llvm/test/CodeGen/X86/O0-pipeline.ll
+++ b/llvm/test/CodeGen/X86/O0-pipeline.ll
@@ -72,6 +72,7 @@
 ; CHECK-NEXT:       Contiguously Lay Out Funclets
 ; CHECK-NEXT:       StackMap Liveness Analysis
 ; CHECK-NEXT:       Live DEBUG_VALUE analysis
+; CHECK-NEXT:       Machine Sanitizer Binary Metadata
 ; CHECK-NEXT:       X86 Speculative Execution Side Effect Suppression
 ; CHECK-NEXT:       X86 Indirect Thunks
 ; CHECK-NEXT:       X86 Return Thunks

diff  --git a/llvm/test/CodeGen/X86/opt-pipeline.ll b/llvm/test/CodeGen/X86/opt-pipeline.ll
index 9de77d2f4c3c8..d3c65f5dffa40 100644
--- a/llvm/test/CodeGen/X86/opt-pipeline.ll
+++ b/llvm/test/CodeGen/X86/opt-pipeline.ll
@@ -206,6 +206,7 @@
 ; CHECK-NEXT:       Contiguously Lay Out Funclets
 ; CHECK-NEXT:       StackMap Liveness Analysis
 ; CHECK-NEXT:       Live DEBUG_VALUE analysis
+; CHECK-NEXT:       Machine Sanitizer Binary Metadata
 ; CHECK-NEXT:       X86 Speculative Execution Side Effect Suppression
 ; CHECK-NEXT:       X86 Indirect Thunks
 ; CHECK-NEXT:       X86 Return Thunks


        


More information about the llvm-commits mailing list