Merge pull request #16512 from nkcsgexi/cherry-migrator-05-10

[4.2] cherry-pick migrator changes
diff --git a/include/swift/SIL/SILBuilder.h b/include/swift/SIL/SILBuilder.h
index d17c66d..7890a9b 100644
--- a/include/swift/SIL/SILBuilder.h
+++ b/include/swift/SIL/SILBuilder.h
@@ -670,10 +670,11 @@
   BeginAccessInst *createBeginAccess(SILLocation loc, SILValue address,
                                      SILAccessKind accessKind,
                                      SILAccessEnforcement enforcement,
-                                     bool noNestedConflict) {
+                                     bool noNestedConflict,
+                                     bool fromBuiltin) {
     return insert(new (getModule()) BeginAccessInst(
         getSILDebugLocation(loc), address, accessKind, enforcement,
-        noNestedConflict));
+        noNestedConflict, fromBuiltin));
   }
 
   EndAccessInst *createEndAccess(SILLocation loc, SILValue address,
@@ -686,18 +687,19 @@
   createBeginUnpairedAccess(SILLocation loc, SILValue address, SILValue buffer,
                             SILAccessKind accessKind,
                             SILAccessEnforcement enforcement,
-                            bool noNestedConflict) {
+                            bool noNestedConflict,
+                            bool fromBuiltin) {
     return insert(new (getModule()) BeginUnpairedAccessInst(
         getSILDebugLocation(loc), address, buffer, accessKind, enforcement,
-        noNestedConflict));
+        noNestedConflict, fromBuiltin));
   }
 
-  EndUnpairedAccessInst *createEndUnpairedAccess(SILLocation loc,
-                                                 SILValue buffer,
-                                              SILAccessEnforcement enforcement,
-                                                 bool aborted) {
+  EndUnpairedAccessInst *
+  createEndUnpairedAccess(SILLocation loc, SILValue buffer,
+                          SILAccessEnforcement enforcement, bool aborted,
+                          bool fromBuiltin) {
     return insert(new (getModule()) EndUnpairedAccessInst(
-        getSILDebugLocation(loc), buffer, enforcement, aborted));
+        getSILDebugLocation(loc), buffer, enforcement, aborted, fromBuiltin));
   }
 
   AssignInst *createAssign(SILLocation Loc, SILValue Src, SILValue DestAddr) {
diff --git a/include/swift/SIL/SILCloner.h b/include/swift/SIL/SILCloner.h
index cfe18d2..643df68 100644
--- a/include/swift/SIL/SILCloner.h
+++ b/include/swift/SIL/SILCloner.h
@@ -792,7 +792,8 @@
                                            getOpValue(Inst->getOperand()),
                                            Inst->getAccessKind(),
                                            Inst->getEnforcement(),
-                                           Inst->hasNoNestedConflict()));
+                                           Inst->hasNoNestedConflict(),
+                                           Inst->isFromBuiltin()));
 }
 
 template <typename ImplClass>
@@ -814,18 +815,19 @@
                                            getOpValue(Inst->getBuffer()),
                                            Inst->getAccessKind(),
                                            Inst->getEnforcement(),
-                                           Inst->hasNoNestedConflict()));
+                                           Inst->hasNoNestedConflict(),
+                                           Inst->isFromBuiltin()));
 }
 
 template <typename ImplClass>
 void SILCloner<ImplClass>::visitEndUnpairedAccessInst(
                                              EndUnpairedAccessInst *Inst) {
   getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
-  doPostProcess(
-      Inst, getBuilder().createEndUnpairedAccess(getOpLocation(Inst->getLoc()),
-                                                 getOpValue(Inst->getOperand()),
-                                                 Inst->getEnforcement(),
-                                                 Inst->isAborting()));
+  doPostProcess(Inst,
+                getBuilder().createEndUnpairedAccess(
+                    getOpLocation(Inst->getLoc()),
+                    getOpValue(Inst->getOperand()), Inst->getEnforcement(),
+                    Inst->isAborting(), Inst->isFromBuiltin()));
 }
 
 template <typename ImplClass>
diff --git a/include/swift/SIL/SILInstruction.h b/include/swift/SIL/SILInstruction.h
index 24078a2..4d511aa 100644
--- a/include/swift/SIL/SILInstruction.h
+++ b/include/swift/SIL/SILInstruction.h
@@ -3258,12 +3258,14 @@
 
   BeginAccessInst(SILDebugLocation loc, SILValue lvalue,
                   SILAccessKind accessKind, SILAccessEnforcement enforcement,
-                  bool noNestedConflict)
+                  bool noNestedConflict, bool fromBuiltin)
       : UnaryInstructionBase(loc, lvalue, lvalue->getType()) {
     SILInstruction::Bits.BeginAccessInst.AccessKind = unsigned(accessKind);
     SILInstruction::Bits.BeginAccessInst.Enforcement = unsigned(enforcement);
     SILInstruction::Bits.BeginAccessInst.NoNestedConflict =
       unsigned(noNestedConflict);
+    SILInstruction::Bits.BeginAccessInst.FromBuiltin =
+      unsigned(fromBuiltin);
 
     static_assert(unsigned(SILAccessKind::Last) < (1 << 2),
                   "reserve sufficient bits for serialized SIL");
@@ -3307,6 +3309,13 @@
     SILInstruction::Bits.BeginAccessInst.NoNestedConflict = noNestedConflict;
   }
 
+  /// Return true if this access marker was emitted for a user-controlled
+  /// Builtin. Return false if this access marker was auto-generated by the
+  /// compiler to enforce formal access that derives from the language.
+  bool isFromBuiltin() const {
+    return SILInstruction::Bits.BeginAccessInst.FromBuiltin;
+  }
+  
   SILValue getSource() const {
     return getOperand();
   }
@@ -3387,7 +3396,8 @@
   BeginUnpairedAccessInst(SILDebugLocation loc, SILValue addr, SILValue buffer,
                           SILAccessKind accessKind,
                           SILAccessEnforcement enforcement,
-                          bool noNestedConflict)
+                          bool noNestedConflict,
+                          bool fromBuiltin)
       : InstructionBase(loc), Operands(this, addr, buffer) {
     SILInstruction::Bits.BeginUnpairedAccessInst.AccessKind =
       unsigned(accessKind);
@@ -3395,6 +3405,8 @@
       unsigned(enforcement);
     SILInstruction::Bits.BeginUnpairedAccessInst.NoNestedConflict =
       unsigned(noNestedConflict);
+    SILInstruction::Bits.BeginUnpairedAccessInst.FromBuiltin =
+      unsigned(fromBuiltin);
   }
 
 public:
@@ -3429,6 +3441,13 @@
       noNestedConflict;
   }
 
+  /// Return true if this access marker was emitted for a user-controlled
+  /// Builtin. Return false if this access marker was auto-generated by the
+  /// compiler to enforce formal access that derives from the language.
+  bool isFromBuiltin() const {
+    return SILInstruction::Bits.BeginUnpairedAccessInst.FromBuiltin;
+  }
+
   SILValue getSource() const {
     return Operands[0].get();
   }
@@ -3457,11 +3476,13 @@
 
 private:
   EndUnpairedAccessInst(SILDebugLocation loc, SILValue buffer,
-                        SILAccessEnforcement enforcement, bool aborting = false)
+                        SILAccessEnforcement enforcement, bool aborting,
+                        bool fromBuiltin)
       : UnaryInstructionBase(loc, buffer) {
     SILInstruction::Bits.EndUnpairedAccessInst.Enforcement
       = unsigned(enforcement);
     SILInstruction::Bits.EndUnpairedAccessInst.Aborting = aborting;
+    SILInstruction::Bits.EndUnpairedAccessInst.FromBuiltin = fromBuiltin;
   }
 
 public:
@@ -3487,6 +3508,13 @@
         unsigned(enforcement);
   }
 
+  /// Return true if this access marker was emitted for a user-controlled
+  /// Builtin. Return false if this access marker was auto-generated by the
+  /// compiler to enforce formal access that derives from the language.
+  bool isFromBuiltin() const {
+    return SILInstruction::Bits.EndUnpairedAccessInst.FromBuiltin;
+  }
+
   SILValue getBuffer() const {
     return getOperand();
   }
diff --git a/include/swift/SIL/SILNode.h b/include/swift/SIL/SILNode.h
index e0c7340..7138e82 100644
--- a/include/swift/SIL/SILNode.h
+++ b/include/swift/SIL/SILNode.h
@@ -263,24 +263,28 @@
 
   SWIFT_INLINE_BITFIELD(BeginAccessInst, SingleValueInstruction,
                         NumSILAccessKindBits+NumSILAccessEnforcementBits
-                        + 1,
+                        + 1 + 1,
     AccessKind : NumSILAccessKindBits,
     Enforcement : NumSILAccessEnforcementBits,
-    NoNestedConflict : 1
+    NoNestedConflict : 1,
+    FromBuiltin : 1
   );
   SWIFT_INLINE_BITFIELD(BeginUnpairedAccessInst, NonValueInstruction,
-                        NumSILAccessKindBits + NumSILAccessEnforcementBits + 1,
+                        NumSILAccessKindBits + NumSILAccessEnforcementBits
+                        + 1 + 1,
                         AccessKind : NumSILAccessKindBits,
                         Enforcement : NumSILAccessEnforcementBits,
-                        NoNestedConflict : 1);
+                        NoNestedConflict : 1,
+                        FromBuiltin : 1);
 
   SWIFT_INLINE_BITFIELD(EndAccessInst, NonValueInstruction, 1,
     Aborting : 1
   );
   SWIFT_INLINE_BITFIELD(EndUnpairedAccessInst, NonValueInstruction,
-                        NumSILAccessEnforcementBits + 1,
+                        NumSILAccessEnforcementBits + 1 + 1,
                         Enforcement : NumSILAccessEnforcementBits,
-                        Aborting : 1);
+                        Aborting : 1,
+                        FromBuiltin : 1);
 
   SWIFT_INLINE_BITFIELD(StoreInst, NonValueInstruction,
                         NumStoreOwnershipQualifierBits,
diff --git a/include/swift/SIL/SILType.h b/include/swift/SIL/SILType.h
index 0918b71..eda81fe 100644
--- a/include/swift/SIL/SILType.h
+++ b/include/swift/SIL/SILType.h
@@ -367,17 +367,6 @@
   /// pointer.
   bool isPointerSizeAndAligned();
 
-  /// Return true if the layout of `toType` is an ABI compatible prefix of
-  /// `fromType` ignoring reference types. `fromType` may be larger than
-  /// `toType` and still be unsafe castable. `fromType` may contain references
-  /// in positions where `toType` does not contain references and still be
-  /// unsafe castable. This is used solely to determine whether an address cast
-  /// can be promoted to a cast between aggregates of scalar values without
-  /// confusing IRGen.
-  static bool canPerformABICompatibleUnsafeCastValue(SILType fromType,
-                                                     SILType toType,
-                                                     SILModule &M);
-
   /// True if `operTy` can be cast by single-reference value into `resultTy`.
   static bool canRefCast(SILType operTy, SILType resultTy, SILModule &M);
 
diff --git a/include/swift/Serialization/ModuleFormat.h b/include/swift/Serialization/ModuleFormat.h
index 1ae4bd0..562aa69 100644
--- a/include/swift/Serialization/ModuleFormat.h
+++ b/include/swift/Serialization/ModuleFormat.h
@@ -55,7 +55,7 @@
 /// describe what change you made. The content of this comment isn't important;
 /// it just ensures a conflict if two people change the module format.
 /// Don't worry about adhering to the 80-column limit for this line.
-const uint16_t VERSION_MINOR = 411; // Last change: copy_block_without_escaping
+const uint16_t VERSION_MINOR = 412; // Last change: add begin_access [builtin].
 
 using DeclIDField = BCFixed<31>;
 
diff --git a/include/swift/Strings.h b/include/swift/Strings.h
index 38a687a..4d02d9d 100644
--- a/include/swift/Strings.h
+++ b/include/swift/Strings.h
@@ -13,9 +13,6 @@
 #ifndef SWIFT_STRINGS_H
 #define SWIFT_STRINGS_H
 
-#include "swift/Basic/LLVM.h"
-#include "llvm/ADT/StringRef.h"
-
 namespace swift {
 
 /// The extension for serialized modules.
@@ -92,10 +89,6 @@
 constexpr static const char BUILTIN_TYPE_NAME_SILTOKEN[] = "Builtin.SILToken";
 /// The name of the Builtin type for Word
 constexpr static const char BUILTIN_TYPE_NAME_WORD[] = "Builtin.Word";
-
-constexpr static StringLiteral OPTIMIZE_SIL_PRESERVE_EXCLUSIVITY =
-    "optimize.sil.preserve_exclusivity";
-
 } // end namespace swift
 
 #endif // SWIFT_STRINGS_H
diff --git a/lib/IRGen/IRGenSIL.cpp b/lib/IRGen/IRGenSIL.cpp
index b4fe9d4..1baba4a 100644
--- a/lib/IRGen/IRGenSIL.cpp
+++ b/lib/IRGen/IRGenSIL.cpp
@@ -4228,11 +4228,12 @@
 
 static ExclusivityFlags getExclusivityFlags(SILModule &M,
                                             SILAccessKind kind,
-                                            bool noNestedConflict) {
+                                            bool noNestedConflict,
+                                            bool fromBuiltin) {
   auto flags = getExclusivityAction(kind);
 
   // In old Swift compatibility modes, downgrade this to a warning.
-  if (M.getASTContext().LangOpts.isSwiftVersion3())
+  if (!fromBuiltin && M.getASTContext().LangOpts.isSwiftVersion3())
     flags |= ExclusivityFlags::WarningOnly;
 
   if (!noNestedConflict)
@@ -4264,7 +4265,7 @@
 template <class BeginAccessInst>
 static ExclusivityFlags getExclusivityFlags(BeginAccessInst *i) {
   return getExclusivityFlags(i->getModule(), i->getAccessKind(),
-                             i->hasNoNestedConflict());
+                             i->hasNoNestedConflict(), i->isFromBuiltin());
 }
 
 void IRGenSILFunction::visitBeginAccessInst(BeginAccessInst *access) {
diff --git a/lib/IRGen/LoadableByAddress.cpp b/lib/IRGen/LoadableByAddress.cpp
index 02b2b60..73bb33f 100644
--- a/lib/IRGen/LoadableByAddress.cpp
+++ b/lib/IRGen/LoadableByAddress.cpp
@@ -2087,7 +2087,8 @@
       auto *convInstr = cast<BeginAccessInst>(instr);
       newInstr = resultTyBuilder.createBeginAccess(
           Loc, convInstr->getOperand(), convInstr->getAccessKind(),
-          convInstr->getEnforcement(), convInstr->hasNoNestedConflict());
+          convInstr->getEnforcement(), convInstr->hasNoNestedConflict(),
+          convInstr->isFromBuiltin());
       break;
     }
     case SILInstructionKind::EnumInst: {
diff --git a/lib/ParseSIL/ParseSIL.cpp b/lib/ParseSIL/ParseSIL.cpp
index 0deae67..9500bf9 100644
--- a/lib/ParseSIL/ParseSIL.cpp
+++ b/lib/ParseSIL/ParseSIL.cpp
@@ -3434,6 +3434,7 @@
     ParsedEnum<SILAccessEnforcement> enforcement;
     ParsedEnum<bool> aborting;
     ParsedEnum<bool> noNestedConflict;
+    ParsedEnum<bool> fromBuiltin;
 
     bool isBeginAccess = (Opcode == SILInstructionKind::BeginAccessInst ||
                           Opcode == SILInstructionKind::BeginUnpairedAccessInst);
@@ -3465,6 +3466,10 @@
       auto setNoNestedConflict = [&](bool value) {
         maybeSetEnum(isBeginAccess, noNestedConflict, value, attr, identLoc);
       };
+      auto setFromBuiltin = [&](bool value) {
+        maybeSetEnum(Opcode != SILInstructionKind::EndAccessInst, fromBuiltin,
+                     value, attr, identLoc);
+      };
 
       if (attr == "unknown") {
         setEnforcement(SILAccessEnforcement::Unknown);
@@ -3486,6 +3491,8 @@
         setAborting(true);
       } else if (attr == "no_nested_conflict") {
         setNoNestedConflict(true);
+      } else if (attr == "builtin") {
+        setFromBuiltin(true);
       } else {
         P.diagnose(identLoc, diag::unknown_attribute, attr);
       }
@@ -3510,6 +3517,9 @@
     if (isBeginAccess && !noNestedConflict.isSet())
       noNestedConflict.Value = false;
 
+    if (!fromBuiltin.isSet())
+      fromBuiltin.Value = false;
+
     SILValue addrVal;
     SourceLoc addrLoc;
     if (parseTypedValueRef(addrVal, addrLoc, B))
@@ -3534,16 +3544,16 @@
     if (Opcode == SILInstructionKind::BeginAccessInst) {
       ResultVal =
           B.createBeginAccess(InstLoc, addrVal, *kind, *enforcement,
-                              *noNestedConflict);
+                              *noNestedConflict, *fromBuiltin);
     } else if (Opcode == SILInstructionKind::EndAccessInst) {
       ResultVal = B.createEndAccess(InstLoc, addrVal, *aborting);
     } else if (Opcode == SILInstructionKind::BeginUnpairedAccessInst) {
       ResultVal = B.createBeginUnpairedAccess(InstLoc, addrVal, bufferVal,
                                               *kind, *enforcement,
-                                              *noNestedConflict);
+                                              *noNestedConflict, *fromBuiltin);
     } else {
-      ResultVal = B.createEndUnpairedAccess(InstLoc, addrVal,
-                                            *enforcement, *aborting);
+      ResultVal = B.createEndUnpairedAccess(InstLoc, addrVal, *enforcement,
+                                            *aborting, *fromBuiltin);
     }
     break;
   }
