[llvm] 97c2220 - [SanitizerBinaryMetadata] Introduce SanitizerBinaryMetadata instrumentation pass

Marco Elver via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 7 12:26:39 PDT 2022


Author: Marco Elver
Date: 2022-09-07T21:25:40+02:00
New Revision: 97c2220565abcef6c3fd674dcca98f7176e132c5

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

LOG: [SanitizerBinaryMetadata] Introduce SanitizerBinaryMetadata instrumentation pass

Introduces the SanitizerBinaryMetadata instrumentation pass which uses
the new MD_pcsections metadata kinds to instrument certain types of
instructions and functions required for breakpoint-based sanitizers.

The first intended user of the binary metadata emitted will be a variant
of GWP-TSan [1]. GWP-TSan will require information about atomic
accesses; to unambiguously determine if an access is atomic or not, we
also require "covered" information which code has been compiled with
SanitizerBinaryMetadata instrumentation enabled.

[1] https://llvm.org/devmtg/2020-09/slides/Morehouse-GWP-Tsan.pdf

Reviewed By: dvyukov

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

Added: 
    llvm/include/llvm/Transforms/Instrumentation/SanitizerBinaryMetadata.h
    llvm/lib/Transforms/Instrumentation/SanitizerBinaryMetadata.cpp
    llvm/test/Instrumentation/SanitizerBinaryMetadata/atomics.ll

Modified: 
    llvm/include/llvm/Transforms/Instrumentation.h
    llvm/lib/Passes/PassBuilder.cpp
    llvm/lib/Passes/PassRegistry.def
    llvm/lib/Transforms/Instrumentation/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Transforms/Instrumentation.h b/llvm/include/llvm/Transforms/Instrumentation.h
index 0c688e3bdaf6f..4b33dad08b6b7 100644
--- a/llvm/include/llvm/Transforms/Instrumentation.h
+++ b/llvm/include/llvm/Transforms/Instrumentation.h
@@ -154,6 +154,13 @@ 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
new file mode 100644
index 0000000000000..a54801309c1d8
--- /dev/null
+++ b/llvm/include/llvm/Transforms/Instrumentation/SanitizerBinaryMetadata.h
@@ -0,0 +1,40 @@
+//===------- Definition of the SanitizerBinaryMetadata class ----*- C++ -*-===//
+//
+// 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 declares the SanitizerBinaryMetadata pass.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_TRANSFORMS_INSTRUMENTATION_SANITIZERBINARYMETADATA_H
+#define LLVM_TRANSFORMS_INSTRUMENTATION_SANITIZERBINARYMETADATA_H
+
+#include "llvm/IR/Function.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/PassManager.h"
+#include "llvm/Transforms/Instrumentation.h"
+
+namespace llvm {
+
+/// Public interface to the SanitizerBinaryMetadata module pass for emitting
+/// metadata for binary analysis sanitizers.
+//
+/// The pass should be inserted after optimizations.
+class SanitizerBinaryMetadataPass
+    : public PassInfoMixin<SanitizerBinaryMetadataPass> {
+public:
+  explicit SanitizerBinaryMetadataPass(
+      SanitizerBinaryMetadataOptions Opts = {});
+  PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
+  static bool isRequired() { return true; }
+
+private:
+  const SanitizerBinaryMetadataOptions Options;
+};
+
+} // namespace llvm
+
+#endif

diff  --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp
index 0f30191182600..bd9ec1e98e188 100644
--- a/llvm/lib/Passes/PassBuilder.cpp
+++ b/llvm/lib/Passes/PassBuilder.cpp
@@ -138,6 +138,7 @@
 #include "llvm/Transforms/Instrumentation/MemorySanitizer.h"
 #include "llvm/Transforms/Instrumentation/PGOInstrumentation.h"
 #include "llvm/Transforms/Instrumentation/PoisonChecking.h"
+#include "llvm/Transforms/Instrumentation/SanitizerBinaryMetadata.h"
 #include "llvm/Transforms/Instrumentation/SanitizerCoverage.h"
 #include "llvm/Transforms/Instrumentation/ThreadSanitizer.h"
 #include "llvm/Transforms/ObjCARC.h"

diff  --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def
index 97b9f07529058..4a4fe779a244b 100644
--- a/llvm/lib/Passes/PassRegistry.def
+++ b/llvm/lib/Passes/PassRegistry.def
@@ -122,6 +122,7 @@ MODULE_PASS("dfsan", DataFlowSanitizerPass())
 MODULE_PASS("module-inline", ModuleInlinerPass())
 MODULE_PASS("tsan-module", ModuleThreadSanitizerPass())
 MODULE_PASS("sancov-module", SanitizerCoveragePass())
+MODULE_PASS("sanmd-module", SanitizerBinaryMetadataPass())
 MODULE_PASS("memprof-module", ModuleMemProfilerPass())
 MODULE_PASS("poison-checking", PoisonCheckingPass())
 MODULE_PASS("pseudo-probe-update", PseudoProbeUpdatePass())