diff --git a/lib/SIL/SILInstruction.cpp b/lib/SIL/SILInstruction.cpp
index 75732df..880dae3 100644
--- a/lib/SIL/SILInstruction.cpp
+++ b/lib/SIL/SILInstruction.cpp
@@ -388,7 +388,8 @@
       auto left = cast<BeginAccessInst>(LHS);
       return left->getAccessKind() == right->getAccessKind()
           && left->getEnforcement() == right->getEnforcement()
-          && left->hasNoNestedConflict() == right->hasNoNestedConflict();
+          && left->hasNoNestedConflict() == right->hasNoNestedConflict()
+          && left->isFromBuiltin() == right->isFromBuiltin();
     }
 
     bool visitEndAccessInst(const EndAccessInst *right) {
@@ -400,13 +401,15 @@
       auto left = cast<BeginUnpairedAccessInst>(LHS);
       return left->getAccessKind() == right->getAccessKind()
           && left->getEnforcement() == right->getEnforcement()
-          && left->hasNoNestedConflict() == right->hasNoNestedConflict();
+          && left->hasNoNestedConflict() == right->hasNoNestedConflict()
+          && left->isFromBuiltin() == right->isFromBuiltin();
     }
 
     bool visitEndUnpairedAccessInst(const EndUnpairedAccessInst *right) {
       auto left = cast<EndUnpairedAccessInst>(LHS);
       return left->getEnforcement() == right->getEnforcement()
-          && left->isAborting() == right->isAborting();
+             && left->isAborting() == right->isAborting()
+             && left->isFromBuiltin() == right->isFromBuiltin();
     }
 
     bool visitStrongReleaseInst(const StrongReleaseInst *RHS) {
diff --git a/lib/SIL/SILPrinter.cpp b/lib/SIL/SILPrinter.cpp
index 551da90..95b5e05 100644
--- a/lib/SIL/SILPrinter.cpp
+++ b/lib/SIL/SILPrinter.cpp
@@ -1842,6 +1842,7 @@
     *this << '[' << getSILAccessKindName(BAI->getAccessKind()) << "] ["
           << getSILAccessEnforcementName(BAI->getEnforcement()) << "] "
           << (BAI->hasNoNestedConflict() ? "[no_nested_conflict] " : "")
+          << (BAI->isFromBuiltin() ? "[builtin] " : "")
           << getIDAndType(BAI->getOperand());
   }
   void visitEndAccessInst(EndAccessInst *EAI) {
@@ -1852,12 +1853,14 @@
     *this << '[' << getSILAccessKindName(BAI->getAccessKind()) << "] ["
           << getSILAccessEnforcementName(BAI->getEnforcement()) << "] "
           << (BAI->hasNoNestedConflict() ? "[no_nested_conflict] " : "")
+          << (BAI->isFromBuiltin() ? "[builtin] " : "")
           << getIDAndType(BAI->getSource()) << ", " 
           << getIDAndType(BAI->getBuffer());
   }
   void visitEndUnpairedAccessInst(EndUnpairedAccessInst *EAI) {
-    *this << (EAI->isAborting() ? "[abort] " : "")
-          << '[' << getSILAccessEnforcementName(EAI->getEnforcement()) << "] "
+    *this << (EAI->isAborting() ? "[abort] " : "") << '['
+          << getSILAccessEnforcementName(EAI->getEnforcement()) << "] "
+          << (EAI->isFromBuiltin() ? "[builtin] " : "")
           << getIDAndType(EAI->getOperand());
   }
 
diff --git a/lib/SIL/SILType.cpp b/lib/SIL/SILType.cpp
index 2bfb8e7..e2160c5 100644
--- a/lib/SIL/SILType.cpp
+++ b/lib/SIL/SILType.cpp
@@ -110,193 +110,6 @@
   return false;
 }
 
-// Allow casting a struct by value when all elements in toType correspond to
-// an element of the same size or larger laid out in the same order in
-// fromType. The assumption is that if fromType has larger elements, or
-// additional elements, their presence cannot induce a more compact layout of
-// the overlapping elements.
-//
-// struct {A, B} -> A is castable
-// struct {A, B, C} -> struct {A, B} is castable
-// struct { struct {A, B}, C} -> struct {A, B} is castable
-// struct { A, B, C} -> struct { struct {A, B}, C} is NOT castable
-//
-// FIXME: This is unnecessarily conservative given the current ABI
-// (TypeLayout.rst). It would be simpler to flatten both `from` and `to` types,
-// exploding all structs and tuples, then trivially check if `to` is a prefix.
-static bool canUnsafeCastStruct(SILType fromType, StructDecl *fromStruct,
-                                SILType toType, SILModule &M) {
-  auto fromRange = fromStruct->getStoredProperties();
-  if (fromRange.begin() == fromRange.end())
-    return false;
-
-  // Can the first element of fromStruct be cast by value into toType?
-  SILType fromEltTy = fromType.getFieldType(*fromRange.begin(), M);
-  if (SILType::canPerformABICompatibleUnsafeCastValue(fromEltTy, toType, M))
-    return true;
-  
-  // Otherwise, flatten one level of struct elements on each side.
-  StructDecl *toStruct = toType.getStructOrBoundGenericStruct();
-  if (!toStruct)
-    return false;
-
-  auto toRange = toStruct->getStoredProperties();
-  for (auto toI = toRange.begin(), toE = toRange.end(),
-         fromI = fromRange.begin(), fromE = fromRange.end();
-       toI != toE; ++toI, ++fromI) {
-
-    if (fromI == fromE)
-      return false; // fromType is a struct with fewer elements.
-      
-    SILType fromEltTy = fromType.getFieldType(*fromI, M);
-    SILType toEltTy = toType.getFieldType(*toI, M);
-    if (!SILType::canPerformABICompatibleUnsafeCastValue(fromEltTy, toEltTy, M))
-      return false;
-  }
-  // fromType's overlapping elements are compatible.
-  return true;
-}
-
-// Allow casting a tuple by value when all elements in toType correspond to an
-// element of the same size or larger in fromType in the same order.
-static bool canUnsafeCastTuple(SILType fromType, CanTupleType fromTupleTy,
-                               SILType toType, SILModule &M) {
-  unsigned numFromElts = fromTupleTy->getNumElements();
-  // Can the first element of fromTupleTy be cast by value into toType?
-  if (numFromElts != 0
-      && SILType::canPerformABICompatibleUnsafeCastValue(
-             fromType.getTupleElementType(0), toType, M)) {
-    return true;
-  }
-  // Otherwise, flatten one level of tuple elements on each side.
-  auto toTupleTy = dyn_cast<TupleType>(toType.getSwiftRValueType());
-  if (!toTupleTy)
-    return false;
-
-  unsigned numToElts = toTupleTy->getNumElements();
-  if (numFromElts < numToElts)
-    return false;
-
-  for (unsigned i = 0; i != numToElts; ++i) {
-    if (!SILType::canPerformABICompatibleUnsafeCastValue(
-            fromType.getTupleElementType(i), toType.getTupleElementType(i),
-            M)) {
-      return false;
-    }
-  }
-  return true;
-}
-
-// Allow casting an enum by value when toType is an enum and each elements is
-// individually castable to toType. An enum cannot be smaller than its payload.
-static bool canUnsafeCastEnum(SILType fromType, EnumDecl *fromEnum,
-                              SILType toType, SILModule &M) {
-  unsigned numToElements = 0;
-  SILType toElementTy;
-  if (EnumDecl *toEnum = toType.getEnumOrBoundGenericEnum()) {
-    for (auto toElement : toEnum->getAllElements()) {
-      ++numToElements;
-      if (!toElement->hasAssociatedValues())
-        continue;
-      // Bail on multiple payloads.
-      if (!toElementTy.isNull())
-        return false;
-      toElementTy = toType.getEnumElementType(toElement, M);
-    }
-  } else {
-    // If toType is not an enum, handle it like a singleton
-    numToElements = 1;
-    toElementTy = toType;
-  }
-  // If toType has more elements, it may be larger.
-  auto fromElements = fromEnum->getAllElements();
-  if (static_cast<ptrdiff_t>(numToElements) >
-      std::distance(fromElements.begin(), fromElements.end()))
-    return false;
-
-  if (toElementTy.isNull())
-    return true;
-
-  // If any of the fromElements can be cast by value to the singleton toElement,
-  // then the overall enum can be cast by value.
-  for (auto fromElement : fromElements) {
-    if (!fromElement->hasAssociatedValues())
-      continue;
-
-    auto fromElementTy = fromType.getEnumElementType(fromElement, M);
-    if (SILType::canPerformABICompatibleUnsafeCastValue(fromElementTy,
-                                                        toElementTy, M))
-      return true;
-  }
-  return false;
-}
-
-static bool canUnsafeCastScalars(SILType fromType, SILType toType,
-                                 SILModule &M) {
-  CanType fromCanTy = fromType.getSwiftRValueType();
-  bool isToPointer = toType.isPointerSizeAndAligned();
-
-  unsigned LeastFromWidth = 0;
-  // Like UnsafeRefBitCast, allow class existentials to be truncated to
-  // single-pointer references. Unlike UnsafeRefBitCast, this also supports raw
-  // pointers and words.
-  if (fromType.isPointerSizeAndAligned()
-      || fromCanTy.isAnyClassReferenceType()) {
-
-    // Allow casting from a value that contains an aligned pointer into another
-    // pointer value regardless of the fixed width.
-    if (isToPointer)
-      return true;
-
-    LeastFromWidth = BuiltinIntegerWidth::pointer().getLeastWidth();
-
-  } else if (auto fromIntTy = dyn_cast<BuiltinIntegerType>(fromCanTy)) {
-    if (fromIntTy->isFixedWidth())
-      LeastFromWidth = fromIntTy->getFixedWidth();
-  }
-
-  unsigned GreatestToWidth = UINT_MAX;
-  if (isToPointer) {
-    GreatestToWidth = BuiltinIntegerWidth::pointer().getGreatestWidth();
-
-  } else if (auto toIntTy = dyn_cast<BuiltinIntegerType>(
-               toType.getSwiftRValueType())) {
-    if (toIntTy->isFixedWidth())
-      GreatestToWidth = toIntTy->getFixedWidth();
-  }
-  return LeastFromWidth >= GreatestToWidth;
-}
-
-bool SILType::canPerformABICompatibleUnsafeCastValue(SILType fromType,
-                                                     SILType toType,
-                                                     SILModule &M) {
-  if (fromType == toType)
-    return true;
-
-  // Unwrap single element structs.
-  if (StructDecl *toStruct = toType.getStructOrBoundGenericStruct()) {
-    auto toRange = toStruct->getStoredProperties();
-    if (toRange.begin() != toRange.end()
-        && std::next(toRange.begin()) == toRange.end()) {
-      toType = toType.getFieldType(*toRange.begin(), M);
-    }
-  }
-  if (canUnsafeCastScalars(fromType, toType, M))
-    return true;
-
-  if (StructDecl *fromStruct = fromType.getStructOrBoundGenericStruct())
-    return canUnsafeCastStruct(fromType, fromStruct, toType, M);
-
-  if (CanTupleType fromTupleTy =
-      dyn_cast<TupleType>(fromType.getSwiftRValueType())) {
-    return canUnsafeCastTuple(fromType, fromTupleTy, toType, M);
-  }
-  if (EnumDecl *fromEnum = fromType.getEnumOrBoundGenericEnum())
-    return canUnsafeCastEnum(fromType, fromEnum, toType, M);
-  
-  return false;
-}
-
 // Reference cast from representations with single pointer low bits.
 // Only reference cast to simple single pointer representations.
 //