diff  --git a/llvm/lib/Transforms/Instrumentation/CMakeLists.txt b/llvm/lib/Transforms/Instrumentation/CMakeLists.txt
index a4e09f6cc54d6..d54175e9fe06b 100644
--- a/llvm/lib/Transforms/Instrumentation/CMakeLists.txt
+++ b/llvm/lib/Transforms/Instrumentation/CMakeLists.txt
@@ -15,6 +15,7 @@ add_llvm_component_library(LLVMInstrumentation
   PGOMemOPSizeOpt.cpp
   PoisonChecking.cpp
   SanitizerCoverage.cpp
+  SanitizerBinaryMetadata.cpp
   ValueProfileCollector.cpp
   ThreadSanitizer.cpp
   HWAddressSanitizer.cpp

diff  --git a/llvm/lib/Transforms/Instrumentation/SanitizerBinaryMetadata.cpp b/llvm/lib/Transforms/Instrumentation/SanitizerBinaryMetadata.cpp
new file mode 100644
index 0000000000000..58c29d8b211e2
--- /dev/null
+++ b/llvm/lib/Transforms/Instrumentation/SanitizerBinaryMetadata.cpp
@@ -0,0 +1,334 @@
+//===- SanitizerBinaryMetadata.cpp - binary analysis sanitizers metadata --===//
+//
+// 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/ADT/SetVector.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/IR/Constant.h"
+#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/GlobalValue.h"
+#include "llvm/IR/GlobalVariable.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/Instruction.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/MDBuilder.h"
+#include "llvm/IR/Metadata.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/Type.h"
+#include "llvm/IR/Value.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Pass.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Transforms/Instrumentation.h"
+#include "llvm/Transforms/Utils/ModuleUtils.h"
+
+#include <array>
+#include <cstdint>
+
+using namespace llvm;
+
+#define DEBUG_TYPE "sanmd"
+
+namespace {
+
+//===--- Constants --------------------------------------------------------===//
+
+constexpr uint32_t kVersionBase = 1;                // occupies lower 16 bits
+constexpr uint32_t kVersionPtrSizeRel = (1u << 16); // offsets are pointer-sized
+constexpr int kCtorDtorPriority = 2;
+
+// Pairs of names of initialization callback functions and which section
+// contains the relevant metadata.
+class MetadataInfo {
+public:
+  const StringRef FunctionPrefix;
+  const StringRef SectionSuffix;
+  const uint32_t FeatureMask;
+
+  static const MetadataInfo Covered;
+  static const MetadataInfo Atomics;
+
+private:
+  // Forbid construction elsewhere.
+  explicit constexpr MetadataInfo(StringRef FunctionPrefix,
+                                  StringRef SectionSuffix, int Feature)
+      : FunctionPrefix(FunctionPrefix), SectionSuffix(SectionSuffix),
+        FeatureMask(Feature != -1 ? (1u << Feature) : 0) {}
+};
+const MetadataInfo MetadataInfo::Covered{"__sanitizer_metadata_covered",
+                                         "sanmd_covered", -1};
+const MetadataInfo MetadataInfo::Atomics{"__sanitizer_metadata_atomics",
+                                         "sanmd_atomics", 0};
+
+// The only instances of MetadataInfo are the constants above, so a set of
+// them may simply store pointers to them. To deterministically generate code,
+// we need to use a set with stable iteration order, such as SetVector.
+using MetadataInfoSet = SetVector<const MetadataInfo *>;
+
+//===--- Command-line options ---------------------------------------------===//
+
+cl::opt<bool> ClEmitCovered("sanitizer-metadata-covered",
+                            cl::desc("Emit PCs for covered functions."),
+                            cl::Hidden, cl::init(false));
+cl::opt<bool> ClEmitAtomics("sanitizer-metadata-atomics",
+                            cl::desc("Emit PCs for atomic operations."),
+                            cl::Hidden, cl::init(false));
+
+//===--- Statistics -------------------------------------------------------===//
+
+STATISTIC(NumMetadataCovered, "Metadata attached to covered functions");
+STATISTIC(NumMetadataAtomics, "Metadata attached to atomics");
+
+//===----------------------------------------------------------------------===//
+
+// Apply opt overrides.
+SanitizerBinaryMetadataOptions &&
+transformOptionsFromCl(SanitizerBinaryMetadataOptions &&Opts) {
+  Opts.Covered |= ClEmitCovered;
+  Opts.Atomics |= ClEmitAtomics;
+  return std::move(Opts);
+}
+
+class SanitizerBinaryMetadata {
+public:
+  SanitizerBinaryMetadata(Module &M, SanitizerBinaryMetadataOptions Opts)
+      : Mod(M), Options(transformOptionsFromCl(std::move(Opts))),
+        TargetTriple(M.getTargetTriple()), IRB(M.getContext()) {
+    // FIXME: Make it work with other formats.
+    assert(TargetTriple.isOSBinFormatELF() && "ELF only");
+  }
+
+  bool run();
+
+private:
+  // Return enabled feature mask of per-instruction metadata.
+  uint32_t getEnabledPerInstructionFeature() const {
+    uint32_t FeatureMask = 0;
+    if (Options.Atomics)
+      FeatureMask |= MetadataInfo::Atomics.FeatureMask;
+    return FeatureMask;
+  }
+
+  uint32_t getVersion() const {
+    uint32_t Version = kVersionBase;
+    const auto CM = Mod.getCodeModel();
+    if (CM.has_value() && (*CM == CodeModel::Medium || *CM == CodeModel::Large))
+      Version |= kVersionPtrSizeRel;
+    return Version;
+  }
+
+  void runOn(Function &F, MetadataInfoSet &MIS);
+
+  // Determines which set of metadata to collect for this instruction.
+  //
+  // Returns true if covered metadata is required to unambiguously interpret
+  // other metadata. For example, if we are interested in atomics metadata, any
+  // 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);
+
+  // Get start/end section marker pointer.
+  GlobalVariable *getSectionMarker(const Twine &MarkerName, Type *Ty);
+
+  // Create a 0-sized object in a section, so that the section is not discarded
+  // if all inputs have been discarded.
+  void createZeroSizedObjectInSection(Type *Ty, StringRef SectionSuffix);
+
+  // Returns the target-dependent section name.
+  StringRef getSectionName(StringRef SectionSuffix);
+
+  // Returns the section start marker name.
+  Twine getSectionStart(StringRef SectionSuffix);
+
+  // Returns the section end marker name.
+  Twine getSectionEnd(StringRef SectionSuffix);
+
+  Module &Mod;
+  const SanitizerBinaryMetadataOptions Options;
+  const Triple TargetTriple;
+  IRBuilder<> IRB;
+};
+
+bool SanitizerBinaryMetadata::run() {
+  MetadataInfoSet MIS;
+
+  for (Function &F : Mod)
+    runOn(F, MIS);
+
+  if (MIS.empty())
+    return false;
+
+  //
+  // Setup constructors and call all initialization functions for requested
+  // metadata features.
+  //
+
+  auto *Int8PtrTy = IRB.getInt8PtrTy();
+  auto *Int8PtrPtrTy = PointerType::getUnqual(Int8PtrTy);
+  auto *Int32Ty = IRB.getInt32Ty();
+  const std::array<Type *, 3> InitTypes = {Int32Ty, Int8PtrPtrTy, Int8PtrPtrTy};
+  auto *Version = ConstantInt::get(Int32Ty, getVersion());
+
+  for (const MetadataInfo *MI : MIS) {
+    const std::array<Value *, InitTypes.size()> InitArgs = {
+        Version,
+        getSectionMarker(getSectionStart(MI->SectionSuffix), Int8PtrTy),
+        getSectionMarker(getSectionEnd(MI->SectionSuffix), Int8PtrTy),
+    };
+    Function *Ctor =
+        createSanitizerCtorAndInitFunctions(
+            Mod, (MI->FunctionPrefix + ".module_ctor").str(),
+            (MI->FunctionPrefix + "_add").str(), InitTypes, InitArgs)
+            .first;
+    Function *Dtor =
+        createSanitizerCtorAndInitFunctions(
+            Mod, (MI->FunctionPrefix + ".module_dtor").str(),
+            (MI->FunctionPrefix + "_del").str(), InitTypes, InitArgs)
+            .first;
+    Constant *CtorData = nullptr;
+    Constant *DtorData = nullptr;
+    if (TargetTriple.supportsCOMDAT()) {
+      // Use COMDAT to deduplicate constructor/destructor function.
+      Ctor->setComdat(Mod.getOrInsertComdat(Ctor->getName()));
+      Dtor->setComdat(Mod.getOrInsertComdat(Dtor->getName()));
+      CtorData = Ctor;
+      DtorData = Dtor;
+    }
+    appendToGlobalCtors(Mod, Ctor, kCtorDtorPriority, CtorData);
+    appendToGlobalDtors(Mod, Dtor, kCtorDtorPriority, DtorData);
+    createZeroSizedObjectInSection(Int8PtrTy, MI->SectionSuffix);
+  }
+
+  return true;
+}
+
+void SanitizerBinaryMetadata::runOn(Function &F, MetadataInfoSet &MIS) {
+  if (F.empty())
+    return;
+  if (F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation))
+    return;
+  // Don't touch available_externally functions, their actual body is elsewhere.
+  if (F.getLinkage() == GlobalValue::AvailableExternallyLinkage)
+    return;
+
+  MDBuilder MDB(F.getContext());
+
+  // The metadata features enabled for this function, stored along covered
+  // metadata (if enabled).
+  uint32_t PerInstrFeatureMask = getEnabledPerInstructionFeature();
+  // Don't emit unnecessary covered metadata for all functions to save space.
+  bool RequiresCovered = false;
+  if (PerInstrFeatureMask) {
+    for (BasicBlock &BB : F)
+      for (Instruction &I : BB)
+        RequiresCovered |= runOn(I, MIS, MDB);
+  }
+
+  // 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) {
+    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);
+    F.setMetadata(LLVMContext::MD_pcsections,
+                  MDB.createPCSections({{Section, {CFM}}}));
+  }
+}
+
+bool SanitizerBinaryMetadata::runOn(Instruction &I, MetadataInfoSet &MIS,
+                                    MDBuilder &MDB) {
+  SmallVector<const MetadataInfo *, 1> InstMetadata;
+  bool RequiresCovered = false;
+
+  if (Options.Atomics && I.mayReadOrWriteMemory()) {
+    auto SSID = getAtomicSyncScopeID(&I);
+    if (SSID.has_value() && SSID.value() != SyncScope::SingleThread) {
+      NumMetadataAtomics++;
+      InstMetadata.push_back(&MetadataInfo::Atomics);
+    }
+    RequiresCovered = true;
+  }
+
+  // Attach MD_pcsections to instruction.
+  if (!InstMetadata.empty()) {
+    MIS.insert(InstMetadata.begin(), InstMetadata.end());
+    SmallVector<MDBuilder::PCSection, 1> Sections;
+    for (const auto &MI : InstMetadata)
+      Sections.push_back({getSectionName(MI->SectionSuffix), {}});
+    I.setMetadata(LLVMContext::MD_pcsections, MDB.createPCSections(Sections));
+  }
+
+  return RequiresCovered;
+}
+
+GlobalVariable *
+SanitizerBinaryMetadata::getSectionMarker(const Twine &MarkerName, Type *Ty) {
+  auto *Marker = new GlobalVariable(Mod, Ty, /*isConstant=*/false,
+                                    GlobalVariable::ExternalLinkage,
+                                    /*Initializer=*/nullptr, MarkerName);
+  Marker->setVisibility(GlobalValue::HiddenVisibility);
+  return Marker;
+}
+
+void SanitizerBinaryMetadata::createZeroSizedObjectInSection(
+    Type *Ty, StringRef SectionSuffix) {
+  auto *DummyInit = ConstantAggregateZero::get(ArrayType::get(Ty, 0));
+  auto *DummyEntry = new GlobalVariable(Mod, DummyInit->getType(), true,
+                                        GlobalVariable::ExternalLinkage,
+                                        DummyInit, "__dummy_" + SectionSuffix);
+  DummyEntry->setSection(getSectionName(SectionSuffix));
+  DummyEntry->setVisibility(GlobalValue::HiddenVisibility);
+  if (TargetTriple.supportsCOMDAT())
+    DummyEntry->setComdat(Mod.getOrInsertComdat(DummyEntry->getName()));
+  // Make sure the section isn't discarded by gc-sections.
+  appendToUsed(Mod, DummyEntry);
+}
+
+StringRef SanitizerBinaryMetadata::getSectionName(StringRef SectionSuffix) {
+  // FIXME: Other TargetTriple (req. string pool)
+  return SectionSuffix;
+}
+
+Twine SanitizerBinaryMetadata::getSectionStart(StringRef SectionSuffix) {
+  return "__start_" + SectionSuffix;
+}
+
+Twine SanitizerBinaryMetadata::getSectionEnd(StringRef SectionSuffix) {
+  return "__stop_" + SectionSuffix;
+}
+
+} // namespace
+
+SanitizerBinaryMetadataPass::SanitizerBinaryMetadataPass(
+    SanitizerBinaryMetadataOptions Opts)
+    : Options(std::move(Opts)) {}
+
+PreservedAnalyses
+SanitizerBinaryMetadataPass::run(Module &M, AnalysisManager<Module> &AM) {
+  SanitizerBinaryMetadata Pass(M, Options);
+  if (Pass.run())
+    return PreservedAnalyses::none();
+  return PreservedAnalyses::all();
+}

diff  --git a/llvm/test/Instrumentation/SanitizerBinaryMetadata/atomics.ll b/llvm/test/Instrumentation/SanitizerBinaryMetadata/atomics.ll
new file mode 100644
index 0000000000000..5511f2286ed52
--- /dev/null
+++ b/llvm/test/Instrumentation/SanitizerBinaryMetadata/atomics.ll
@@ -0,0 +1,2046 @@
+; RUN: opt < %s -passes='module(sanmd-module)' -sanitizer-metadata-atomics -S | FileCheck %s
+
+; Check that atomic memory operations receive PC sections metadata.
+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"
+
+define i8 @atomic8_load_unordered(i8* %a) nounwind uwtable {
+entry:
+  %0 = load atomic i8, i8* %a unordered, align 1
+  ret i8 %0
+}
+; CHECK-LABEL: atomic8_load_unordered{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define i8 @atomic8_load_monotonic(i8* %a) nounwind uwtable {
+entry:
+  %0 = load atomic i8, i8* %a monotonic, align 1
+  ret i8 %0
+}
+; CHECK-LABEL: atomic8_load_monotonic{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define i8 @atomic8_load_acquire(i8* %a) nounwind uwtable {
+entry:
+  %0 = load atomic i8, i8* %a acquire, align 1
+  ret i8 %0
+}
+; CHECK-LABEL: atomic8_load_acquire{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define i8 @atomic8_load_seq_cst(i8* %a) nounwind uwtable {
+entry:
+  %0 = load atomic i8, i8* %a seq_cst, align 1
+  ret i8 %0
+}
+; CHECK-LABEL: atomic8_load_seq_cst{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic8_store_unordered(i8* %a) nounwind uwtable {
+entry:
+  store atomic i8 0, i8* %a unordered, align 1
+  ret void
+}
+; CHECK-LABEL: atomic8_store_unordered{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic8_store_monotonic(i8* %a) nounwind uwtable {
+entry:
+  store atomic i8 0, i8* %a monotonic, align 1
+  ret void
+}
+; CHECK-LABEL: atomic8_store_monotonic{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic8_store_release(i8* %a) nounwind uwtable {
+entry:
+  store atomic i8 0, i8* %a release, align 1
+  ret void
+}
+; CHECK-LABEL: atomic8_store_release{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic8_store_seq_cst(i8* %a) nounwind uwtable {
+entry:
+  store atomic i8 0, i8* %a seq_cst, align 1
+  ret void
+}
+; CHECK-LABEL: atomic8_store_seq_cst{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic8_xchg_monotonic(i8* %a) nounwind uwtable {
+entry:
+  atomicrmw xchg i8* %a, i8 0 monotonic
+  ret void
+}
+; CHECK-LABEL: atomic8_xchg_monotonic{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic8_add_monotonic(i8* %a) nounwind uwtable {
+entry:
+  atomicrmw add i8* %a, i8 0 monotonic
+  ret void
+}
+; CHECK-LABEL: atomic8_add_monotonic{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic8_sub_monotonic(i8* %a) nounwind uwtable {
+entry:
+  atomicrmw sub i8* %a, i8 0 monotonic
+  ret void
+}
+; CHECK-LABEL: atomic8_sub_monotonic{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic8_and_monotonic(i8* %a) nounwind uwtable {
+entry:
+  atomicrmw and i8* %a, i8 0 monotonic
+  ret void
+}
+; CHECK-LABEL: atomic8_and_monotonic{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic8_or_monotonic(i8* %a) nounwind uwtable {
+entry:
+  atomicrmw or i8* %a, i8 0 monotonic
+  ret void
+}
+; CHECK-LABEL: atomic8_or_monotonic{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic8_xor_monotonic(i8* %a) nounwind uwtable {
+entry:
+  atomicrmw xor i8* %a, i8 0 monotonic
+  ret void
+}
+; CHECK-LABEL: atomic8_xor_monotonic{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic8_nand_monotonic(i8* %a) nounwind uwtable {
+entry:
+  atomicrmw nand i8* %a, i8 0 monotonic
+  ret void
+}
+; CHECK-LABEL: atomic8_nand_monotonic{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic8_xchg_acquire(i8* %a) nounwind uwtable {
+entry:
+  atomicrmw xchg i8* %a, i8 0 acquire
+  ret void
+}
+; CHECK-LABEL: atomic8_xchg_acquire{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic8_add_acquire(i8* %a) nounwind uwtable {
+entry:
+  atomicrmw add i8* %a, i8 0 acquire
+  ret void
+}
+; CHECK-LABEL: atomic8_add_acquire{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic8_sub_acquire(i8* %a) nounwind uwtable {
+entry:
+  atomicrmw sub i8* %a, i8 0 acquire
+  ret void
+}
+; CHECK-LABEL: atomic8_sub_acquire{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic8_and_acquire(i8* %a) nounwind uwtable {
+entry:
+  atomicrmw and i8* %a, i8 0 acquire
+  ret void
+}
+; CHECK-LABEL: atomic8_and_acquire{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic8_or_acquire(i8* %a) nounwind uwtable {
+entry:
+  atomicrmw or i8* %a, i8 0 acquire
+  ret void
+}
+; CHECK-LABEL: atomic8_or_acquire{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic8_xor_acquire(i8* %a) nounwind uwtable {
+entry:
+  atomicrmw xor i8* %a, i8 0 acquire
+  ret void
+}
+; CHECK-LABEL: atomic8_xor_acquire{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic8_nand_acquire(i8* %a) nounwind uwtable {
+entry:
+  atomicrmw nand i8* %a, i8 0 acquire
+  ret void
+}
+; CHECK-LABEL: atomic8_nand_acquire{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic8_xchg_release(i8* %a) nounwind uwtable {
+entry:
+  atomicrmw xchg i8* %a, i8 0 release
+  ret void
+}
+; CHECK-LABEL: atomic8_xchg_release{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic8_add_release(i8* %a) nounwind uwtable {
+entry:
+  atomicrmw add i8* %a, i8 0 release
+  ret void
+}
+; CHECK-LABEL: atomic8_add_release{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic8_sub_release(i8* %a) nounwind uwtable {
+entry:
+  atomicrmw sub i8* %a, i8 0 release
+  ret void
+}
+; CHECK-LABEL: atomic8_sub_release{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic8_and_release(i8* %a) nounwind uwtable {
+entry:
+  atomicrmw and i8* %a, i8 0 release
+  ret void
+}
+; CHECK-LABEL: atomic8_and_release{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic8_or_release(i8* %a) nounwind uwtable {
+entry:
+  atomicrmw or i8* %a, i8 0 release
+  ret void
+}
+; CHECK-LABEL: atomic8_or_release{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic8_xor_release(i8* %a) nounwind uwtable {
+entry:
+  atomicrmw xor i8* %a, i8 0 release
+  ret void
+}
+; CHECK-LABEL: atomic8_xor_release{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic8_nand_release(i8* %a) nounwind uwtable {
+entry:
+  atomicrmw nand i8* %a, i8 0 release
+  ret void
+}
+; CHECK-LABEL: atomic8_nand_release{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic8_xchg_acq_rel(i8* %a) nounwind uwtable {
+entry:
+  atomicrmw xchg i8* %a, i8 0 acq_rel
+  ret void
+}
+; CHECK-LABEL: atomic8_xchg_acq_rel{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic8_add_acq_rel(i8* %a) nounwind uwtable {
+entry:
+  atomicrmw add i8* %a, i8 0 acq_rel
+  ret void
+}
+; CHECK-LABEL: atomic8_add_acq_rel{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic8_sub_acq_rel(i8* %a) nounwind uwtable {
+entry:
+  atomicrmw sub i8* %a, i8 0 acq_rel
+  ret void
+}
+; CHECK-LABEL: atomic8_sub_acq_rel{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic8_and_acq_rel(i8* %a) nounwind uwtable {
+entry:
+  atomicrmw and i8* %a, i8 0 acq_rel
+  ret void
+}
+; CHECK-LABEL: atomic8_and_acq_rel{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic8_or_acq_rel(i8* %a) nounwind uwtable {
+entry:
+  atomicrmw or i8* %a, i8 0 acq_rel
+  ret void
+}
+; CHECK-LABEL: atomic8_or_acq_rel{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic8_xor_acq_rel(i8* %a) nounwind uwtable {
+entry:
+  atomicrmw xor i8* %a, i8 0 acq_rel
+  ret void
+}
+; CHECK-LABEL: atomic8_xor_acq_rel{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic8_nand_acq_rel(i8* %a) nounwind uwtable {
+entry:
+  atomicrmw nand i8* %a, i8 0 acq_rel
+  ret void
+}
+; CHECK-LABEL: atomic8_nand_acq_rel{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic8_xchg_seq_cst(i8* %a) nounwind uwtable {
+entry:
+  atomicrmw xchg i8* %a, i8 0 seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic8_xchg_seq_cst{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic8_add_seq_cst(i8* %a) nounwind uwtable {
+entry:
+  atomicrmw add i8* %a, i8 0 seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic8_add_seq_cst{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic8_sub_seq_cst(i8* %a) nounwind uwtable {
+entry:
+  atomicrmw sub i8* %a, i8 0 seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic8_sub_seq_cst{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic8_and_seq_cst(i8* %a) nounwind uwtable {
+entry:
+  atomicrmw and i8* %a, i8 0 seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic8_and_seq_cst{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic8_or_seq_cst(i8* %a) nounwind uwtable {
+entry:
+  atomicrmw or i8* %a, i8 0 seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic8_or_seq_cst{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic8_xor_seq_cst(i8* %a) nounwind uwtable {
+entry:
+  atomicrmw xor i8* %a, i8 0 seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic8_xor_seq_cst{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic8_nand_seq_cst(i8* %a) nounwind uwtable {
+entry:
+  atomicrmw nand i8* %a, i8 0 seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic8_nand_seq_cst{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic8_cas_monotonic(i8* %a) nounwind uwtable {
+entry:
+  cmpxchg i8* %a, i8 0, i8 1 monotonic monotonic
+  cmpxchg i8* %a, i8 0, i8 1 monotonic acquire
+  cmpxchg i8* %a, i8 0, i8 1 monotonic seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic8_cas_monotonic{{.*}}!pcsections !0
+; CHECK: cmpxchg i8* %a, i8 0, i8 1 monotonic monotonic, align 1, !pcsections !2
+; CHECK: cmpxchg i8* %a, i8 0, i8 1 monotonic acquire, align 1, !pcsections !2
+; CHECK: cmpxchg i8* %a, i8 0, i8 1 monotonic seq_cst, align 1, !pcsections !2
+
+define void @atomic8_cas_acquire(i8* %a) nounwind uwtable {
+entry:
+  cmpxchg i8* %a, i8 0, i8 1 acquire monotonic
+  cmpxchg i8* %a, i8 0, i8 1 acquire acquire
+  cmpxchg i8* %a, i8 0, i8 1 acquire seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic8_cas_acquire{{.*}}!pcsections !0
+; CHECK: cmpxchg i8* %a, i8 0, i8 1 acquire monotonic, align 1, !pcsections !2
+; CHECK: cmpxchg i8* %a, i8 0, i8 1 acquire acquire, align 1, !pcsections !2
+; CHECK: cmpxchg i8* %a, i8 0, i8 1 acquire seq_cst, align 1, !pcsections !2
+
+define void @atomic8_cas_release(i8* %a) nounwind uwtable {
+entry:
+  cmpxchg i8* %a, i8 0, i8 1 release monotonic
+  cmpxchg i8* %a, i8 0, i8 1 release acquire
+  cmpxchg i8* %a, i8 0, i8 1 release seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic8_cas_release{{.*}}!pcsections !0
+; CHECK: cmpxchg i8* %a, i8 0, i8 1 release monotonic, align 1, !pcsections !2
+; CHECK: cmpxchg i8* %a, i8 0, i8 1 release acquire, align 1, !pcsections !2
+; CHECK: cmpxchg i8* %a, i8 0, i8 1 release seq_cst, align 1, !pcsections !2
+
+define void @atomic8_cas_acq_rel(i8* %a) nounwind uwtable {
+entry:
+  cmpxchg i8* %a, i8 0, i8 1 acq_rel monotonic
+  cmpxchg i8* %a, i8 0, i8 1 acq_rel acquire
+  cmpxchg i8* %a, i8 0, i8 1 acq_rel seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic8_cas_acq_rel{{.*}}!pcsections !0
+; CHECK: cmpxchg i8* %a, i8 0, i8 1 acq_rel monotonic, align 1, !pcsections !2
+; CHECK: cmpxchg i8* %a, i8 0, i8 1 acq_rel acquire, align 1, !pcsections !2
+; CHECK: cmpxchg i8* %a, i8 0, i8 1 acq_rel seq_cst, align 1, !pcsections !2
+
+define void @atomic8_cas_seq_cst(i8* %a) nounwind uwtable {
+entry:
+  cmpxchg i8* %a, i8 0, i8 1 seq_cst monotonic
+  cmpxchg i8* %a, i8 0, i8 1 seq_cst acquire
+  cmpxchg i8* %a, i8 0, i8 1 seq_cst seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic8_cas_seq_cst{{.*}}!pcsections !0
+; CHECK: cmpxchg i8* %a, i8 0, i8 1 seq_cst monotonic, align 1, !pcsections !2
+; CHECK: cmpxchg i8* %a, i8 0, i8 1 seq_cst acquire, align 1, !pcsections !2
+; CHECK: cmpxchg i8* %a, i8 0, i8 1 seq_cst seq_cst, align 1, !pcsections !2
+
+define i16 @atomic16_load_unordered(i16* %a) nounwind uwtable {
+entry:
+  %0 = load atomic i16, i16* %a unordered, align 2
+  ret i16 %0
+}
+; CHECK-LABEL: atomic16_load_unordered{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define i16 @atomic16_load_monotonic(i16* %a) nounwind uwtable {
+entry:
+  %0 = load atomic i16, i16* %a monotonic, align 2
+  ret i16 %0
+}
+; CHECK-LABEL: atomic16_load_monotonic{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define i16 @atomic16_load_acquire(i16* %a) nounwind uwtable {
+entry:
+  %0 = load atomic i16, i16* %a acquire, align 2
+  ret i16 %0
+}
+; CHECK-LABEL: atomic16_load_acquire{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define i16 @atomic16_load_seq_cst(i16* %a) nounwind uwtable {
+entry:
+  %0 = load atomic i16, i16* %a seq_cst, align 2
+  ret i16 %0
+}
+; CHECK-LABEL: atomic16_load_seq_cst{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic16_store_unordered(i16* %a) nounwind uwtable {
+entry:
+  store atomic i16 0, i16* %a unordered, align 2
+  ret void
+}
+; CHECK-LABEL: atomic16_store_unordered{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic16_store_monotonic(i16* %a) nounwind uwtable {
+entry:
+  store atomic i16 0, i16* %a monotonic, align 2
+  ret void
+}
+; CHECK-LABEL: atomic16_store_monotonic{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic16_store_release(i16* %a) nounwind uwtable {
+entry:
+  store atomic i16 0, i16* %a release, align 2
+  ret void
+}
+; CHECK-LABEL: atomic16_store_release{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic16_store_seq_cst(i16* %a) nounwind uwtable {
+entry:
+  store atomic i16 0, i16* %a seq_cst, align 2
+  ret void
+}
+; CHECK-LABEL: atomic16_store_seq_cst{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic16_xchg_monotonic(i16* %a) nounwind uwtable {
+entry:
+  atomicrmw xchg i16* %a, i16 0 monotonic
+  ret void
+}
+; CHECK-LABEL: atomic16_xchg_monotonic{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic16_add_monotonic(i16* %a) nounwind uwtable {
+entry:
+  atomicrmw add i16* %a, i16 0 monotonic
+  ret void
+}
+; CHECK-LABEL: atomic16_add_monotonic{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic16_sub_monotonic(i16* %a) nounwind uwtable {
+entry:
+  atomicrmw sub i16* %a, i16 0 monotonic
+  ret void
+}
+; CHECK-LABEL: atomic16_sub_monotonic{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic16_and_monotonic(i16* %a) nounwind uwtable {
+entry:
+  atomicrmw and i16* %a, i16 0 monotonic
+  ret void
+}
+; CHECK-LABEL: atomic16_and_monotonic{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic16_or_monotonic(i16* %a) nounwind uwtable {
+entry:
+  atomicrmw or i16* %a, i16 0 monotonic
+  ret void
+}
+; CHECK-LABEL: atomic16_or_monotonic{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic16_xor_monotonic(i16* %a) nounwind uwtable {
+entry:
+  atomicrmw xor i16* %a, i16 0 monotonic
+  ret void
+}
+; CHECK-LABEL: atomic16_xor_monotonic{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic16_nand_monotonic(i16* %a) nounwind uwtable {
+entry:
+  atomicrmw nand i16* %a, i16 0 monotonic
+  ret void
+}
+; CHECK-LABEL: atomic16_nand_monotonic{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic16_xchg_acquire(i16* %a) nounwind uwtable {
+entry:
+  atomicrmw xchg i16* %a, i16 0 acquire
+  ret void
+}
+; CHECK-LABEL: atomic16_xchg_acquire{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic16_add_acquire(i16* %a) nounwind uwtable {
+entry:
+  atomicrmw add i16* %a, i16 0 acquire
+  ret void
+}
+; CHECK-LABEL: atomic16_add_acquire{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic16_sub_acquire(i16* %a) nounwind uwtable {
+entry:
+  atomicrmw sub i16* %a, i16 0 acquire
+  ret void
+}
+; CHECK-LABEL: atomic16_sub_acquire{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic16_and_acquire(i16* %a) nounwind uwtable {
+entry:
+  atomicrmw and i16* %a, i16 0 acquire
+  ret void
+}
+; CHECK-LABEL: atomic16_and_acquire{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic16_or_acquire(i16* %a) nounwind uwtable {
+entry:
+  atomicrmw or i16* %a, i16 0 acquire
+  ret void
+}
+; CHECK-LABEL: atomic16_or_acquire{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic16_xor_acquire(i16* %a) nounwind uwtable {
+entry:
+  atomicrmw xor i16* %a, i16 0 acquire
+  ret void
+}
+; CHECK-LABEL: atomic16_xor_acquire{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic16_nand_acquire(i16* %a) nounwind uwtable {
+entry:
+  atomicrmw nand i16* %a, i16 0 acquire
+  ret void
+}
+; CHECK-LABEL: atomic16_nand_acquire{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic16_xchg_release(i16* %a) nounwind uwtable {
+entry:
+  atomicrmw xchg i16* %a, i16 0 release
+  ret void
+}
+; CHECK-LABEL: atomic16_xchg_release{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic16_add_release(i16* %a) nounwind uwtable {
+entry:
+  atomicrmw add i16* %a, i16 0 release
+  ret void
+}
+; CHECK-LABEL: atomic16_add_release{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic16_sub_release(i16* %a) nounwind uwtable {
+entry:
+  atomicrmw sub i16* %a, i16 0 release
+  ret void
+}
+; CHECK-LABEL: atomic16_sub_release{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic16_and_release(i16* %a) nounwind uwtable {
+entry:
+  atomicrmw and i16* %a, i16 0 release
+  ret void
+}
+; CHECK-LABEL: atomic16_and_release{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic16_or_release(i16* %a) nounwind uwtable {
+entry:
+  atomicrmw or i16* %a, i16 0 release
+  ret void
+}
+; CHECK-LABEL: atomic16_or_release{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic16_xor_release(i16* %a) nounwind uwtable {
+entry:
+  atomicrmw xor i16* %a, i16 0 release
+  ret void
+}
+; CHECK-LABEL: atomic16_xor_release{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic16_nand_release(i16* %a) nounwind uwtable {
+entry:
+  atomicrmw nand i16* %a, i16 0 release
+  ret void
+}
+; CHECK-LABEL: atomic16_nand_release{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic16_xchg_acq_rel(i16* %a) nounwind uwtable {
+entry:
+  atomicrmw xchg i16* %a, i16 0 acq_rel
+  ret void
+}
+; CHECK-LABEL: atomic16_xchg_acq_rel{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic16_add_acq_rel(i16* %a) nounwind uwtable {
+entry:
+  atomicrmw add i16* %a, i16 0 acq_rel
+  ret void
+}
+; CHECK-LABEL: atomic16_add_acq_rel{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic16_sub_acq_rel(i16* %a) nounwind uwtable {
+entry:
+  atomicrmw sub i16* %a, i16 0 acq_rel
+  ret void
+}
+; CHECK-LABEL: atomic16_sub_acq_rel{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic16_and_acq_rel(i16* %a) nounwind uwtable {
+entry:
+  atomicrmw and i16* %a, i16 0 acq_rel
+  ret void
+}
+; CHECK-LABEL: atomic16_and_acq_rel{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic16_or_acq_rel(i16* %a) nounwind uwtable {
+entry:
+  atomicrmw or i16* %a, i16 0 acq_rel
+  ret void
+}
+; CHECK-LABEL: atomic16_or_acq_rel{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic16_xor_acq_rel(i16* %a) nounwind uwtable {
+entry:
+  atomicrmw xor i16* %a, i16 0 acq_rel
+  ret void
+}
+; CHECK-LABEL: atomic16_xor_acq_rel{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic16_nand_acq_rel(i16* %a) nounwind uwtable {
+entry:
+  atomicrmw nand i16* %a, i16 0 acq_rel
+  ret void
+}
+; CHECK-LABEL: atomic16_nand_acq_rel{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic16_xchg_seq_cst(i16* %a) nounwind uwtable {
+entry:
+  atomicrmw xchg i16* %a, i16 0 seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic16_xchg_seq_cst{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic16_add_seq_cst(i16* %a) nounwind uwtable {
+entry:
+  atomicrmw add i16* %a, i16 0 seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic16_add_seq_cst{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic16_sub_seq_cst(i16* %a) nounwind uwtable {
+entry:
+  atomicrmw sub i16* %a, i16 0 seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic16_sub_seq_cst{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic16_and_seq_cst(i16* %a) nounwind uwtable {
+entry:
+  atomicrmw and i16* %a, i16 0 seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic16_and_seq_cst{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic16_or_seq_cst(i16* %a) nounwind uwtable {
+entry:
+  atomicrmw or i16* %a, i16 0 seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic16_or_seq_cst{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic16_xor_seq_cst(i16* %a) nounwind uwtable {
+entry:
+  atomicrmw xor i16* %a, i16 0 seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic16_xor_seq_cst{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic16_nand_seq_cst(i16* %a) nounwind uwtable {
+entry:
+  atomicrmw nand i16* %a, i16 0 seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic16_nand_seq_cst{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic16_cas_monotonic(i16* %a) nounwind uwtable {
+entry:
+  cmpxchg i16* %a, i16 0, i16 1 monotonic monotonic
+  cmpxchg i16* %a, i16 0, i16 1 monotonic acquire
+  cmpxchg i16* %a, i16 0, i16 1 monotonic seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic16_cas_monotonic{{.*}}!pcsections !0
+; CHECK: cmpxchg i16* %a, i16 0, i16 1 monotonic monotonic, align 2, !pcsections !2
+; CHECK: cmpxchg i16* %a, i16 0, i16 1 monotonic acquire, align 2, !pcsections !2
+; CHECK: cmpxchg i16* %a, i16 0, i16 1 monotonic seq_cst, align 2, !pcsections !2
+
+define void @atomic16_cas_acquire(i16* %a) nounwind uwtable {
+entry:
+  cmpxchg i16* %a, i16 0, i16 1 acquire monotonic
+  cmpxchg i16* %a, i16 0, i16 1 acquire acquire
+  cmpxchg i16* %a, i16 0, i16 1 acquire seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic16_cas_acquire{{.*}}!pcsections !0
+; CHECK: cmpxchg i16* %a, i16 0, i16 1 acquire monotonic, align 2, !pcsections !2
+; CHECK: cmpxchg i16* %a, i16 0, i16 1 acquire acquire, align 2, !pcsections !2
+; CHECK: cmpxchg i16* %a, i16 0, i16 1 acquire seq_cst, align 2, !pcsections !2
+
+define void @atomic16_cas_release(i16* %a) nounwind uwtable {
+entry:
+  cmpxchg i16* %a, i16 0, i16 1 release monotonic
+  cmpxchg i16* %a, i16 0, i16 1 release acquire
+  cmpxchg i16* %a, i16 0, i16 1 release seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic16_cas_release{{.*}}!pcsections !0
+; CHECK: cmpxchg i16* %a, i16 0, i16 1 release monotonic, align 2, !pcsections !2
+; CHECK: cmpxchg i16* %a, i16 0, i16 1 release acquire, align 2, !pcsections !2
+; CHECK: cmpxchg i16* %a, i16 0, i16 1 release seq_cst, align 2, !pcsections !2
+
+define void @atomic16_cas_acq_rel(i16* %a) nounwind uwtable {
+entry:
+  cmpxchg i16* %a, i16 0, i16 1 acq_rel monotonic
+  cmpxchg i16* %a, i16 0, i16 1 acq_rel acquire
+  cmpxchg i16* %a, i16 0, i16 1 acq_rel seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic16_cas_acq_rel{{.*}}!pcsections !0
+; CHECK: cmpxchg i16* %a, i16 0, i16 1 acq_rel monotonic, align 2, !pcsections !2
+; CHECK: cmpxchg i16* %a, i16 0, i16 1 acq_rel acquire, align 2, !pcsections !2
+; CHECK: cmpxchg i16* %a, i16 0, i16 1 acq_rel seq_cst, align 2, !pcsections !2
+
+define void @atomic16_cas_seq_cst(i16* %a) nounwind uwtable {
+entry:
+  cmpxchg i16* %a, i16 0, i16 1 seq_cst monotonic
+  cmpxchg i16* %a, i16 0, i16 1 seq_cst acquire
+  cmpxchg i16* %a, i16 0, i16 1 seq_cst seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic16_cas_seq_cst{{.*}}!pcsections !0
+; CHECK: cmpxchg i16* %a, i16 0, i16 1 seq_cst monotonic, align 2, !pcsections !2
+; CHECK: cmpxchg i16* %a, i16 0, i16 1 seq_cst acquire, align 2, !pcsections !2
+; CHECK: cmpxchg i16* %a, i16 0, i16 1 seq_cst seq_cst, align 2, !pcsections !2
+
+define i32 @atomic32_load_unordered(i32* %a) nounwind uwtable {
+entry:
+  %0 = load atomic i32, i32* %a unordered, align 4
+  ret i32 %0
+}
+; CHECK-LABEL: atomic32_load_unordered{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define i32 @atomic32_load_monotonic(i32* %a) nounwind uwtable {
+entry:
+  %0 = load atomic i32, i32* %a monotonic, align 4
+  ret i32 %0
+}
+; CHECK-LABEL: atomic32_load_monotonic{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define i32 @atomic32_load_acquire(i32* %a) nounwind uwtable {
+entry:
+  %0 = load atomic i32, i32* %a acquire, align 4
+  ret i32 %0
+}
+; CHECK-LABEL: atomic32_load_acquire{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define i32 @atomic32_load_seq_cst(i32* %a) nounwind uwtable {
+entry:
+  %0 = load atomic i32, i32* %a seq_cst, align 4
+  ret i32 %0
+}
+; CHECK-LABEL: atomic32_load_seq_cst{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic32_store_unordered(i32* %a) nounwind uwtable {
+entry:
+  store atomic i32 0, i32* %a unordered, align 4
+  ret void
+}
+; CHECK-LABEL: atomic32_store_unordered{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic32_store_monotonic(i32* %a) nounwind uwtable {
+entry:
+  store atomic i32 0, i32* %a monotonic, align 4
+  ret void
+}
+; CHECK-LABEL: atomic32_store_monotonic{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic32_store_release(i32* %a) nounwind uwtable {
+entry:
+  store atomic i32 0, i32* %a release, align 4
+  ret void
+}
+; CHECK-LABEL: atomic32_store_release{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic32_store_seq_cst(i32* %a) nounwind uwtable {
+entry:
+  store atomic i32 0, i32* %a seq_cst, align 4
+  ret void
+}
+; CHECK-LABEL: atomic32_store_seq_cst{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic32_xchg_monotonic(i32* %a) nounwind uwtable {
+entry:
+  atomicrmw xchg i32* %a, i32 0 monotonic
+  ret void
+}
+; CHECK-LABEL: atomic32_xchg_monotonic{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic32_add_monotonic(i32* %a) nounwind uwtable {
+entry:
+  atomicrmw add i32* %a, i32 0 monotonic
+  ret void
+}
+; CHECK-LABEL: atomic32_add_monotonic{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic32_sub_monotonic(i32* %a) nounwind uwtable {
+entry:
+  atomicrmw sub i32* %a, i32 0 monotonic
+  ret void
+}
+; CHECK-LABEL: atomic32_sub_monotonic{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic32_and_monotonic(i32* %a) nounwind uwtable {
+entry:
+  atomicrmw and i32* %a, i32 0 monotonic
+  ret void
+}
+; CHECK-LABEL: atomic32_and_monotonic{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic32_or_monotonic(i32* %a) nounwind uwtable {
+entry:
+  atomicrmw or i32* %a, i32 0 monotonic
+  ret void
+}
+; CHECK-LABEL: atomic32_or_monotonic{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic32_xor_monotonic(i32* %a) nounwind uwtable {
+entry:
+  atomicrmw xor i32* %a, i32 0 monotonic
+  ret void
+}
+; CHECK-LABEL: atomic32_xor_monotonic{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic32_nand_monotonic(i32* %a) nounwind uwtable {
+entry:
+  atomicrmw nand i32* %a, i32 0 monotonic
+  ret void
+}
+; CHECK-LABEL: atomic32_nand_monotonic{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic32_xchg_acquire(i32* %a) nounwind uwtable {
+entry:
+  atomicrmw xchg i32* %a, i32 0 acquire
+  ret void
+}
+; CHECK-LABEL: atomic32_xchg_acquire{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic32_add_acquire(i32* %a) nounwind uwtable {
+entry:
+  atomicrmw add i32* %a, i32 0 acquire
+  ret void
+}
+; CHECK-LABEL: atomic32_add_acquire{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic32_sub_acquire(i32* %a) nounwind uwtable {
+entry:
+  atomicrmw sub i32* %a, i32 0 acquire
+  ret void
+}
+; CHECK-LABEL: atomic32_sub_acquire{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic32_and_acquire(i32* %a) nounwind uwtable {
+entry:
+  atomicrmw and i32* %a, i32 0 acquire
+  ret void
+}
+; CHECK-LABEL: atomic32_and_acquire{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic32_or_acquire(i32* %a) nounwind uwtable {
+entry:
+  atomicrmw or i32* %a, i32 0 acquire
+  ret void
+}
+; CHECK-LABEL: atomic32_or_acquire{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic32_xor_acquire(i32* %a) nounwind uwtable {
+entry:
+  atomicrmw xor i32* %a, i32 0 acquire
+  ret void
+}
+; CHECK-LABEL: atomic32_xor_acquire{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic32_nand_acquire(i32* %a) nounwind uwtable {
+entry:
+  atomicrmw nand i32* %a, i32 0 acquire
+  ret void
+}
+; CHECK-LABEL: atomic32_nand_acquire{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic32_xchg_release(i32* %a) nounwind uwtable {
+entry:
+  atomicrmw xchg i32* %a, i32 0 release
+  ret void
+}
+; CHECK-LABEL: atomic32_xchg_release{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic32_add_release(i32* %a) nounwind uwtable {
+entry:
+  atomicrmw add i32* %a, i32 0 release
+  ret void
+}
+; CHECK-LABEL: atomic32_add_release{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic32_sub_release(i32* %a) nounwind uwtable {
+entry:
+  atomicrmw sub i32* %a, i32 0 release
+  ret void
+}
+; CHECK-LABEL: atomic32_sub_release{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic32_and_release(i32* %a) nounwind uwtable {
+entry:
+  atomicrmw and i32* %a, i32 0 release
+  ret void
+}
+; CHECK-LABEL: atomic32_and_release{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic32_or_release(i32* %a) nounwind uwtable {
+entry:
+  atomicrmw or i32* %a, i32 0 release
+  ret void
+}
+; CHECK-LABEL: atomic32_or_release{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic32_xor_release(i32* %a) nounwind uwtable {
+entry:
+  atomicrmw xor i32* %a, i32 0 release
+  ret void
+}
+; CHECK-LABEL: atomic32_xor_release{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic32_nand_release(i32* %a) nounwind uwtable {
+entry:
+  atomicrmw nand i32* %a, i32 0 release
+  ret void
+}
+; CHECK-LABEL: atomic32_nand_release{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic32_xchg_acq_rel(i32* %a) nounwind uwtable {
+entry:
+  atomicrmw xchg i32* %a, i32 0 acq_rel
+  ret void
+}
+; CHECK-LABEL: atomic32_xchg_acq_rel{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic32_add_acq_rel(i32* %a) nounwind uwtable {
+entry:
+  atomicrmw add i32* %a, i32 0 acq_rel
+  ret void
+}
+; CHECK-LABEL: atomic32_add_acq_rel{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic32_sub_acq_rel(i32* %a) nounwind uwtable {
+entry:
+  atomicrmw sub i32* %a, i32 0 acq_rel
+  ret void
+}
+; CHECK-LABEL: atomic32_sub_acq_rel{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic32_and_acq_rel(i32* %a) nounwind uwtable {
+entry:
+  atomicrmw and i32* %a, i32 0 acq_rel
+  ret void
+}
+; CHECK-LABEL: atomic32_and_acq_rel{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic32_or_acq_rel(i32* %a) nounwind uwtable {
+entry:
+  atomicrmw or i32* %a, i32 0 acq_rel
+  ret void
+}
+; CHECK-LABEL: atomic32_or_acq_rel{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic32_xor_acq_rel(i32* %a) nounwind uwtable {
+entry:
+  atomicrmw xor i32* %a, i32 0 acq_rel
+  ret void
+}
+; CHECK-LABEL: atomic32_xor_acq_rel{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic32_nand_acq_rel(i32* %a) nounwind uwtable {
+entry:
+  atomicrmw nand i32* %a, i32 0 acq_rel
+  ret void
+}
+; CHECK-LABEL: atomic32_nand_acq_rel{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic32_xchg_seq_cst(i32* %a) nounwind uwtable {
+entry:
+  atomicrmw xchg i32* %a, i32 0 seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic32_xchg_seq_cst{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic32_add_seq_cst(i32* %a) nounwind uwtable {
+entry:
+  atomicrmw add i32* %a, i32 0 seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic32_add_seq_cst{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic32_sub_seq_cst(i32* %a) nounwind uwtable {
+entry:
+  atomicrmw sub i32* %a, i32 0 seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic32_sub_seq_cst{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic32_and_seq_cst(i32* %a) nounwind uwtable {
+entry:
+  atomicrmw and i32* %a, i32 0 seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic32_and_seq_cst{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic32_or_seq_cst(i32* %a) nounwind uwtable {
+entry:
+  atomicrmw or i32* %a, i32 0 seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic32_or_seq_cst{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic32_xor_seq_cst(i32* %a) nounwind uwtable {
+entry:
+  atomicrmw xor i32* %a, i32 0 seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic32_xor_seq_cst{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic32_nand_seq_cst(i32* %a) nounwind uwtable {
+entry:
+  atomicrmw nand i32* %a, i32 0 seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic32_nand_seq_cst{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic32_cas_monotonic(i32* %a) nounwind uwtable {
+entry:
+  cmpxchg i32* %a, i32 0, i32 1 monotonic monotonic
+  cmpxchg i32* %a, i32 0, i32 1 monotonic acquire
+  cmpxchg i32* %a, i32 0, i32 1 monotonic seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic32_cas_monotonic{{.*}}!pcsections !0
+; CHECK: cmpxchg i32* %a, i32 0, i32 1 monotonic monotonic, align 4, !pcsections !2
+; CHECK: cmpxchg i32* %a, i32 0, i32 1 monotonic acquire, align 4, !pcsections !2
+; CHECK: cmpxchg i32* %a, i32 0, i32 1 monotonic seq_cst, align 4, !pcsections !2
+
+define void @atomic32_cas_acquire(i32* %a) nounwind uwtable {
+entry:
+  cmpxchg i32* %a, i32 0, i32 1 acquire monotonic
+  cmpxchg i32* %a, i32 0, i32 1 acquire acquire
+  cmpxchg i32* %a, i32 0, i32 1 acquire seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic32_cas_acquire{{.*}}!pcsections !0
+; CHECK: cmpxchg i32* %a, i32 0, i32 1 acquire monotonic, align 4, !pcsections !2
+; CHECK: cmpxchg i32* %a, i32 0, i32 1 acquire acquire, align 4, !pcsections !2
+; CHECK: cmpxchg i32* %a, i32 0, i32 1 acquire seq_cst, align 4, !pcsections !2
+
+define void @atomic32_cas_release(i32* %a) nounwind uwtable {
+entry:
+  cmpxchg i32* %a, i32 0, i32 1 release monotonic
+  cmpxchg i32* %a, i32 0, i32 1 release acquire
+  cmpxchg i32* %a, i32 0, i32 1 release seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic32_cas_release{{.*}}!pcsections !0
+; CHECK: cmpxchg i32* %a, i32 0, i32 1 release monotonic, align 4, !pcsections !2
+; CHECK: cmpxchg i32* %a, i32 0, i32 1 release acquire, align 4, !pcsections !2
+; CHECK: cmpxchg i32* %a, i32 0, i32 1 release seq_cst, align 4, !pcsections !2
+
+define void @atomic32_cas_acq_rel(i32* %a) nounwind uwtable {
+entry:
+  cmpxchg i32* %a, i32 0, i32 1 acq_rel monotonic
+  cmpxchg i32* %a, i32 0, i32 1 acq_rel acquire
+  cmpxchg i32* %a, i32 0, i32 1 acq_rel seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic32_cas_acq_rel{{.*}}!pcsections !0
+; CHECK: cmpxchg i32* %a, i32 0, i32 1 acq_rel monotonic, align 4, !pcsections !2
+; CHECK: cmpxchg i32* %a, i32 0, i32 1 acq_rel acquire, align 4, !pcsections !2
+; CHECK: cmpxchg i32* %a, i32 0, i32 1 acq_rel seq_cst, align 4, !pcsections !2
+
+define void @atomic32_cas_seq_cst(i32* %a) nounwind uwtable {
+entry:
+  cmpxchg i32* %a, i32 0, i32 1 seq_cst monotonic
+  cmpxchg i32* %a, i32 0, i32 1 seq_cst acquire
+  cmpxchg i32* %a, i32 0, i32 1 seq_cst seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic32_cas_seq_cst{{.*}}!pcsections !0
+; CHECK: cmpxchg i32* %a, i32 0, i32 1 seq_cst monotonic, align 4, !pcsections !2
+; CHECK: cmpxchg i32* %a, i32 0, i32 1 seq_cst acquire, align 4, !pcsections !2
+; CHECK: cmpxchg i32* %a, i32 0, i32 1 seq_cst seq_cst, align 4, !pcsections !2
+
+define i64 @atomic64_load_unordered(i64* %a) nounwind uwtable {
+entry:
+  %0 = load atomic i64, i64* %a unordered, align 8
+  ret i64 %0
+}
+; CHECK-LABEL: atomic64_load_unordered{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define i64 @atomic64_load_monotonic(i64* %a) nounwind uwtable {
+entry:
+  %0 = load atomic i64, i64* %a monotonic, align 8
+  ret i64 %0
+}
+; CHECK-LABEL: atomic64_load_monotonic{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define i64 @atomic64_load_acquire(i64* %a) nounwind uwtable {
+entry:
+  %0 = load atomic i64, i64* %a acquire, align 8
+  ret i64 %0
+}
+; CHECK-LABEL: atomic64_load_acquire{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define i64 @atomic64_load_seq_cst(i64* %a) nounwind uwtable {
+entry:
+  %0 = load atomic i64, i64* %a seq_cst, align 8
+  ret i64 %0
+}
+; CHECK-LABEL: atomic64_load_seq_cst{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define i8* @atomic64_load_seq_cst_ptr_ty(i8** %a) nounwind uwtable {
+entry:
+  %0 = load atomic i8*, i8** %a seq_cst, align 8
+  ret i8* %0
+}
+; CHECK-LABEL: atomic64_load_seq_cst{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic64_store_unordered(i64* %a) nounwind uwtable {
+entry:
+  store atomic i64 0, i64* %a unordered, align 8
+  ret void
+}
+; CHECK-LABEL: atomic64_store_unordered{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic64_store_monotonic(i64* %a) nounwind uwtable {
+entry:
+  store atomic i64 0, i64* %a monotonic, align 8
+  ret void
+}
+; CHECK-LABEL: atomic64_store_monotonic{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic64_store_release(i64* %a) nounwind uwtable {
+entry:
+  store atomic i64 0, i64* %a release, align 8
+  ret void
+}
+; CHECK-LABEL: atomic64_store_release{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic64_store_seq_cst(i64* %a) nounwind uwtable {
+entry:
+  store atomic i64 0, i64* %a seq_cst, align 8
+  ret void
+}
+; CHECK-LABEL: atomic64_store_seq_cst{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic64_store_seq_cst_ptr_ty(i8** %a, i8* %v) nounwind uwtable {
+entry:
+  store atomic i8* %v, i8** %a seq_cst, align 8
+  ret void
+}
+; CHECK-LABEL: atomic64_store_seq_cst{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic64_xchg_monotonic(i64* %a) nounwind uwtable {
+entry:
+  atomicrmw xchg i64* %a, i64 0 monotonic
+  ret void
+}
+; CHECK-LABEL: atomic64_xchg_monotonic{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic64_add_monotonic(i64* %a) nounwind uwtable {
+entry:
+  atomicrmw add i64* %a, i64 0 monotonic
+  ret void
+}
+; CHECK-LABEL: atomic64_add_monotonic{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic64_sub_monotonic(i64* %a) nounwind uwtable {
+entry:
+  atomicrmw sub i64* %a, i64 0 monotonic
+  ret void
+}
+; CHECK-LABEL: atomic64_sub_monotonic{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic64_and_monotonic(i64* %a) nounwind uwtable {
+entry:
+  atomicrmw and i64* %a, i64 0 monotonic
+  ret void
+}
+; CHECK-LABEL: atomic64_and_monotonic{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic64_or_monotonic(i64* %a) nounwind uwtable {
+entry:
+  atomicrmw or i64* %a, i64 0 monotonic
+  ret void
+}
+; CHECK-LABEL: atomic64_or_monotonic{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic64_xor_monotonic(i64* %a) nounwind uwtable {
+entry:
+  atomicrmw xor i64* %a, i64 0 monotonic
+  ret void
+}
+; CHECK-LABEL: atomic64_xor_monotonic{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic64_nand_monotonic(i64* %a) nounwind uwtable {
+entry:
+  atomicrmw nand i64* %a, i64 0 monotonic
+  ret void
+}
+; CHECK-LABEL: atomic64_nand_monotonic{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic64_xchg_acquire(i64* %a) nounwind uwtable {
+entry:
+  atomicrmw xchg i64* %a, i64 0 acquire
+  ret void
+}
+; CHECK-LABEL: atomic64_xchg_acquire{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic64_add_acquire(i64* %a) nounwind uwtable {
+entry:
+  atomicrmw add i64* %a, i64 0 acquire
+  ret void
+}
+; CHECK-LABEL: atomic64_add_acquire{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic64_sub_acquire(i64* %a) nounwind uwtable {
+entry:
+  atomicrmw sub i64* %a, i64 0 acquire
+  ret void
+}
+; CHECK-LABEL: atomic64_sub_acquire{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic64_and_acquire(i64* %a) nounwind uwtable {
+entry:
+  atomicrmw and i64* %a, i64 0 acquire
+  ret void
+}
+; CHECK-LABEL: atomic64_and_acquire{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic64_or_acquire(i64* %a) nounwind uwtable {
+entry:
+  atomicrmw or i64* %a, i64 0 acquire
+  ret void
+}
+; CHECK-LABEL: atomic64_or_acquire{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic64_xor_acquire(i64* %a) nounwind uwtable {
+entry:
+  atomicrmw xor i64* %a, i64 0 acquire
+  ret void
+}
+; CHECK-LABEL: atomic64_xor_acquire{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic64_nand_acquire(i64* %a) nounwind uwtable {
+entry:
+  atomicrmw nand i64* %a, i64 0 acquire
+  ret void
+}
+; CHECK-LABEL: atomic64_nand_acquire{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic64_xchg_release(i64* %a) nounwind uwtable {
+entry:
+  atomicrmw xchg i64* %a, i64 0 release
+  ret void
+}
+; CHECK-LABEL: atomic64_xchg_release{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic64_add_release(i64* %a) nounwind uwtable {
+entry:
+  atomicrmw add i64* %a, i64 0 release
+  ret void
+}
+; CHECK-LABEL: atomic64_add_release{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic64_sub_release(i64* %a) nounwind uwtable {
+entry:
+  atomicrmw sub i64* %a, i64 0 release
+  ret void
+}
+; CHECK-LABEL: atomic64_sub_release{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic64_and_release(i64* %a) nounwind uwtable {
+entry:
+  atomicrmw and i64* %a, i64 0 release
+  ret void
+}
+; CHECK-LABEL: atomic64_and_release{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic64_or_release(i64* %a) nounwind uwtable {
+entry:
+  atomicrmw or i64* %a, i64 0 release
+  ret void
+}
+; CHECK-LABEL: atomic64_or_release{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic64_xor_release(i64* %a) nounwind uwtable {
+entry:
+  atomicrmw xor i64* %a, i64 0 release
+  ret void
+}
+; CHECK-LABEL: atomic64_xor_release{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic64_nand_release(i64* %a) nounwind uwtable {
+entry:
+  atomicrmw nand i64* %a, i64 0 release
+  ret void
+}
+; CHECK-LABEL: atomic64_nand_release{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic64_xchg_acq_rel(i64* %a) nounwind uwtable {
+entry:
+  atomicrmw xchg i64* %a, i64 0 acq_rel
+  ret void
+}
+; CHECK-LABEL: atomic64_xchg_acq_rel{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic64_add_acq_rel(i64* %a) nounwind uwtable {
+entry:
+  atomicrmw add i64* %a, i64 0 acq_rel
+  ret void
+}
+; CHECK-LABEL: atomic64_add_acq_rel{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic64_sub_acq_rel(i64* %a) nounwind uwtable {
+entry:
+  atomicrmw sub i64* %a, i64 0 acq_rel
+  ret void
+}
+; CHECK-LABEL: atomic64_sub_acq_rel{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic64_and_acq_rel(i64* %a) nounwind uwtable {
+entry:
+  atomicrmw and i64* %a, i64 0 acq_rel
+  ret void
+}
+; CHECK-LABEL: atomic64_and_acq_rel{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic64_or_acq_rel(i64* %a) nounwind uwtable {
+entry:
+  atomicrmw or i64* %a, i64 0 acq_rel
+  ret void
+}
+; CHECK-LABEL: atomic64_or_acq_rel{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic64_xor_acq_rel(i64* %a) nounwind uwtable {
+entry:
+  atomicrmw xor i64* %a, i64 0 acq_rel
+  ret void
+}
+; CHECK-LABEL: atomic64_xor_acq_rel{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic64_nand_acq_rel(i64* %a) nounwind uwtable {
+entry:
+  atomicrmw nand i64* %a, i64 0 acq_rel
+  ret void
+}
+; CHECK-LABEL: atomic64_nand_acq_rel{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic64_xchg_seq_cst(i64* %a) nounwind uwtable {
+entry:
+  atomicrmw xchg i64* %a, i64 0 seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic64_xchg_seq_cst{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic64_add_seq_cst(i64* %a) nounwind uwtable {
+entry:
+  atomicrmw add i64* %a, i64 0 seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic64_add_seq_cst{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic64_sub_seq_cst(i64* %a) nounwind uwtable {
+entry:
+  atomicrmw sub i64* %a, i64 0 seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic64_sub_seq_cst{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic64_and_seq_cst(i64* %a) nounwind uwtable {
+entry:
+  atomicrmw and i64* %a, i64 0 seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic64_and_seq_cst{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic64_or_seq_cst(i64* %a) nounwind uwtable {
+entry:
+  atomicrmw or i64* %a, i64 0 seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic64_or_seq_cst{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic64_xor_seq_cst(i64* %a) nounwind uwtable {
+entry:
+  atomicrmw xor i64* %a, i64 0 seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic64_xor_seq_cst{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic64_nand_seq_cst(i64* %a) nounwind uwtable {
+entry:
+  atomicrmw nand i64* %a, i64 0 seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic64_nand_seq_cst{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic64_cas_monotonic(i64* %a) nounwind uwtable {
+entry:
+  cmpxchg i64* %a, i64 0, i64 1 monotonic monotonic
+  cmpxchg i64* %a, i64 0, i64 1 monotonic acquire
+  cmpxchg i64* %a, i64 0, i64 1 monotonic seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic64_cas_monotonic{{.*}}!pcsections !0
+; CHECK: cmpxchg i64* %a, i64 0, i64 1 monotonic monotonic, align 8, !pcsections !2
+; CHECK: cmpxchg i64* %a, i64 0, i64 1 monotonic acquire, align 8, !pcsections !2
+; CHECK: cmpxchg i64* %a, i64 0, i64 1 monotonic seq_cst, align 8, !pcsections !2
+
+define void @atomic64_cas_acquire(i64* %a) nounwind uwtable {
+entry:
+  cmpxchg i64* %a, i64 0, i64 1 acquire monotonic
+  cmpxchg i64* %a, i64 0, i64 1 acquire acquire
+  cmpxchg i64* %a, i64 0, i64 1 acquire seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic64_cas_acquire{{.*}}!pcsections !0
+; CHECK: cmpxchg i64* %a, i64 0, i64 1 acquire monotonic, align 8, !pcsections !2
+; CHECK: cmpxchg i64* %a, i64 0, i64 1 acquire acquire, align 8, !pcsections !2
+; CHECK: cmpxchg i64* %a, i64 0, i64 1 acquire seq_cst, align 8, !pcsections !2
+
+define void @atomic64_cas_release(i64* %a) nounwind uwtable {
+entry:
+  cmpxchg i64* %a, i64 0, i64 1 release monotonic
+  cmpxchg i64* %a, i64 0, i64 1 release acquire
+  cmpxchg i64* %a, i64 0, i64 1 release seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic64_cas_release{{.*}}!pcsections !0
+; CHECK: cmpxchg i64* %a, i64 0, i64 1 release monotonic, align 8, !pcsections !2
+; CHECK: cmpxchg i64* %a, i64 0, i64 1 release acquire, align 8, !pcsections !2
+; CHECK: cmpxchg i64* %a, i64 0, i64 1 release seq_cst, align 8, !pcsections !2
+
+define void @atomic64_cas_acq_rel(i64* %a) nounwind uwtable {
+entry:
+  cmpxchg i64* %a, i64 0, i64 1 acq_rel monotonic
+  cmpxchg i64* %a, i64 0, i64 1 acq_rel acquire
+  cmpxchg i64* %a, i64 0, i64 1 acq_rel seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic64_cas_acq_rel{{.*}}!pcsections !0
+; CHECK: cmpxchg i64* %a, i64 0, i64 1 acq_rel monotonic, align 8, !pcsections !2
+; CHECK: cmpxchg i64* %a, i64 0, i64 1 acq_rel acquire, align 8, !pcsections !2
+; CHECK: cmpxchg i64* %a, i64 0, i64 1 acq_rel seq_cst, align 8, !pcsections !2
+
+define void @atomic64_cas_seq_cst(i64* %a) nounwind uwtable {
+entry:
+  cmpxchg i64* %a, i64 0, i64 1 seq_cst monotonic
+  cmpxchg i64* %a, i64 0, i64 1 seq_cst acquire
+  cmpxchg i64* %a, i64 0, i64 1 seq_cst seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic64_cas_seq_cst{{.*}}!pcsections !0
+; CHECK: cmpxchg i64* %a, i64 0, i64 1 seq_cst monotonic, align 8, !pcsections !2
+; CHECK: cmpxchg i64* %a, i64 0, i64 1 seq_cst acquire, align 8, !pcsections !2
+; CHECK: cmpxchg i64* %a, i64 0, i64 1 seq_cst seq_cst, align 8, !pcsections !2
+
+define void @atomic64_cas_seq_cst_ptr_ty(i8** %a, i8* %v1, i8* %v2) nounwind uwtable {
+entry:
+  cmpxchg i8** %a, i8* %v1, i8* %v2 seq_cst seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic64_cas_seq_cst{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define i128 @atomic128_load_unordered(i128* %a) nounwind uwtable {
+entry:
+  %0 = load atomic i128, i128* %a unordered, align 16
+  ret i128 %0
+}
+; CHECK-LABEL: atomic128_load_unordered{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define i128 @atomic128_load_monotonic(i128* %a) nounwind uwtable {
+entry:
+  %0 = load atomic i128, i128* %a monotonic, align 16
+  ret i128 %0
+}
+; CHECK-LABEL: atomic128_load_monotonic{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define i128 @atomic128_load_acquire(i128* %a) nounwind uwtable {
+entry:
+  %0 = load atomic i128, i128* %a acquire, align 16
+  ret i128 %0
+}
+; CHECK-LABEL: atomic128_load_acquire{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define i128 @atomic128_load_seq_cst(i128* %a) nounwind uwtable {
+entry:
+  %0 = load atomic i128, i128* %a seq_cst, align 16
+  ret i128 %0
+}
+; CHECK-LABEL: atomic128_load_seq_cst{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic128_store_unordered(i128* %a) nounwind uwtable {
+entry:
+  store atomic i128 0, i128* %a unordered, align 16
+  ret void
+}
+; CHECK-LABEL: atomic128_store_unordered{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic128_store_monotonic(i128* %a) nounwind uwtable {
+entry:
+  store atomic i128 0, i128* %a monotonic, align 16
+  ret void
+}
+; CHECK-LABEL: atomic128_store_monotonic{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic128_store_release(i128* %a) nounwind uwtable {
+entry:
+  store atomic i128 0, i128* %a release, align 16
+  ret void
+}
+; CHECK-LABEL: atomic128_store_release{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic128_store_seq_cst(i128* %a) nounwind uwtable {
+entry:
+  store atomic i128 0, i128* %a seq_cst, align 16
+  ret void
+}
+; CHECK-LABEL: atomic128_store_seq_cst{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic128_xchg_monotonic(i128* %a) nounwind uwtable {
+entry:
+  atomicrmw xchg i128* %a, i128 0 monotonic
+  ret void
+}
+; CHECK-LABEL: atomic128_xchg_monotonic{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic128_add_monotonic(i128* %a) nounwind uwtable {
+entry:
+  atomicrmw add i128* %a, i128 0 monotonic
+  ret void
+}
+; CHECK-LABEL: atomic128_add_monotonic{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic128_sub_monotonic(i128* %a) nounwind uwtable {
+entry:
+  atomicrmw sub i128* %a, i128 0 monotonic
+  ret void
+}
+; CHECK-LABEL: atomic128_sub_monotonic{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic128_and_monotonic(i128* %a) nounwind uwtable {
+entry:
+  atomicrmw and i128* %a, i128 0 monotonic
+  ret void
+}
+; CHECK-LABEL: atomic128_and_monotonic{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic128_or_monotonic(i128* %a) nounwind uwtable {
+entry:
+  atomicrmw or i128* %a, i128 0 monotonic
+  ret void
+}
+; CHECK-LABEL: atomic128_or_monotonic{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic128_xor_monotonic(i128* %a) nounwind uwtable {
+entry:
+  atomicrmw xor i128* %a, i128 0 monotonic
+  ret void
+}
+; CHECK-LABEL: atomic128_xor_monotonic{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic128_nand_monotonic(i128* %a) nounwind uwtable {
+entry:
+  atomicrmw nand i128* %a, i128 0 monotonic
+  ret void
+}
+; CHECK-LABEL: atomic128_nand_monotonic{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic128_xchg_acquire(i128* %a) nounwind uwtable {
+entry:
+  atomicrmw xchg i128* %a, i128 0 acquire
+  ret void
+}
+; CHECK-LABEL: atomic128_xchg_acquire{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic128_add_acquire(i128* %a) nounwind uwtable {
+entry:
+  atomicrmw add i128* %a, i128 0 acquire
+  ret void
+}
+; CHECK-LABEL: atomic128_add_acquire{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic128_sub_acquire(i128* %a) nounwind uwtable {
+entry:
+  atomicrmw sub i128* %a, i128 0 acquire
+  ret void
+}
+; CHECK-LABEL: atomic128_sub_acquire{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic128_and_acquire(i128* %a) nounwind uwtable {
+entry:
+  atomicrmw and i128* %a, i128 0 acquire
+  ret void
+}
+; CHECK-LABEL: atomic128_and_acquire{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic128_or_acquire(i128* %a) nounwind uwtable {
+entry:
+  atomicrmw or i128* %a, i128 0 acquire
+  ret void
+}
+; CHECK-LABEL: atomic128_or_acquire{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic128_xor_acquire(i128* %a) nounwind uwtable {
+entry:
+  atomicrmw xor i128* %a, i128 0 acquire
+  ret void
+}
+; CHECK-LABEL: atomic128_xor_acquire{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic128_nand_acquire(i128* %a) nounwind uwtable {
+entry:
+  atomicrmw nand i128* %a, i128 0 acquire
+  ret void
+}
+; CHECK-LABEL: atomic128_nand_acquire{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic128_xchg_release(i128* %a) nounwind uwtable {
+entry:
+  atomicrmw xchg i128* %a, i128 0 release
+  ret void
+}
+; CHECK-LABEL: atomic128_xchg_release{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic128_add_release(i128* %a) nounwind uwtable {
+entry:
+  atomicrmw add i128* %a, i128 0 release
+  ret void
+}
+; CHECK-LABEL: atomic128_add_release{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic128_sub_release(i128* %a) nounwind uwtable {
+entry:
+  atomicrmw sub i128* %a, i128 0 release
+  ret void
+}
+; CHECK-LABEL: atomic128_sub_release{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic128_and_release(i128* %a) nounwind uwtable {
+entry:
+  atomicrmw and i128* %a, i128 0 release
+  ret void
+}
+; CHECK-LABEL: atomic128_and_release{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic128_or_release(i128* %a) nounwind uwtable {
+entry:
+  atomicrmw or i128* %a, i128 0 release
+  ret void
+}
+; CHECK-LABEL: atomic128_or_release{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic128_xor_release(i128* %a) nounwind uwtable {
+entry:
+  atomicrmw xor i128* %a, i128 0 release
+  ret void
+}
+; CHECK-LABEL: atomic128_xor_release{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic128_nand_release(i128* %a) nounwind uwtable {
+entry:
+  atomicrmw nand i128* %a, i128 0 release
+  ret void
+}
+; CHECK-LABEL: atomic128_nand_release{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic128_xchg_acq_rel(i128* %a) nounwind uwtable {
+entry:
+  atomicrmw xchg i128* %a, i128 0 acq_rel
+  ret void
+}
+; CHECK-LABEL: atomic128_xchg_acq_rel{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic128_add_acq_rel(i128* %a) nounwind uwtable {
+entry:
+  atomicrmw add i128* %a, i128 0 acq_rel
+  ret void
+}
+; CHECK-LABEL: atomic128_add_acq_rel{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic128_sub_acq_rel(i128* %a) nounwind uwtable {
+entry:
+  atomicrmw sub i128* %a, i128 0 acq_rel
+  ret void
+}
+; CHECK-LABEL: atomic128_sub_acq_rel{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic128_and_acq_rel(i128* %a) nounwind uwtable {
+entry:
+  atomicrmw and i128* %a, i128 0 acq_rel
+  ret void
+}
+; CHECK-LABEL: atomic128_and_acq_rel{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic128_or_acq_rel(i128* %a) nounwind uwtable {
+entry:
+  atomicrmw or i128* %a, i128 0 acq_rel
+  ret void
+}
+; CHECK-LABEL: atomic128_or_acq_rel{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic128_xor_acq_rel(i128* %a) nounwind uwtable {
+entry:
+  atomicrmw xor i128* %a, i128 0 acq_rel
+  ret void
+}
+; CHECK-LABEL: atomic128_xor_acq_rel{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic128_nand_acq_rel(i128* %a) nounwind uwtable {
+entry:
+  atomicrmw nand i128* %a, i128 0 acq_rel
+  ret void
+}
+; CHECK-LABEL: atomic128_nand_acq_rel{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic128_xchg_seq_cst(i128* %a) nounwind uwtable {
+entry:
+  atomicrmw xchg i128* %a, i128 0 seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic128_xchg_seq_cst{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic128_add_seq_cst(i128* %a) nounwind uwtable {
+entry:
+  atomicrmw add i128* %a, i128 0 seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic128_add_seq_cst{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic128_sub_seq_cst(i128* %a) nounwind uwtable {
+entry:
+  atomicrmw sub i128* %a, i128 0 seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic128_sub_seq_cst{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic128_and_seq_cst(i128* %a) nounwind uwtable {
+entry:
+  atomicrmw and i128* %a, i128 0 seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic128_and_seq_cst{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic128_or_seq_cst(i128* %a) nounwind uwtable {
+entry:
+  atomicrmw or i128* %a, i128 0 seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic128_or_seq_cst{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic128_xor_seq_cst(i128* %a) nounwind uwtable {
+entry:
+  atomicrmw xor i128* %a, i128 0 seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic128_xor_seq_cst{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic128_nand_seq_cst(i128* %a) nounwind uwtable {
+entry:
+  atomicrmw nand i128* %a, i128 0 seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic128_nand_seq_cst{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic128_cas_monotonic(i128* %a) nounwind uwtable {
+entry:
+  cmpxchg i128* %a, i128 0, i128 1 monotonic monotonic
+  ret void
+}
+; CHECK-LABEL: atomic128_cas_monotonic{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic128_cas_acquire(i128* %a) nounwind uwtable {
+entry:
+  cmpxchg i128* %a, i128 0, i128 1 acquire acquire
+  ret void
+}
+; CHECK-LABEL: atomic128_cas_acquire{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic128_cas_release(i128* %a) nounwind uwtable {
+entry:
+  cmpxchg i128* %a, i128 0, i128 1 release monotonic
+  ret void
+}
+; CHECK-LABEL: atomic128_cas_release{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic128_cas_acq_rel(i128* %a) nounwind uwtable {
+entry:
+  cmpxchg i128* %a, i128 0, i128 1 acq_rel acquire
+  ret void
+}
+; CHECK-LABEL: atomic128_cas_acq_rel{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+define void @atomic128_cas_seq_cst(i128* %a) nounwind uwtable {
+entry:
+  cmpxchg i128* %a, i128 0, i128 1 seq_cst seq_cst
+  ret void
+}
+; CHECK-LABEL: atomic128_cas_seq_cst{{.*}}!pcsections !0
+; CHECK: !pcsections !2
+
+; Check that callbacks are emitted.
+
+; CHECK-LABEL: __sanitizer_metadata_atomics.module_ctor
+; CHECK: call void @__sanitizer_metadata_atomics_add(i32 1, i8** @__start_sanmd_atomics, i8** @__stop_sanmd_atomics)
+
+; CHECK-LABEL: __sanitizer_metadata_atomics.module_dtor
+; CHECK: call void @__sanitizer_metadata_atomics_del(i32 1, i8** @__start_sanmd_atomics, i8** @__stop_sanmd_atomics)
+
+; CHECK-LABEL: __sanitizer_metadata_covered.module_ctor
+; CHECK: call void @__sanitizer_metadata_covered_add(i32 1, i8** @__start_sanmd_covered, i8** @__stop_sanmd_covered)
+
+; CHECK-LABEL: __sanitizer_metadata_covered.module_dtor
+; CHECK: call void @__sanitizer_metadata_covered_del(i32 1, i8** @__start_sanmd_covered, i8** @__stop_sanmd_covered)
+
+; CHECK: !0 = !{!"sanmd_covered", !1}
+; CHECK: !1 = !{i32 1}
+; CHECK: !2 = !{!"sanmd_atomics"}


        


More information about the llvm-commits mailing list