diff --git a/lib/SILGen/SILGenBuiltin.cpp b/lib/SILGen/SILGenBuiltin.cpp
index aa72932..781e3d7 100644
--- a/lib/SILGen/SILGenBuiltin.cpp
+++ b/lib/SILGen/SILGenBuiltin.cpp
@@ -581,7 +581,8 @@
                                  /*invariant*/ false);
   SGF.B.createBeginUnpairedAccess(loc, addr, buffer, SILAccessKind::Modify,
                                   SILAccessEnforcement::Dynamic,
-                                  /*noNestedConflict*/ false);
+                                  /*noNestedConflict*/ false,
+                                  /*fromBuiltin*/ true);
 
   return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc));
 }
@@ -617,7 +618,8 @@
   // use will be trivially optimized away.
   SGF.B.createBeginUnpairedAccess(loc, addr, unusedBuffer, SILAccessKind::Read,
                                   SILAccessEnforcement::Dynamic,
-                                  /*noNestedConflict*/ true);
+                                  /*noNestedConflict*/ true,
+                                  /*fromBuiltin*/ true);
 
   return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc));
 }
@@ -641,7 +643,8 @@
                                                  /*strict*/ true,
                                                  /*invariant*/ false);
   SGF.B.createEndUnpairedAccess(loc, buffer, SILAccessEnforcement::Dynamic,
-                                /*aborted*/ false);
+                                /*aborted*/ false,
+                                /*fromBuiltin*/ true);
 
   return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc));
 }
diff --git a/lib/SILGen/SILGenLValue.cpp b/lib/SILGen/SILGenLValue.cpp
index 5d81218..ac89fd4 100644
--- a/lib/SILGen/SILGenLValue.cpp
+++ b/lib/SILGen/SILGenLValue.cpp
@@ -466,7 +466,8 @@
     if (enforcement == SILAccessEnforcement::Dynamic) {
       SGF.B.createBeginUnpairedAccess(loc, addr, unpairedAccesses->Buffer,
                                       silAccessKind, enforcement,
-                                      /*hasNoNestedConflict=*/false);
+                                      /*hasNoNestedConflict=*/false,
+                                      /*fromBuiltin=*/false);
       unpairedAccesses->NumAccesses++;
     }
     return addr;
@@ -474,7 +475,8 @@
 
   // Enter the access.
   addr = SGF.B.createBeginAccess(loc, addr, silAccessKind, enforcement,
-                                 /*hasNoNestedConflict=*/false);
+                                 /*hasNoNestedConflict=*/false,
+                                 /*fromBuiltin=*/false);
 
   // Push a writeback to end it.
   auto accessedMV = ManagedValue::forLValue(addr);
@@ -508,7 +510,8 @@
 
   auto BAI =
     SGF.B.createBeginAccess(loc, address, kind, SILAccessEnforcement::Unsafe,
-                            /*hasNoNestedConflict=*/false);
+                            /*hasNoNestedConflict=*/false,
+                            /*fromBuiltin=*/false);
   beginAccessPtr = BeginAccessPtr(BAI, DeleterCheck());
 
   return BAI;
diff --git a/lib/SILGen/SILGenMaterializeForSet.cpp b/lib/SILGen/SILGenMaterializeForSet.cpp
index b1dac7e..ea6d9f2 100644
--- a/lib/SILGen/SILGenMaterializeForSet.cpp
+++ b/lib/SILGen/SILGenMaterializeForSet.cpp
@@ -794,7 +794,8 @@
            "multiple unpaired accesses not supported");
     SGF.B.createEndUnpairedAccess(loc, callbackStorage,
                                   SILAccessEnforcement::Dynamic,
-                                  /*aborting*/ false);
+                                  /*aborting*/ false,
+                                  /*fromBuiltin*/ false);
   });
 }
 
diff --git a/lib/SILOptimizer/Mandatory/AccessMarkerElimination.cpp b/lib/SILOptimizer/Mandatory/AccessMarkerElimination.cpp
index 60e1797..6f353d3 100644
--- a/lib/SILOptimizer/Mandatory/AccessMarkerElimination.cpp
+++ b/lib/SILOptimizer/Mandatory/AccessMarkerElimination.cpp
@@ -31,7 +31,6 @@
 #include "swift/Basic/Range.h"
 #include "swift/SIL/SILFunction.h"
 #include "swift/SILOptimizer/PassManager/Transforms.h"
-#include "swift/Strings.h"
 #include "llvm/Support/CommandLine.h"
 
 using namespace swift;
@@ -112,6 +111,12 @@
 // updated the SIL, short of erasing the marker itself, and return true.
 bool AccessMarkerElimination::checkAndEliminateMarker(SILInstruction *inst) {
   if (auto beginAccess = dyn_cast<BeginAccessInst>(inst)) {
+    // Builtins used by the standard library must emit markers regardless of the
+    // current compiler options so that any user code that initiates access via
+    // the standard library is fully enforced.
+    if (beginAccess->isFromBuiltin())
+      return false;
+
     // Leave dynamic accesses in place, but delete all others.
     if (shouldPreserveAccess(beginAccess->getEnforcement()))
       return false;
@@ -126,6 +131,11 @@
   // begin_unpaired_access instructions will be directly removed and
   // simply replaced with their operand.
   if (auto BUA = dyn_cast<BeginUnpairedAccessInst>(inst)) {
+    // Builtins used by the standard library must emit markers regardless of the
+    // current compiler options.
+    if (BUA->isFromBuiltin())
+      return false;
+
     if (shouldPreserveAccess(BUA->getEnforcement()))
       return false;
 
@@ -134,6 +144,11 @@
   // end_unpaired_access instructions will be directly removed and
   // simply replaced with their operand.
   if (auto EUA = dyn_cast<EndUnpairedAccessInst>(inst)) {
+    // Builtins used by the standard library must emit markers regardless of the
+    // current compiler options.
+    if (EUA->isFromBuiltin())
+      return false;
+
     if (shouldPreserveAccess(EUA->getEnforcement()))
       return false;
 
@@ -174,12 +189,6 @@
   void run() override {
     auto &M = *getModule();
     for (auto &F : M) {
-      if (F.hasSemanticsAttr(OPTIMIZE_SIL_PRESERVE_EXCLUSIVITY)) {
-        DEBUG(llvm::dbgs() << "Skipping " << F.getName() << ". Found "
-                           << OPTIMIZE_SIL_PRESERVE_EXCLUSIVITY << " tag!\n");
-        continue;
-      }
-
       bool removedAny = AccessMarkerElimination(&F).stripMarkers();
 
       // Only invalidate analyses if we removed some markers.
diff --git a/lib/SILOptimizer/SILCombiner/SILCombinerCastVisitors.cpp b/lib/SILOptimizer/SILCombiner/SILCombinerCastVisitors.cpp
index b2c65d6..d857567 100644
--- a/lib/SILOptimizer/SILCombiner/SILCombinerCastVisitors.cpp
+++ b/lib/SILOptimizer/SILCombiner/SILCombinerCastVisitors.cpp
@@ -208,68 +208,7 @@
     return Builder.createUpcast(UADCI->getLoc(), UADCI->getOperand(),
                                 UADCI->getType());
 
-  // See if we have all loads from this unchecked_addr_cast. If we do, load the
-  // original type and create the appropriate bitcast.
-
-  // First if our UADCI has not users, bail. This will be eliminated by DCE.
-  if (UADCI->use_empty())
-    return nullptr;
-
-  SILType InputTy = UADCI->getOperand()->getType();
-  SILType OutputTy = UADCI->getType();
-
-  // If either type is address only, do not do anything here.
-  if (InputTy.isAddressOnly(Mod) || OutputTy.isAddressOnly(Mod))
-    return nullptr;
-
-  bool InputIsTrivial = InputTy.isTrivial(Mod);
-  bool OutputIsTrivial = OutputTy.isTrivial(Mod);
-
-  // If our input is trivial and our output type is not, do not do
-  // anything. This is to ensure that we do not change any types reference
-  // semantics from trivial -> reference counted.
-  if (InputIsTrivial && !OutputIsTrivial)
-    return nullptr;
-
-  // Check that the input type can be value cast to the output type.  It is
-  // possible to cast the address of a smaller InputType to the address of a
-  // larger OutputType (the actual memory object must be large enough to hold
-  // both types). However, such address casts cannot be converted to value
-  // casts.
-  if (!SILType::canPerformABICompatibleUnsafeCastValue(InputTy, OutputTy,
-                                                       UADCI->getModule())) {
-    return nullptr;
-  }
-  // For each user U of the unchecked_addr_cast...
-  for (auto U : getNonDebugUses(UADCI))
-    // Check if it is load. If it is not a load, bail...
-    if (!isa<LoadInst>(U->getUser()))
-      return nullptr;
-
-  SILValue Op = UADCI->getOperand();
-  SILLocation Loc = UADCI->getLoc();
-
-  // Ok, we have all loads. Lets simplify this. Go back through the loads a
-  // second time, rewriting them into a load + bitcast from our source.
-  auto UsesRange = getNonDebugUses(UADCI);
-  for (auto UI = UsesRange.begin(), E = UsesRange.end(); UI != E;) {
-    // Grab the original load.
-    LoadInst *L = cast<LoadInst>(UI->getUser());
-    UI++;
-
-    // Insert a new load from our source and bitcast that as appropriate.
-    LoadInst *NewLoad =
-        Builder.createLoad(Loc, Op, LoadOwnershipQualifier::Unqualified);
-    auto *BitCast = Builder.createUncheckedBitCast(Loc, NewLoad,
-                                                    OutputTy.getObjectType());
-    // Replace all uses of the old load with the new bitcasted result and erase
-    // the old load.
-    replaceInstUsesWith(*L, BitCast);
-    eraseInstFromFunction(*L);
-  }
-
-  // Delete the old cast.
-  return eraseInstFromFunction(*UADCI);
+  return nullptr;
 }
 
 SILInstruction *
diff --git a/lib/Serialization/DeserializeSIL.cpp b/lib/Serialization/DeserializeSIL.cpp
index 3e4ae65..1c2ad04 100644
--- a/lib/Serialization/DeserializeSIL.cpp
+++ b/lib/Serialization/DeserializeSIL.cpp
@@ -1720,10 +1720,11 @@
         ValID, getSILType(MF->getType(TyID), (SILValueCategory)TyCategory));
     auto accessKind = SILAccessKind(Attr & 0x3);
     auto enforcement = SILAccessEnforcement((Attr >> 2) & 0x3);
-    bool noNestedConflict = Attr >> 4;
+    bool noNestedConflict = (Attr >> 4) & 0x01;
+    bool fromBuiltin = (Attr >> 5) & 0x01;
     ResultVal =
         Builder.createBeginAccess(Loc, op, accessKind, enforcement,
-                                  noNestedConflict);
+                                  noNestedConflict, fromBuiltin);
     break;
   }
   case SILInstructionKind::EndAccessInst: {
@@ -1740,17 +1741,21 @@
         ValID2, getSILType(MF->getType(TyID2), (SILValueCategory)TyCategory2));
     auto accessKind = SILAccessKind(Attr & 0x3);
     auto enforcement = SILAccessEnforcement((Attr >> 2) & 0x03);
-    bool noNestedConflict = Attr >> 4;
+    bool noNestedConflict = (Attr >> 4) & 0x01;
+    bool fromBuiltin = (Attr >> 5) & 0x01;
     ResultVal = Builder.createBeginUnpairedAccess(
-        Loc, source, buffer, accessKind, enforcement, noNestedConflict);
+      Loc, source, buffer, accessKind, enforcement, noNestedConflict,
+      fromBuiltin);
     break;
   }
   case SILInstructionKind::EndUnpairedAccessInst: {
     SILValue op = getLocalValue(
         ValID, getSILType(MF->getType(TyID), (SILValueCategory)TyCategory));
     bool aborted = Attr & 0x1;
-    auto enforcement = SILAccessEnforcement(Attr >> 1);
-    ResultVal = Builder.createEndUnpairedAccess(Loc, op, enforcement, aborted);
+    auto enforcement = SILAccessEnforcement((Attr >> 1) & 0x03);
+    bool fromBuiltin = (Attr >> 3) & 0x01;
+    ResultVal = Builder.createEndUnpairedAccess(Loc, op, enforcement, aborted,
+                                                fromBuiltin);
     break;
   }
   case SILInstructionKind::StoreUnownedInst: {
diff --git a/lib/Serialization/SILFormat.h b/lib/Serialization/SILFormat.h
index 225be47..d1e30da 100644
--- a/lib/Serialization/SILFormat.h
+++ b/lib/Serialization/SILFormat.h
@@ -415,7 +415,7 @@
   using SILOneOperandExtraAttributeLayout = BCRecordLayout<
     SIL_ONE_OPERAND_EXTRA_ATTR,
     SILInstOpCodeField,
-    BCFixed<5>, // Optional attributes
+    BCFixed<6>, // Optional attributes
     TypeIDField, SILTypeCategoryField, ValueIDField
   >;
 
@@ -435,7 +435,7 @@
   using SILTwoOperandsExtraAttributeLayout = BCRecordLayout<
     SIL_TWO_OPERANDS_EXTRA_ATTR,
     SILInstOpCodeField,
-    BCFixed<5>,          // Optional attributes
+    BCFixed<6>,          // Optional attributes
     TypeIDField,
     SILTypeCategoryField,
     ValueIDField,
diff --git a/lib/Serialization/SerializeSIL.cpp b/lib/Serialization/SerializeSIL.cpp
index 13780e6..79278d0 100644
--- a/lib/Serialization/SerializeSIL.cpp
+++ b/lib/Serialization/SerializeSIL.cpp
@@ -1596,7 +1596,8 @@
     auto *BAI = cast<BeginAccessInst>(&SI);
     unsigned attr = unsigned(BAI->getAccessKind())
                     + (unsigned(BAI->getEnforcement()) << 2)
-                    + (BAI->hasNoNestedConflict() << 4);
+                    + (BAI->hasNoNestedConflict() << 4)
+                    + (BAI->isFromBuiltin() << 5);
     SILValue operand = BAI->getOperand();
 
     SILOneOperandExtraAttributeLayout::emitRecord(
@@ -1626,7 +1627,8 @@
     auto *BAI = cast<BeginUnpairedAccessInst>(&SI);
     unsigned attr = unsigned(BAI->getAccessKind())
                     + (unsigned(BAI->getEnforcement()) << 2)
-                    + (unsigned(BAI->hasNoNestedConflict()) << 4);
+                    + (unsigned(BAI->hasNoNestedConflict()) << 4)
+                    + (unsigned(BAI->isFromBuiltin()) << 5);
     SILValue source = BAI->getSource();
     SILValue buffer = BAI->getBuffer();
 
@@ -1645,7 +1647,8 @@
     unsigned abbrCode = SILAbbrCodes[SILOneOperandExtraAttributeLayout::Code];
     auto *EAI = cast<EndUnpairedAccessInst>(&SI);
     unsigned attr = unsigned(EAI->isAborting())
-                  + (unsigned(EAI->getEnforcement()) << 1);
+                    + (unsigned(EAI->getEnforcement()) << 1)
+                    + (unsigned(EAI->isFromBuiltin()) << 3);
     SILValue operand = EAI->getOperand();
 
     SILOneOperandExtraAttributeLayout::emitRecord(
diff --git a/stdlib/public/core/KeyPath.swift b/stdlib/public/core/KeyPath.swift
index bc1a42e..65adf76 100644
--- a/stdlib/public/core/KeyPath.swift
+++ b/stdlib/public/core/KeyPath.swift
@@ -646,41 +646,6 @@
   }
 }
 
-// _semantics("optimize.sil.preserve_exclusivity" forces the compiler to
-// generate access markers regardless of the current build settings. This way,
-// user code that accesses keypaths are properly enforced even if the standard
-// library has exclusivity checking internally disabled. The semantic attribute
-// must be consistently applied to both the begin and end unpaired access
-// markers, otherwise the runtime will fail catastrophically and unpredictably.
-// This relies on Swift module serialization occurring before these _semantic
-// function are inlined, since inlining would unpredictably cause the attribute
-// to be dropped.
-//
-// An exclusivity violation will report the caller's stack frame location.
-// Runtime diagnostics will be improved by inlining this function. However, this
-// cannot be marked @transparent because it can't be inlined prior to
-// serialization.
-@inlinable
-@inline(__always)
-@_semantics("optimize.sil.preserve_exclusivity")
-func beginAccessHelper<T>(_ address: Builtin.RawPointer, _ accessRecordPtr: Builtin.RawPointer, _ type: T.Type) {
-  Builtin.beginUnpairedModifyAccess(address, accessRecordPtr, type)
-}
-
-@inlinable
-@inline(__always)
-@_semantics("optimize.sil.preserve_exclusivity")
-func endAccessHelper(_ accessRecordPtr: Builtin.RawPointer) {
-  Builtin.endUnpairedAccess(accessRecordPtr)
-}
-
-@inlinable
-@inline(__always)
-@_semantics("optimize.sil.preserve_exclusivity")
-func instantaneousAccessHelper<T>(_ address: Builtin.RawPointer, _ type: T.Type) {
-  Builtin.performInstantaneousReadAccess(address, T.self)
-}
-
 // A class that maintains ownership of another object while a mutable projection
 // into it is underway. The lifetime of the instance of this class is also used
 // to begin and end exclusive 'modify' access to the projected address.
@@ -735,7 +700,7 @@
 
     // Begin a 'modify' access to the address. This access is ended in
     // ClassHolder's deinitializer.
-    beginAccessHelper(address._rawValue, accessRecordPtr, type)
+    Builtin.beginUnpairedModifyAccess(address._rawValue, accessRecordPtr, type)
 
     return holder
   }
@@ -745,7 +710,7 @@
     let accessRecordPtr = Builtin.projectTailElems(self, AccessRecord.self)
 
     // Ends the access begun in _create().
-    endAccessHelper(accessRecordPtr)
+    Builtin.endUnpairedAccess(accessRecordPtr)
   }
 }
 
@@ -1296,7 +1261,8 @@
       // Perform an instaneous record access on the address in order to
       // ensure that the read will not conflict with an already in-progress
       // 'modify' access.
-      instantaneousAccessHelper(offsetAddress._rawValue, NewValue.self)
+      Builtin.performInstantaneousReadAccess(offsetAddress._rawValue,
+        NewValue.self)
       return .continue(offsetAddress
         .assumingMemoryBound(to: NewValue.self)
         .pointee)
diff --git a/test/IRGen/preserve_exclusivity.swift b/test/IRGen/preserve_exclusivity.swift
index 119eea3..14e1a87 100644
--- a/test/IRGen/preserve_exclusivity.swift
+++ b/test/IRGen/preserve_exclusivity.swift
@@ -1,10 +1,7 @@
-// RUN: %target-swift-frontend -parse-stdlib -emit-ir -Onone %s | %FileCheck --check-prefix=IR-Onone %s
+// RUN: %target-swift-frontend -swift-version 3 -parse-stdlib -Xllvm -sil-disable-pass=FunctionSignatureOpts -Xllvm -sil-disable-pass=GenericSpecializer -emit-ir -O %s | %FileCheck %s
+// RUN: %target-swift-frontend -swift-version 4 -parse-stdlib -Xllvm -sil-disable-pass=FunctionSignatureOpts -Xllvm -sil-disable-pass=GenericSpecializer -emit-ir -O %s | %FileCheck %s
 //
-// Check that access markers in @_semantics("optimize.sil.preserve_exclusivity") functions generate runtime calls.
-
-// RUN: %target-swift-frontend -parse-stdlib -Xllvm -sil-disable-pass=FunctionSignatureOpts -Xllvm -sil-disable-pass=GenericSpecializer -emit-ir -O %s | %FileCheck --check-prefix=IR-O %s
-//
-// Check that the -O pipeline preserves the runtime calls for @_semantics("optimize.sil.preserve_exclusivity") functions.
+// Check that the -O pipeline always preserves the runtime calls for Builtin access markers and that the KeyPath implementation is fully inlined.
 
 @_silgen_name("marker1")
 func marker1() -> ()
@@ -15,122 +12,44 @@
 @_silgen_name("marker3")
 func marker3() -> ()
 
-@_silgen_name("marker4")
-func marker4() -> ()
+// IR-LABEL: define {{.*}}swiftcc void @"$S20preserve_exclusivity11beginAccessyyBp_BpxmtlF"(i8*, i8*, %swift.type*{{.*}}, %swift.type*{{.*}} %T1)
+// IR:   call void @swift_beginAccess
+// IR-NEXT: ret void
 
-@_silgen_name("marker5")
-func marker5() -> ()
-
-@_silgen_name("marker6")
-func marker6() -> ()
-
-// IR-Onone-LABEL: define {{.*}}swiftcc void @"$S20preserve_exclusivity10beginNoOptyyBp_BpxmtlF"(i8*, i8*, %swift.type*, %swift.type* %T1)
-// IR-Onone: call void @swift_beginAccess
-// IR-Onone-NEXT: ret void
-
-// IR-O-LABEL: define {{.*}}swiftcc void @"$S20preserve_exclusivity10beginNoOptyyBp_BpxmtlF"(i8*, i8*, %swift.type*{{.*}}, %swift.type*{{.*}} %T1)
-// IR-O:   call void @swift_beginAccess
-// IR-O-NEXT: ret void
-
-@_semantics("optimize.sil.preserve_exclusivity")
-public func beginNoOpt<T1>(_ address: Builtin.RawPointer, _ scratch: Builtin.RawPointer, _ ty1: T1.Type) {
+public func beginAccess<T1>(_ address: Builtin.RawPointer, _ scratch: Builtin.RawPointer, _ ty1: T1.Type) {
   marker1()
   Builtin.beginUnpairedModifyAccess(address, scratch, ty1);
 }
 
-// IR-Onone-LABEL: define {{.*}}swiftcc void @"$S20preserve_exclusivity8endNoOptyyBpF"(i8*)
-// IR-Onone: call void @swift_endAccess
-// IR-Onone-NEXT: ret void
-
-// IR-O-LABEL: define {{.*}}swiftcc void @"$S20preserve_exclusivity8endNoOptyyBpF"(i8*)
-// IR-O:   call void @swift_endAccess
-// IR-O-NEXT: ret void
-@_semantics("optimize.sil.preserve_exclusivity")
-public func endNoOpt(_ address: Builtin.RawPointer) {
+// CHECK-LABEL: define {{.*}}swiftcc void @"$S20preserve_exclusivity9endAccessyyBpF"(i8*{{.*}})
+// CHECK:   call void @swift_endAccess
+// CHECK-NEXT: ret void
+public func endAccess(_ address: Builtin.RawPointer) {
   marker2()
   Builtin.endUnpairedAccess(address)
 }
 
-// IR-Onone-LABEL: define {{.*}}swiftcc void @"$S20preserve_exclusivity9readNoOptyyBp_xmtlF"(i8*, %swift.type*, %swift.type* %T1)
-// IR-Onone: call void @swift_beginAccess
-// IR-Onone: ret void
-
-// IR-O-LABEL: define {{.*}}swiftcc void @"$S20preserve_exclusivity9readNoOptyyBp_xmtlF"(i8*, %swift.type*{{.*}}, %swift.type*{{.*}} %T1)
-// IR-O:   call void @swift_beginAccess
-// IR-O: ret void
+// CHECK-LABEL: define {{.*}}swiftcc void @"$S20preserve_exclusivity10readAccessyyBp_xmtlF"(i8*, %swift.type*{{.*}}, %swift.type*{{.*}} %T1)
+// CHECK:   call void @swift_beginAccess
+// CHECK: ret void
 @_semantics("optimize.sil.preserve_exclusivity")
-public func readNoOpt<T1>(_ address: Builtin.RawPointer, _ ty1: T1.Type) {
+public func readAccess<T1>(_ address: Builtin.RawPointer, _ ty1: T1.Type) {
   marker3()
   Builtin.performInstantaneousReadAccess(address, ty1);
 }
 
-// Make sure testNoOpt properly inlines in our functions.
+// Make sure testAccess properly inlines in our functions.
 //
-// IR-O-LABEL: define {{.*}}swiftcc void @"$S20preserve_exclusivity9testNoOptyyBpF"(i8*)
-// IR-O: call swiftcc void @marker1
-// IR-O: call void @swift_beginAccess
-// IR-O: call swiftcc void @marker2
-// IR-O: call void @swift_endAccess
-// IR-O: call swiftcc void @marker3
-// IR-O: call void @swift_beginAccess
-// IR-O: ret void
-public func testNoOpt(_ k1: Builtin.RawPointer) {
-  beginNoOpt(k1, k1, Builtin.RawPointer.self)
-  endNoOpt(k1)
-  readNoOpt(k1, Builtin.RawPointer.self)
-}
-
-// IR-Onone-LABEL: define {{.*}}swiftcc void @"$S20preserve_exclusivity8beginOptyyBp_BpxmtlF"(i8*, i8*, %swift.type*, %swift.type* %T1)
-// IR-Onone: call void @swift_beginAccess
-// IR-Onone-NEXT: ret void
-
-// IR-O-LABEL: define {{.*}}swiftcc void @"$S20preserve_exclusivity8beginOptyyBp_BpxmtlF"(i8*{{.*}}, i8*{{.*}}, %swift.type*{{.*}}, %swift.type*{{.*}} %T1)
-// IR-O-NEXT: entry
-// IR-O-NEXT: call swiftcc void @marker4
-// IR-O-NEXT: ret void
-
-public func beginOpt<T1>(_ address: Builtin.RawPointer, _ scratch: Builtin.RawPointer, _ ty1: T1.Type) {
-  marker4()
-  Builtin.beginUnpairedModifyAccess(address, scratch, ty1);
-}
-
-// IR-Onone-LABEL: define {{.*}}swiftcc void @"$S20preserve_exclusivity6endOptyyBpF"(i8*)
-// IR-Onone: call void @swift_endAccess
-// IR-Onone-NEXT: ret void
-
-// IR-O-LABEL: define {{.*}}swiftcc void @"$S20preserve_exclusivity6endOptyyBpF"(i8*{{.*}})
-// IR-O-NEXT: entry
-// IR-O-NEXT: call swiftcc void @marker5
-// IR-O-NEXT: ret void
-
-public func endOpt(_ address: Builtin.RawPointer) {
-  marker5()
-  Builtin.endUnpairedAccess(address)
-}
-
-// IR-Onone-LABEL: define {{.*}}swiftcc void @"$S20preserve_exclusivity7readOptyyBp_xmtlF"(i8*, %swift.type*, %swift.type* %T1)
-// IR-Onone: call void @swift_beginAccess
-// IR-Onone: ret void
-
-// IR-O-LABEL: define {{.*}}swiftcc void @"$S20preserve_exclusivity7readOptyyBp_xmtlF"(i8*{{.*}}, %swift.type*{{.*}}, %swift.type*{{.*}} %T1)
-// IR-O-NEXT: entry
-// IR-O-NEXT: call swiftcc void @marker6
-// IR-O-NEXT: ret void
-
-public func readOpt<T1>(_ address: Builtin.RawPointer, _ ty1: T1.Type) {
-  marker6()
-  Builtin.performInstantaneousReadAccess(address, ty1);
-}
-
-// Make sure testOpt properly inlines in our functions.
-//
-// IR-O-LABEL: define {{.*}}swiftcc void @"$S20preserve_exclusivity7testOptyyBpF"(i8*{{.*}})
-// IR-O: call swiftcc void @marker4
-// IR-O: call swiftcc void @marker5
-// IR-O: call swiftcc void @marker6
-// IR-O: ret void
-public func testOpt(_ k1: Builtin.RawPointer) {
-  beginOpt(k1, k1, Builtin.RawPointer.self)
-  endOpt(k1)
-  readOpt(k1, Builtin.RawPointer.self)
+// CHECK-LABEL: define {{.*}}swiftcc void @"$S20preserve_exclusivity10testAccessyyBpF"(i8*)
+// CHECK: call swiftcc void @marker1
+// CHECK: call void @swift_beginAccess
+// CHECK: call swiftcc void @marker2
+// CHECK: call void @swift_endAccess
+// CHECK: call swiftcc void @marker3
+// CHECK: call void @swift_beginAccess
+// CHECK: ret void
+public func testAccess(_ k1: Builtin.RawPointer) {
+  beginAccess(k1, k1, Builtin.RawPointer.self)
+  endAccess(k1)
+  readAccess(k1, Builtin.RawPointer.self)
 }
diff --git a/test/Interpreter/enforce_exclusive_access.swift b/test/Interpreter/enforce_exclusive_access.swift
index 4b34899..722e6d7 100644
--- a/test/Interpreter/enforce_exclusive_access.swift
+++ b/test/Interpreter/enforce_exclusive_access.swift
@@ -308,13 +308,18 @@
   c[keyPath: getF] += c[keyPath: getF] + 1 // no-trap
 }
 
-// This does not trap, for now, because the standard library (and thus KeyPath) is
-// compiled in Swift 3 mode and we currently log rather than trap in Swift mode.
 ExclusiveAccessTestSuite.test("KeyPathInoutKeyPathWriteClassStoredProp")
+  .skip(.custom(
+    { _isFastAssertConfiguration() },
+    reason: "this trap is not guaranteed to happen in -Ounchecked"))
+  .crashOutputMatches("Previous access (a modification) started at")
+  .crashOutputMatches("Current access (a modification) started at")
+  .code
 {
   let getF = \ClassWithStoredProperty.f
   let c = ClassWithStoredProperty()
 
+  expectCrashLater()
   modifyAndPerform(&c[keyPath: getF]) {
     c[keyPath: getF] = 12
   }
@@ -322,10 +327,18 @@
 
 // This does not currently trap because the standard library is compiled in Swift 3 mode,
 // which logs.
-ExclusiveAccessTestSuite.test("KeyPathInoutKeyPathReadClassStoredProp") {
+ExclusiveAccessTestSuite.test("KeyPathInoutKeyPathReadClassStoredProp")
+  .skip(.custom(
+    { _isFastAssertConfiguration() },
+    reason: "this trap is not guaranteed to happen in -Ounchecked"))
+  .crashOutputMatches("Previous access (a modification) started at")
+  .crashOutputMatches("Current access (a read) started at")
+  .code
+{
   let getF = \ClassWithStoredProperty.f
   let c = ClassWithStoredProperty()
 
+  expectCrashLater()
   modifyAndPerform(&c[keyPath: getF]) {
     let y = c[keyPath: getF]
     _blackHole(y)
diff --git a/test/Interpreter/enforce_exclusive_access_backtrace.swift b/test/Interpreter/enforce_exclusive_access_backtrace.swift
index b50b114..9c80313 100644
--- a/test/Interpreter/enforce_exclusive_access_backtrace.swift
+++ b/test/Interpreter/enforce_exclusive_access_backtrace.swift
@@ -44,34 +44,3 @@
 var c = C()
 withUnsafePointer(to: &c.f) { _ = fputs(String(format: "c.f: 0x%lx\n", Int(bitPattern: $0)), stderr) }
 // CHECK: c.f: [[C_F_ADDR:0x.*]]
-
-// Key path accesses are performed in the Standard Library. The Standard Library
-// is currently compiled in Swift 3 mode and the compiler currently logs conflicts
-// (rather than trapping on them) code compiled in Swift 3 mode. For this reason
-// conflicts where the second conflicting access is via a key path will log rather than
-// trap.
-
-fputs("Overlapping Key Path Write Accesses\n", stderr);
-writeAndPerform(&c[keyPath: \C.f]) {
-  c[keyPath: \C.f] = 8
-  // CHECK-LABEL: Overlapping Key Path Write Accesses
-  // CHECK: Simultaneous accesses to [[C_F_ADDR]], but modification requires exclusive access.
-  // CHECK: Previous access (a modification)
-  // CHECK: Current access (a modification)
-  // CHECK: a.out {{.*}} closure
-  // CHECK: a.out {{.*}} writeAndPerform
-  // CHECK: a.out {{.*}} main
-}
-
-fputs("Overlapping Key Path Write Access and Key Path Read Access\n", stderr);
-writeAndPerform(&c[keyPath: \C.f]) {
-  let x = c[keyPath: \C.f]
-  _blackHole(x)
-  // CHECK-LABEL: Overlapping Key Path Write Access and Key Path Read Access
-  // CHECK: Simultaneous accesses to [[C_F_ADDR]], but modification requires exclusive access.
-  // CHECK: Previous access (a modification)
-  // CHECK: Current access (a read)
-  // CHECK: a.out {{.*}} closure
-  // CHECK: a.out {{.*}} writeAndPerform
-  // CHECK: a.out {{.*}} main
-}
diff --git a/test/SIL/Parser/basic.sil b/test/SIL/Parser/basic.sil
index f67e554..32c7f39 100644
--- a/test/SIL/Parser/basic.sil
+++ b/test/SIL/Parser/basic.sil
@@ -1663,6 +1663,29 @@
   return %20 : $()
 }
 
+// CHECK-LABEL: sil @test_builtin_access : $@convention(thin) (@guaranteed A) -> () {
+// CHECK: begin_access [read] [dynamic] [builtin]
+// CHECK: begin_unpaired_access [read] [dynamic] [builtin]
+// CHECK: end_unpaired_access [dynamic] [builtin]
+// CHECK-LABEL: } // end sil function 'test_builtin_access'
+sil @test_builtin_access : $(@guaranteed A) -> () {
+bb0(%0 : $A):
+  %1 = alloc_stack $Any
+  %2 = ref_element_addr %0 : $A, #A.property
+  %6 = begin_access [read] [dynamic] [builtin] %2 : $*Any
+  copy_addr %6 to %1 : $*Any
+  end_access %6 : $*Any
+  %9 = alloc_stack $Builtin.UnsafeValueBuffer
+  begin_unpaired_access [read] [dynamic] [builtin] %2 : $*Any, %9 : $*Builtin.UnsafeValueBuffer
+  copy_addr %2 to %1 : $*Any
+  end_unpaired_access [dynamic] [builtin] %9 : $*Builtin.UnsafeValueBuffer
+  destroy_addr %1 : $*Any
+  dealloc_stack %9 : $*Builtin.UnsafeValueBuffer
+  dealloc_stack %1 : $*Any
+  %20 = tuple ()
+  return %20 : $()
+}
+
 struct EmptyStruct {}
 
 sil @test_empty_destructure : $@convention(thin) () -> () {
diff --git a/test/SILGen/builtins.swift b/test/SILGen/builtins.swift
index d8ef79f..85cc9ee 100644
--- a/test/SILGen/builtins.swift
+++ b/test/SILGen/builtins.swift
@@ -373,7 +373,7 @@
 func beginUnpairedModifyAccess<T1>(address: Builtin.RawPointer, scratch: Builtin.RawPointer, ty1: T1.Type) {
   // CHECK: [[P2A_ADDR:%.*]] = pointer_to_address %0
   // CHECK: [[P2A_SCRATCH:%.*]] = pointer_to_address %1
-  // CHECK: begin_unpaired_access [modify] [dynamic] [[P2A_ADDR]] : $*T1, [[P2A_SCRATCH]] : $*Builtin.UnsafeValueBuffer
+  // CHECK: begin_unpaired_access [modify] [dynamic] [builtin] [[P2A_ADDR]] : $*T1, [[P2A_SCRATCH]] : $*Builtin.UnsafeValueBuffer
   // CHECK: [[RESULT:%.*]] = tuple ()
   // CHECK: [[RETURN:%.*]] = tuple ()
   // CHECK: return [[RETURN]] : $()
@@ -385,7 +385,7 @@
 func performInstantaneousReadAccess<T1>(address: Builtin.RawPointer, scratch: Builtin.RawPointer, ty1: T1.Type) {
   // CHECK: [[P2A_ADDR:%.*]] = pointer_to_address %0
   // CHECK: [[SCRATCH:%.*]] = alloc_stack $Builtin.UnsafeValueBuffer
-  // CHECK: begin_unpaired_access [read] [dynamic] [no_nested_conflict] [[P2A_ADDR]] : $*T1, [[SCRATCH]] : $*Builtin.UnsafeValueBuffer
+  // CHECK: begin_unpaired_access [read] [dynamic] [no_nested_conflict] [builtin] [[P2A_ADDR]] : $*T1, [[SCRATCH]] : $*Builtin.UnsafeValueBuffer
   // CHECK-NOT: end_{{.*}}access
   // CHECK: [[RESULT:%.*]] = tuple ()
   // CHECK: [[RETURN:%.*]] = tuple ()
diff --git a/test/SILGen/preserve_exclusivity.swift b/test/SILGen/preserve_exclusivity.swift
deleted file mode 100644
index 7902e3d..0000000
--- a/test/SILGen/preserve_exclusivity.swift
+++ /dev/null
@@ -1,118 +0,0 @@
-// RUN: %target-swift-frontend -parse-stdlib -emit-silgen %s | %FileCheck --check-prefix=SILGEN %s
-//
-// Check that SILGen emits the correct SIL attributes for @_semantics("optimize.sil.preserve_exclusivity")/
-
-// RUN: %target-swift-frontend -parse-stdlib -parse-stdlib -emit-sil -Onone %s | %FileCheck --check-prefix=CANONICAL %s
-//
-// Check that -Onone pipeline does not eliminate the attribute or access markers.
-
-@_silgen_name("marker1")
-func marker1() -> ()
-
-@_silgen_name("marker2")
-func marker2() -> ()
-
-@_silgen_name("marker3")
-func marker3() -> ()
-
-@_silgen_name("marker4")
-func marker4() -> ()
-
-@_silgen_name("marker5")
-func marker5() -> ()
-
-@_silgen_name("marker6")
-func marker6() -> ()
-
-// SILGEN-LABEL: sil [_semantics "optimize.sil.preserve_exclusivity"] @$S20preserve_exclusivity10beginNoOptyyBp_BpxmtlF : $@convention(thin) <T1> (Builtin.RawPointer, Builtin.RawPointer, @thick T1.Type) -> () {
-// SILGEN:   begin_unpaired_access
-// SILGEN: } // end sil function '$S20preserve_exclusivity10beginNoOptyyBp_BpxmtlF
-
-// CANONICAL-LABEL: sil [_semantics "optimize.sil.preserve_exclusivity"] @$S20preserve_exclusivity10beginNoOptyyBp_BpxmtlF : $@convention(thin) <T1> (Builtin.RawPointer, Builtin.RawPointer, @thick T1.Type) -> () {
-// CANONICAL:   begin_unpaired_access
-// CANONICAL: } // end sil function '$S20preserve_exclusivity10beginNoOptyyBp_BpxmtlF
-
-@_semantics("optimize.sil.preserve_exclusivity")
-public func beginNoOpt<T1>(_ address: Builtin.RawPointer, _ scratch: Builtin.RawPointer, _ ty1: T1.Type) {
-  marker1()
-  Builtin.beginUnpairedModifyAccess(address, scratch, ty1);
-}
-
-// SILGEN-LABEL: sil [_semantics "optimize.sil.preserve_exclusivity"] @$S20preserve_exclusivity8endNoOptyyBpF : $@convention(thin) (Builtin.RawPointer) -> () {
-// SILGEN:   end_unpaired_access
-// SILGEN: } // end sil function '$S20preserve_exclusivity8endNoOptyyBpF'
-
-// CANONICAL-LABEL: sil [_semantics "optimize.sil.preserve_exclusivity"] @$S20preserve_exclusivity8endNoOptyyBpF : $@convention(thin) (Builtin.RawPointer) -> () {
-// CANONICAL:   end_unpaired_access
-// CANONICAL: } // end sil function '$S20preserve_exclusivity8endNoOptyyBpF'
-
-@_semantics("optimize.sil.preserve_exclusivity")
-public func endNoOpt(_ address: Builtin.RawPointer) {
-  marker2()
-  Builtin.endUnpairedAccess(address)
-}
-
-// SILGEN-LABEL: sil [_semantics "optimize.sil.preserve_exclusivity"] @$S20preserve_exclusivity9readNoOptyyBp_BpmtF : $@convention(thin) (Builtin.RawPointer, @thin Builtin.RawPointer.Type) -> () {
-// SILGEN:   begin_unpaired_access
-// SILGEN: } // end sil function '$S20preserve_exclusivity9readNoOptyyBp_BpmtF'
-
-// CANONICAL-LABEL: sil [_semantics "optimize.sil.preserve_exclusivity"] @$S20preserve_exclusivity9readNoOptyyBp_BpmtF : $@convention(thin) (Builtin.RawPointer, @thin Builtin.RawPointer.Type) -> () {
-// CANONICAL:   begin_unpaired_access
-// CANONICAL: } // end sil function '$S20preserve_exclusivity9readNoOptyyBp_BpmtF'
-
-@_semantics("optimize.sil.preserve_exclusivity")
-public func readNoOpt(_ address: Builtin.RawPointer, _ ty1: Builtin.RawPointer.Type) {
-  marker3()
-  Builtin.performInstantaneousReadAccess(address, ty1);
-}
-
-public func testNoOpt(_ k1: Builtin.RawPointer) {
-  beginNoOpt(k1, k1, Builtin.RawPointer.self)
-  endNoOpt(k1)
-  readNoOpt(k1, Builtin.RawPointer.self)
-}
-
-// SILGEN-LABEL: sil @$S20preserve_exclusivity8beginOptyyBp_BpxmtlF : $@convention(thin) <T1> (Builtin.RawPointer, Builtin.RawPointer, @thick T1.Type) -> () {
-// SILGEN: begin_unpaired_access
-// SILGEN: } // end sil function '$S20preserve_exclusivity8beginOptyyBp_BpxmtlF'
-
-// CANONICAL-LABEL: sil @$S20preserve_exclusivity8beginOptyyBp_BpxmtlF : $@convention(thin) <T1> (Builtin.RawPointer, Builtin.RawPointer, @thick T1.Type) -> () {
-// CANONICAL: begin_unpaired_access
-// CANONICAL: } // end sil function '$S20preserve_exclusivity8beginOptyyBp_BpxmtlF'
-
-public func beginOpt<T1>(_ address: Builtin.RawPointer, _ scratch: Builtin.RawPointer, _ ty1: T1.Type) {
-  marker4()
-  Builtin.beginUnpairedModifyAccess(address, scratch, ty1);
-}
-
-// SILGEN-LABEL: sil @$S20preserve_exclusivity6endOptyyBpF : $@convention(thin) (Builtin.RawPointer) -> () {
-// SILGEN: end_unpaired_access
-// SILGEN: } // end sil function '$S20preserve_exclusivity6endOptyyBpF'
-
-// CANONICAL-LABEL: sil @$S20preserve_exclusivity6endOptyyBpF : $@convention(thin) (Builtin.RawPointer) -> () {
-// CANONICAL: end_unpaired_access
-// CANONICAL: } // end sil function '$S20preserve_exclusivity6endOptyyBpF'
-
-public func endOpt(_ address: Builtin.RawPointer) {
-  marker5()
-  Builtin.endUnpairedAccess(address)
-}
-
-// SILGEN-LABEL: sil @$S20preserve_exclusivity7readOptyyBp_BpmtF : $@convention(thin) (Builtin.RawPointer, @thin Builtin.RawPointer.Type) -> () {
-// SILGEN: begin_unpaired_access
-// SILGEN: } // end sil function '$S20preserve_exclusivity7readOptyyBp_BpmtF'
-
-// CANONICAL-LABEL: sil @$S20preserve_exclusivity7readOptyyBp_BpmtF : $@convention(thin) (Builtin.RawPointer, @thin Builtin.RawPointer.Type) -> () {
-// CANONICAL: begin_unpaired_access
-// CANONICAL: } // end sil function '$S20preserve_exclusivity7readOptyyBp_BpmtF'
-
-public func readOpt(_ address: Builtin.RawPointer, _ ty1: Builtin.RawPointer.Type) {
-  marker6()
-  Builtin.performInstantaneousReadAccess(address, ty1);
-}
-
-public func testOpt(_ k1: Builtin.RawPointer) {
-  beginOpt(k1, k1, Builtin.RawPointer.self)
-  endOpt(k1)
-  readOpt(k1, Builtin.RawPointer.self)
-}
diff --git a/test/SILOptimizer/cast_promote.sil b/test/SILOptimizer/cast_promote.sil
deleted file mode 100644
index d28b0b2..0000000
--- a/test/SILOptimizer/cast_promote.sil
+++ /dev/null
@@ -1,304 +0,0 @@
-// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all %s -sil-combine | %FileCheck %s
-
-sil_stage canonical
-
-import Builtin
-import Swift
-import SwiftShims
-
-public class Base {}
-
-@objc
-public protocol ObjCProto {}
-
-public protocol NativeProto {}
-
-// CHECK-LABEL: sil @promote_super : $@convention(thin) <T where T : Base> (@owned AnyObject) -> @owned T {
-// CHECK: bb0(%0 : $AnyObject):
-// CHECK: unchecked_ref_cast %{{.*}} : $AnyObject to $T
-sil @promote_super : $@convention(thin) <T where T : Base> (@owned AnyObject) -> @owned T {
-bb0(%0 : $AnyObject):
-  %1 = alloc_stack $AnyObject
-  store %0 to %1 : $*AnyObject
-  %3 = unchecked_addr_cast %1 : $*AnyObject to $*T
-  %4 = load %3 : $*T
-  dealloc_stack %1 : $*AnyObject
-  return %4 : $T
-}
-
-// CHECK-LABEL: sil @promote_anyobject : $@convention(thin) <T where T : AnyObject> (@owned AnyObject) -> @owned T {
-// CHECK: bb0(%0 : $AnyObject):
-// CHECK: unchecked_ref_cast %{{.*}} : $AnyObject to $T
-sil @promote_anyobject : $@convention(thin) <T where T : AnyObject> (@owned AnyObject) -> @owned T {
-bb0(%0 : $AnyObject):
-  %1 = alloc_stack $AnyObject
-  store %0 to %1 : $*AnyObject
-  %3 = unchecked_addr_cast %1 : $*AnyObject to $*T
-  %4 = load %3 : $*T
-  dealloc_stack %1 : $*AnyObject
-  return %4 : $T
-}
-
-// CHECK-LABEL: sil @promote_objc : $@convention(thin) <T where T : ObjCProto> (@owned AnyObject) -> @owned T {
-// CHECK: bb0(%0 : $AnyObject):
-// CHECK: unchecked_ref_cast %{{.*}} : $AnyObject to $T
-sil @promote_objc : $@convention(thin) <T where T : ObjCProto> (@owned AnyObject) -> @owned T {
-bb0(%0 : $AnyObject):
-  %1 = alloc_stack $AnyObject
-  store %0 to %1 : $*AnyObject
-  %3 = unchecked_addr_cast %1 : $*AnyObject to $*T
-  %4 = load %3 : $*T
-  dealloc_stack %1 : $*AnyObject
-  return %4 : $T
-}
-
-// CHECK-LABEL: sil @promote_objcproto : $@convention(thin) (@owned AnyObject) -> @owned ObjCProto {
-// CHECK: bb0(%0 : $AnyObject):
-// CHECK: unchecked_ref_cast %{{.*}} : $AnyObject to $ObjCProto
-sil @promote_objcproto : $@convention(thin) (@owned AnyObject) -> @owned ObjCProto {
-bb0(%0 : $AnyObject):
-  %1 = alloc_stack $AnyObject
-  store %0 to %1 : $*AnyObject
-  %3 = unchecked_addr_cast %1 : $*AnyObject to $*ObjCProto
-  %4 = load %3 : $*ObjCProto
-  dealloc_stack %1 : $*AnyObject
-  return %4 : $ObjCProto
-}
-
-// CHECK-LABEL: sil @nopromote_nativeproto : $@convention(thin) (@owned AnyObject) -> @out NativeProto {
-// CHECK: bb0(%0 : $*NativeProto, %1 : $AnyObject):
-// CHECK: unchecked_addr_cast %{{.*}} : $*AnyObject to $*NativeProto
-sil @nopromote_nativeproto : $@convention(thin) (@owned AnyObject) -> @out NativeProto {
-bb0(%0 : $*NativeProto, %1 : $AnyObject):
-  %3 = alloc_stack $AnyObject
-  store %1 to %3 : $*AnyObject
-  %5 = unchecked_addr_cast %3 : $*AnyObject to $*NativeProto
-  copy_addr %5 to [initialization] %0 : $*NativeProto
-  dealloc_stack %3 : $*AnyObject
-  strong_release %1 : $AnyObject
-  %9 = tuple ()
-  return %9 : $()
-}
-
-class B {}
-
-// CHECK-LABEL: sil @load_uncheckedaddrcast_to_uncheckedrefcast_load : $@convention(thin) (@inout Optional<B>) -> (Builtin.NativeObject, Optional<Builtin.NativeObject>) {
-// CHECK-NOT: unchecked_addr_cast
-// CHECK: unchecked_ref_cast
-// CHECK-NOT: unchecked_addr_cast
-// CHECK: unchecked_ref_cast
-// CHECK-NOT: unchecked_addr_cast
-sil @load_uncheckedaddrcast_to_uncheckedrefcast_load : $@convention(thin) (@inout Optional<B>) -> (Builtin.NativeObject, Optional<Builtin.NativeObject>) {
-bb0(%0 : $*Optional<B>):
-  %1 = unchecked_addr_cast %0 : $*Optional<B> to $*Builtin.NativeObject
-  %2 = unchecked_addr_cast %0 : $*Optional<B> to $*Optional<Builtin.NativeObject>
-  %3 = load %1 : $*Builtin.NativeObject
-  %4 = load %2 : $*Optional<Builtin.NativeObject>
-  %5 = tuple(%3 : $Builtin.NativeObject, %4 : $Optional<Builtin.NativeObject>)
-  return %5 : $(Builtin.NativeObject, Optional<Builtin.NativeObject>)
-}
-
-struct rs_E {
-  var ptr : Builtin.NativeObject
-  var i : Int
-}
-struct rs_F {
-  var e : rs_E
-}
-struct rs_D {
-  var i : Int
-}
-struct rs_C {
-  var d : rs_D
-}
-
-struct rs_B {
-  var ptr : Builtin.NativeObject
-}
-struct rs_A {
-  var b : rs_B
-}
-
-enum TwoStateEnum {
-  case State1(rs_A)
-  case State2(rs_C)
-}
-
-enum FakeOptional<T> {
-  case nOne
-  case some(T)
-}
-
-// CHECK-LABEL: sil @reinterpretcast_simplification_unchecked_addr : $@convention(thin) (@inout FakeOptional<rs_A>, @inout FakeOptional<rs_C>, @inout FakeOptional<rs_F>, @inout TwoStateEnum, @inout TwoStateEnum) -> (Builtin.NativeObject, Int, Builtin.NativeObject, Builtin.NativeObject, Int) {
-// CHECK: bb0(
-// CHECK-NEXT: load
-// CHECK-NEXT: unchecked_bitwise_cast
-// CHECK-NEXT: load
-// CHECK-NEXT: unchecked_trivial_bit_cast
-// CHECK-NEXT: load
-// CHECK-NEXT: unchecked_bitwise_cast
-// CHECK-NEXT: load
-// CHECK-NEXT: unchecked_bitwise_cast
-// CHECK-NEXT: load
-// CHECK-NEXT: unchecked_trivial_bit_cast
-// CHECK-NEXT: tuple
-// CHECK-NEXT: return
-sil @reinterpretcast_simplification_unchecked_addr
-  : $@convention(thin) (@inout FakeOptional<rs_A>, @inout FakeOptional<rs_C>, @inout FakeOptional<rs_F>, @inout TwoStateEnum,
-            @inout TwoStateEnum)
-     -> (Builtin.NativeObject, Int, Builtin.NativeObject, Builtin.NativeObject, Int) {
-bb0(%0 : $*FakeOptional<rs_A>, %1 : $*FakeOptional<rs_C>, %2 : $*FakeOptional<rs_F>, %3 : $*TwoStateEnum, %4 : $*TwoStateEnum):
-  %5 = unchecked_addr_cast %0 : $*FakeOptional<rs_A> to $*Builtin.NativeObject
-  %6 = unchecked_addr_cast %1 : $*FakeOptional<rs_C> to $*Int
-  %7 = unchecked_addr_cast %2 : $*FakeOptional<rs_F> to $*Builtin.NativeObject
-  %8 = unchecked_addr_cast %3 : $*TwoStateEnum to $*Builtin.NativeObject
-  %9 = unchecked_addr_cast %4 : $*TwoStateEnum to $*Int
-  %10 = load %5 : $*Builtin.NativeObject
-  %11 = load %6 : $*Int
-  %12 = load %7 : $*Builtin.NativeObject
-  %13 = load %8 : $*Builtin.NativeObject
-  %14 = load %9 : $*Int
-  %15 = tuple(%10 : $Builtin.NativeObject, %11 : $Int, %12 : $Builtin.NativeObject, %13 : $Builtin.NativeObject, %14 : $Int)
-  return %15 : $(Builtin.NativeObject, Int, Builtin.NativeObject, Builtin.NativeObject, Int)
-}
-
-enum ValEnum {case X, Y, Z}
-
-struct PtrInt {
-  var Ptr: Builtin.RawPointer
-  var Val: Builtin.Int32
-}
-struct PtrInt2 {
-  var Ptr: Builtin.RawPointer
-  var Val1: Builtin.Int32
-  var Val2: ValEnum
-}
-struct Agg {
-  var pi: PtrInt
-  var Val: ValEnum
-}
-
-// struct {A, B} -> A is safe
-// struct {A, B, C} -> struct {A, B} is safe
-// struct { struct {A, B}, C} -> struct {A, B} is safe
-// struct { struct {A, B}, C} -> struct {A, B, C} is NOT safe
-// CHECK-LABEL: sil @unchecked_addr_cast_struct_promote : $@convention(thin) (@inout PtrInt, @inout PtrInt2, @inout Agg) -> (Builtin.RawPointer, PtrInt, PtrInt, PtrInt2) {
-// CHECK: bb0(%0 : $*PtrInt, %1 : $*PtrInt2, %2 : $*Agg):
-// CHECK: load %0 : $*PtrInt
-// CHECK: unchecked_trivial_bit_cast %{{.*}} : $PtrInt to $Builtin.RawPointer
-// CHECK: load %1 : $*PtrInt2
-// CHECK: unchecked_trivial_bit_cast %{{.*}} : $PtrInt2 to $PtrInt
-// CHECK: load %2 : $*Agg
-// CHECK: unchecked_trivial_bit_cast %{{.*}} : $Agg to $PtrInt
-// CHECK: [[LOCAL:%.*]] = alloc_stack $Agg
-// CHECK: store %{{.*}} to [[LOCAL]] : $*Agg
-// CHECK: [[CAST:%.*]] = unchecked_addr_cast [[LOCAL]] : $*Agg to $*PtrInt2
-// CHECK: load [[CAST]] : $*PtrInt2
-// CHECK: dealloc_stack
-// CHECK: return
-sil @unchecked_addr_cast_struct_promote : $@convention(thin) (@inout PtrInt, @inout PtrInt2, @inout Agg) -> (Builtin.RawPointer, PtrInt, PtrInt, PtrInt2) {
-bb0(%0 : $*PtrInt, %1 : $*PtrInt2, %2 : $*Agg):
-  %3 = load %0 : $*PtrInt
-  %4 = alloc_stack $PtrInt
-  store %3 to %4 : $*PtrInt
-  %6 = unchecked_addr_cast %4 : $*PtrInt to $*Builtin.RawPointer
-  %7 = load %6 : $*Builtin.RawPointer
-  %8 = load %1 : $*PtrInt2
-  %9 = alloc_stack $PtrInt2
-  store %8 to %9 : $*PtrInt2
-  %11 = unchecked_addr_cast %9 : $*PtrInt2 to $*PtrInt
-  %12 = load %11 : $*PtrInt
-  %13 = load %2 : $*Agg
-  %14 = alloc_stack $Agg
-  store %13 to %14 : $*Agg
-  %16 = unchecked_addr_cast %14 : $*Agg to $*PtrInt
-  %17 = load %16 : $*PtrInt
-  %18 = alloc_stack $Agg
-  store %13 to %18 : $*Agg
-  %20 = unchecked_addr_cast %18 : $*Agg to $*PtrInt2
-  %21 = load %20 : $*PtrInt2
-  %22 = tuple (%7 : $Builtin.RawPointer, %12 : $PtrInt, %17 : $PtrInt, %21 : $PtrInt2)
-  dealloc_stack %18 : $*Agg
-  dealloc_stack %14 : $*Agg
-  dealloc_stack %9 : $*PtrInt2
-  dealloc_stack %4 : $*PtrInt
-  return %22 : $(Builtin.RawPointer, PtrInt, PtrInt, PtrInt2)
-}
-
-public enum E0 {}
-public enum E0_ {}
-public enum E1 {case A}
-public enum E2 {case A, B}
-public enum E3 {case A, B, C}
-
-public enum PB2 {case A, B(Int)}
-public enum PX2 {case X(Int), Y}
-public enum PAB2 {case A(Int), B(Int)}
-public enum PXY2 {case X(Int), Y(Int)}
-public enum PX3 {case X(Int), Y, Z}
-
-// enum {} -> enum {} is safe
-// enum {A, B} -> enum {X} is safe
-// enum {A, B(Int)} -> Int is safe
-// enum {A, B(Int)} -> enum {X(Int), Y} is safe
-// enum {A, B(Int)} -> enum {X(Int), Y, Z} is NOT safe
-// enum {A(Int), B(Int)} -> enum {X(Int), Y(Int)} is NOT safe
-// CHECK-LABEL: sil @unchecked_addr_cast_enum_promote : $@convention(thin) (@inout E0, @inout E2, @inout PB2, @inout PAB2) -> (E0_, E1, Int, PX2, PX3, PXY2)
-// CHECK: load %0 : $*E0
-// CHECK: unchecked_trivial_bit_cast %{{.*}} : $E0 to $E0_
-// CHECK: load %1 : $*E2
-// CHECK: unchecked_trivial_bit_cast %{{.*}} : $E2 to $E1
-// CHECK: load %2 : $*PB2
-// CHECK: unchecked_trivial_bit_cast %{{.*}} : $PB2 to $Int
-// CHECK: unchecked_trivial_bit_cast %{{.*}} : $PB2 to $PX2
-// CHECK: alloc_stack $PB2
-// CHECK: store %{{.*}} to %{{.*}} : $*PB2
-// CHECK: unchecked_addr_cast %{{.*}} : $*PB2 to $*PX3
-// CHECK: load %{{.*}} : $*PX3
-// CHECK: load %3 : $*PAB2
-// CHECK: alloc_stack $PAB2
-// CHECK: store %{{.*}} to %{{.*}} : $*PAB2
-// CHECK: unchecked_addr_cast %{{.*}} : $*PAB2 to $*PXY2
-// CHECK: load %{{.*}} : $*PXY2
-// CHECK: dealloc_stack %{{.*}} : $*PAB2
-// CHECK: dealloc_stack %{{.*}} : $*PB2
-// CHECK: return %{{.*}} : $(E0_, E1, Int, PX2, PX3, PXY2)
-sil @unchecked_addr_cast_enum_promote : $@convention(thin) (@inout E0, @inout E2, @inout PB2, @inout PAB2) -> (E0_, E1, Int, PX2, PX3, PXY2) {
-bb0(%0 : $*E0, %1 : $*E2, %2 : $*PB2, %3 : $*PAB2):
-  %9 = load %0 : $*E0                             // user: %11
-  %10 = alloc_stack $E0                           // users: %11, %12, %43
-  store %9 to %10 : $*E0                        // id: %11
-  %12 = unchecked_addr_cast %10 : $*E0 to $*E0_ // user: %13
-  %13 = load %12 : $*E0_                          // user: %37
-  %14 = load %1 : $*E2                            // user: %16
-  %15 = alloc_stack $E2                           // users: %16, %17, %42
-  store %14 to %15 : $*E2                       // id: %16
-  %17 = unchecked_addr_cast %15 : $*E2 to $*E1  // user: %18
-  %18 = load %17 : $*E1                           // user: %37
-  %19 = load %2 : $*PB2                           // users: %21, %25, %29
-  %20 = alloc_stack $PB2                          // users: %21, %22, %41
-  store %19 to %20 : $*PB2                      // id: %21
-  %22 = unchecked_addr_cast %20 : $*PB2 to $*Int // user: %23
-  %23 = load %22 : $*Int                          // user: %37
-  %24 = alloc_stack $PB2                          // users: %25, %26, %40
-  store %19 to %24 : $*PB2                      // id: %25
-  %26 = unchecked_addr_cast %24 : $*PB2 to $*PX2 // user: %27
-  %27 = load %26 : $*PX2                          // user: %37
-  %28 = alloc_stack $PB2                          // users: %29, %30, %39
-  store %19 to %28 : $*PB2                      // id: %29
-  %30 = unchecked_addr_cast %28 : $*PB2 to $*PX3 // user: %31
-  %31 = load %30 : $*PX3                          // user: %37
-  %32 = load %3 : $*PAB2                          // user: %34
-  %33 = alloc_stack $PAB2                         // users: %34, %35, %38
-  store %32 to %33 : $*PAB2                     // id: %34
-  %35 = unchecked_addr_cast %33 : $*PAB2 to $*PXY2 // user: %36
-  %36 = load %35 : $*PXY2                         // user: %37
-  %37 = tuple (%13 : $E0_, %18 : $E1, %23 : $Int, %27 : $PX2, %31 : $PX3, %36 : $PXY2) // user: %44
-  dealloc_stack %33 : $*PAB2     // id: %38
-  dealloc_stack %28 : $*PB2      // id: %39
-  dealloc_stack %24 : $*PB2      // id: %40
-  dealloc_stack %20 : $*PB2      // id: %41
-  dealloc_stack %15 : $*E2       // id: %42
-  dealloc_stack %10 : $*E0       // id: %43
-  return %37 : $(E0_, E1, Int, PX2, PX3, PXY2)    // id: %44
-}
diff --git a/test/SILOptimizer/preserve_exclusivity.swift b/test/SILOptimizer/preserve_exclusivity.swift
deleted file mode 100644
index 9ba7e28..0000000
--- a/test/SILOptimizer/preserve_exclusivity.swift
+++ /dev/null
@@ -1,150 +0,0 @@
-// RUN: %target-swift-frontend -parse-stdlib -Xllvm -sil-disable-pass=FunctionSignatureOpts -Xllvm -sil-disable-pass=GenericSpecializer -emit-sil -O %s | %FileCheck %s
-//
-// The -O pipeline should respect
-// @_semantics("optimize.sil.preserve_exclusivity") and avoid eliminating access
-// markers as long as the semantics call is not inlined.
-
-// RUN: %empty-directory(%t)
-// RUN: %target-swift-frontend -parse-stdlib -emit-module -O -primary-file %s -emit-module-path %t/preserve_exclusivity.swiftmodule
-// RUN: %target-sil-opt %t/preserve_exclusivity.swiftmodule -emit-sorted-sil -verify -o - | %FileCheck --check-prefix=DESERIALIZED %s
-//
-// Access markers cannot be stripped prior to module serialization, even when their functions are inlined.
-
-@usableFromInline
-@_silgen_name("marker1")
-func marker1() -> ()
-
-@usableFromInline
-@_silgen_name("marker2")
-func marker2() -> ()
-
-@usableFromInline
-@_silgen_name("marker3")
-func marker3() -> ()
-
-@usableFromInline
-@_silgen_name("marker4")
-func marker4() -> ()
-
-@usableFromInline
-@_silgen_name("marker5")
-func marker5() -> ()
-
-@usableFromInline
-@_silgen_name("marker6")
-func marker6() -> ()
-
-// CHECK-LABEL: sil [_semantics "optimize.sil.preserve_exclusivity"] @$S20preserve_exclusivity13f1_beginNoOptyyBp_BpxmtlF : $@convention(thin) <T1> (Builtin.RawPointer, Builtin.RawPointer, @thick T1.Type) -> () {
-// CHECK:   begin_unpaired_access
-// CHECK: } // end sil function '$S20preserve_exclusivity13f1_beginNoOptyyBp_BpxmtlF'
-
-// DESERIALIZED-LABEL: sil [serialized] [_semantics "optimize.sil.preserve_exclusivity"] [canonical] @$S20preserve_exclusivity13f1_beginNoOptyyBp_BpxmtlF : $@convention(thin) <T1> (Builtin.RawPointer, Builtin.RawPointer, @thick T1.Type) -> () {
-// DESERIALIZED:   begin_unpaired_access
-// DESERIALIZED: } // end sil function '$S20preserve_exclusivity13f1_beginNoOptyyBp_BpxmtlF'
-
-@inlinable
-@_semantics("optimize.sil.preserve_exclusivity")
-public func f1_beginNoOpt<T1>(_ address: Builtin.RawPointer, _ scratch: Builtin.RawPointer, _ ty1: T1.Type) {
-  marker1()
-  Builtin.beginUnpairedModifyAccess(address, scratch, ty1);
-}
-
-// CHECK-LABEL: sil [_semantics "optimize.sil.preserve_exclusivity"] @$S20preserve_exclusivity13f2___endNoOptyyBpF : $@convention(thin) (Builtin.RawPointer) -> () {
-// CHECK:   end_unpaired_access
-// CHECK: } // end sil function '$S20preserve_exclusivity13f2___endNoOptyyBpF'
-
-// DESERIALIZED-LABEL: sil [serialized] [_semantics "optimize.sil.preserve_exclusivity"] [canonical] @$S20preserve_exclusivity13f2___endNoOptyyBpF : $@convention(thin) (Builtin.RawPointer) -> () {
-// DESERIALIZED:   end_unpaired_access
-// DESERIALIZED: } // end sil function '$S20preserve_exclusivity13f2___endNoOptyyBpF'
-
-@inlinable
-@_semantics("optimize.sil.preserve_exclusivity")
-public func f2___endNoOpt(_ address: Builtin.RawPointer) {
-  marker2()
-  Builtin.endUnpairedAccess(address)
-}
-
-// CHECK-LABEL: sil [_semantics "optimize.sil.preserve_exclusivity"] @$S20preserve_exclusivity13f3__readNoOptyyBp_BpmtF : $@convention(thin) (Builtin.RawPointer, @thin Builtin.RawPointer.Type) -> () {
-// CHECK:   begin_unpaired_access
-// CHECK: } // end sil function '$S20preserve_exclusivity13f3__readNoOptyyBp_BpmtF
-
-// DESERIALIZED-LABEL: sil [serialized] [_semantics "optimize.sil.preserve_exclusivity"] [canonical] @$S20preserve_exclusivity13f3__readNoOptyyBp_BpmtF : $@convention(thin) (Builtin.RawPointer, @thin Builtin.RawPointer.Type) -> () {
-// DESERIALIZED:   begin_unpaired_access
-// DESERIALIZED: } // end sil function '$S20preserve_exclusivity13f3__readNoOptyyBp_BpmtF
-
-@inlinable
-@_semantics("optimize.sil.preserve_exclusivity")
-public func f3__readNoOpt(_ address: Builtin.RawPointer, _ ty1: Builtin.RawPointer.Type) {
-  marker3()
-  Builtin.performInstantaneousReadAccess(address, ty1);
-}
-
-// DESERIALIZED-LABEL: sil [serialized] [canonical] @$S20preserve_exclusivity13f4__testNoOptyyBpF : $@convention(thin) (Builtin.RawPointer) -> () {
-// DESERIALIZED: marker1
-// DESERIALIZED: begin_unpaired_access
-// DESERIALIZED: marker2
-// DESERIALIZED: end_unpaired_access
-// DESERIALIZED: marker3
-// DESERIALIZED: begin_unpaired_access
-// DESERIALIZED: return
-
-@inlinable
-public func f4__testNoOpt(_ k1: Builtin.RawPointer) {
-  f1_beginNoOpt(k1, k1, Builtin.RawPointer.self)
-  f2___endNoOpt(k1)
-  f3__readNoOpt(k1, Builtin.RawPointer.self)
-}
-
-// CHECK-LABEL: sil @$S20preserve_exclusivity13f5_beginDoOptyyBp_BpxmtlF : $@convention(thin) <T1> (Builtin.RawPointer, Builtin.RawPointer, @thick T1.Type) -> () {
-// CHECK-NOT: begin_unpaired_access
-// CHECK: } // end sil function '$S20preserve_exclusivity13f5_beginDoOptyyBp_BpxmtlF'
-
-// DESERIALIZED-LABEL: sil [serialized] [canonical] @$S20preserve_exclusivity13f5_beginDoOptyyBp_BpxmtlF : $@convention(thin) <T1> (Builtin.RawPointer, Builtin.RawPointer, @thick T1.Type) -> () {
-// DESERIALIZED-NOT: begin_unpaired_access
-// DESERIALIZED: } // end sil function '$S20preserve_exclusivity13f5_beginDoOptyyBp_BpxmtlF'
-
-@inlinable
-public func f5_beginDoOpt<T1>(_ address: Builtin.RawPointer, _ scratch: Builtin.RawPointer, _ ty1: T1.Type) {
-  marker4()
-  Builtin.beginUnpairedModifyAccess(address, scratch, ty1);
-}
-
-// CHECK-LABEL: sil @$S20preserve_exclusivity13f6___endDoOptyyBpF : $@convention(thin) (Builtin.RawPointer) -> () {
-// CHECK-NOT: end_unpaired_access
-// CHECK: } // end sil function '$S20preserve_exclusivity13f6___endDoOptyyBpF'
-
-// DESERIALIZED-LABEL: sil [serialized] [canonical] @$S20preserve_exclusivity13f6___endDoOptyyBpF : $@convention(thin) (Builtin.RawPointer) -> () {
-// DESERIALIZED-NOT: end_unpaired_access
-// DESERIALIZED: } // end sil function '$S20preserve_exclusivity13f6___endDoOptyyBpF'
-
-@inlinable
-public func f6___endDoOpt(_ address: Builtin.RawPointer) {
-  marker5()
-  Builtin.endUnpairedAccess(address)
-}
-
-// CHECK-LABEL: sil @$S20preserve_exclusivity13f7__readDoOptyyBp_BpmtF : $@convention(thin) (Builtin.RawPointer, @thin Builtin.RawPointer.Type) -> () {
-// CHECK-NOT: begin_unpaired_access
-// CHECK: } // end sil function '$S20preserve_exclusivity13f7__readDoOptyyBp_BpmtF'
-
-// DESERIALIZED-LABEL: sil [serialized] [canonical] @$S20preserve_exclusivity13f7__readDoOptyyBp_BpmtF : $@convention(thin) (Builtin.RawPointer, @thin Builtin.RawPointer.Type) -> () {
-// DESERIALIZED-NOT: begin_unpaired_access
-// DESERIALIZED: } // end sil function '$S20preserve_exclusivity13f7__readDoOptyyBp_BpmtF'
-
-@inlinable
-public func f7__readDoOpt(_ address: Builtin.RawPointer, _ ty1: Builtin.RawPointer.Type) {
-  marker6()
-  Builtin.performInstantaneousReadAccess(address, ty1);
-}
-
-// DESERIALIZED-LABEL: sil [serialized] [canonical] @$S20preserve_exclusivity13f8__testDoOptyyBpF : $@convention(thin) (Builtin.RawPointer) -> () {
-// DESERIALIZED: marker4
-// DESERIALIZED: marker5
-// DESERIALIZED: marker6
-// DESERIALIZED: return
-@inlinable
-public func f8__testDoOpt(_ k1: Builtin.RawPointer) {
-  f5_beginDoOpt(k1, k1, Builtin.RawPointer.self)
-  f6___endDoOpt(k1)
-  f7__readDoOpt(k1, Builtin.RawPointer.self)
-}
diff --git a/test/SILOptimizer/sil_combine.sil b/test/SILOptimizer/sil_combine.sil
index 0f4a3af..994feaa 100644
--- a/test/SILOptimizer/sil_combine.sil
+++ b/test/SILOptimizer/sil_combine.sil
@@ -404,8 +404,8 @@
 
 // CHECK-LABEL: sil @a2p_p2a_reinterpret_cast_word_raw_pointer
 // CHECK: bb0
+// CHECK-NEXT: unchecked_addr_cast
 // CHECK-NEXT: load
-// CHECK-NEXT: unchecked_trivial_bit_cast
 // CHECK-NEXT: return
 sil @a2p_p2a_reinterpret_cast_word_raw_pointer : $@convention(thin) (@inout Builtin.Word, Builtin.RawPointer) -> Int32 {
 bb0(%0 : $*Builtin.Word, %1 : $Builtin.RawPointer):
@@ -1133,9 +1133,9 @@
 
 // CHECK-LABEL: sil @unchecked_addr_cast_formation : $@convention(thin) (@inout Builtin.NativeObject) -> Builtin.Word {
 // CHECK: bb0([[INPUT_PTR:%[0-9]+]] : $*Builtin.NativeObject):
-// CHECK-NEXT: [[INPUT_VALUE:%[0-9]+]] = load [[INPUT_PTR]] : $*Builtin.NativeObject
-// CHECK-NEXT: [[CAST_VALUE:%[0-9]+]] = unchecked_trivial_bit_cast [[INPUT_VALUE]] : $Builtin.NativeObject to $Builtin.Word
-// CHECK-NEXT: return
+// CHECK-NEXT: [[ADDR_CAST:%[0-9]+]] = unchecked_addr_cast [[INPUT_PTR]] : $*Builtin.NativeObject to $*Builtin.Word
+// CHECK-NEXT: [[RETURN_VALUE:%[0-9]+]] = load [[ADDR_CAST]] : $*Builtin.Word
+// CHECK-NEXT: return [[RETURN_VALUE]]
 sil @unchecked_addr_cast_formation : $@convention(thin) (@inout Builtin.NativeObject) -> Builtin.Word {
 bb0(%0 : $*Builtin.NativeObject):
   %1 = address_to_pointer %0 : $*Builtin.NativeObject to $Builtin.RawPointer
@@ -1146,9 +1146,10 @@
 
 // CHECK-LABEL: sil @unchecked_addr_cast_forwarding : $@convention(thin) (@inout Builtin.NativeObject) -> Builtin.Word {
 // CHECK: bb0([[INPUT_PTR:%[0-9]+]] : $*Builtin.NativeObject):
-// CHECK-NEXT: [[INPUT_VALUE:%[0-9]+]] = load [[INPUT_PTR]] : $*Builtin.NativeObject
-// CHECK-NEXT: [[CAST_VALUE:%[0-9]+]] = unchecked_trivial_bit_cast [[INPUT_VALUE]] : $Builtin.NativeObject to $Builtin.Word
-// CHECK-NEXT: return
+// CHECK-NEXT: [[ADDR_CAST:%[0-9]+]] = unchecked_addr_cast [[INPUT_PTR]] : $*Builtin.NativeObject to $*Builtin.Word
+// CHECK-NEXT: debug_value [[ADDR_CAST]]
+// CHECK-NEXT: [[RETURN_VALUE:%[0-9]+]] = load [[ADDR_CAST]] : $*Builtin.Word
+// CHECK-NEXT: return [[RETURN_VALUE]]
 sil @unchecked_addr_cast_forwarding : $@convention(thin) (@inout Builtin.NativeObject) -> Builtin.Word {
 bb0(%0 : $*Builtin.NativeObject):
   %1 = unchecked_addr_cast %0 : $*Builtin.NativeObject to $*Builtin.RawPointer
diff --git a/test/Serialization/Inputs/def_basic.sil b/test/Serialization/Inputs/def_basic.sil
index b14ff89..a3b1a25 100644
--- a/test/Serialization/Inputs/def_basic.sil
+++ b/test/Serialization/Inputs/def_basic.sil
@@ -1287,6 +1287,31 @@
   return %20 : $()
 }
 
+// CHECK-LABEL: sil public_external [transparent] [serialized] @test_builtin_access : $@convention(thin) (@guaranteed A) -> () {
+// CHECK: begin_access [read] [dynamic] [builtin]
+// CHECK: end_access
+// CHECK: begin_unpaired_access [read] [dynamic] [builtin]
+// CHECK: end_unpaired_access [dynamic] [builtin]
+// CHECK-LABEL: } // end sil function 'test_builtin_access'
+sil [transparent] [serialized] @test_builtin_access : $@convention(thin) (@guaranteed A) -> () {
+bb0(%0 : $A):
+  %1 = alloc_stack $Any
+  %2 = ref_element_addr %0 : $A, #A.property
+  %6 = begin_access [dynamic] [read] [builtin] %2 : $*Any
+  copy_addr %6 to %1 : $*Any
+  end_access %6 : $*Any
+  destroy_addr %1 : $*Any
+  %9 = alloc_stack $Builtin.UnsafeValueBuffer
+  begin_unpaired_access [read] [dynamic] [builtin] %2 : $*Any, %9 : $*Builtin.UnsafeValueBuffer
+  copy_addr %2 to %1 : $*Any
+  end_unpaired_access [dynamic] [builtin] %9 : $*Builtin.UnsafeValueBuffer
+  destroy_addr %1 : $*Any
+  dealloc_stack %9 : $*Builtin.UnsafeValueBuffer
+  dealloc_stack %1 : $*Any
+  %20 = tuple ()
+  return %20 : $()
+}
+
 public class Foo {
   subscript (x: Int, y: Int) -> Int32 { get set }
   var x: Int
@@ -1494,6 +1519,7 @@
   %152 = function_ref @a_regular_thunk: $@convention(thin) () -> ()
   %153 = function_ref @weak_unowned: $@convention(thin) (@owned WeakUnownedTest, @owned AnyObject) -> ()
   %154 = function_ref @test_access : $@convention(thin) (@guaranteed A) -> ()
+  %155 = function_ref @test_builtin_access : $@convention(thin) (@guaranteed A) -> ()
 
   %r = tuple ()
   return %r : $()
diff --git a/validation-test/stdlib/OpenCLSDKOverlay.swift b/validation-test/stdlib/OpenCLSDKOverlay.swift
index 58959c5..e877aeb 100644
--- a/validation-test/stdlib/OpenCLSDKOverlay.swift
+++ b/validation-test/stdlib/OpenCLSDKOverlay.swift
@@ -194,7 +194,7 @@
           kernel!, 3,
           0, MemoryLayout<cl_mem>.size, inputPtr,
           1, MemoryLayout<cl_mem>.size, outputPtr,
-          2, MemoryLayout.size(ofValue: count), countPtr)
+          2, MemoryLayout.size(ofValue: countPtr.pointee), countPtr)
       }
     }
   }